blume 2.0.2 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -0
- package/CHANGELOG.md +113 -0
- package/README.md +1 -1
- package/dist/cli/{chunk-6k4ftwze.js → chunk-0gz36akr.js} +18 -2
- package/dist/cli/{chunk-6k4ftwze.js.map → chunk-0gz36akr.js.map} +3 -3
- package/dist/cli/{chunk-zp79m0ts.js → chunk-1n228xqb.js} +2 -2
- package/dist/cli/{chunk-ddndchfr.js → chunk-2f3ndkpw.js} +57 -29
- package/dist/cli/chunk-2f3ndkpw.js.map +14 -0
- package/dist/cli/{chunk-fsmrqk8a.js → chunk-2f7n4qzt.js} +8 -2
- package/dist/cli/{chunk-fsmrqk8a.js.map → chunk-2f7n4qzt.js.map} +3 -3
- package/dist/cli/{chunk-ppzjqwx2.js → chunk-2n4ps1b3.js} +17 -18
- package/dist/cli/{chunk-ppzjqwx2.js.map → chunk-2n4ps1b3.js.map} +3 -3
- package/dist/cli/{chunk-5r8g91qn.js → chunk-43zcf4gz.js} +398 -159
- package/dist/cli/chunk-43zcf4gz.js.map +36 -0
- package/dist/cli/chunk-4ejxbzee.js +39 -0
- package/dist/cli/chunk-4ejxbzee.js.map +10 -0
- package/dist/cli/{chunk-hr8ne106.js → chunk-4h8z9vv5.js} +296 -77
- package/dist/cli/chunk-4h8z9vv5.js.map +16 -0
- package/dist/cli/{chunk-k7pj68a8.js → chunk-5cg2rzgf.js} +18 -16
- package/dist/cli/{chunk-k7pj68a8.js.map → chunk-5cg2rzgf.js.map} +2 -2
- package/dist/cli/{chunk-h2ez8dzb.js → chunk-5ffywsmb.js} +4 -4
- package/dist/cli/{chunk-g698a744.js → chunk-5wj2qwn2.js} +5 -5
- package/dist/cli/chunk-6bm0xpgd.js +18 -0
- package/dist/cli/chunk-6bm0xpgd.js.map +10 -0
- package/dist/cli/{chunk-3yce002v.js → chunk-713mngdq.js} +15 -8
- package/dist/cli/chunk-713mngdq.js.map +14 -0
- package/dist/cli/{chunk-91ws1n6j.js → chunk-9geymqns.js} +17 -15
- package/dist/cli/{chunk-91ws1n6j.js.map → chunk-9geymqns.js.map} +2 -2
- package/dist/cli/{chunk-6dtt0zfn.js → chunk-9xr4dgee.js} +27 -18
- package/dist/cli/chunk-9xr4dgee.js.map +10 -0
- package/dist/cli/{chunk-sqw4ekg1.js → chunk-amrb6hgh.js} +2 -2
- package/dist/cli/chunk-cm89scdv.js +443 -0
- package/dist/cli/chunk-cm89scdv.js.map +11 -0
- package/dist/cli/{chunk-wdrt2k2v.js → chunk-cmtcnh9f.js} +90 -26
- package/dist/cli/chunk-cmtcnh9f.js.map +10 -0
- package/dist/cli/chunk-cy5bm0j0.js +104 -0
- package/dist/cli/chunk-cy5bm0j0.js.map +11 -0
- package/dist/cli/{chunk-7mbqtmgb.js → chunk-e7vvk5ya.js} +21 -12
- package/dist/cli/chunk-e7vvk5ya.js.map +10 -0
- package/dist/cli/{chunk-qkb5a8sa.js → chunk-g2z9x01v.js} +6 -98
- package/dist/cli/chunk-g2z9x01v.js.map +10 -0
- package/dist/cli/{chunk-273ygyr4.js → chunk-ga0pf4aj.js} +7 -7
- package/dist/cli/{chunk-273ygyr4.js.map → chunk-ga0pf4aj.js.map} +3 -3
- package/dist/cli/{chunk-h7k3nq3v.js → chunk-gp84za0h.js} +2 -2
- package/dist/cli/{chunk-hqp2ajnh.js → chunk-h2a48yhd.js} +195 -73
- package/dist/cli/chunk-h2a48yhd.js.map +36 -0
- package/dist/cli/{chunk-pbg5a4s3.js → chunk-jnwj5kjj.js} +71 -47
- package/dist/cli/chunk-jnwj5kjj.js.map +19 -0
- package/dist/cli/chunk-kwrg63tm.js +31 -0
- package/dist/cli/chunk-kwrg63tm.js.map +10 -0
- package/dist/cli/{chunk-8g8ytmgx.js → chunk-nd1821sk.js} +21 -19
- package/dist/cli/{chunk-8g8ytmgx.js.map → chunk-nd1821sk.js.map} +2 -2
- package/dist/cli/{chunk-w4bxdvsa.js → chunk-ntv4qrt7.js} +17 -15
- package/dist/cli/{chunk-w4bxdvsa.js.map → chunk-ntv4qrt7.js.map} +2 -2
- package/dist/cli/{chunk-bfwp9vp6.js → chunk-p804f3pe.js} +7 -7
- package/dist/cli/{chunk-4e9b9ra6.js → chunk-py62fewh.js} +6 -6
- package/dist/cli/{chunk-4e9b9ra6.js.map → chunk-py62fewh.js.map} +1 -1
- package/dist/cli/chunk-q3wxxq39.js +126 -0
- package/dist/cli/chunk-q3wxxq39.js.map +11 -0
- package/dist/cli/{chunk-j85scx15.js → chunk-rekqz4qg.js} +142 -46
- package/dist/cli/chunk-rekqz4qg.js.map +10 -0
- package/dist/cli/{chunk-00gs3wqs.js → chunk-ta27feev.js} +1 -1
- package/dist/cli/{chunk-v6ya5kcb.js → chunk-xkz5xbtv.js} +4031 -1132
- package/dist/cli/chunk-xkz5xbtv.js.map +213 -0
- package/dist/cli/{chunk-bbnwccaz.js → chunk-y4ykbark.js} +2 -2
- package/dist/cli/{chunk-n1yg3tj3.js → chunk-y5h4r2y0.js} +6 -6
- package/dist/cli/{chunk-n1yg3tj3.js.map → chunk-y5h4r2y0.js.map} +3 -3
- package/dist/cli/{chunk-nfcyttvj.js → chunk-yj17vs39.js} +9 -9
- package/dist/cli/{chunk-nfcyttvj.js.map → chunk-yj17vs39.js.map} +1 -1
- package/dist/cli/{chunk-7vtckvaw.js → chunk-yxmk4pec.js} +16 -14
- package/dist/cli/{chunk-7vtckvaw.js.map → chunk-yxmk4pec.js.map} +2 -2
- package/dist/cli/{chunk-gs7r695n.js → chunk-zccbjcj0.js} +22 -8
- package/dist/cli/{chunk-gs7r695n.js.map → chunk-zccbjcj0.js.map} +3 -3
- package/dist/cli/{chunk-xh43dwgw.js → chunk-zf748avv.js} +415 -225
- package/dist/cli/chunk-zf748avv.js.map +37 -0
- package/dist/cli/{chunk-d1v5rhy0.js → chunk-zhvd6adm.js} +16 -14
- package/dist/cli/{chunk-d1v5rhy0.js.map → chunk-zhvd6adm.js.map} +2 -2
- package/dist/cli/index.js +28 -20
- package/dist/cli/index.js.map +5 -5
- package/dist/types/ai/agent-surface.d.ts +8 -7
- package/dist/types/ai/ai-catalog.d.ts +7 -0
- package/dist/types/ai/ask-context.d.ts +22 -0
- package/dist/types/ai/ask.d.ts +271 -58
- package/dist/types/ai/index.d.ts +2 -2
- package/dist/types/ai/link-headers.d.ts +8 -1
- package/dist/types/ai/openapi-components.d.ts +5 -2
- package/dist/types/ai/relative-links.d.ts +9 -7
- package/dist/types/ai/site-skill.d.ts +26 -0
- package/dist/types/ai/skills.d.ts +20 -1
- package/dist/types/ai/tar.d.ts +1 -3
- package/dist/types/analytics/index.d.ts +2 -0
- package/dist/types/analytics/one-dollar-stats.d.ts +48 -0
- package/dist/types/analytics/schema.d.ts +14 -0
- package/dist/types/astro/integration.d.ts +11 -2
- package/dist/types/captcha/hcaptcha.d.ts +27 -0
- package/dist/types/captcha/index.d.ts +28 -0
- package/dist/types/captcha/schema.d.ts +29 -0
- package/dist/types/captcha/turnstile.d.ts +28 -0
- package/dist/types/components/content/api-field.d.ts +59 -0
- package/dist/types/components/content/api-page.d.ts +95 -0
- package/dist/types/components/layout/nav-utils.d.ts +26 -0
- package/dist/types/components/openapi/helpers.d.ts +137 -0
- package/dist/types/components/openapi/security.d.ts +85 -0
- package/dist/types/consent/ethyca.d.ts +48 -0
- package/dist/types/consent/index.d.ts +37 -0
- package/dist/types/consent/native.d.ts +28 -0
- package/dist/types/consent/osano.d.ts +42 -0
- package/dist/types/consent/schema.d.ts +110 -0
- package/dist/types/core/base-path.d.ts +21 -7
- package/dist/types/core/config-input.d.ts +196 -27
- package/dist/types/core/data.d.ts +49 -4
- package/dist/types/core/directive-diagnostics.d.ts +12 -0
- package/dist/types/core/footer.d.ts +8 -0
- package/dist/types/core/heading-markers.d.ts +5 -7
- package/dist/types/core/i18n-ui.d.ts +86 -0
- package/dist/types/core/i18n.d.ts +2 -0
- package/dist/types/core/includes.d.ts +8 -2
- package/dist/types/core/last-modified.d.ts +10 -0
- package/dist/types/core/localizable.d.ts +7 -0
- package/dist/types/core/meta.d.ts +8 -0
- package/dist/types/core/page-modes.d.ts +29 -0
- package/dist/types/core/redirect-patterns.d.ts +144 -0
- package/dist/types/core/related.d.ts +40 -0
- package/dist/types/core/schema.d.ts +558 -56
- package/dist/types/core/sources/lower.d.ts +29 -16
- package/dist/types/core/sources/normalize.d.ts +13 -1
- package/dist/types/core/sources/read.d.ts +5 -0
- package/dist/types/core/sources/watch.d.ts +12 -5
- package/dist/types/core/standard-schema.d.ts +5 -0
- package/dist/types/core/types.d.ts +1 -1
- package/dist/types/core/variables.d.ts +42 -0
- package/dist/types/deploy/artifacts.d.ts +6 -4
- package/dist/types/deploy/headers.d.ts +5 -0
- package/dist/types/deploy/node-headers.d.ts +13 -2
- package/dist/types/deploy/platforms/cloudflare.d.ts +5 -0
- package/dist/types/deploy/platforms/netlify.d.ts +7 -0
- package/dist/types/deploy/platforms/types.d.ts +8 -0
- package/dist/types/deploy/platforms/vercel.d.ts +6 -0
- package/dist/types/deploy/redirects.d.ts +61 -22
- package/dist/types/deploy/vercel-negotiation.d.ts +9 -0
- package/dist/types/markdown/code-title.d.ts +17 -0
- package/dist/types/markdown/directives.d.ts +62 -0
- package/dist/types/markdown/features.d.ts +24 -2
- package/dist/types/markdown/mdast.d.ts +63 -0
- package/dist/types/narration/build.d.ts +70 -0
- package/dist/types/narration/provider.d.ts +26 -0
- package/dist/types/narration/script.d.ts +154 -0
- package/dist/types/openapi/asyncapi.d.ts +4 -2
- package/dist/types/openapi/model.d.ts +12 -6
- package/dist/types/openapi/overlay.d.ts +54 -0
- package/dist/types/openapi/parse.d.ts +13 -0
- package/dist/types/openapi/references.d.ts +14 -4
- package/dist/types/ratelimit/cloudflare.d.ts +39 -0
- package/dist/types/ratelimit/index.d.ts +27 -0
- package/dist/types/ratelimit/memory.d.ts +36 -0
- package/dist/types/ratelimit/schema.d.ts +111 -0
- package/dist/types/ratelimit/upstash.d.ts +21 -0
- package/dist/types/ratelimit/wrangler.d.ts +23 -0
- package/dist/types/reference/asyncapi.d.ts +10 -10
- package/dist/types/reference/graphql.d.ts +13 -10
- package/dist/types/reference/openapi.d.ts +33 -12
- package/dist/types/reference/options.d.ts +45 -5
- package/dist/types/reference/scalar.d.ts +13 -0
- package/dist/types/reference/schema.d.ts +60 -36
- package/dist/types/search/documents.d.ts +12 -1
- package/dist/types/search/orama-index.d.ts +4 -0
- package/dist/types/seo/metatags.d.ts +20 -0
- package/docs/02-deployment.mdx +44 -6
- package/docs/03-upgrading.mdx +4 -4
- package/docs/04-migrating.mdx +1 -1
- package/docs/08-faq.mdx +1 -1
- package/docs/advanced/changelog.mdx +2 -2
- package/docs/advanced/custom-pages.mdx +3 -3
- package/docs/advanced/skills.mdx +14 -0
- package/docs/cli/audit.mdx +38 -2
- package/docs/cli/evals.mdx +3 -3
- package/docs/cli/index.mdx +1 -0
- package/docs/cli/translate.mdx +3 -3
- package/docs/cli/version.mdx +1 -1
- package/docs/configuration/analytics.mdx +22 -1
- package/docs/configuration/assistant.mdx +188 -36
- package/docs/configuration/consent.mdx +100 -0
- package/docs/configuration/customization.mdx +6 -4
- package/docs/configuration/index.mdx +63 -5
- package/docs/configuration/meta.ts +3 -0
- package/docs/configuration/narration.mdx +119 -0
- package/docs/configuration/rate-limiting.mdx +69 -0
- package/docs/configuration/search.mdx +30 -2
- package/docs/configuration/theming.mdx +3 -1
- package/docs/content/components.mdx +107 -1
- package/docs/content/frontmatter.mdx +77 -1
- package/docs/content/i18n.mdx +40 -3
- package/docs/content/includes.mdx +16 -0
- package/docs/content/index.mdx +4 -2
- package/docs/content/islands.mdx +1 -1
- package/docs/content/meta.mdx +4 -1
- package/docs/content/meta.ts +1 -0
- package/docs/content/navigation.mdx +28 -6
- package/docs/content/sources/contentful.mdx +32 -0
- package/docs/content/sources/custom.mdx +39 -0
- package/docs/content/sources/github-releases.mdx +31 -0
- package/docs/content/sources/index.mdx +91 -0
- package/docs/content/sources/meta.ts +16 -0
- package/docs/content/sources/notion.mdx +32 -0
- package/docs/content/sources/obsidian.mdx +37 -0
- package/docs/content/sources/payload.mdx +30 -0
- package/docs/content/sources/remote-mdx.mdx +40 -0
- package/docs/content/sources/sanity.mdx +29 -0
- package/docs/content/sources/strapi.mdx +31 -0
- package/docs/content/syntax.mdx +81 -2
- package/docs/content/variables.mdx +41 -0
- package/docs/content/versioning.mdx +1 -1
- package/docs/discoverability/agent-discovery.mdx +30 -3
- package/docs/discoverability/index.mdx +3 -2
- package/docs/discoverability/llms-txt.mdx +1 -1
- package/docs/discoverability/markdown.mdx +2 -2
- package/docs/discoverability/metadata.mdx +17 -0
- package/docs/discoverability/open-graph.mdx +5 -3
- package/docs/discoverability/rss.mdx +1 -1
- package/docs/references/api-pages.mdx +74 -0
- package/docs/references/asyncapi.mdx +2 -2
- package/docs/references/graphql.mdx +3 -3
- package/docs/references/meta.ts +1 -1
- package/docs/references/openapi.mdx +106 -5
- package/docs/references/scalar.mdx +3 -1
- package/package.json +36 -1
- package/skills/blume/SKILL.md +3 -0
- package/skills/blume-migrate/SKILL.md +5 -5
- package/skills/blume-migrate/references/docusaurus.md +3 -3
- package/skills/blume-migrate/references/fumadocs.md +1 -1
- package/skills/blume-migrate/references/mintlify.md +37 -19
- package/skills/blume-migrate/references/nextra.md +3 -3
- package/skills/blume-migrate/references/starlight.md +2 -1
- package/skills/blume-migrate/scripts/mintlify-codemod.mjs +67 -16
- package/skills/blume-write-skill/SKILL.md +82 -0
- package/src/ai/agent-readability.ts +4 -3
- package/src/ai/agent-surface.ts +9 -7
- package/src/ai/ai-catalog.ts +12 -5
- package/src/ai/api/handlers.ts +2 -2
- package/src/ai/api/spec.ts +2 -2
- package/src/ai/api-catalog.ts +6 -2
- package/src/ai/ask-context.ts +73 -20
- package/src/ai/ask-data.ts +6 -0
- package/src/ai/ask-tools.ts +142 -0
- package/src/ai/ask.ts +354 -76
- package/src/ai/changelog-markdown.ts +2 -2
- package/src/ai/component-markdown.ts +75 -0
- package/src/ai/cors.ts +2 -0
- package/src/ai/index.ts +12 -0
- package/src/ai/link-headers.ts +14 -5
- package/src/ai/llms.ts +24 -9
- package/src/ai/markdown.ts +2 -1
- package/src/ai/mcp/data.ts +6 -0
- package/src/ai/mcp/discovery.ts +2 -2
- package/src/ai/mcp/query.ts +2 -2
- package/src/ai/mcp/server.ts +2 -2
- package/src/ai/openapi-components.ts +31 -9
- package/src/ai/relative-links.ts +42 -26
- package/src/ai/serializers.ts +2 -1
- package/src/ai/site-skill.ts +274 -0
- package/src/ai/skills.ts +49 -3
- package/src/ai/tar.ts +139 -12
- package/src/ai/write-skill.ts +97 -0
- package/src/analytics/head.ts +4 -0
- package/src/analytics/index.ts +5 -0
- package/src/analytics/one-dollar-stats.ts +86 -0
- package/src/analytics/schema.ts +2 -0
- package/src/astro/generate.ts +133 -19
- package/src/astro/include-hmr.ts +31 -12
- package/src/astro/include-refresh.ts +19 -8
- package/src/astro/index.ts +1 -0
- package/src/astro/integration.ts +143 -14
- package/src/astro/module-types.ts +6 -0
- package/src/astro/runtime-modules.ts +28 -13
- package/src/astro/templates.ts +364 -67
- package/src/astro/variables.ts +31 -0
- package/src/audit/catalog.ts +19 -0
- package/src/audit/checks/contrast.ts +183 -0
- package/src/audit/checks/i18n.ts +2 -3
- package/src/audit/checks/indexability.ts +2 -3
- package/src/audit/checks/links.ts +13 -13
- package/src/audit/checks/sitemap.ts +2 -3
- package/src/audit/graph.ts +3 -1
- package/src/audit/redirects.ts +46 -15
- package/src/audit/run.ts +14 -9
- package/src/audit/snapshot.ts +5 -0
- package/src/audit/types.ts +2 -1
- package/src/blume-modules.d.ts +7 -0
- package/src/captcha/client.ts +152 -0
- package/src/captcha/hcaptcha.ts +36 -0
- package/src/captcha/index.ts +28 -0
- package/src/captcha/schema.ts +32 -0
- package/src/captcha/turnstile.ts +38 -0
- package/src/captcha/verify.ts +71 -0
- package/src/cli/args.ts +32 -0
- package/src/cli/command-meta.ts +5 -0
- package/src/cli/commands/audit.ts +4 -1
- package/src/cli/commands/doctor.ts +25 -17
- package/src/cli/commands/eval.ts +19 -11
- package/src/cli/commands/skill.ts +96 -0
- package/src/cli/commands/translate.ts +9 -12
- package/src/cli/commands/validate.ts +3 -1
- package/src/cli/dev-lock.ts +157 -37
- package/src/cli/index.ts +5 -0
- package/src/cli/report-format.ts +11 -6
- package/src/cli/required-secrets.ts +71 -29
- package/src/components/BlumePage.astro +2 -0
- package/src/components/colors.ts +19 -0
- package/src/components/content/ApiEndpoint.astro +18 -0
- package/src/components/content/ApiField.astro +79 -0
- package/src/components/content/ApiPlayground.astro +62 -0
- package/src/components/content/ApiRail.astro +19 -0
- package/src/components/content/Badge.astro +5 -3
- package/src/components/content/Color.astro +1 -0
- package/src/components/content/Component.astro +2 -2
- package/src/components/content/FileTree.astro +1 -0
- package/src/components/content/GithubInfo.astro +1 -0
- package/src/components/content/Panel.astro +1 -0
- package/src/components/content/ParamField.astro +25 -0
- package/src/components/content/RequestExample.astro +17 -0
- package/src/components/content/ResponseExample.astro +17 -0
- package/src/components/content/ResponseField.astro +32 -0
- package/src/components/content/Step.astro +1 -0
- package/src/components/content/Tab.astro +0 -1
- package/src/components/content/Tabs.astro +4 -0
- package/src/components/content/Tile.astro +1 -0
- package/src/components/content/Tooltip.astro +1 -0
- package/src/components/content/Tree.astro +1 -0
- package/src/components/content/TypeTable.astro +4 -1
- package/src/components/content/View.astro +21 -0
- package/src/components/content/ViewSwitcher.astro +168 -0
- package/src/components/content/api-field.ts +100 -0
- package/src/components/content/api-page.ts +224 -0
- package/src/components/content/badge-color.ts +5 -2
- package/src/components/content/base-href.ts +13 -36
- package/src/components/content/view-switcher.ts +71 -0
- package/src/components/index.ts +2 -0
- package/src/components/islands/Assistant.astro +10 -1
- package/src/components/islands/assistant.tsx +125 -18
- package/src/components/islands/base-path.ts +47 -10
- package/src/components/islands/code-question.ts +62 -0
- package/src/components/islands/hooks.ts +145 -40
- package/src/components/islands/support-link.ts +68 -0
- package/src/components/islands/webmcp.ts +4 -2
- package/src/components/layout/Analytics.astro +11 -2
- package/src/components/layout/Banner.astro +14 -10
- package/src/components/layout/Breadcrumbs.astro +11 -4
- package/src/components/layout/ConsentBanner.astro +62 -0
- package/src/components/layout/ConsentHead.astro +38 -0
- package/src/components/layout/Directory.astro +94 -0
- package/src/components/layout/DiscoveryLinks.astro +9 -5
- package/src/components/layout/DrawerSwitchers.astro +51 -0
- package/src/components/layout/Empty.astro +2 -2
- package/src/components/layout/Header.astro +124 -82
- package/src/components/layout/LanguageSwitcher.astro +50 -17
- package/src/components/layout/NarrationPlayer.astro +1085 -0
- package/src/components/layout/NavSelector.astro +35 -9
- package/src/components/layout/NavTabMenu.astro +3 -3
- package/src/components/layout/NavTree.astro +16 -6
- package/src/components/layout/PageActions.astro +4 -3
- package/src/components/layout/PageFeedback.astro +54 -49
- package/src/components/layout/PageLayout.astro +78 -9
- package/src/components/layout/Pagination.astro +3 -3
- package/src/components/layout/ReferenceLayout.astro +17 -6
- package/src/components/layout/RelatedPages.astro +42 -0
- package/src/components/layout/RootLayout.astro +313 -50
- package/src/components/layout/Search.astro +64 -30
- package/src/components/layout/SiteFooter.astro +124 -0
- package/src/components/layout/SiteMetatags.astro +16 -0
- package/src/components/layout/VersionBanner.astro +2 -2
- package/src/components/layout/analytics-client.ts +12 -0
- package/src/components/layout/consent/native.ts +79 -0
- package/src/components/layout/consent/types.ts +37 -0
- package/src/components/layout/footer-links.ts +53 -0
- package/src/components/layout/footer-socials.ts +87 -0
- package/src/components/layout/locale-redirect.ts +107 -0
- package/src/components/layout/nav-utils.ts +83 -0
- package/src/components/layout/page-feedback.ts +96 -0
- package/src/components/layout/search/analytics.ts +98 -0
- package/src/components/layout/search/flexsearch.ts +17 -5
- package/src/components/layout/search/orama-cloud.ts +26 -14
- package/src/components/layout/search/types.ts +20 -0
- package/src/components/layout/search/typesense.ts +5 -1
- package/src/components/layout/toc-active.ts +41 -0
- package/src/components/layout/toc-element.ts +8 -14
- package/src/components/openapi/ApiTagOperations.astro +2 -2
- package/src/components/openapi/AsyncApiOperation.astro +7 -4
- package/src/components/openapi/GraphqlChip.astro +2 -2
- package/src/components/openapi/Operation.astro +163 -13
- package/src/components/openapi/Playground.astro +4 -4
- package/src/components/openapi/RequestBody.astro +6 -4
- package/src/components/openapi/RequestPanel.astro +63 -8
- package/src/components/openapi/Responses.astro +6 -4
- package/src/components/openapi/SchemaTable.astro +7 -0
- package/src/components/openapi/async-snippets.ts +4 -4
- package/src/components/openapi/async.ts +38 -6
- package/src/components/openapi/code-samples.ts +97 -0
- package/src/components/openapi/helpers.ts +19 -9
- package/src/components/openapi/message-composer.ts +6 -1
- package/src/components/openapi/message.ts +17 -2
- package/src/components/openapi/operation-model.ts +81 -11
- package/src/components/openapi/panel.ts +4 -2
- package/src/components/openapi/param-style.ts +181 -0
- package/src/components/openapi/playground-client.ts +73 -16
- package/src/components/openapi/request.ts +190 -26
- package/src/components/openapi/schema-tree.ts +30 -24
- package/src/components/openapi/security.ts +6 -3
- package/src/components/openapi/snippets.ts +953 -13
- package/src/components/openapi/ws-client.ts +18 -2
- package/src/components/props.ts +6 -0
- package/src/consent/client.ts +95 -0
- package/src/consent/clients.ts +19 -0
- package/src/consent/ethyca.ts +71 -0
- package/src/consent/head.ts +24 -0
- package/src/consent/index.ts +37 -0
- package/src/consent/init.ts +29 -0
- package/src/consent/native.ts +36 -0
- package/src/consent/osano.ts +59 -0
- package/src/consent/schema.ts +30 -0
- package/src/core/base-path.ts +62 -16
- package/src/core/builtin-tags.ts +5 -0
- package/src/core/client-address.ts +19 -0
- package/src/core/config-input.ts +203 -27
- package/src/core/data.ts +44 -4
- package/src/core/diagnostics.ts +5 -2
- package/src/core/directive-diagnostics.ts +99 -0
- package/src/core/footer.ts +26 -0
- package/src/core/frontmatter.ts +21 -18
- package/src/core/graph.ts +39 -36
- package/src/core/heading-markers.ts +5 -18
- package/src/core/i18n-ui.ts +82 -2
- package/src/core/i18n.ts +31 -3
- package/src/core/includes.ts +20 -3
- package/src/core/last-modified.ts +25 -3
- package/src/core/links.ts +16 -2
- package/src/core/locale-links.ts +5 -1
- package/src/core/localizable.ts +26 -0
- package/src/core/meta.ts +33 -19
- package/src/core/navigation.ts +71 -20
- package/src/core/page-modes.ts +56 -0
- package/src/core/project-graph.ts +138 -10
- package/src/core/redirect-patterns.ts +491 -0
- package/src/core/related.ts +131 -0
- package/src/core/schema.ts +342 -68
- package/src/core/sources/contentful-rich-text.ts +27 -20
- package/src/core/sources/filesystem.ts +20 -2
- package/src/core/sources/github-releases.ts +25 -6
- package/src/core/sources/lexical.ts +23 -18
- package/src/core/sources/lower.ts +201 -34
- package/src/core/sources/mdx-remote.ts +51 -16
- package/src/core/sources/normalize.ts +327 -91
- package/src/core/sources/notion.ts +52 -25
- package/src/core/sources/obsidian.ts +23 -6
- package/src/core/sources/portable-text.ts +38 -21
- package/src/core/sources/read.ts +8 -3
- package/src/core/sources/strapi-blocks.ts +20 -16
- package/src/core/sources/watch.ts +20 -7
- package/src/core/standard-schema.ts +10 -6
- package/src/core/types.ts +1 -1
- package/src/core/ui-packs/ar.ts +43 -0
- package/src/core/ui-packs/bg.ts +45 -0
- package/src/core/ui-packs/bn.ts +43 -0
- package/src/core/ui-packs/ca.ts +46 -0
- package/src/core/ui-packs/cs.ts +44 -0
- package/src/core/ui-packs/da.ts +45 -0
- package/src/core/ui-packs/de.ts +46 -0
- package/src/core/ui-packs/el.ts +45 -0
- package/src/core/ui-packs/es.ts +46 -0
- package/src/core/ui-packs/fa.ts +45 -0
- package/src/core/ui-packs/fi.ts +45 -0
- package/src/core/ui-packs/fr.ts +46 -0
- package/src/core/ui-packs/he.ts +43 -0
- package/src/core/ui-packs/hi.ts +44 -0
- package/src/core/ui-packs/hr.ts +45 -0
- package/src/core/ui-packs/hu.ts +44 -0
- package/src/core/ui-packs/id.ts +45 -0
- package/src/core/ui-packs/it.ts +45 -0
- package/src/core/ui-packs/ja.ts +45 -0
- package/src/core/ui-packs/ko.ts +44 -0
- package/src/core/ui-packs/nl.ts +46 -0
- package/src/core/ui-packs/no.ts +44 -0
- package/src/core/ui-packs/pl.ts +45 -0
- package/src/core/ui-packs/pt-br.ts +46 -0
- package/src/core/ui-packs/pt.ts +45 -0
- package/src/core/ui-packs/ro.ts +45 -0
- package/src/core/ui-packs/ru.ts +45 -0
- package/src/core/ui-packs/sk.ts +44 -0
- package/src/core/ui-packs/sr.ts +45 -0
- package/src/core/ui-packs/sv.ts +44 -0
- package/src/core/ui-packs/th.ts +43 -0
- package/src/core/ui-packs/tr.ts +45 -0
- package/src/core/ui-packs/uk.ts +45 -0
- package/src/core/ui-packs/vi.ts +45 -0
- package/src/core/ui-packs/zh-tw.ts +43 -0
- package/src/core/ui-packs/zh.ts +43 -0
- package/src/core/variables.ts +103 -0
- package/src/core/version-cut.ts +52 -15
- package/src/deploy/artifacts.ts +104 -14
- package/src/deploy/cloudflare-negotiation.ts +39 -17
- package/src/deploy/headers.ts +10 -5
- package/src/deploy/node-headers.ts +64 -10
- package/src/deploy/platforms/cloudflare.ts +44 -3
- package/src/deploy/platforms/netlify.ts +34 -1
- package/src/deploy/platforms/node.ts +1 -0
- package/src/deploy/platforms/static.ts +1 -0
- package/src/deploy/platforms/types.ts +8 -0
- package/src/deploy/platforms/vercel.ts +38 -2
- package/src/deploy/redirects.ts +139 -36
- package/src/deploy/robots.ts +2 -2
- package/src/deploy/rss.ts +4 -3
- package/src/deploy/sitemap.ts +7 -5
- package/src/deploy/vercel-negotiation.ts +36 -0
- package/src/markdown/api-rail.ts +259 -0
- package/src/markdown/base-links.ts +34 -36
- package/src/markdown/code-title.ts +35 -9
- package/src/markdown/directives.ts +242 -36
- package/src/markdown/features.ts +20 -2
- package/src/markdown/fence-meta.ts +2 -0
- package/src/markdown/include.ts +11 -1
- package/src/markdown/index.ts +35 -11
- package/src/markdown/math.ts +4 -4
- package/src/markdown/mdast.ts +5 -2
- package/src/markdown/relative-links.ts +12 -4
- package/src/markdown/variables.ts +56 -0
- package/src/markdown/views.ts +82 -0
- package/src/narration/build.ts +412 -0
- package/src/narration/player.ts +249 -0
- package/src/narration/provider.ts +29 -0
- package/src/narration/script.ts +592 -0
- package/src/og/card.ts +136 -11
- package/src/og/derive.ts +41 -31
- package/src/og/index.ts +1 -0
- package/src/openapi/asyncapi.ts +4 -2
- package/src/openapi/model.ts +77 -36
- package/src/openapi/overlay.ts +256 -0
- package/src/openapi/parse.ts +55 -2
- package/src/openapi/proxy.ts +63 -10
- package/src/openapi/references.ts +21 -5
- package/src/openapi/render-mdx.ts +46 -3
- package/src/openapi/scalar.ts +40 -6
- package/src/openapi/source.ts +1 -1
- package/src/ratelimit/cloudflare.ts +54 -0
- package/src/ratelimit/index.ts +30 -0
- package/src/ratelimit/memory.ts +45 -0
- package/src/ratelimit/runtime.ts +229 -0
- package/src/ratelimit/schema.ts +28 -0
- package/src/ratelimit/upstash.ts +30 -0
- package/src/ratelimit/wrangler.ts +70 -0
- package/src/reference/asyncapi.ts +2 -2
- package/src/reference/graphql.ts +5 -2
- package/src/reference/openapi.ts +21 -7
- package/src/reference/options.ts +51 -7
- package/src/reference/scalar.ts +33 -8
- package/src/registry/eject.ts +201 -28
- package/src/registry/registry.ts +7 -0
- package/src/search/adapters/version-scope.ts +30 -0
- package/src/search/documents.ts +93 -28
- package/src/search/orama-index.ts +28 -3
- package/src/search/pagefind-ranking.ts +39 -0
- package/src/search/popular.ts +2 -1
- package/src/search/sync/algolia.ts +15 -4
- package/src/search/sync/orama-cloud.ts +3 -0
- package/src/search/sync/typesense.ts +5 -0
- package/src/seo/jsonld.ts +7 -3
- package/src/seo/metatags.ts +67 -0
- package/src/theme/chrome-icons.ts +1 -0
- package/src/theme/color.ts +500 -0
- package/src/theme/entry.ts +56 -3
- package/src/theme/palette.ts +121 -45
- package/src/translate/meta.ts +68 -24
- package/src/translate/prompts.ts +1 -0
- package/src/translate/run.ts +3 -3
- package/src/translate/validate.ts +12 -3
- package/src/translate/work-list.ts +56 -17
- package/src/upgrade/upgrade.ts +4 -171
- package/dist/cli/chunk-3yce002v.js.map +0 -14
- package/dist/cli/chunk-5r8g91qn.js.map +0 -34
- package/dist/cli/chunk-6dtt0zfn.js.map +0 -10
- package/dist/cli/chunk-7mbqtmgb.js.map +0 -10
- package/dist/cli/chunk-ddndchfr.js.map +0 -14
- package/dist/cli/chunk-esh98wmb.js +0 -23
- package/dist/cli/chunk-esh98wmb.js.map +0 -10
- package/dist/cli/chunk-hqp2ajnh.js.map +0 -35
- package/dist/cli/chunk-hr8ne106.js.map +0 -13
- package/dist/cli/chunk-j85scx15.js.map +0 -10
- package/dist/cli/chunk-mqc662a6.js +0 -75
- package/dist/cli/chunk-mqc662a6.js.map +0 -11
- package/dist/cli/chunk-pbg5a4s3.js.map +0 -19
- package/dist/cli/chunk-qkb5a8sa.js.map +0 -10
- package/dist/cli/chunk-v6ya5kcb.js.map +0 -189
- package/dist/cli/chunk-wdrt2k2v.js.map +0 -10
- package/dist/cli/chunk-xh43dwgw.js.map +0 -36
- package/docs/content/sources.mdx +0 -338
- /package/dist/cli/{chunk-zp79m0ts.js.map → chunk-1n228xqb.js.map} +0 -0
- /package/dist/cli/{chunk-h2ez8dzb.js.map → chunk-5ffywsmb.js.map} +0 -0
- /package/dist/cli/{chunk-g698a744.js.map → chunk-5wj2qwn2.js.map} +0 -0
- /package/dist/cli/{chunk-sqw4ekg1.js.map → chunk-amrb6hgh.js.map} +0 -0
- /package/dist/cli/{chunk-h7k3nq3v.js.map → chunk-gp84za0h.js.map} +0 -0
- /package/dist/cli/{chunk-bfwp9vp6.js.map → chunk-p804f3pe.js.map} +0 -0
- /package/dist/cli/{chunk-00gs3wqs.js.map → chunk-ta27feev.js.map} +0 -0
- /package/dist/cli/{chunk-bbnwccaz.js.map → chunk-y4ykbark.js.map} +0 -0
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/meta.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
1
2
|
import { readFile } from "node:fs/promises";
|
|
2
3
|
|
|
3
4
|
import { dirname, join, relative } from "pathe";
|
|
4
|
-
import { glob } from "tinyglobby";
|
|
5
5
|
|
|
6
|
+
import { localeTargetPath } from "../core/i18n.ts";
|
|
6
7
|
import { createModuleLoader } from "../core/load-module.ts";
|
|
8
|
+
import { findFolderMetaFiles } from "../core/meta.ts";
|
|
7
9
|
import type { BlumeProject } from "../core/project-graph.ts";
|
|
8
10
|
import { folderMetaSchema } from "../core/schema.ts";
|
|
9
|
-
import type { FolderMeta } from "../core/schema.ts";
|
|
11
|
+
import type { FolderMeta, ResolvedI18nConfig } from "../core/schema.ts";
|
|
10
12
|
import type { Diagnostic } from "../core/types.ts";
|
|
11
13
|
|
|
12
14
|
/**
|
|
@@ -37,7 +39,10 @@ export interface TranslatableMeta {
|
|
|
37
39
|
title: string;
|
|
38
40
|
}
|
|
39
41
|
|
|
40
|
-
|
|
42
|
+
/** A folder's meta module names, in the order a lookup prefers them. */
|
|
43
|
+
const META_NAMES = ["meta.ts", "meta.js", "meta.mjs"];
|
|
44
|
+
|
|
45
|
+
const META_FILES = META_NAMES.map((name) => `**/${name}`);
|
|
41
46
|
|
|
42
47
|
/**
|
|
43
48
|
* Whether a loaded meta module default-exports a factory function. Generic so
|
|
@@ -48,21 +53,44 @@ const isFactoryModule = <T>(
|
|
|
48
53
|
): value is T & ((...args: never[]) => FolderMeta) =>
|
|
49
54
|
typeof value === "function";
|
|
50
55
|
|
|
51
|
-
/**
|
|
56
|
+
/**
|
|
57
|
+
* Where a locale's meta module lives. The locale folder is resolved the way
|
|
58
|
+
* pages resolve it (`localeTargetPath`): `folders` are the content root's
|
|
59
|
+
* existing top-level folders, and one naming the locale in another casing
|
|
60
|
+
* (`pt-br/` for a configured `pt-BR`) is the locale's folder already. In that
|
|
61
|
+
* folder, a `meta.js`/`meta.mjs` that already exists is the target — the
|
|
62
|
+
* generated module is plain JavaScript, and writing a `meta.ts` beside it
|
|
63
|
+
* would leave the folder with two meta files. Otherwise it's a new `meta.ts`.
|
|
64
|
+
*/
|
|
52
65
|
export const metaTargetPath = (
|
|
53
66
|
meta: TranslatableMeta,
|
|
54
|
-
locale: string
|
|
55
|
-
|
|
67
|
+
locale: string,
|
|
68
|
+
i18n: ResolvedI18nConfig,
|
|
69
|
+
folders: readonly string[]
|
|
70
|
+
): string => {
|
|
71
|
+
const dir = join(
|
|
72
|
+
meta.contentRoot,
|
|
73
|
+
dirname(
|
|
74
|
+
localeTargetPath(join(meta.dir, "meta.ts"), ".ts", locale, i18n, folders)
|
|
75
|
+
)
|
|
76
|
+
);
|
|
77
|
+
const existing = META_NAMES.find((name) => existsSync(join(dir, name)));
|
|
78
|
+
return join(dir, existing ?? "meta.ts");
|
|
79
|
+
};
|
|
56
80
|
|
|
57
81
|
/**
|
|
58
82
|
* Discover the default-locale `meta.{ts,js,mjs}` files whose titles a
|
|
59
83
|
* translation run covers. Skips (in order): non-`dir` i18n projects entirely,
|
|
60
|
-
* files
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
84
|
+
* files the scan's own folder-meta discovery never reads either — those
|
|
85
|
+
* matching the source's `exclude` globs (application code) or in folders its
|
|
86
|
+
* `include` globs don't reach (see `findFolderMetaFiles`) — files inside a
|
|
87
|
+
* configured locale directory (those ARE translations), files inside an
|
|
88
|
+
* archived-version snapshot (frozen, with their own translations — the same
|
|
89
|
+
* folders the navigation's meta lookup hoists as versions), modules that fail
|
|
90
|
+
* to load (the scan already errors on those), factory-form modules (a warning
|
|
91
|
+
* — the generator can't re-emit a function), modules that fail meta
|
|
92
|
+
* validation (the scan already errors on those too), and modules with no
|
|
93
|
+
* `title` (nothing to translate).
|
|
66
94
|
*/
|
|
67
95
|
export const discoverTranslatableMeta = async (
|
|
68
96
|
project: BlumeProject
|
|
@@ -85,16 +113,26 @@ export const discoverTranslatableMeta = async (
|
|
|
85
113
|
const diagnostics: Diagnostic[] = [];
|
|
86
114
|
|
|
87
115
|
const roots = project.sources.flatMap((source) =>
|
|
88
|
-
source.staged || !source.contentRoot
|
|
116
|
+
source.staged || !source.contentRoot
|
|
117
|
+
? []
|
|
118
|
+
: [
|
|
119
|
+
{
|
|
120
|
+
contentRoot: source.contentRoot,
|
|
121
|
+
exclude: source.exclude,
|
|
122
|
+
include: source.include,
|
|
123
|
+
},
|
|
124
|
+
]
|
|
89
125
|
);
|
|
90
|
-
for (const contentRoot of roots) {
|
|
126
|
+
for (const { contentRoot, exclude, include } of roots) {
|
|
127
|
+
// The scan's own file set (`discoverFolderMeta`): a `meta.ts` under an
|
|
128
|
+
// excluded folder (`src/lib/meta.ts` beside `exclude: ["src/**"]`) is
|
|
129
|
+
// application code, and one in a folder no `include` glob reaches
|
|
130
|
+
// configures no group the build renders.
|
|
91
131
|
// oxlint-disable-next-line no-await-in-loop -- a project has O(1) sources
|
|
92
|
-
const files = await
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
onlyFiles: true,
|
|
97
|
-
});
|
|
132
|
+
const files = await findFolderMetaFiles(
|
|
133
|
+
{ exclude, include, root: contentRoot },
|
|
134
|
+
META_FILES
|
|
135
|
+
);
|
|
98
136
|
for (const file of files.toSorted()) {
|
|
99
137
|
const dir = relative(contentRoot, dirname(file));
|
|
100
138
|
const [head] = dir.split("/");
|
|
@@ -104,11 +142,17 @@ export const discoverTranslatableMeta = async (
|
|
|
104
142
|
) {
|
|
105
143
|
continue;
|
|
106
144
|
}
|
|
145
|
+
let mod: Awaited<ReturnType<typeof load>>;
|
|
146
|
+
try {
|
|
147
|
+
// oxlint-disable-next-line no-await-in-loop -- sequential, ordered discovery
|
|
148
|
+
mod = await load(file);
|
|
149
|
+
} catch {
|
|
150
|
+
// Folder meta that fails to load is the scan's BLUME_META_LOAD_FAILED
|
|
151
|
+
// error, not a crash here; either way there's no title to read.
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
107
154
|
// oxlint-disable-next-line no-await-in-loop -- sequential, ordered discovery
|
|
108
|
-
const
|
|
109
|
-
readFile(file, "utf-8"),
|
|
110
|
-
load(file),
|
|
111
|
-
]);
|
|
155
|
+
const raw = await readFile(file, "utf-8");
|
|
112
156
|
if (isFactoryModule(mod)) {
|
|
113
157
|
diagnostics.push({
|
|
114
158
|
code: "BLUME_TRANSLATE_META_FACTORY",
|
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
|
|
package/src/translate/run.ts
CHANGED
|
@@ -146,9 +146,9 @@ const runPageItem = async (
|
|
|
146
146
|
// SAFETY: `targets` maps every configured locale, and work items only carry
|
|
147
147
|
// configured locale codes.
|
|
148
148
|
const target = context.targets.get(item.locale) as LocaleConfig;
|
|
149
|
-
// A
|
|
150
|
-
//
|
|
151
|
-
//
|
|
149
|
+
// A stale item's target is the existing translation's own file, even at a
|
|
150
|
+
// non-canonical name (see `PageWorkItem.targetPath`), so it's the style
|
|
151
|
+
// precedent and the file rewritten; a missing item has nothing to read.
|
|
152
152
|
const previousTranslation = existsSync(item.targetPath)
|
|
153
153
|
? await readFile(item.targetPath, "utf-8")
|
|
154
154
|
: undefined;
|
|
@@ -32,7 +32,10 @@ interface FrontmatterData {
|
|
|
32
32
|
[key: string]: FrontmatterValue;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
// gray-matter strips a leading byte order mark before it looks for the fence,
|
|
36
|
+
// so a BOM-prefixed file still has frontmatter — this test must agree, or the
|
|
37
|
+
// reconstruction below writes the body alone and the metadata is lost.
|
|
38
|
+
const FRONTMATTER_OPEN = /^?---\r?\n/u;
|
|
36
39
|
const FENCE_LINE = /^\s*(?:```|~~~)/u;
|
|
37
40
|
|
|
38
41
|
/**
|
|
@@ -129,8 +132,14 @@ export const validateTranslation = (
|
|
|
129
132
|
let parsed: { content: string; data: FrontmatterData };
|
|
130
133
|
try {
|
|
131
134
|
parsed = matter(candidate);
|
|
132
|
-
} catch {
|
|
133
|
-
|
|
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
|
+
};
|
|
134
143
|
}
|
|
135
144
|
|
|
136
145
|
const rawBody = ensureTrailingNewline(parsed.content.replace(/^\r?\n/u, ""));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, readdirSync } from "node:fs";
|
|
2
2
|
import { readFile } from "node:fs/promises";
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { extname, join, relative } from "pathe";
|
|
5
5
|
|
|
6
6
|
import { localeCodes, localeTargetPath } from "../core/i18n.ts";
|
|
7
7
|
import { scanProject } from "../core/project-graph.ts";
|
|
@@ -35,7 +35,11 @@ export interface PageWorkItem {
|
|
|
35
35
|
/** POSIX root-relative source path — the ledger key. */
|
|
36
36
|
sourceRel: string;
|
|
37
37
|
status: WorkStatus;
|
|
38
|
-
/**
|
|
38
|
+
/**
|
|
39
|
+
* Absolute target path: an existing translation's own file (which can sit
|
|
40
|
+
* at a non-canonical name, like a hand-written `fr/guide.md` for
|
|
41
|
+
* `guide.mdx`), otherwise the canonical `localeTargetPath`.
|
|
42
|
+
*/
|
|
39
43
|
targetPath: string;
|
|
40
44
|
/** POSIX root-relative target path, for display. */
|
|
41
45
|
targetRel: string;
|
|
@@ -49,7 +53,7 @@ export interface PageWorkItem {
|
|
|
49
53
|
export interface MetaWorkEntry {
|
|
50
54
|
meta: TranslatableMeta;
|
|
51
55
|
status: WorkStatus;
|
|
52
|
-
/** Absolute path of the
|
|
56
|
+
/** Absolute path of the per-locale meta module (see `metaTargetPath`). */
|
|
53
57
|
targetPath: string;
|
|
54
58
|
}
|
|
55
59
|
|
|
@@ -283,6 +287,37 @@ const partialWorkItems = async (
|
|
|
283
287
|
return work;
|
|
284
288
|
};
|
|
285
289
|
|
|
290
|
+
/**
|
|
291
|
+
* Every existing translation, keyed by `translationKey` and locale, with the
|
|
292
|
+
* file it was read from when that file is on disk in a filesystem source. A
|
|
293
|
+
* retranslation writes there: an adopted hand-written `fr/guide.md` for a
|
|
294
|
+
* `guide.mdx` source is replaced in place, never joined by a canonical
|
|
295
|
+
* `fr/guide.mdx` that would publish the route twice.
|
|
296
|
+
*/
|
|
297
|
+
const existingTranslations = (
|
|
298
|
+
project: BlumeProject
|
|
299
|
+
): Map<string, string | undefined> => {
|
|
300
|
+
const writableSources = new Set(
|
|
301
|
+
project.sources.flatMap((source) =>
|
|
302
|
+
source.staged || !source.contentRoot ? [] : [source.name]
|
|
303
|
+
)
|
|
304
|
+
);
|
|
305
|
+
const translated = new Map<string, string | undefined>();
|
|
306
|
+
for (const page of project.graph.pages) {
|
|
307
|
+
const key = `${page.translationKey}\0${page.locale}`;
|
|
308
|
+
if (page.fallback || translated.has(key)) {
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
translated.set(
|
|
312
|
+
key,
|
|
313
|
+
page.sourcePath && writableSources.has(page.source.name)
|
|
314
|
+
? page.sourcePath
|
|
315
|
+
: undefined
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
return translated;
|
|
319
|
+
};
|
|
320
|
+
|
|
286
321
|
/**
|
|
287
322
|
* Compute the run's work: which (source, locale) pairs are missing or stale,
|
|
288
323
|
* which existing translations to adopt, and what's already up to date.
|
|
@@ -310,11 +345,7 @@ export const computeWorkList = async (
|
|
|
310
345
|
(options.locales === undefined || options.locales.includes(code))
|
|
311
346
|
);
|
|
312
347
|
|
|
313
|
-
const translated =
|
|
314
|
-
project.graph.pages.flatMap((page) =>
|
|
315
|
-
page.fallback ? [] : [`${page.translationKey}${page.locale}`]
|
|
316
|
-
)
|
|
317
|
-
);
|
|
348
|
+
const translated = existingTranslations(project);
|
|
318
349
|
|
|
319
350
|
const { root } = project.context;
|
|
320
351
|
const knownSources = new Set<string>();
|
|
@@ -333,10 +364,13 @@ export const computeWorkList = async (
|
|
|
333
364
|
const contentRel = relative(contentRoot, sourcePath);
|
|
334
365
|
|
|
335
366
|
for (const locale of targetLocales) {
|
|
336
|
-
const
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
367
|
+
const key = `${page.translationKey}\0${locale}`;
|
|
368
|
+
const targetPath =
|
|
369
|
+
translated.get(key) ??
|
|
370
|
+
join(
|
|
371
|
+
contentRoot,
|
|
372
|
+
localeTargetPath(contentRel, ext, locale, i18n, folders(contentRoot))
|
|
373
|
+
);
|
|
340
374
|
const item = (status: WorkStatus): PageWorkItem => ({
|
|
341
375
|
kind: "page",
|
|
342
376
|
locale,
|
|
@@ -346,7 +380,7 @@ export const computeWorkList = async (
|
|
|
346
380
|
targetPath,
|
|
347
381
|
targetRel: relative(root, targetPath),
|
|
348
382
|
});
|
|
349
|
-
const exists = translated.has(
|
|
383
|
+
const exists = translated.has(key);
|
|
350
384
|
const stamp = ledger.files[sourceRel]?.[locale];
|
|
351
385
|
const outcome = classifyPair(exists, stamp, hash, options.force === true);
|
|
352
386
|
if (outcome === "untracked") {
|
|
@@ -380,16 +414,21 @@ export const computeWorkList = async (
|
|
|
380
414
|
const entries: MetaWorkEntry[] = [];
|
|
381
415
|
for (const source of meta.metas) {
|
|
382
416
|
knownSources.add(source.sourceRel);
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
417
|
+
// The locale folder's existing meta module when there is one, so a
|
|
418
|
+
// retranslation rewrites it instead of adding a `meta.ts` beside it.
|
|
419
|
+
const targetPath = metaTargetPath(
|
|
420
|
+
source,
|
|
421
|
+
locale,
|
|
422
|
+
i18n,
|
|
423
|
+
folders(source.contentRoot)
|
|
386
424
|
);
|
|
425
|
+
const exists = existsSync(targetPath);
|
|
387
426
|
const hash = hashSource(source.raw);
|
|
388
427
|
const stamp = ledger.files[source.sourceRel]?.[locale];
|
|
389
428
|
const entry = (status: WorkStatus): MetaWorkEntry => ({
|
|
390
429
|
meta: source,
|
|
391
430
|
status,
|
|
392
|
-
targetPath
|
|
431
|
+
targetPath,
|
|
393
432
|
});
|
|
394
433
|
const outcome = classifyPair(exists, stamp, hash, options.force === true);
|
|
395
434
|
if (outcome === "untracked") {
|