blume 2.0.3 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -0
- package/CHANGELOG.md +48 -0
- package/README.md +1 -1
- package/dist/cli/{chunk-1d7ve1dm.js → chunk-0gz36akr.js} +18 -2
- package/dist/cli/{chunk-1d7ve1dm.js.map → chunk-0gz36akr.js.map} +3 -3
- package/dist/cli/{chunk-2eytanqx.js → chunk-1n228xqb.js} +2 -2
- package/dist/cli/{chunk-yfyb25rh.js → chunk-2f3ndkpw.js} +24 -8
- package/dist/cli/chunk-2f3ndkpw.js.map +14 -0
- package/dist/cli/{chunk-r20tn01b.js → chunk-2f7n4qzt.js} +8 -2
- package/dist/cli/{chunk-r20tn01b.js.map → chunk-2f7n4qzt.js.map} +3 -3
- package/dist/cli/{chunk-35d4wj9f.js → chunk-2n4ps1b3.js} +7 -7
- package/dist/cli/{chunk-j85vccga.js → chunk-43zcf4gz.js} +97 -57
- package/dist/cli/{chunk-j85vccga.js.map → chunk-43zcf4gz.js.map} +6 -6
- package/dist/cli/{chunk-e04dxsz1.js → chunk-4ejxbzee.js} +1 -1
- package/dist/cli/{chunk-5m5nmvyq.js → chunk-4h8z9vv5.js} +233 -39
- package/dist/cli/chunk-4h8z9vv5.js.map +16 -0
- package/dist/cli/{chunk-5f86nr5m.js → chunk-5cg2rzgf.js} +18 -16
- package/dist/cli/{chunk-5f86nr5m.js.map → chunk-5cg2rzgf.js.map} +2 -2
- package/dist/cli/{chunk-tzmab476.js → chunk-5ffywsmb.js} +4 -4
- package/dist/cli/{chunk-2z928egk.js → chunk-5wj2qwn2.js} +5 -5
- package/dist/cli/chunk-6bm0xpgd.js +18 -0
- package/dist/cli/chunk-6bm0xpgd.js.map +10 -0
- package/dist/cli/{chunk-vg9r4eb9.js → chunk-713mngdq.js} +12 -5
- package/dist/cli/{chunk-vg9r4eb9.js.map → chunk-713mngdq.js.map} +3 -3
- package/dist/cli/{chunk-5xvm6tfj.js → chunk-9geymqns.js} +17 -15
- package/dist/cli/{chunk-5xvm6tfj.js.map → chunk-9geymqns.js.map} +2 -2
- package/dist/cli/{chunk-q58y5e6a.js → chunk-9xr4dgee.js} +26 -17
- package/dist/cli/chunk-9xr4dgee.js.map +10 -0
- package/dist/cli/{chunk-b07cmahc.js → chunk-amrb6hgh.js} +2 -2
- package/dist/cli/chunk-cm89scdv.js +443 -0
- package/dist/cli/chunk-cm89scdv.js.map +11 -0
- package/dist/cli/{chunk-akbpwfxc.js → chunk-cmtcnh9f.js} +2 -2
- package/dist/cli/chunk-cy5bm0j0.js +104 -0
- package/dist/cli/chunk-cy5bm0j0.js.map +11 -0
- package/dist/cli/{chunk-crgn1q09.js → chunk-e7vvk5ya.js} +4 -4
- package/dist/cli/{chunk-pehfxfta.js → chunk-g2z9x01v.js} +6 -98
- package/dist/cli/chunk-g2z9x01v.js.map +10 -0
- package/dist/cli/{chunk-tkacnehg.js → chunk-gp84za0h.js} +2 -2
- package/dist/cli/{chunk-wrr3j9w9.js → chunk-h2a48yhd.js} +186 -63
- package/dist/cli/chunk-h2a48yhd.js.map +36 -0
- package/dist/cli/{chunk-hm3vjy5s.js → chunk-jnwj5kjj.js} +14 -9
- package/dist/cli/{chunk-hm3vjy5s.js.map → chunk-jnwj5kjj.js.map} +4 -4
- package/dist/cli/chunk-kwrg63tm.js +31 -0
- package/dist/cli/chunk-kwrg63tm.js.map +10 -0
- package/dist/cli/{chunk-2hsdwb9n.js → chunk-nd1821sk.js} +18 -16
- package/dist/cli/{chunk-2hsdwb9n.js.map → chunk-nd1821sk.js.map} +2 -2
- package/dist/cli/{chunk-6dsbexzp.js → chunk-ntv4qrt7.js} +17 -15
- package/dist/cli/{chunk-6dsbexzp.js.map → chunk-ntv4qrt7.js.map} +2 -2
- package/dist/cli/{chunk-r9rcc4w7.js → chunk-p804f3pe.js} +7 -7
- package/dist/cli/{chunk-ey84smr6.js → chunk-py62fewh.js} +6 -6
- package/dist/cli/{chunk-ey84smr6.js.map → chunk-py62fewh.js.map} +1 -1
- package/dist/cli/chunk-q3wxxq39.js +126 -0
- package/dist/cli/chunk-q3wxxq39.js.map +11 -0
- package/dist/cli/{chunk-9t7a85s3.js → chunk-rekqz4qg.js} +23 -13
- package/dist/cli/chunk-rekqz4qg.js.map +10 -0
- package/dist/cli/{chunk-8ktnccpt.js → chunk-ta27feev.js} +1 -1
- package/dist/cli/{chunk-pv29h0wf.js → chunk-xkz5xbtv.js} +3476 -822
- package/dist/cli/chunk-xkz5xbtv.js.map +213 -0
- package/dist/cli/{chunk-a58773jm.js → chunk-y4ykbark.js} +2 -2
- package/dist/cli/{chunk-p3v96n38.js → chunk-y5h4r2y0.js} +4 -4
- package/dist/cli/{chunk-acanzt5p.js → chunk-yj17vs39.js} +6 -6
- package/dist/cli/{chunk-p73c0m7w.js → chunk-yxmk4pec.js} +16 -14
- package/dist/cli/{chunk-p73c0m7w.js.map → chunk-yxmk4pec.js.map} +2 -2
- package/dist/cli/{chunk-3em5wd2y.js → chunk-zccbjcj0.js} +4 -3
- package/dist/cli/{chunk-3em5wd2y.js.map → chunk-zccbjcj0.js.map} +2 -2
- package/dist/cli/{chunk-c8chx29p.js → chunk-zf748avv.js} +384 -207
- package/dist/cli/chunk-zf748avv.js.map +37 -0
- package/dist/cli/{chunk-g4hq16wv.js → chunk-zhvd6adm.js} +16 -14
- package/dist/cli/{chunk-g4hq16wv.js.map → chunk-zhvd6adm.js.map} +2 -2
- package/dist/cli/index.js +26 -20
- package/dist/cli/index.js.map +5 -5
- package/dist/types/ai/agent-surface.d.ts +8 -7
- package/dist/types/ai/ai-catalog.d.ts +7 -0
- package/dist/types/ai/ask-context.d.ts +22 -0
- package/dist/types/ai/ask.d.ts +271 -58
- package/dist/types/ai/index.d.ts +2 -2
- package/dist/types/ai/site-skill.d.ts +26 -0
- package/dist/types/ai/skills.d.ts +16 -0
- package/dist/types/astro/integration.d.ts +8 -0
- package/dist/types/captcha/hcaptcha.d.ts +27 -0
- package/dist/types/captcha/index.d.ts +28 -0
- package/dist/types/captcha/schema.d.ts +29 -0
- package/dist/types/captcha/turnstile.d.ts +28 -0
- package/dist/types/components/content/api-field.d.ts +59 -0
- package/dist/types/components/content/api-page.d.ts +95 -0
- package/dist/types/components/layout/nav-utils.d.ts +26 -0
- package/dist/types/components/openapi/helpers.d.ts +137 -0
- package/dist/types/components/openapi/security.d.ts +85 -0
- package/dist/types/consent/ethyca.d.ts +48 -0
- package/dist/types/consent/index.d.ts +37 -0
- package/dist/types/consent/native.d.ts +28 -0
- package/dist/types/consent/osano.d.ts +42 -0
- package/dist/types/consent/schema.d.ts +110 -0
- package/dist/types/core/config-input.d.ts +187 -20
- package/dist/types/core/data.d.ts +49 -4
- package/dist/types/core/footer.d.ts +8 -0
- package/dist/types/core/i18n-ui.d.ts +86 -0
- package/dist/types/core/includes.d.ts +8 -2
- package/dist/types/core/localizable.d.ts +7 -0
- package/dist/types/core/page-modes.d.ts +29 -0
- package/dist/types/core/redirect-patterns.d.ts +144 -0
- package/dist/types/core/related.d.ts +40 -0
- package/dist/types/core/schema.d.ts +551 -56
- package/dist/types/core/sources/read.d.ts +5 -0
- package/dist/types/core/types.d.ts +1 -1
- package/dist/types/core/variables.d.ts +42 -0
- package/dist/types/deploy/node-headers.d.ts +13 -2
- package/dist/types/deploy/platforms/cloudflare.d.ts +5 -0
- package/dist/types/deploy/platforms/netlify.d.ts +7 -0
- package/dist/types/deploy/platforms/vercel.d.ts +6 -0
- package/dist/types/deploy/redirects.d.ts +39 -11
- package/dist/types/deploy/vercel-negotiation.d.ts +9 -0
- package/dist/types/markdown/code-title.d.ts +17 -0
- package/dist/types/markdown/features.d.ts +3 -2
- package/dist/types/narration/build.d.ts +70 -0
- package/dist/types/narration/provider.d.ts +26 -0
- package/dist/types/narration/script.d.ts +154 -0
- package/dist/types/openapi/model.d.ts +12 -6
- package/dist/types/openapi/overlay.d.ts +54 -0
- package/dist/types/openapi/parse.d.ts +13 -0
- package/dist/types/openapi/references.d.ts +14 -4
- package/dist/types/ratelimit/cloudflare.d.ts +39 -0
- package/dist/types/ratelimit/index.d.ts +27 -0
- package/dist/types/ratelimit/memory.d.ts +36 -0
- package/dist/types/ratelimit/schema.d.ts +111 -0
- package/dist/types/ratelimit/upstash.d.ts +21 -0
- package/dist/types/ratelimit/wrangler.d.ts +23 -0
- package/dist/types/reference/asyncapi.d.ts +10 -10
- package/dist/types/reference/graphql.d.ts +13 -10
- package/dist/types/reference/openapi.d.ts +33 -12
- package/dist/types/reference/options.d.ts +45 -5
- package/dist/types/reference/scalar.d.ts +13 -0
- package/dist/types/reference/schema.d.ts +60 -36
- package/dist/types/search/documents.d.ts +12 -1
- package/dist/types/search/orama-index.d.ts +4 -0
- package/dist/types/seo/metatags.d.ts +20 -0
- package/docs/02-deployment.mdx +41 -5
- package/docs/03-upgrading.mdx +4 -4
- package/docs/04-migrating.mdx +1 -1
- package/docs/advanced/changelog.mdx +2 -2
- package/docs/advanced/skills.mdx +14 -0
- package/docs/cli/audit.mdx +21 -1
- package/docs/cli/index.mdx +1 -0
- package/docs/configuration/analytics.mdx +3 -1
- package/docs/configuration/assistant.mdx +188 -36
- package/docs/configuration/consent.mdx +100 -0
- package/docs/configuration/customization.mdx +4 -4
- package/docs/configuration/index.mdx +63 -5
- package/docs/configuration/meta.ts +3 -0
- package/docs/configuration/narration.mdx +119 -0
- package/docs/configuration/rate-limiting.mdx +69 -0
- package/docs/configuration/search.mdx +29 -1
- package/docs/configuration/theming.mdx +3 -1
- package/docs/content/components.mdx +106 -0
- package/docs/content/frontmatter.mdx +76 -0
- package/docs/content/i18n.mdx +38 -3
- package/docs/content/includes.mdx +16 -0
- package/docs/content/meta.mdx +1 -0
- package/docs/content/meta.ts +1 -0
- package/docs/content/navigation.mdx +28 -6
- package/docs/content/sources/contentful.mdx +32 -0
- package/docs/content/sources/custom.mdx +39 -0
- package/docs/content/sources/github-releases.mdx +31 -0
- package/docs/content/sources/index.mdx +91 -0
- package/docs/content/sources/meta.ts +16 -0
- package/docs/content/sources/notion.mdx +32 -0
- package/docs/content/sources/obsidian.mdx +37 -0
- package/docs/content/sources/payload.mdx +30 -0
- package/docs/content/sources/remote-mdx.mdx +40 -0
- package/docs/content/sources/sanity.mdx +29 -0
- package/docs/content/sources/strapi.mdx +31 -0
- package/docs/content/syntax.mdx +67 -2
- package/docs/content/variables.mdx +41 -0
- package/docs/discoverability/agent-discovery.mdx +29 -2
- package/docs/discoverability/index.mdx +1 -1
- package/docs/discoverability/llms-txt.mdx +1 -1
- package/docs/discoverability/metadata.mdx +17 -0
- package/docs/references/api-pages.mdx +74 -0
- package/docs/references/asyncapi.mdx +1 -1
- package/docs/references/graphql.mdx +2 -2
- package/docs/references/meta.ts +1 -1
- package/docs/references/openapi.mdx +102 -3
- package/docs/references/scalar.mdx +3 -1
- package/package.json +36 -1
- package/skills/blume/SKILL.md +3 -0
- package/skills/blume-migrate/SKILL.md +5 -5
- package/skills/blume-migrate/references/docusaurus.md +3 -3
- package/skills/blume-migrate/references/mintlify.md +37 -19
- package/skills/blume-migrate/references/nextra.md +2 -2
- package/skills/blume-migrate/references/starlight.md +2 -1
- package/skills/blume-migrate/scripts/mintlify-codemod.mjs +60 -14
- package/skills/blume-write-skill/SKILL.md +82 -0
- package/src/ai/agent-readability.ts +2 -1
- package/src/ai/agent-surface.ts +9 -7
- package/src/ai/ai-catalog.ts +6 -3
- package/src/ai/ask-context.ts +73 -20
- package/src/ai/ask-data.ts +6 -0
- package/src/ai/ask-tools.ts +142 -0
- package/src/ai/ask.ts +354 -76
- package/src/ai/component-markdown.ts +75 -0
- package/src/ai/cors.ts +2 -0
- package/src/ai/index.ts +12 -0
- package/src/ai/llms.ts +6 -2
- package/src/ai/markdown.ts +2 -1
- package/src/ai/mcp/data.ts +6 -0
- package/src/ai/openapi-components.ts +9 -3
- package/src/ai/site-skill.ts +274 -0
- package/src/ai/skills.ts +35 -2
- package/src/ai/write-skill.ts +97 -0
- package/src/astro/generate.ts +132 -18
- package/src/astro/index.ts +1 -0
- package/src/astro/integration.ts +35 -0
- package/src/astro/module-types.ts +6 -0
- package/src/astro/templates.ts +283 -30
- package/src/astro/variables.ts +31 -0
- package/src/audit/catalog.ts +19 -0
- package/src/audit/checks/contrast.ts +183 -0
- package/src/audit/checks/i18n.ts +2 -3
- package/src/audit/checks/indexability.ts +2 -3
- package/src/audit/checks/links.ts +5 -12
- package/src/audit/checks/sitemap.ts +2 -3
- package/src/audit/redirects.ts +46 -15
- package/src/audit/run.ts +2 -0
- package/src/audit/types.ts +2 -1
- package/src/blume-modules.d.ts +7 -0
- package/src/captcha/client.ts +152 -0
- package/src/captcha/hcaptcha.ts +36 -0
- package/src/captcha/index.ts +28 -0
- package/src/captcha/schema.ts +32 -0
- package/src/captcha/turnstile.ts +38 -0
- package/src/captcha/verify.ts +71 -0
- package/src/cli/command-meta.ts +5 -0
- package/src/cli/commands/doctor.ts +22 -16
- package/src/cli/commands/skill.ts +96 -0
- package/src/cli/index.ts +5 -0
- package/src/cli/required-secrets.ts +71 -29
- package/src/components/BlumePage.astro +2 -0
- package/src/components/content/ApiEndpoint.astro +18 -0
- package/src/components/content/ApiField.astro +79 -0
- package/src/components/content/ApiPlayground.astro +62 -0
- package/src/components/content/ApiRail.astro +19 -0
- package/src/components/content/Color.astro +1 -0
- package/src/components/content/FileTree.astro +1 -0
- package/src/components/content/GithubInfo.astro +1 -0
- package/src/components/content/Panel.astro +1 -0
- package/src/components/content/ParamField.astro +25 -0
- package/src/components/content/RequestExample.astro +17 -0
- package/src/components/content/ResponseExample.astro +17 -0
- package/src/components/content/ResponseField.astro +32 -0
- package/src/components/content/Step.astro +1 -0
- package/src/components/content/Tile.astro +1 -0
- package/src/components/content/Tooltip.astro +1 -0
- package/src/components/content/Tree.astro +1 -0
- package/src/components/content/TypeTable.astro +4 -1
- package/src/components/content/View.astro +21 -0
- package/src/components/content/ViewSwitcher.astro +168 -0
- package/src/components/content/api-field.ts +100 -0
- package/src/components/content/api-page.ts +224 -0
- package/src/components/content/view-switcher.ts +71 -0
- package/src/components/index.ts +2 -0
- package/src/components/islands/Assistant.astro +10 -1
- package/src/components/islands/assistant.tsx +104 -14
- package/src/components/islands/code-question.ts +62 -0
- package/src/components/islands/hooks.ts +110 -21
- package/src/components/islands/support-link.ts +68 -0
- package/src/components/layout/Analytics.astro +11 -2
- package/src/components/layout/Banner.astro +14 -10
- package/src/components/layout/Breadcrumbs.astro +6 -2
- package/src/components/layout/ConsentBanner.astro +62 -0
- package/src/components/layout/ConsentHead.astro +38 -0
- package/src/components/layout/Directory.astro +94 -0
- package/src/components/layout/DrawerSwitchers.astro +51 -0
- package/src/components/layout/Empty.astro +2 -2
- package/src/components/layout/Header.astro +122 -80
- package/src/components/layout/LanguageSwitcher.astro +48 -15
- package/src/components/layout/NarrationPlayer.astro +1085 -0
- package/src/components/layout/NavSelector.astro +33 -7
- package/src/components/layout/PageFeedback.astro +54 -49
- package/src/components/layout/PageLayout.astro +71 -3
- package/src/components/layout/ReferenceLayout.astro +17 -6
- package/src/components/layout/RelatedPages.astro +42 -0
- package/src/components/layout/RootLayout.astro +308 -45
- package/src/components/layout/Search.astro +31 -17
- package/src/components/layout/SiteFooter.astro +124 -0
- package/src/components/layout/SiteMetatags.astro +16 -0
- package/src/components/layout/consent/native.ts +79 -0
- package/src/components/layout/consent/types.ts +37 -0
- package/src/components/layout/footer-links.ts +53 -0
- package/src/components/layout/footer-socials.ts +87 -0
- package/src/components/layout/locale-redirect.ts +107 -0
- package/src/components/layout/nav-utils.ts +83 -0
- package/src/components/layout/page-feedback.ts +96 -0
- package/src/components/layout/search/analytics.ts +98 -0
- package/src/components/layout/search/flexsearch.ts +17 -5
- package/src/components/layout/search/orama-cloud.ts +26 -14
- package/src/components/layout/search/types.ts +20 -0
- package/src/components/layout/search/typesense.ts +5 -1
- package/src/components/openapi/Operation.astro +161 -13
- package/src/components/openapi/RequestBody.astro +6 -4
- package/src/components/openapi/RequestPanel.astro +59 -7
- package/src/components/openapi/Responses.astro +6 -4
- package/src/components/openapi/async-snippets.ts +4 -4
- package/src/components/openapi/code-samples.ts +97 -0
- package/src/components/openapi/security.ts +6 -3
- package/src/components/openapi/snippets.ts +869 -8
- package/src/components/props.ts +6 -0
- package/src/consent/client.ts +95 -0
- package/src/consent/clients.ts +19 -0
- package/src/consent/ethyca.ts +71 -0
- package/src/consent/head.ts +24 -0
- package/src/consent/index.ts +37 -0
- package/src/consent/init.ts +29 -0
- package/src/consent/native.ts +36 -0
- package/src/consent/osano.ts +59 -0
- package/src/consent/schema.ts +30 -0
- package/src/core/builtin-tags.ts +5 -0
- package/src/core/client-address.ts +19 -0
- package/src/core/config-input.ts +194 -20
- package/src/core/data.ts +44 -4
- package/src/core/diagnostics.ts +3 -2
- package/src/core/footer.ts +26 -0
- package/src/core/graph.ts +39 -36
- package/src/core/i18n-ui.ts +82 -2
- package/src/core/includes.ts +20 -3
- package/src/core/links.ts +16 -2
- package/src/core/localizable.ts +26 -0
- package/src/core/navigation.ts +43 -12
- package/src/core/page-modes.ts +56 -0
- package/src/core/project-graph.ts +111 -5
- package/src/core/redirect-patterns.ts +491 -0
- package/src/core/related.ts +131 -0
- package/src/core/schema.ts +318 -64
- package/src/core/sources/normalize.ts +2 -1
- package/src/core/sources/read.ts +8 -3
- package/src/core/types.ts +1 -1
- package/src/core/ui-packs/ar.ts +43 -0
- package/src/core/ui-packs/bg.ts +45 -0
- package/src/core/ui-packs/bn.ts +43 -0
- package/src/core/ui-packs/ca.ts +46 -0
- package/src/core/ui-packs/cs.ts +44 -0
- package/src/core/ui-packs/da.ts +45 -0
- package/src/core/ui-packs/de.ts +46 -0
- package/src/core/ui-packs/el.ts +45 -0
- package/src/core/ui-packs/es.ts +46 -0
- package/src/core/ui-packs/fa.ts +45 -0
- package/src/core/ui-packs/fi.ts +45 -0
- package/src/core/ui-packs/fr.ts +46 -0
- package/src/core/ui-packs/he.ts +43 -0
- package/src/core/ui-packs/hi.ts +44 -0
- package/src/core/ui-packs/hr.ts +45 -0
- package/src/core/ui-packs/hu.ts +44 -0
- package/src/core/ui-packs/id.ts +45 -0
- package/src/core/ui-packs/it.ts +45 -0
- package/src/core/ui-packs/ja.ts +45 -0
- package/src/core/ui-packs/ko.ts +44 -0
- package/src/core/ui-packs/nl.ts +46 -0
- package/src/core/ui-packs/no.ts +44 -0
- package/src/core/ui-packs/pl.ts +45 -0
- package/src/core/ui-packs/pt-br.ts +46 -0
- package/src/core/ui-packs/pt.ts +45 -0
- package/src/core/ui-packs/ro.ts +45 -0
- package/src/core/ui-packs/ru.ts +45 -0
- package/src/core/ui-packs/sk.ts +44 -0
- package/src/core/ui-packs/sr.ts +45 -0
- package/src/core/ui-packs/sv.ts +44 -0
- package/src/core/ui-packs/th.ts +43 -0
- package/src/core/ui-packs/tr.ts +45 -0
- package/src/core/ui-packs/uk.ts +45 -0
- package/src/core/ui-packs/vi.ts +45 -0
- package/src/core/ui-packs/zh-tw.ts +43 -0
- package/src/core/ui-packs/zh.ts +43 -0
- package/src/core/variables.ts +103 -0
- package/src/deploy/artifacts.ts +77 -8
- package/src/deploy/cloudflare-negotiation.ts +35 -5
- package/src/deploy/headers.ts +2 -1
- package/src/deploy/node-headers.ts +63 -9
- package/src/deploy/platforms/cloudflare.ts +32 -0
- package/src/deploy/platforms/netlify.ts +33 -1
- package/src/deploy/platforms/vercel.ts +37 -2
- package/src/deploy/redirects.ts +91 -24
- package/src/deploy/vercel-negotiation.ts +36 -0
- package/src/markdown/api-rail.ts +259 -0
- package/src/markdown/code-title.ts +35 -9
- package/src/markdown/features.ts +3 -2
- package/src/markdown/fence-meta.ts +2 -0
- package/src/markdown/include.ts +11 -1
- package/src/markdown/index.ts +28 -5
- package/src/markdown/math.ts +4 -4
- package/src/markdown/variables.ts +56 -0
- package/src/markdown/views.ts +82 -0
- package/src/narration/build.ts +412 -0
- package/src/narration/player.ts +249 -0
- package/src/narration/provider.ts +29 -0
- package/src/narration/script.ts +592 -0
- package/src/og/card.ts +7 -6
- package/src/openapi/model.ts +57 -24
- package/src/openapi/overlay.ts +256 -0
- package/src/openapi/parse.ts +55 -2
- package/src/openapi/references.ts +21 -5
- package/src/openapi/render-mdx.ts +5 -1
- package/src/openapi/scalar.ts +40 -6
- package/src/openapi/source.ts +1 -1
- package/src/ratelimit/cloudflare.ts +54 -0
- package/src/ratelimit/index.ts +30 -0
- package/src/ratelimit/memory.ts +45 -0
- package/src/ratelimit/runtime.ts +229 -0
- package/src/ratelimit/schema.ts +28 -0
- package/src/ratelimit/upstash.ts +30 -0
- package/src/ratelimit/wrangler.ts +70 -0
- package/src/reference/asyncapi.ts +2 -2
- package/src/reference/graphql.ts +5 -2
- package/src/reference/openapi.ts +21 -7
- package/src/reference/options.ts +51 -7
- package/src/reference/scalar.ts +33 -8
- package/src/registry/eject.ts +20 -4
- package/src/registry/registry.ts +7 -0
- package/src/search/documents.ts +26 -2
- package/src/search/orama-index.ts +28 -3
- package/src/search/pagefind-ranking.ts +39 -0
- package/src/search/sync/algolia.ts +15 -4
- package/src/search/sync/orama-cloud.ts +3 -0
- package/src/search/sync/typesense.ts +5 -0
- package/src/seo/metatags.ts +67 -0
- package/src/theme/chrome-icons.ts +1 -0
- package/src/theme/color.ts +500 -0
- package/src/theme/entry.ts +56 -3
- package/src/theme/palette.ts +121 -45
- package/src/translate/prompts.ts +1 -0
- package/src/translate/validate.ts +8 -2
- package/src/upgrade/upgrade.ts +4 -171
- package/dist/cli/chunk-364znk6q.js +0 -75
- package/dist/cli/chunk-364znk6q.js.map +0 -11
- package/dist/cli/chunk-5m5nmvyq.js.map +0 -13
- package/dist/cli/chunk-9t7a85s3.js.map +0 -10
- package/dist/cli/chunk-c8chx29p.js.map +0 -36
- package/dist/cli/chunk-pehfxfta.js.map +0 -10
- package/dist/cli/chunk-pv29h0wf.js.map +0 -190
- package/dist/cli/chunk-q58y5e6a.js.map +0 -10
- package/dist/cli/chunk-wrr3j9w9.js.map +0 -35
- package/dist/cli/chunk-yfyb25rh.js.map +0 -14
- package/docs/content/sources.mdx +0 -334
- /package/dist/cli/{chunk-2eytanqx.js.map → chunk-1n228xqb.js.map} +0 -0
- /package/dist/cli/{chunk-35d4wj9f.js.map → chunk-2n4ps1b3.js.map} +0 -0
- /package/dist/cli/{chunk-e04dxsz1.js.map → chunk-4ejxbzee.js.map} +0 -0
- /package/dist/cli/{chunk-tzmab476.js.map → chunk-5ffywsmb.js.map} +0 -0
- /package/dist/cli/{chunk-2z928egk.js.map → chunk-5wj2qwn2.js.map} +0 -0
- /package/dist/cli/{chunk-b07cmahc.js.map → chunk-amrb6hgh.js.map} +0 -0
- /package/dist/cli/{chunk-akbpwfxc.js.map → chunk-cmtcnh9f.js.map} +0 -0
- /package/dist/cli/{chunk-crgn1q09.js.map → chunk-e7vvk5ya.js.map} +0 -0
- /package/dist/cli/{chunk-tkacnehg.js.map → chunk-gp84za0h.js.map} +0 -0
- /package/dist/cli/{chunk-r9rcc4w7.js.map → chunk-p804f3pe.js.map} +0 -0
- /package/dist/cli/{chunk-8ktnccpt.js.map → chunk-ta27feev.js.map} +0 -0
- /package/dist/cli/{chunk-a58773jm.js.map → chunk-y4ykbark.js.map} +0 -0
- /package/dist/cli/{chunk-p3v96n38.js.map → chunk-y5h4r2y0.js.map} +0 -0
- /package/dist/cli/{chunk-acanzt5p.js.map → chunk-yj17vs39.js.map} +0 -0
package/src/theme/palette.ts
CHANGED
|
@@ -1,21 +1,90 @@
|
|
|
1
1
|
import type { ResolvedConfig } from "../core/schema.ts";
|
|
2
|
+
import { composite, contrastRatio, parseColor } from "./color.ts";
|
|
3
|
+
import type { Rgba } from "./color.ts";
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
/** Per-mode CSS colors. */
|
|
6
|
+
export interface AccentColors {
|
|
7
|
+
dark: string;
|
|
8
|
+
light: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** A color mode. */
|
|
12
|
+
export type ColorMode = keyof AccentColors;
|
|
4
13
|
|
|
5
14
|
/**
|
|
6
|
-
* Named accent presets mapped to OKLCH values. The single source of
|
|
7
|
-
* preset colors: the theme CSS and the OG card (og/card.ts) both
|
|
8
|
-
* this table, so a site and its social cards can't disagree
|
|
15
|
+
* Named accent presets mapped to OKLCH values, per mode. The single source of
|
|
16
|
+
* truth for preset colors: the theme CSS and the OG card (og/card.ts) both
|
|
17
|
+
* resolve from this table, so a site and its social cards can't disagree
|
|
18
|
+
* about "blue". Each clears WCAG AA (4.5:1) as text on its mode's page and
|
|
19
|
+
* under its button label ({@link readableOn}), with room to spare on the
|
|
20
|
+
* tinted surfaces accent text also sits on: the light shades are dark enough
|
|
21
|
+
* for white labels, the dark shades light enough to read on the dark page.
|
|
9
22
|
*/
|
|
10
23
|
export const ACCENTS = {
|
|
11
|
-
blue:
|
|
12
|
-
green: "oklch(0.6 0.16 150)",
|
|
13
|
-
orange: "oklch(0.68 0.17 50)",
|
|
14
|
-
pink: "oklch(0.65 0.2 350)",
|
|
15
|
-
purple: "oklch(0.
|
|
16
|
-
red: "oklch(0.58 0.22 25)",
|
|
17
|
-
teal: "oklch(0.6 0.12 195)",
|
|
18
|
-
} satisfies Record<string,
|
|
24
|
+
blue: { dark: "oklch(0.62 0.16 250)", light: "oklch(0.55 0.16 250)" },
|
|
25
|
+
green: { dark: "oklch(0.6 0.16 150)", light: "oklch(0.53 0.16 150)" },
|
|
26
|
+
orange: { dark: "oklch(0.68 0.17 50)", light: "oklch(0.56 0.17 50)" },
|
|
27
|
+
pink: { dark: "oklch(0.65 0.2 350)", light: "oklch(0.58 0.2 350)" },
|
|
28
|
+
purple: { dark: "oklch(0.6 0.2 290)", light: "oklch(0.57 0.2 290)" },
|
|
29
|
+
red: { dark: "oklch(0.61 0.22 25)", light: "oklch(0.58 0.22 25)" },
|
|
30
|
+
teal: { dark: "oklch(0.6 0.12 195)", light: "oklch(0.53 0.12 195)" },
|
|
31
|
+
} satisfies Record<string, AccentColors>;
|
|
32
|
+
|
|
33
|
+
/** The contrast WCAG AA asks of body-size text. */
|
|
34
|
+
export const MIN_TEXT_CONTRAST = 4.5;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The theme's own colors a configured accent is drawn against: each mode's
|
|
38
|
+
* page background and text, and the dark ink a filled accent can carry.
|
|
39
|
+
* Mirrors the defaults in `entry.ts`.
|
|
40
|
+
*/
|
|
41
|
+
export const THEME_INKS = {
|
|
42
|
+
dark: {
|
|
43
|
+
background: "oklch(0.085 0 0)",
|
|
44
|
+
foreground: "oklch(0.96 0 0)",
|
|
45
|
+
ink: "oklch(0.085 0 0)",
|
|
46
|
+
mutedForeground: "oklch(0.68 0 0)",
|
|
47
|
+
},
|
|
48
|
+
light: {
|
|
49
|
+
background: "oklch(1 0 0)",
|
|
50
|
+
foreground: "oklch(0.145 0 0)",
|
|
51
|
+
ink: "oklch(0.145 0 0)",
|
|
52
|
+
mutedForeground: "oklch(0.53 0 0)",
|
|
53
|
+
},
|
|
54
|
+
} satisfies Record<ColorMode, Record<string, string>>;
|
|
55
|
+
|
|
56
|
+
const WHITE = "oklch(1 0 0)";
|
|
57
|
+
|
|
58
|
+
/** A color this module writes itself, parsed (they all parse). */
|
|
59
|
+
const own = (value: string): Rgba =>
|
|
60
|
+
parseColor(value) ?? { alpha: 1, blue: 0, green: 0, red: 0 };
|
|
61
|
+
|
|
62
|
+
/** {@link THEME_INKS}, parsed, for contrast math. */
|
|
63
|
+
export const themeInk = (
|
|
64
|
+
mode: ColorMode,
|
|
65
|
+
name: keyof (typeof THEME_INKS)[ColorMode]
|
|
66
|
+
): Rgba => own(THEME_INKS[mode][name]);
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* The label color for text on a filled `fill` (a button, a step number): white
|
|
70
|
+
* while it reaches AA, else the mode's dark ink when that reads better, so a
|
|
71
|
+
* light accent (every dark-mode preset) gets dark text instead of white text
|
|
72
|
+
* nobody can read.
|
|
73
|
+
*/
|
|
74
|
+
export const labelOn = (fill: Rgba, mode: ColorMode): string => {
|
|
75
|
+
const opaque = composite(fill, themeInk(mode, "background"));
|
|
76
|
+
const onWhite = contrastRatio(own(WHITE), opaque);
|
|
77
|
+
return onWhite >= MIN_TEXT_CONTRAST ||
|
|
78
|
+
onWhite >= contrastRatio(themeInk(mode, "ink"), opaque)
|
|
79
|
+
? WHITE
|
|
80
|
+
: THEME_INKS[mode].ink;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
/** {@link labelOn} for a CSS color; one this module can't parse keeps white. */
|
|
84
|
+
export const readableOn = (fill: string, mode: ColorMode): string => {
|
|
85
|
+
const color = parseColor(fill);
|
|
86
|
+
return color ? labelOn(color, mode) : WHITE;
|
|
87
|
+
};
|
|
19
88
|
|
|
20
89
|
/**
|
|
21
90
|
* Whether a raw config value names an accent preset. `hasOwn` keeps a value
|
|
@@ -35,9 +104,11 @@ const CSS_COLOR = /^[\w\s#%.,()/+-]+$/u;
|
|
|
35
104
|
const safeColor = (value: string, fallback: string): string =>
|
|
36
105
|
CSS_COLOR.test(value.trim()) ? value.trim() : fallback;
|
|
37
106
|
|
|
38
|
-
/** Resolve a named preset or fall back to {@link safeColor}. */
|
|
39
|
-
const presetOrColor = (value: string): string =>
|
|
40
|
-
isAccentPreset(value)
|
|
107
|
+
/** Resolve a named preset in `mode`, or fall back to {@link safeColor}. */
|
|
108
|
+
const presetOrColor = (value: string, mode: ColorMode): string =>
|
|
109
|
+
isAccentPreset(value)
|
|
110
|
+
? ACCENTS[value][mode]
|
|
111
|
+
: safeColor(value, ACCENTS.blue[mode]);
|
|
41
112
|
|
|
42
113
|
/** Like {@link safeColor} but drops an unsafe/absent value to `null`. */
|
|
43
114
|
const safeColorOrNull = (value: string | undefined): string | null =>
|
|
@@ -58,20 +129,23 @@ const backgroundImageCss = (image: string): string =>
|
|
|
58
129
|
const cssToken = (name: string, value?: string | null): string[] =>
|
|
59
130
|
value ? [` ${name}: ${value};`] : [];
|
|
60
131
|
|
|
132
|
+
/** One mode's resolved accent and action fills. */
|
|
133
|
+
interface ModeFills {
|
|
134
|
+
accent: string;
|
|
135
|
+
action: string | null;
|
|
136
|
+
}
|
|
137
|
+
|
|
61
138
|
const themeRootCss = (
|
|
62
139
|
theme: ResolvedConfig["theme"],
|
|
63
|
-
options: {
|
|
64
|
-
accent: string;
|
|
65
|
-
action: string | null;
|
|
66
|
-
radius: string;
|
|
67
|
-
}
|
|
140
|
+
options: ModeFills & { radius: string }
|
|
68
141
|
): string =>
|
|
69
142
|
[
|
|
70
143
|
` --blume-accent: ${options.accent};`,
|
|
144
|
+
` --blume-accent-foreground: ${readableOn(options.accent, "light")};`,
|
|
71
145
|
...cssToken("--blume-action", options.action),
|
|
72
146
|
...cssToken(
|
|
73
147
|
"--blume-action-foreground",
|
|
74
|
-
options.action ?
|
|
148
|
+
options.action ? readableOn(options.action, "light") : null
|
|
75
149
|
),
|
|
76
150
|
...cssToken("--blume-background", safeColorOrNull(theme.background?.light)),
|
|
77
151
|
...cssToken(
|
|
@@ -87,10 +161,7 @@ const themeRootCss = (
|
|
|
87
161
|
|
|
88
162
|
const themeDarkCss = (
|
|
89
163
|
theme: ResolvedConfig["theme"],
|
|
90
|
-
options:
|
|
91
|
-
accent: string;
|
|
92
|
-
action: string | null;
|
|
93
|
-
}
|
|
164
|
+
options: ModeFills
|
|
94
165
|
): string => {
|
|
95
166
|
// Mode-shared tokens (accent, action) must be re-declared here: the base
|
|
96
167
|
// stylesheet's own `:root[data-theme="dark"]` block outranks the `:root`
|
|
@@ -98,11 +169,11 @@ const themeDarkCss = (
|
|
|
98
169
|
// silently keep its neutral defaults and ignore the config.
|
|
99
170
|
const tokens = [
|
|
100
171
|
` --blume-accent: ${options.accent};`,
|
|
101
|
-
|
|
172
|
+
` --blume-accent-foreground: ${readableOn(options.accent, "dark")};`,
|
|
102
173
|
...cssToken("--blume-action", options.action),
|
|
103
174
|
...cssToken(
|
|
104
175
|
"--blume-action-foreground",
|
|
105
|
-
options.action ?
|
|
176
|
+
options.action ? readableOn(options.action, "dark") : null
|
|
106
177
|
),
|
|
107
178
|
...cssToken("--blume-background", safeColorOrNull(theme.background?.dark)),
|
|
108
179
|
...cssToken(
|
|
@@ -118,26 +189,31 @@ ${tokens.join("\n")}
|
|
|
118
189
|
`;
|
|
119
190
|
};
|
|
120
191
|
|
|
121
|
-
/** Per-mode accent CSS colors. */
|
|
122
|
-
export interface AccentColors {
|
|
123
|
-
dark: string;
|
|
124
|
-
light: string;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
192
|
/**
|
|
128
193
|
* Resolve the configured accent to per-mode CSS colors. A named accent
|
|
129
|
-
* resolves to its preset; any other value is treated as
|
|
130
|
-
* users can pass arbitrary colors without a config change.
|
|
131
|
-
* has already been normalized by the config schema to the
|
|
132
|
-
* both modes.
|
|
194
|
+
* resolves to its preset's shade for each mode; any other value is treated as
|
|
195
|
+
* a raw CSS color so users can pass arbitrary colors without a config change.
|
|
196
|
+
* A string accent has already been normalized by the config schema to the
|
|
197
|
+
* same value for both modes.
|
|
133
198
|
*/
|
|
134
199
|
export const resolveAccent = (
|
|
135
200
|
theme: ResolvedConfig["theme"]
|
|
136
201
|
): AccentColors => ({
|
|
137
|
-
dark: presetOrColor(theme.accent.dark),
|
|
138
|
-
light: presetOrColor(theme.accent.light),
|
|
202
|
+
dark: presetOrColor(theme.accent.dark, "dark"),
|
|
203
|
+
light: presetOrColor(theme.accent.light, "light"),
|
|
139
204
|
});
|
|
140
205
|
|
|
206
|
+
/** Resolve the configured `action` fill per mode, or `null` when unset. */
|
|
207
|
+
export const resolveAction = (
|
|
208
|
+
theme: ResolvedConfig["theme"]
|
|
209
|
+
): AccentColors | null =>
|
|
210
|
+
theme.action
|
|
211
|
+
? {
|
|
212
|
+
dark: presetOrColor(theme.action, "dark"),
|
|
213
|
+
light: presetOrColor(theme.action, "light"),
|
|
214
|
+
}
|
|
215
|
+
: null;
|
|
216
|
+
|
|
141
217
|
/** Resolve the configured radius preset to a CSS length. */
|
|
142
218
|
export const resolveRadius = (theme: ResolvedConfig["theme"]): string =>
|
|
143
219
|
RADII[theme.radius];
|
|
@@ -145,20 +221,20 @@ export const resolveRadius = (theme: ResolvedConfig["theme"]): string =>
|
|
|
145
221
|
/**
|
|
146
222
|
* Compile theme config into CSS custom properties. A named accent resolves to
|
|
147
223
|
* its preset; any other value is treated as a raw CSS color so users can pass
|
|
148
|
-
* arbitrary colors without a config change.
|
|
224
|
+
* arbitrary colors without a config change. Labels on accent and action fills
|
|
225
|
+
* take whichever of white or dark ink reads ({@link readableOn}).
|
|
149
226
|
*/
|
|
150
227
|
export const buildThemeCss = (theme: ResolvedConfig["theme"]): string => {
|
|
151
228
|
const accent = resolveAccent(theme);
|
|
152
|
-
const action =
|
|
153
|
-
const radius = RADII[theme.radius];
|
|
229
|
+
const action = resolveAction(theme);
|
|
154
230
|
const root = themeRootCss(theme, {
|
|
155
231
|
accent: accent.light,
|
|
156
|
-
action,
|
|
157
|
-
radius,
|
|
232
|
+
action: action?.light ?? null,
|
|
233
|
+
radius: RADII[theme.radius],
|
|
158
234
|
});
|
|
159
235
|
const dark = themeDarkCss(theme, {
|
|
160
236
|
accent: accent.dark,
|
|
161
|
-
action,
|
|
237
|
+
action: action?.dark ?? null,
|
|
162
238
|
});
|
|
163
239
|
|
|
164
240
|
return `/* Generated by Blume from theme config. */
|
package/src/translate/prompts.ts
CHANGED
|
@@ -64,6 +64,7 @@ ${previousTranslation}`;
|
|
|
64
64
|
Rules:
|
|
65
65
|
- Translate the prose: headings, paragraphs, list items, table cells, admonitions, and image alt text.
|
|
66
66
|
- In the YAML frontmatter, translate ONLY the values of these keys: ${KEY_LIST}. Copy every other frontmatter key and value exactly as written.
|
|
67
|
+
- Keep the frontmatter valid YAML: if a translated value contains a colon followed by a space (\`: \`) or a space followed by \`#\`, or starts with a quote, a backtick, or another YAML indicator character, write it as a double-quoted string and escape any double quotes inside it.
|
|
67
68
|
- Never translate or alter: code blocks, inline code, import/export statements, JSX/MDX component names and their attributes, URLs, link targets, HTML tags, or frontmatter keys.
|
|
68
69
|
- A heading may end with anchor markers: \`[#some-id]\`, \`{#some-id}\` (also written \`\\{#some-id\\}\`), \`[!toc]\`, or \`[toc]\`. Copy every marker exactly as written, in the same position at the end of the translated heading — never translate, reorder, or drop a marker, and never change the id inside \`[#...]\` or \`{#...}\` (anchors must stay identical across languages).
|
|
69
70
|
|
|
@@ -132,8 +132,14 @@ export const validateTranslation = (
|
|
|
132
132
|
let parsed: { content: string; data: FrontmatterData };
|
|
133
133
|
try {
|
|
134
134
|
parsed = matter(candidate);
|
|
135
|
-
} catch {
|
|
136
|
-
|
|
135
|
+
} catch (error) {
|
|
136
|
+
// js-yaml's message leads with the problem and its line:column in the
|
|
137
|
+
// file, then a multi-line code frame; the first line is enough to act on.
|
|
138
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
139
|
+
return {
|
|
140
|
+
ok: false,
|
|
141
|
+
reason: `frontmatter does not parse as YAML: ${message.replace(/\n[\s\S]*$/u, "")}`,
|
|
142
|
+
};
|
|
137
143
|
}
|
|
138
144
|
|
|
139
145
|
const rawBody = ensureTrailingNewline(parsed.content.replace(/^\r?\n/u, ""));
|
package/src/upgrade/upgrade.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
import { readFile, writeFile } from "node:fs/promises";
|
|
3
3
|
|
|
4
|
-
import { join, relative
|
|
5
|
-
import { glob } from "tinyglobby";
|
|
4
|
+
import { join, relative } from "pathe";
|
|
6
5
|
import { z } from "zod";
|
|
7
6
|
|
|
8
7
|
import {
|
|
@@ -10,17 +9,9 @@ import {
|
|
|
10
9
|
ComponentOverridesError,
|
|
11
10
|
} from "../core/component-overrides.ts";
|
|
12
11
|
import { ConfigValidationError, loadConfig } from "../core/config.ts";
|
|
13
|
-
import { BlumeError
|
|
14
|
-
import matter from "../core/frontmatter.ts";
|
|
15
|
-
import { createModuleLoader } from "../core/load-module.ts";
|
|
12
|
+
import { BlumeError } from "../core/diagnostics.ts";
|
|
16
13
|
import { findComponentsFile, findConfigFile } from "../core/project.ts";
|
|
17
|
-
import { pageMetaSchema } from "../core/schema.ts";
|
|
18
|
-
import { baselineScanIgnore } from "../core/sources/watch.ts";
|
|
19
14
|
import type { Diagnostic } from "../core/types.ts";
|
|
20
|
-
import {
|
|
21
|
-
DEFAULT_CONTENT_EXCLUDE,
|
|
22
|
-
DEFAULT_CONTENT_INCLUDE,
|
|
23
|
-
} from "../sources/filesystem.ts";
|
|
24
15
|
|
|
25
16
|
/**
|
|
26
17
|
* `blume upgrade`'s logic, kept out of the command module so it runs (and is
|
|
@@ -280,163 +271,6 @@ const scriptFindings = async (root: string): Promise<Diagnostic[]> => {
|
|
|
280
271
|
});
|
|
281
272
|
};
|
|
282
273
|
|
|
283
|
-
// ---------------------------------------------------------------------------
|
|
284
|
-
// Removed front matter fields
|
|
285
|
-
// ---------------------------------------------------------------------------
|
|
286
|
-
|
|
287
|
-
/** Where a project's local content lives, as its config names it. */
|
|
288
|
-
interface ContentGlobs {
|
|
289
|
-
exclude: string[];
|
|
290
|
-
include: string[];
|
|
291
|
-
root: string;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
const globFields = {
|
|
295
|
-
exclude: z.array(z.string()).optional(),
|
|
296
|
-
include: z.array(z.string()).optional(),
|
|
297
|
-
root: z.string().optional(),
|
|
298
|
-
};
|
|
299
|
-
|
|
300
|
-
/**
|
|
301
|
-
* A filesystem source in either form a config being upgraded may hold: the
|
|
302
|
-
* `filesystem()` descriptor, or Blume 1's `{ type: "filesystem" }` object.
|
|
303
|
-
*/
|
|
304
|
-
const rawFilesystemSourceSchema = z.union([
|
|
305
|
-
z
|
|
306
|
-
.looseObject({
|
|
307
|
-
kind: z.literal("filesystem"),
|
|
308
|
-
options: z.looseObject(globFields).default({}),
|
|
309
|
-
})
|
|
310
|
-
.transform((source) => source.options),
|
|
311
|
-
z.looseObject({ type: z.literal("filesystem"), ...globFields }),
|
|
312
|
-
]);
|
|
313
|
-
|
|
314
|
-
/** The `content` slice of a config as written, before validation. */
|
|
315
|
-
const rawContentSchema = z.looseObject({
|
|
316
|
-
content: z
|
|
317
|
-
.looseObject({ ...globFields, sources: z.array(z.unknown()).optional() })
|
|
318
|
-
.optional(),
|
|
319
|
-
});
|
|
320
|
-
|
|
321
|
-
/**
|
|
322
|
-
* The content roots to scan, read from the config as written rather than the
|
|
323
|
-
* validated config: the upgrade runs on configs that don't validate yet. Its
|
|
324
|
-
* filesystem sources when it lists any, else the `content.root` shorthand,
|
|
325
|
-
* else the zero-config `docs` folder.
|
|
326
|
-
*/
|
|
327
|
-
export const contentGlobs = ({
|
|
328
|
-
content,
|
|
329
|
-
}: z.infer<typeof rawContentSchema>): ContentGlobs[] => {
|
|
330
|
-
const sources = (content?.sources ?? []).flatMap((source) => {
|
|
331
|
-
const filesystem = rawFilesystemSourceSchema.safeParse(source);
|
|
332
|
-
return filesystem.success ? [filesystem.data] : [];
|
|
333
|
-
});
|
|
334
|
-
return (sources.length > 0 ? sources : [content ?? {}]).map((globs) => ({
|
|
335
|
-
exclude: globs.exclude ?? DEFAULT_CONTENT_EXCLUDE,
|
|
336
|
-
include: globs.include ?? DEFAULT_CONTENT_INCLUDE,
|
|
337
|
-
root: globs.root ?? "docs",
|
|
338
|
-
}));
|
|
339
|
-
};
|
|
340
|
-
|
|
341
|
-
/** The content roots the project's config names, loaded as written. */
|
|
342
|
-
const configContentGlobs = async (root: string): Promise<ContentGlobs[]> => {
|
|
343
|
-
const file = findConfigFile(root);
|
|
344
|
-
let raw: z.infer<typeof rawContentSchema> = {};
|
|
345
|
-
if (file) {
|
|
346
|
-
try {
|
|
347
|
-
const parsed = rawContentSchema.safeParse(
|
|
348
|
-
await createModuleLoader()(file)
|
|
349
|
-
);
|
|
350
|
-
raw = parsed.success ? parsed.data : {};
|
|
351
|
-
} catch {
|
|
352
|
-
// A config that won't load is already reported by the config check;
|
|
353
|
-
// its content still gets the zero-config scan.
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
return contentGlobs(raw);
|
|
357
|
-
};
|
|
358
|
-
|
|
359
|
-
const isPathKey = (segment: PropertyKey): segment is number | string =>
|
|
360
|
-
typeof segment !== "symbol";
|
|
361
|
-
|
|
362
|
-
// Zod's own wording for an unknown key; a removed field's hint replaces it.
|
|
363
|
-
const PLAIN_UNKNOWN_KEY = "Unrecognized key";
|
|
364
|
-
|
|
365
|
-
/**
|
|
366
|
-
* The removed fields among one page's front matter issues, each at its own
|
|
367
|
-
* line. Only issues the page schema words as a removed-field hint count: a
|
|
368
|
-
* key a project declares through `frontmatter.extend` is unknown to the bare
|
|
369
|
-
* schema, and any other invalid value was already an error on Blume 1.
|
|
370
|
-
*/
|
|
371
|
-
const removedFieldFindings = (
|
|
372
|
-
file: string,
|
|
373
|
-
text: string,
|
|
374
|
-
issues: readonly z.core.$ZodIssue[]
|
|
375
|
-
): Diagnostic[] =>
|
|
376
|
-
issues.flatMap((issue) => {
|
|
377
|
-
if (
|
|
378
|
-
issue.code !== "unrecognized_keys" ||
|
|
379
|
-
issue.message.startsWith(PLAIN_UNKNOWN_KEY)
|
|
380
|
-
) {
|
|
381
|
-
return [];
|
|
382
|
-
}
|
|
383
|
-
const path = issue.path.filter(isPathKey);
|
|
384
|
-
const position =
|
|
385
|
-
locateFrontmatterKey(text, [...path, ...issue.keys.slice(0, 1)]) ??
|
|
386
|
-
locateFrontmatterKey(text, path);
|
|
387
|
-
return [
|
|
388
|
-
{
|
|
389
|
-
code: "BLUME_FRONTMATTER_INVALID",
|
|
390
|
-
column: position?.column,
|
|
391
|
-
file,
|
|
392
|
-
line: position?.line,
|
|
393
|
-
message: issue.message,
|
|
394
|
-
severity: "error",
|
|
395
|
-
} satisfies Diagnostic,
|
|
396
|
-
];
|
|
397
|
-
});
|
|
398
|
-
|
|
399
|
-
/** The removed front matter fields in one page, or none it can't parse. */
|
|
400
|
-
const pageFindings = async (file: string): Promise<Diagnostic[]> => {
|
|
401
|
-
const text = await readFile(file, "utf-8");
|
|
402
|
-
let parsed: ReturnType<typeof pageMetaSchema.safeParse>;
|
|
403
|
-
try {
|
|
404
|
-
parsed = pageMetaSchema.safeParse(matter(text).data);
|
|
405
|
-
} catch {
|
|
406
|
-
// Unparseable front matter fails the build with its own diagnostic.
|
|
407
|
-
return [];
|
|
408
|
-
}
|
|
409
|
-
return parsed.success
|
|
410
|
-
? []
|
|
411
|
-
: removedFieldFindings(file, text, parsed.error.issues);
|
|
412
|
-
};
|
|
413
|
-
|
|
414
|
-
/**
|
|
415
|
-
* A finding for each front matter field Blume 2 removed, across the project's
|
|
416
|
-
* local content. A page with one fails validation and drops out of the build,
|
|
417
|
-
* which the config and components checks alone would report as ready.
|
|
418
|
-
*/
|
|
419
|
-
const frontmatterFindings = async (root: string): Promise<Diagnostic[]> => {
|
|
420
|
-
const roots = await configContentGlobs(root);
|
|
421
|
-
const matches = await Promise.all(
|
|
422
|
-
roots.map((globs) => {
|
|
423
|
-
const cwd = resolve(root, globs.root);
|
|
424
|
-
return existsSync(cwd)
|
|
425
|
-
? glob(globs.include, {
|
|
426
|
-
absolute: true,
|
|
427
|
-
cwd,
|
|
428
|
-
ignore: [...globs.exclude, ...baselineScanIgnore()],
|
|
429
|
-
onlyFiles: true,
|
|
430
|
-
})
|
|
431
|
-
: [];
|
|
432
|
-
})
|
|
433
|
-
);
|
|
434
|
-
// Two sources can share a folder; each page is checked once.
|
|
435
|
-
const files = [...new Set(matches.flat())].toSorted();
|
|
436
|
-
const findings = await Promise.all(files.map(pageFindings));
|
|
437
|
-
return findings.flat();
|
|
438
|
-
};
|
|
439
|
-
|
|
440
274
|
/**
|
|
441
275
|
* Run one check, turning the {@link BlumeError} it throws into its findings:
|
|
442
276
|
* each config issue or `components.ts` entry on its own, or the one diagnostic
|
|
@@ -466,8 +300,8 @@ const findingsOf = async (
|
|
|
466
300
|
* Check a project against this version of Blume: its config through the
|
|
467
301
|
* loader (every invalid field, each with its line and replacement), its
|
|
468
302
|
* `components.ts` through the static override planner (each entry at its
|
|
469
|
-
* line), its
|
|
470
|
-
*
|
|
303
|
+
* line), and its package.json scripts for `blume build` flags that no longer
|
|
304
|
+
* exist. Returns the failures;
|
|
471
305
|
* an empty list means the project is ready.
|
|
472
306
|
*/
|
|
473
307
|
export const collectUpgradeFindings = async (
|
|
@@ -486,7 +320,6 @@ export const collectUpgradeFindings = async (
|
|
|
486
320
|
);
|
|
487
321
|
})
|
|
488
322
|
: []),
|
|
489
|
-
...(await frontmatterFindings(root)),
|
|
490
323
|
...(await scriptFindings(root)),
|
|
491
324
|
];
|
|
492
325
|
};
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
needsPlaygroundProxy,
|
|
4
|
-
resolveAskBackend
|
|
5
|
-
} from "./chunk-pv29h0wf.js";
|
|
6
|
-
|
|
7
|
-
// src/core/server-features.ts
|
|
8
|
-
var serverFeatures = (config) => {
|
|
9
|
-
const features = [];
|
|
10
|
-
if (config.ai.assistant?.enabled && !config.ai.assistant.endpoint) {
|
|
11
|
-
features.push("Assistant");
|
|
12
|
-
}
|
|
13
|
-
if (config.agents.mcp.enabled) {
|
|
14
|
-
features.push("MCP server");
|
|
15
|
-
}
|
|
16
|
-
if (needsPlaygroundProxy(config)) {
|
|
17
|
-
features.push("API playground proxy");
|
|
18
|
-
}
|
|
19
|
-
if (config.search.provider.mode === "server") {
|
|
20
|
-
features.push(`Search (${config.search.provider.kind})`);
|
|
21
|
-
}
|
|
22
|
-
return features;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
// src/cli/required-secrets.ts
|
|
26
|
-
var checkRequiredSecrets = (config) => {
|
|
27
|
-
const diagnostics = [];
|
|
28
|
-
const requireSecret = (feature, env, note) => {
|
|
29
|
-
if (process.env[env]) {
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
const noteSuffix = note ? ` (${note})` : "";
|
|
33
|
-
diagnostics.push({
|
|
34
|
-
code: "BLUME_MISSING_SECRET",
|
|
35
|
-
message: `${feature} is enabled but ${env} is not set${noteSuffix}.`,
|
|
36
|
-
severity: "warning",
|
|
37
|
-
suggestion: `Set ${env} in .env.local for local dev, or in your host's environment for production.`
|
|
38
|
-
});
|
|
39
|
-
};
|
|
40
|
-
if (config.ai.assistant?.enabled && !config.ai.assistant.endpoint) {
|
|
41
|
-
const { provider } = config.ai.assistant;
|
|
42
|
-
const backend = resolveAskBackend(provider);
|
|
43
|
-
for (const env of provider.requiredSecrets) {
|
|
44
|
-
requireSecret(`Assistant (${backend.label})`, env, backend.secretNote);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
const { provider } = config.search;
|
|
48
|
-
for (const env of provider.requiredSecrets) {
|
|
49
|
-
requireSecret(`Search (${provider.kind})`, env);
|
|
50
|
-
}
|
|
51
|
-
for (const adapter of config.analytics) {
|
|
52
|
-
for (const env of adapter.requiredSecrets) {
|
|
53
|
-
requireSecret(`Analytics (${adapter.kind})`, env);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
for (const source of config.content.sources) {
|
|
57
|
-
for (const env of source.requiredSecrets) {
|
|
58
|
-
requireSecret(`Content source (${source.kind})`, env);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
for (const adapter of config.reference) {
|
|
62
|
-
for (const env of adapter.requiredSecrets) {
|
|
63
|
-
requireSecret(`API reference (${adapter.kind})`, env);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
for (const env of config.deployment.requiredSecrets) {
|
|
67
|
-
requireSecret(`Deployment (${config.deployment.kind})`, env);
|
|
68
|
-
}
|
|
69
|
-
return diagnostics;
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
export { serverFeatures, checkRequiredSecrets };
|
|
73
|
-
|
|
74
|
-
//# debugId=26CFBC953FC234CC64756E2164756E21
|
|
75
|
-
//# sourceMappingURL=chunk-364znk6q.js.map
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/core/server-features.ts", "../src/cli/required-secrets.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"import { needsPlaygroundProxy } from \"../openapi/references.ts\";\nimport type { ResolvedConfig } from \"./schema.ts\";\n\n/**\n * List the enabled features that require Astro server output. Static builds\n * fail clearly when any of these are enabled.\n */\nexport const serverFeatures = (config: ResolvedConfig): string[] => {\n const features: string[] = [];\n if (config.ai.assistant?.enabled && !config.ai.assistant.endpoint) {\n features.push(\"Assistant\");\n }\n // The hosted MCP server is a live JSON-RPC endpoint, so it needs a runtime.\n if (config.agents.mcp.enabled) {\n features.push(\"MCP server\");\n }\n // The built-in playground proxy (`playground.proxy: true` on an `openapi()`\n // or `graphql()` adapter) is a live fetch endpoint at `/_api-proxy`; an\n // external proxy URL (string) or a proxy-less playground stays fully static.\n if (needsPlaygroundProxy(config)) {\n features.push(\"API playground proxy\");\n }\n // A `server` adapter (Mixedbread) proxies queries through a secret server\n // endpoint, so it can't run on a static build.\n if (config.search.provider.mode === \"server\") {\n features.push(`Search (${config.search.provider.kind})`);\n }\n return features;\n};\n",
|
|
6
|
-
"import { resolveAskBackend } from \"../ai/ask.ts\";\nimport type { ResolvedConfig } from \"../core/schema.ts\";\nimport type { Diagnostic } from \"../core/types.ts\";\n\n/**\n * Warn early when an enabled feature needs a secret env var that isn't set, so\n * the failure surfaces at `blume dev`/`build` instead of at the first request in\n * production. These are runtime secrets (the endpoint reads them on the server),\n * so this warns rather than hard-fails — the value may live only in the deploy\n * environment. Build-time secrets (search-index sync) already warn during sync.\n */\nexport const checkRequiredSecrets = (config: ResolvedConfig): Diagnostic[] => {\n const diagnostics: Diagnostic[] = [];\n const requireSecret = (feature: string, env: string, note?: string): void => {\n if (process.env[env]) {\n return;\n }\n const noteSuffix = note ? ` (${note})` : \"\";\n diagnostics.push({\n code: \"BLUME_MISSING_SECRET\",\n message: `${feature} is enabled but ${env} is not set${noteSuffix}.`,\n severity: \"warning\",\n suggestion: `Set ${env} in .env.local for local dev, or in your host's environment for production.`,\n });\n };\n\n if (config.ai.assistant?.enabled && !config.ai.assistant.endpoint) {\n // The adapter descriptor names the env vars its route reads.\n const { provider } = config.ai.assistant;\n const backend = resolveAskBackend(provider);\n for (const env of provider.requiredSecrets) {\n requireSecret(`Assistant (${backend.label})`, env, backend.secretNote);\n }\n }\n\n // Each search adapter declares the secrets its generated runtime reads.\n const { provider } = config.search;\n for (const env of provider.requiredSecrets) {\n requireSecret(`Search (${provider.kind})`, env);\n }\n\n // Adapters name their own secrets; the built-in analytics adapters ship\n // public tokens in the page and declare none.\n for (const adapter of config.analytics) {\n for (const env of adapter.requiredSecrets) {\n requireSecret(`Analytics (${adapter.kind})`, env);\n }\n }\n\n // Each content source adapter declares the env vars its fetch reads.\n for (const source of config.content.sources) {\n for (const env of source.requiredSecrets) {\n requireSecret(`Content source (${source.kind})`, env);\n }\n }\n\n // Adapters name their own secrets; the built-in reference adapters read\n // public specs and declare none.\n for (const adapter of config.reference) {\n for (const env of adapter.requiredSecrets) {\n requireSecret(`API reference (${adapter.kind})`, env);\n }\n }\n\n // The deployment adapter names its own secrets; the built-in host adapters\n // read platform-injected env and declare none.\n for (const env of config.deployment.requiredSecrets) {\n requireSecret(`Deployment (${config.deployment.kind})`, env);\n }\n\n return diagnostics;\n};\n"
|
|
7
|
-
],
|
|
8
|
-
"mappings": ";;;;;;;AAOO,IAAM,iBAAiB,CAAC,WAAqC;AAAA,EAClE,MAAM,WAAqB,CAAC;AAAA,EAC5B,IAAI,OAAO,GAAG,WAAW,WAAW,CAAC,OAAO,GAAG,UAAU,UAAU;AAAA,IACjE,SAAS,KAAK,WAAW;AAAA,EAC3B;AAAA,EAEA,IAAI,OAAO,OAAO,IAAI,SAAS;AAAA,IAC7B,SAAS,KAAK,YAAY;AAAA,EAC5B;AAAA,EAIA,IAAI,qBAAqB,MAAM,GAAG;AAAA,IAChC,SAAS,KAAK,sBAAsB;AAAA,EACtC;AAAA,EAGA,IAAI,OAAO,OAAO,SAAS,SAAS,UAAU;AAAA,IAC5C,SAAS,KAAK,WAAW,OAAO,OAAO,SAAS,OAAO;AAAA,EACzD;AAAA,EACA,OAAO;AAAA;;;AChBF,IAAM,uBAAuB,CAAC,WAAyC;AAAA,EAC5E,MAAM,cAA4B,CAAC;AAAA,EACnC,MAAM,gBAAgB,CAAC,SAAiB,KAAa,SAAwB;AAAA,IAC3E,IAAI,QAAQ,IAAI,MAAM;AAAA,MACpB;AAAA,IACF;AAAA,IACA,MAAM,aAAa,OAAO,KAAK,UAAU;AAAA,IACzC,YAAY,KAAK;AAAA,MACf,MAAM;AAAA,MACN,SAAS,GAAG,0BAA0B,iBAAiB;AAAA,MACvD,UAAU;AAAA,MACV,YAAY,OAAO;AAAA,IACrB,CAAC;AAAA;AAAA,EAGH,IAAI,OAAO,GAAG,WAAW,WAAW,CAAC,OAAO,GAAG,UAAU,UAAU;AAAA,IAEjE,QAAQ,aAAa,OAAO,GAAG;AAAA,IAC/B,MAAM,UAAU,kBAAkB,QAAQ;AAAA,IAC1C,WAAW,OAAO,SAAS,iBAAiB;AAAA,MAC1C,cAAc,cAAc,QAAQ,UAAU,KAAK,QAAQ,UAAU;AAAA,IACvE;AAAA,EACF;AAAA,EAGA,QAAQ,aAAa,OAAO;AAAA,EAC5B,WAAW,OAAO,SAAS,iBAAiB;AAAA,IAC1C,cAAc,WAAW,SAAS,SAAS,GAAG;AAAA,EAChD;AAAA,EAIA,WAAW,WAAW,OAAO,WAAW;AAAA,IACtC,WAAW,OAAO,QAAQ,iBAAiB;AAAA,MACzC,cAAc,cAAc,QAAQ,SAAS,GAAG;AAAA,IAClD;AAAA,EACF;AAAA,EAGA,WAAW,UAAU,OAAO,QAAQ,SAAS;AAAA,IAC3C,WAAW,OAAO,OAAO,iBAAiB;AAAA,MACxC,cAAc,mBAAmB,OAAO,SAAS,GAAG;AAAA,IACtD;AAAA,EACF;AAAA,EAIA,WAAW,WAAW,OAAO,WAAW;AAAA,IACtC,WAAW,OAAO,QAAQ,iBAAiB;AAAA,MACzC,cAAc,kBAAkB,QAAQ,SAAS,GAAG;AAAA,IACtD;AAAA,EACF;AAAA,EAIA,WAAW,OAAO,OAAO,WAAW,iBAAiB;AAAA,IACnD,cAAc,eAAe,OAAO,WAAW,SAAS,GAAG;AAAA,EAC7D;AAAA,EAEA,OAAO;AAAA;",
|
|
9
|
-
"debugId": "26CFBC953FC234CC64756E2164756E21",
|
|
10
|
-
"names": []
|
|
11
|
-
}
|