blume 2.1.3 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -1
- package/CHANGELOG.md +134 -0
- package/README.md +4 -4
- package/dist/cli/{chunk-y4msrwm9.js → chunk-080mfch6.js} +15 -15
- package/dist/cli/{chunk-gfc5fqvf.js → chunk-1ch3ct3r.js} +18 -18
- package/dist/cli/{chunk-gfc5fqvf.js.map → chunk-1ch3ct3r.js.map} +1 -1
- package/dist/cli/{chunk-32khwcb6.js → chunk-2ssh60qh.js} +42 -69
- package/dist/cli/{chunk-32khwcb6.js.map → chunk-2ssh60qh.js.map} +9 -10
- package/dist/cli/{chunk-9qzgg6mj.js → chunk-34wap3ed.js} +3 -3
- package/dist/cli/{chunk-k3gr1nm9.js → chunk-40vk8kgf.js} +13 -16
- package/dist/cli/{chunk-k3gr1nm9.js.map → chunk-40vk8kgf.js.map} +3 -3
- package/dist/cli/chunk-487b95qy.js +329 -0
- package/dist/cli/chunk-487b95qy.js.map +13 -0
- package/dist/cli/chunk-4zxh25hc.js +157 -0
- package/dist/cli/chunk-4zxh25hc.js.map +10 -0
- package/dist/cli/chunk-69rjf786.js +146 -0
- package/dist/cli/chunk-69rjf786.js.map +11 -0
- package/dist/cli/{chunk-dqhg54mr.js → chunk-9h8mh2tk.js} +3 -3
- package/dist/cli/{chunk-dqhg54mr.js.map → chunk-9h8mh2tk.js.map} +2 -2
- package/dist/cli/{chunk-bqxaqn5p.js → chunk-9jqmq5hv.js} +8 -8
- package/dist/cli/{chunk-bqxaqn5p.js.map → chunk-9jqmq5hv.js.map} +1 -1
- package/dist/cli/{chunk-dv2z0rzf.js → chunk-aafhwx74.js} +38 -13
- package/dist/cli/{chunk-dv2z0rzf.js.map → chunk-aafhwx74.js.map} +5 -4
- package/dist/cli/{chunk-desvm72z.js → chunk-b680sv30.js} +22 -26
- package/dist/cli/chunk-b680sv30.js.map +13 -0
- package/dist/cli/{chunk-0w6hs479.js → chunk-beb0z983.js} +30 -18
- package/dist/cli/chunk-beb0z983.js.map +10 -0
- package/dist/cli/{chunk-1f882900.js → chunk-c5bjxq8v.js} +2 -2
- package/dist/cli/chunk-e1n41w9m.js +155 -0
- package/dist/cli/chunk-e1n41w9m.js.map +11 -0
- package/dist/cli/{chunk-sc93apfs.js → chunk-etckvbrh.js} +17 -17
- package/dist/cli/{chunk-sc93apfs.js.map → chunk-etckvbrh.js.map} +2 -2
- package/dist/cli/{chunk-bxwhtvw8.js → chunk-f260jdrn.js} +5 -5
- package/dist/cli/{chunk-74wfhv79.js → chunk-fnxgtjeq.js} +1 -1
- package/dist/cli/{chunk-ms9z66nz.js → chunk-gwy55cx3.js} +2 -2
- package/dist/cli/{chunk-ms9z66nz.js.map → chunk-gwy55cx3.js.map} +2 -2
- package/dist/cli/{chunk-dhwtqnnd.js → chunk-gxhcf2hs.js} +2 -2
- package/dist/cli/{chunk-tfycddbt.js → chunk-h0qwdbem.js} +2 -2
- package/dist/cli/{chunk-nbyvgnnm.js → chunk-hktq4j5r.js} +109 -49
- package/dist/cli/chunk-hktq4j5r.js.map +36 -0
- package/dist/cli/{chunk-twy7psdz.js → chunk-hn3g2b89.js} +14 -10
- package/dist/cli/chunk-hn3g2b89.js.map +10 -0
- package/dist/cli/{chunk-j1x92mx9.js → chunk-j4nfgn2j.js} +1 -1
- package/dist/cli/{chunk-dpy8qdjf.js → chunk-k45sq16q.js} +74 -183
- package/dist/cli/chunk-k45sq16q.js.map +18 -0
- package/dist/cli/{chunk-5cmts6dv.js → chunk-kmswjxj9.js} +7 -7
- package/dist/cli/{chunk-5cmts6dv.js.map → chunk-kmswjxj9.js.map} +1 -1
- package/dist/cli/{chunk-36bxs9c7.js → chunk-nqna8dzp.js} +27 -23
- package/dist/cli/chunk-nqna8dzp.js.map +10 -0
- package/dist/cli/{chunk-a57yh0h9.js → chunk-p834rkcn.js} +7 -7
- package/dist/cli/{chunk-a57yh0h9.js.map → chunk-p834rkcn.js.map} +1 -1
- package/dist/cli/{chunk-60hz265r.js → chunk-ppa6mg4d.js} +24 -11
- package/dist/cli/chunk-ppa6mg4d.js.map +10 -0
- package/dist/cli/{chunk-s0bdnc7v.js → chunk-q1wwrxzw.js} +5 -4
- package/dist/cli/chunk-q1wwrxzw.js.map +10 -0
- package/dist/cli/{chunk-ave1wcbr.js → chunk-qcyxkj44.js} +1 -1
- package/dist/cli/{chunk-124fvmzq.js → chunk-r5nm9w0c.js} +11183 -8806
- package/dist/cli/{chunk-124fvmzq.js.map → chunk-r5nm9w0c.js.map} +82 -66
- package/dist/cli/{chunk-ckrcm08h.js → chunk-rtvgmg2j.js} +48 -62
- package/dist/cli/{chunk-ckrcm08h.js.map → chunk-rtvgmg2j.js.map} +4 -5
- package/dist/cli/{chunk-297ajdcv.js → chunk-t2h8pwy1.js} +6 -6
- package/dist/cli/{chunk-297ajdcv.js.map → chunk-t2h8pwy1.js.map} +3 -3
- package/dist/cli/{chunk-gxtg6ed2.js → chunk-x60e15st.js} +21 -21
- package/dist/cli/{chunk-gxtg6ed2.js.map → chunk-x60e15st.js.map} +3 -3
- package/dist/cli/{chunk-58bt3hag.js → chunk-x7bh6d9j.js} +4 -4
- package/dist/cli/{chunk-hvcxng5f.js → chunk-ydqzkhjn.js} +6 -6
- package/dist/cli/{chunk-kdpzw38a.js → chunk-yg8ckc3g.js} +95 -7
- package/dist/cli/chunk-yg8ckc3g.js.map +11 -0
- package/dist/cli/{chunk-0pmb4tr4.js → chunk-zxd5jrgx.js} +1205 -222
- package/dist/cli/chunk-zxd5jrgx.js.map +44 -0
- package/dist/cli/index.js +78 -42
- package/dist/cli/index.js.map +7 -6
- package/dist/types/ai/changelog-components.d.ts +18 -0
- package/dist/types/ai/changelog-markdown.d.ts +12 -0
- package/dist/types/ai/openapi-components.d.ts +7 -7
- package/dist/types/ai/operation-details.d.ts +39 -0
- package/dist/types/ai/relative-links.d.ts +3 -1
- package/dist/types/ai/serializers.d.ts +6 -4
- package/dist/types/analytics/head.d.ts +4 -2
- package/dist/types/analytics/script.d.ts +8 -2
- package/dist/types/components/content/youtube.d.ts +20 -0
- package/dist/types/components/layout/nav-utils.d.ts +8 -0
- package/dist/types/components/openapi/example-panels.d.ts +33 -0
- package/dist/types/components/openapi/helpers.d.ts +53 -11
- package/dist/types/components/openapi/snippets.d.ts +7 -1
- package/dist/types/core/alert-diagnostics.d.ts +10 -0
- package/dist/types/core/builtin-tags.d.ts +16 -0
- package/dist/types/core/changelog-list.d.ts +48 -0
- package/dist/types/core/closest-match.d.ts +6 -0
- package/dist/types/core/code-fence-diagnostics.d.ts +18 -0
- package/dist/types/core/code-fences.d.ts +8 -1
- package/dist/types/core/config-input.d.ts +38 -6
- package/dist/types/core/content-assets.d.ts +16 -18
- package/dist/types/core/data.d.ts +6 -2
- package/dist/types/core/diagnostics.d.ts +14 -0
- package/dist/types/core/directive-diagnostics.d.ts +22 -8
- package/dist/types/core/former-routes.d.ts +14 -0
- package/dist/types/core/github.d.ts +5 -4
- package/dist/types/core/heading-markers.d.ts +65 -2
- package/dist/types/core/hidden-pages.d.ts +3 -0
- package/dist/types/core/includes.d.ts +23 -0
- package/dist/types/core/last-modified.d.ts +18 -6
- package/dist/types/core/links.d.ts +42 -2
- package/dist/types/core/load-module.d.ts +19 -4
- package/dist/types/core/manifest.d.ts +14 -1
- package/dist/types/core/markdown-mirrors.d.ts +22 -0
- package/dist/types/core/mcp-clients.d.ts +47 -0
- package/dist/types/core/mdx-elements.d.ts +32 -0
- package/dist/types/core/mdx-syntax.d.ts +100 -0
- package/dist/types/core/meta-diagnostics.d.ts +7 -0
- package/dist/types/core/meta.d.ts +32 -5
- package/dist/types/core/nav-diagnostics.d.ts +16 -2
- package/dist/types/core/navigation.d.ts +13 -0
- package/dist/types/core/ordering-prefix.d.ts +6 -0
- package/dist/types/core/pinned-ids.d.ts +23 -0
- package/dist/types/core/project-graph.d.ts +9 -1
- package/dist/types/core/redirect-patterns.d.ts +18 -0
- package/dist/types/core/relative-files.d.ts +31 -0
- package/dist/types/core/schema.d.ts +322 -11
- package/dist/types/core/sources/normalize.d.ts +101 -9
- package/dist/types/core/sources/types.d.ts +16 -0
- package/dist/types/core/static-files.d.ts +10 -0
- package/dist/types/core/static-host.d.ts +42 -0
- package/dist/types/core/svg-images.d.ts +26 -0
- package/dist/types/core/syntax-diagnostics.d.ts +14 -0
- package/dist/types/core/types.d.ts +42 -1
- package/dist/types/deploy/generated-files.d.ts +41 -0
- package/dist/types/deploy/redirects.d.ts +21 -7
- package/dist/types/markdown/code-title.d.ts +9 -5
- package/dist/types/markdown/directives.d.ts +8 -0
- package/dist/types/markdown/fence-language.d.ts +51 -0
- package/dist/types/markdown/fence-meta.d.ts +5 -0
- package/dist/types/markdown/github-alerts.d.ts +35 -0
- package/dist/types/openapi/asyncapi.d.ts +6 -5
- package/dist/types/openapi/checks.d.ts +10 -5
- package/dist/types/openapi/model.d.ts +55 -8
- package/dist/types/openapi/parse.d.ts +4 -1
- package/dist/types/ratelimit/index.d.ts +2 -0
- package/dist/types/ratelimit/memory.d.ts +1 -1
- package/dist/types/ratelimit/schema.d.ts +40 -0
- package/dist/types/ratelimit/unkey.d.ts +48 -0
- package/dist/types/sources/filesystem.d.ts +14 -4
- package/dist/types/sources/mdx-remote.d.ts +6 -3
- package/dist/types/sources/registry.d.ts +3 -3
- package/dist/types/theme/color.d.ts +33 -0
- package/dist/types/theme/palette.d.ts +122 -0
- package/docs/01-quickstart.mdx +1 -1
- package/docs/02-deployment.mdx +24 -8
- package/docs/04-migrating.mdx +16 -4
- package/docs/advanced/changelog.mdx +27 -1
- package/docs/advanced/skills.mdx +1 -1
- package/docs/cli/audit.mdx +1 -1
- package/docs/cli/doctor.mdx +2 -2
- package/docs/cli/evals.mdx +1 -1
- package/docs/cli/index.mdx +4 -2
- package/docs/cli/validate.mdx +10 -7
- package/docs/configuration/analytics.mdx +2 -0
- package/docs/configuration/customization.mdx +3 -1
- package/docs/configuration/index.mdx +7 -6
- package/docs/configuration/rate-limiting.mdx +20 -1
- package/docs/configuration/theming.mdx +5 -1
- package/docs/content/components.mdx +26 -6
- package/docs/content/frontmatter.mdx +1 -1
- package/docs/content/i18n.mdx +1 -1
- package/docs/content/includes.mdx +6 -2
- package/docs/content/index.mdx +11 -1
- package/docs/content/islands.mdx +2 -0
- package/docs/content/meta.mdx +9 -3
- package/docs/content/navigation.mdx +14 -6
- package/docs/content/sources/obsidian.mdx +1 -1
- package/docs/content/sources/remote-mdx.mdx +3 -1
- package/docs/content/syntax.mdx +76 -8
- package/docs/content/variables.mdx +3 -1
- package/docs/discoverability/agent-discovery.mdx +1 -1
- package/docs/discoverability/json-api.mdx +1 -1
- package/docs/discoverability/llms-txt.mdx +1 -1
- package/docs/discoverability/markdown.mdx +2 -2
- package/docs/discoverability/mcp.mdx +40 -8
- package/docs/discoverability/open-graph.mdx +1 -1
- package/docs/discoverability/sitemap-and-robots.mdx +1 -1
- package/docs/references/graphql.mdx +2 -0
- package/docs/references/openapi.mdx +45 -7
- package/package.json +4 -4
- package/skills/blume/SKILL.md +2 -2
- package/skills/blume-migrate/SKILL.md +51 -29
- package/skills/blume-migrate/references/docsify.md +262 -0
- package/skills/blume-migrate/references/docus.md +298 -0
- package/skills/blume-migrate/references/docusaurus.md +5 -5
- package/skills/blume-migrate/references/fern.md +327 -0
- package/skills/blume-migrate/references/fumadocs.md +1 -1
- package/skills/blume-migrate/references/gitbook.md +267 -0
- package/skills/blume-migrate/references/github-wiki.md +259 -0
- package/skills/blume-migrate/references/jekyll.md +253 -0
- package/skills/blume-migrate/references/mdbook.md +256 -0
- package/skills/blume-migrate/references/mintlify.md +5 -5
- package/skills/blume-migrate/references/mkdocs.md +236 -0
- package/skills/blume-migrate/references/monorepo.md +20 -8
- package/skills/blume-migrate/references/nextra.md +5 -5
- package/skills/blume-migrate/references/readme.md +257 -0
- package/skills/blume-migrate/references/redocly.md +198 -0
- package/skills/blume-migrate/references/starlight.md +3 -3
- package/skills/blume-migrate/references/vitepress.md +204 -0
- package/skills/blume-migrate/references/vuepress.md +271 -0
- package/skills/blume-migrate/scripts/docsify-codemod.mjs +2387 -0
- package/skills/blume-migrate/scripts/docus-codemod.mjs +2542 -0
- package/skills/blume-migrate/scripts/fern-codemod.mjs +2633 -0
- package/skills/blume-migrate/scripts/github-wiki-codemod.mjs +2808 -0
- package/skills/blume-migrate/scripts/include-excerpts.mjs +649 -0
- package/skills/blume-migrate/scripts/jekyll-codemod.mjs +3649 -0
- package/skills/blume-migrate/scripts/mintlify-codemod.mjs +17 -13
- package/skills/blume-migrate/scripts/mkdocs-codemod.mjs +2526 -0
- package/skills/blume-migrate/scripts/operation-routes.mjs +508 -0
- package/skills/blume-migrate/scripts/pin-heading-ids.mjs +1049 -0
- package/skills/blume-migrate/scripts/readme-codemod.mjs +4139 -0
- package/skills/blume-migrate/scripts/vitepress-codemod.mjs +1511 -0
- package/src/ai/changelog-components.ts +24 -0
- package/src/ai/changelog-markdown.ts +45 -41
- package/src/ai/component-markdown.ts +22 -9
- package/src/ai/llms.ts +36 -5
- package/src/ai/markdown.ts +2 -2
- package/src/ai/openapi-components.ts +25 -9
- package/src/ai/operation-details.ts +208 -0
- package/src/ai/relative-links.ts +48 -8
- package/src/ai/serializers.ts +7 -6
- package/src/ai/site-skill.ts +6 -2
- package/src/analytics/head.ts +11 -5
- package/src/analytics/script.ts +13 -3
- package/src/astro/generate.ts +47 -11
- package/src/astro/index.ts +1 -0
- package/src/astro/integration.ts +27 -1
- package/src/astro/mdx-source-errors.ts +46 -0
- package/src/astro/templates.ts +93 -189
- package/src/audit/checks/redirects.ts +5 -1
- package/src/audit/redirects.ts +36 -19
- package/src/audit/report.ts +22 -9
- package/src/audit/run.ts +12 -28
- package/src/audit/terms.ts +23 -0
- package/src/audit/url.ts +2 -2
- package/src/cli/build-failure.ts +256 -7
- package/src/cli/command-meta.ts +1 -1
- package/src/cli/commands/audit.ts +1 -1
- package/src/cli/commands/build.ts +12 -3
- package/src/cli/commands/check.ts +13 -2
- package/src/cli/commands/dev.ts +1 -1
- package/src/cli/commands/doctor.ts +4 -2
- package/src/cli/commands/init.ts +3 -3
- package/src/cli/commands/preview.ts +17 -1
- package/src/cli/commands/validate.ts +22 -10
- package/src/cli/prepare.ts +1 -1
- package/src/cli/preview-pages.ts +161 -0
- package/src/cli/required-secrets.ts +0 -1
- package/src/cli/unknown-flags.ts +1 -42
- package/src/components/code-copy.ts +51 -0
- package/src/components/code-language.ts +75 -0
- package/src/components/content/AccordionItem.astro +16 -1
- package/src/components/content/Callout.astro +11 -1
- package/src/components/content/Changelog.astro +189 -0
- package/src/components/content/CodeBlock.astro +8 -11
- package/src/components/content/Tabs.astro +16 -2
- package/src/components/content/YouTube.astro +6 -4
- package/src/components/content/code-block.ts +33 -0
- package/src/components/content/content-strings.ts +5 -1
- package/src/components/content/inline-markdown.ts +35 -8
- package/src/components/content/youtube.ts +49 -7
- package/src/components/layout/Analytics.astro +5 -1
- package/src/components/layout/NavTree.astro +8 -3
- package/src/components/layout/PageActions.astro +81 -23
- package/src/components/layout/RootLayout.astro +35 -32
- package/src/components/layout/SiteFooter.astro +31 -8
- package/src/components/layout/nav-utils.ts +14 -0
- package/src/components/layout/search/pagefind.ts +2 -1
- package/src/components/openapi/Operation.astro +4 -0
- package/src/components/openapi/PanelTabs.astro +9 -3
- package/src/components/openapi/RequestBody.astro +42 -8
- package/src/components/openapi/RequestPanel.astro +34 -53
- package/src/components/openapi/example-panels.ts +110 -0
- package/src/components/openapi/helpers.ts +195 -20
- package/src/components/openapi/operation-model.ts +63 -26
- package/src/components/openapi/request.ts +13 -0
- package/src/components/openapi/snippets.ts +14 -2
- package/src/core/alert-diagnostics.ts +89 -0
- package/src/core/builtin-tags.ts +76 -0
- package/src/core/changelog-list.ts +87 -0
- package/src/core/closest-match.ts +41 -0
- package/src/core/code-fence-diagnostics.ts +267 -0
- package/src/core/code-fences.ts +43 -7
- package/src/core/component-diagnostics.ts +65 -12
- package/src/core/config-input.ts +39 -5
- package/src/core/config.ts +46 -1
- package/src/core/content-assets.ts +64 -144
- package/src/core/data.ts +10 -3
- package/src/core/diagnostics.ts +36 -3
- package/src/core/directive-diagnostics.ts +265 -47
- package/src/core/former-routes.ts +46 -0
- package/src/core/git-ignored.ts +53 -0
- package/src/core/github.ts +5 -4
- package/src/core/heading-markers.ts +156 -2
- package/src/core/hidden-pages.ts +64 -0
- package/src/core/includes.ts +181 -41
- package/src/core/last-modified.ts +47 -10
- package/src/core/links.ts +438 -83
- package/src/core/load-module.ts +98 -9
- package/src/core/manifest.ts +12 -9
- package/src/core/markdown-mirrors.ts +52 -0
- package/src/core/mcp-clients.ts +87 -0
- package/src/core/mdx-elements.ts +153 -0
- package/src/core/mdx-syntax.ts +377 -0
- package/src/core/meta-diagnostics.ts +134 -0
- package/src/core/meta.ts +154 -55
- package/src/core/nav-diagnostics.ts +41 -4
- package/src/core/navigation.ts +70 -10
- package/src/core/ordering-prefix.ts +22 -2
- package/src/core/pinned-ids.ts +141 -0
- package/src/core/project-graph.ts +221 -29
- package/src/core/redirect-patterns.ts +41 -0
- package/src/core/relative-files.ts +145 -0
- package/src/core/schema.ts +110 -6
- package/src/core/sources/mdx-remote.ts +75 -14
- package/src/core/sources/normalize.ts +885 -179
- package/src/core/sources/notion.ts +5 -4
- package/src/core/sources/obsidian.ts +2 -5
- package/src/core/sources/types.ts +17 -0
- package/src/core/static-files.ts +40 -0
- package/src/core/static-host.ts +125 -0
- package/src/core/svg-images.ts +98 -0
- package/src/core/syntax-diagnostics.ts +491 -0
- package/src/core/types.ts +43 -1
- package/src/deploy/artifacts.ts +2 -28
- package/src/deploy/generated-files.ts +128 -0
- package/src/deploy/platforms/vercel.ts +25 -1
- package/src/deploy/redirects.ts +43 -16
- package/src/deploy/sitemap.ts +2 -1
- package/src/markdown/base-links.ts +87 -6
- package/src/markdown/code-title.ts +29 -13
- package/src/markdown/content-assets.ts +210 -0
- package/src/markdown/directives.ts +69 -5
- package/src/markdown/fence-language.ts +106 -0
- package/src/markdown/fence-meta.ts +42 -0
- package/src/markdown/github-alerts.ts +172 -0
- package/src/markdown/heading-anchors.ts +265 -56
- package/src/markdown/include.ts +30 -3
- package/src/markdown/index.ts +145 -40
- package/src/markdown/prompt-text.ts +95 -0
- package/src/markdown/relative-links.ts +37 -2
- package/src/markdown/route-snapshot.ts +22 -12
- package/src/markdown/svg-fallback.ts +51 -0
- package/src/markdown/title-heading.ts +134 -0
- package/src/migrate/migrate.ts +127 -2
- package/src/og/card.ts +14 -4
- package/src/openapi/asyncapi.ts +14 -6
- package/src/openapi/checks.ts +160 -15
- package/src/openapi/model.ts +172 -33
- package/src/openapi/parse.ts +13 -4
- package/src/openapi/render-mdx.ts +55 -9
- package/src/openapi/source.ts +87 -6
- package/src/ratelimit/index.ts +2 -0
- package/src/ratelimit/memory.ts +1 -1
- package/src/ratelimit/runtime.ts +81 -0
- package/src/ratelimit/schema.ts +2 -0
- package/src/ratelimit/unkey.ts +61 -0
- package/src/registry/eject.ts +0 -1
- package/src/registry/registry.ts +1 -1
- package/src/search/documents.ts +10 -2
- package/src/sources/filesystem.ts +28 -3
- package/src/sources/mdx-remote.ts +7 -15
- package/src/theme/color.ts +14 -0
- package/src/theme/entry.ts +22 -1
- package/src/theme/palette.ts +74 -1
- package/dist/cli/chunk-0pmb4tr4.js.map +0 -35
- package/dist/cli/chunk-0w6hs479.js.map +0 -10
- package/dist/cli/chunk-150jk7km.js +0 -52
- package/dist/cli/chunk-150jk7km.js.map +0 -10
- package/dist/cli/chunk-36bxs9c7.js.map +0 -10
- package/dist/cli/chunk-53jqw8z0.js +0 -89
- package/dist/cli/chunk-53jqw8z0.js.map +0 -10
- package/dist/cli/chunk-60hz265r.js.map +0 -10
- package/dist/cli/chunk-desvm72z.js.map +0 -14
- package/dist/cli/chunk-dpy8qdjf.js.map +0 -17
- package/dist/cli/chunk-es8h0v3j.js +0 -441
- package/dist/cli/chunk-es8h0v3j.js.map +0 -11
- package/dist/cli/chunk-kdpzw38a.js.map +0 -11
- package/dist/cli/chunk-nbyvgnnm.js.map +0 -36
- package/dist/cli/chunk-s0bdnc7v.js.map +0 -10
- package/dist/cli/chunk-twy7psdz.js.map +0 -10
- package/dist/cli/chunk-ydp3065p.js +0 -64
- package/dist/cli/chunk-ydp3065p.js.map +0 -10
- /package/dist/cli/{chunk-y4msrwm9.js.map → chunk-080mfch6.js.map} +0 -0
- /package/dist/cli/{chunk-9qzgg6mj.js.map → chunk-34wap3ed.js.map} +0 -0
- /package/dist/cli/{chunk-1f882900.js.map → chunk-c5bjxq8v.js.map} +0 -0
- /package/dist/cli/{chunk-bxwhtvw8.js.map → chunk-f260jdrn.js.map} +0 -0
- /package/dist/cli/{chunk-74wfhv79.js.map → chunk-fnxgtjeq.js.map} +0 -0
- /package/dist/cli/{chunk-dhwtqnnd.js.map → chunk-gxhcf2hs.js.map} +0 -0
- /package/dist/cli/{chunk-tfycddbt.js.map → chunk-h0qwdbem.js.map} +0 -0
- /package/dist/cli/{chunk-j1x92mx9.js.map → chunk-j4nfgn2j.js.map} +0 -0
- /package/dist/cli/{chunk-ave1wcbr.js.map → chunk-qcyxkj44.js.map} +0 -0
- /package/dist/cli/{chunk-58bt3hag.js.map → chunk-x7bh6d9j.js.map} +0 -0
- /package/dist/cli/{chunk-hvcxng5f.js.map → chunk-ydqzkhjn.js.map} +0 -0
package/src/ratelimit/runtime.ts
CHANGED
|
@@ -11,11 +11,14 @@
|
|
|
11
11
|
* the shared store fails to count (logged, not blocked). A shared store
|
|
12
12
|
* without its secrets or binding falls back to counting in memory.
|
|
13
13
|
*/
|
|
14
|
+
import { z } from "zod";
|
|
15
|
+
|
|
14
16
|
import { clientAddressOf } from "../core/client-address.ts";
|
|
15
17
|
import type { ClientContext } from "../core/client-address.ts";
|
|
16
18
|
import { RATE_LIMIT_BINDING } from "./cloudflare.ts";
|
|
17
19
|
import { DEFAULT_REQUESTS, DEFAULT_WINDOW } from "./memory.ts";
|
|
18
20
|
import type { RateLimitAdapter } from "./schema.ts";
|
|
21
|
+
import { UNKEY_MAX_WINDOW, UNKEY_NAMESPACE, unkeySecrets } from "./unkey.ts";
|
|
19
22
|
import { upstashSecrets } from "./upstash.ts";
|
|
20
23
|
|
|
21
24
|
/** What a limiter says about one request. */
|
|
@@ -152,6 +155,68 @@ export const upstashLimiter = (
|
|
|
152
155
|
};
|
|
153
156
|
};
|
|
154
157
|
|
|
158
|
+
/** Unkey's rate limit endpoint. */
|
|
159
|
+
const UNKEY_LIMIT_URL = "https://api.unkey.com/v2/ratelimit.limit";
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* How long Unkey gets to count a request, in milliseconds, before the
|
|
163
|
+
* request is let through without it.
|
|
164
|
+
*/
|
|
165
|
+
export const UNKEY_TIMEOUT = 2000;
|
|
166
|
+
|
|
167
|
+
/** The part of Unkey's reply the limiter reads. */
|
|
168
|
+
const unkeyReplySchema = z.object({
|
|
169
|
+
data: z.object({
|
|
170
|
+
overrideId: z.string().optional(),
|
|
171
|
+
reset: z.number(),
|
|
172
|
+
success: z.boolean(),
|
|
173
|
+
}),
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Count with Unkey's rate limit API. Unkey takes identifiers of letters,
|
|
178
|
+
* digits, and `_.:/-`, so anything else in the key (an IPv6 host's brackets,
|
|
179
|
+
* an address's `%` zone) becomes `_`. Its `reset` is a timestamp on Unkey's
|
|
180
|
+
* clock, which this server's may not match, so `retryAfter` is kept between
|
|
181
|
+
* one second and the window: the configured one, or Unkey's longest when an
|
|
182
|
+
* override set in Unkey replaced it.
|
|
183
|
+
*/
|
|
184
|
+
export const unkeyLimiter =
|
|
185
|
+
(
|
|
186
|
+
requests: number,
|
|
187
|
+
window: number,
|
|
188
|
+
namespace: string,
|
|
189
|
+
rootKey: string,
|
|
190
|
+
{ fetch: fetchImpl = fetch, now = Date.now }: LimiterRuntime = {}
|
|
191
|
+
): Limiter =>
|
|
192
|
+
async (key) => {
|
|
193
|
+
const response = await fetchImpl(UNKEY_LIMIT_URL, {
|
|
194
|
+
body: JSON.stringify({
|
|
195
|
+
duration: window * 1000,
|
|
196
|
+
identifier: key.replaceAll(/[^\w.:/-]/gu, "_"),
|
|
197
|
+
limit: requests,
|
|
198
|
+
namespace,
|
|
199
|
+
}),
|
|
200
|
+
headers: {
|
|
201
|
+
authorization: `Bearer ${rootKey}`,
|
|
202
|
+
"content-type": "application/json",
|
|
203
|
+
},
|
|
204
|
+
method: "POST",
|
|
205
|
+
signal: AbortSignal.timeout(UNKEY_TIMEOUT),
|
|
206
|
+
});
|
|
207
|
+
if (!response.ok) {
|
|
208
|
+
await response.body?.cancel();
|
|
209
|
+
throw new Error(`Unkey answered ${response.status}.`);
|
|
210
|
+
}
|
|
211
|
+
const { data } = unkeyReplySchema.parse(await response.json());
|
|
212
|
+
const seconds = Math.ceil((data.reset - now()) / 1000);
|
|
213
|
+
const longest = data.overrideId ? UNKEY_MAX_WINDOW : window;
|
|
214
|
+
return {
|
|
215
|
+
allowed: data.success,
|
|
216
|
+
retryAfter: Math.min(longest, Math.max(1, seconds)),
|
|
217
|
+
};
|
|
218
|
+
};
|
|
219
|
+
|
|
155
220
|
/** Count with a Workers rate limiting binding. */
|
|
156
221
|
export const bindingLimiter =
|
|
157
222
|
(binding: RateLimitBinding, window: number): Limiter =>
|
|
@@ -185,6 +250,22 @@ export const createLimiter = (
|
|
|
185
250
|
return null;
|
|
186
251
|
}
|
|
187
252
|
const { requests, window } = limitOf(adapter);
|
|
253
|
+
if (adapter.kind === "unkey") {
|
|
254
|
+
const [secret] = unkeySecrets(adapter.options);
|
|
255
|
+
const rootKey = runtime.secret?.(secret);
|
|
256
|
+
if (rootKey) {
|
|
257
|
+
return unkeyLimiter(
|
|
258
|
+
requests,
|
|
259
|
+
window,
|
|
260
|
+
adapter.options.namespace ?? UNKEY_NAMESPACE,
|
|
261
|
+
rootKey,
|
|
262
|
+
runtime
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
console.warn(
|
|
266
|
+
`Rate limiting counts in memory: set ${secret} to share the count through Unkey.`
|
|
267
|
+
);
|
|
268
|
+
}
|
|
188
269
|
if (adapter.kind === "cloudflare") {
|
|
189
270
|
if (runtime.binding) {
|
|
190
271
|
return bindingLimiter(runtime.binding, window);
|
package/src/ratelimit/schema.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { z } from "zod";
|
|
|
2
2
|
|
|
3
3
|
import { cloudflareRateLimitAdapterSchema } from "./cloudflare.ts";
|
|
4
4
|
import { memory, memoryAdapterSchema } from "./memory.ts";
|
|
5
|
+
import { unkeyAdapterSchema } from "./unkey.ts";
|
|
5
6
|
import { upstashAdapterSchema } from "./upstash.ts";
|
|
6
7
|
|
|
7
8
|
const ADAPTER_HINT =
|
|
@@ -12,6 +13,7 @@ export const rateLimitAdapterSchema = z.discriminatedUnion("kind", [
|
|
|
12
13
|
cloudflareRateLimitAdapterSchema,
|
|
13
14
|
memoryAdapterSchema,
|
|
14
15
|
upstashAdapterSchema,
|
|
16
|
+
unkeyAdapterSchema,
|
|
15
17
|
]);
|
|
16
18
|
|
|
17
19
|
export type RateLimitAdapter = z.output<typeof rateLimitAdapterSchema>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
import type { AdapterDescriptor } from "../core/adapter.ts";
|
|
4
|
+
import { adapterDescriptorSchema } from "../core/adapter.ts";
|
|
5
|
+
import { rateLimitOptionsSchema } from "./memory.ts";
|
|
6
|
+
import type { RateLimitOptions } from "./memory.ts";
|
|
7
|
+
|
|
8
|
+
/** The env var holding the Unkey root key, unless set. */
|
|
9
|
+
const UNKEY_ROOT_KEY_ENV = "UNKEY_ROOT_KEY";
|
|
10
|
+
|
|
11
|
+
/** The Unkey rate limit namespace the count is kept in, unless set. */
|
|
12
|
+
export const UNKEY_NAMESPACE = "docs";
|
|
13
|
+
|
|
14
|
+
/** The longest window Unkey takes, in seconds (30 days). */
|
|
15
|
+
export const UNKEY_MAX_WINDOW = 2_592_000;
|
|
16
|
+
|
|
17
|
+
/** Options for {@link unkey}. */
|
|
18
|
+
export interface UnkeyOptions extends RateLimitOptions {
|
|
19
|
+
/**
|
|
20
|
+
* The Unkey rate limit namespace, up to 512 characters. Defaults to `docs`;
|
|
21
|
+
* Unkey creates it on the first request.
|
|
22
|
+
*/
|
|
23
|
+
namespace?: string;
|
|
24
|
+
/** Name of the env var holding the root key. Defaults to `UNKEY_ROOT_KEY`. */
|
|
25
|
+
rootKeyEnv?: string;
|
|
26
|
+
/** The window, in seconds: Unkey takes up to 30 days. */
|
|
27
|
+
window?: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const unkeyOptionsSchema = rateLimitOptionsSchema.extend({
|
|
31
|
+
namespace: z.string().min(1).max(512).optional(),
|
|
32
|
+
rootKeyEnv: z.string().min(1).optional(),
|
|
33
|
+
window: z.number().int().positive().max(UNKEY_MAX_WINDOW).optional(),
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
export type UnkeyAdapter = AdapterDescriptor<"unkey", UnkeyOptions>;
|
|
37
|
+
|
|
38
|
+
export const unkeyAdapterSchema = adapterDescriptorSchema(
|
|
39
|
+
"unkey",
|
|
40
|
+
unkeyOptionsSchema
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
/** The env var the root key is read from. */
|
|
44
|
+
export const unkeySecrets = (options: UnkeyOptions): [string] => [
|
|
45
|
+
options.rootKeyEnv ?? UNKEY_ROOT_KEY_ENV,
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Counts with Unkey's rate limiting, which every instance on every host
|
|
50
|
+
* shares. Unkey counts in each region and shares the counts between them
|
|
51
|
+
* within moments, so a short burst split across regions can pass more than
|
|
52
|
+
* the limit. It talks to Unkey's REST API, so there is nothing to install;
|
|
53
|
+
* the root key comes from `UNKEY_ROOT_KEY`, or the env var `rootKeyEnv`
|
|
54
|
+
* names.
|
|
55
|
+
*/
|
|
56
|
+
export const unkey = (options: UnkeyOptions = {}): UnkeyAdapter => ({
|
|
57
|
+
kind: "unkey",
|
|
58
|
+
options,
|
|
59
|
+
requiredSecrets: unkeySecrets(options),
|
|
60
|
+
runtimeDeps: [],
|
|
61
|
+
});
|
package/src/registry/eject.ts
CHANGED
package/src/registry/registry.ts
CHANGED
|
@@ -264,7 +264,7 @@ export const registry: RegistryItem[] = [
|
|
|
264
264
|
}),
|
|
265
265
|
layoutComponent({
|
|
266
266
|
description:
|
|
267
|
-
"The site footer: a row of links, social icons,
|
|
267
|
+
"The site footer: a copyright line, a row of links, social icons, and the Cookie settings link.",
|
|
268
268
|
file: "SiteFooter.astro",
|
|
269
269
|
name: "footer",
|
|
270
270
|
slot: "Footer",
|
package/src/search/documents.ts
CHANGED
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
MARKDOWN_BODY_FEATURES,
|
|
30
30
|
MDX_BODY_FEATURES,
|
|
31
31
|
} from "../markdown/features.ts";
|
|
32
|
+
import { normalizeFence } from "../markdown/fence-language.ts";
|
|
32
33
|
import { pageFacets } from "./facets.ts";
|
|
33
34
|
|
|
34
35
|
/** A document indexed by the client-side search providers (Orama, FlexSearch). */
|
|
@@ -177,7 +178,13 @@ const collectCode = (
|
|
|
177
178
|
if (!walk.includeCodeBlocks) {
|
|
178
179
|
return;
|
|
179
180
|
}
|
|
180
|
-
|
|
181
|
+
// The fence as the page renders it (`[file.ts]{2}` splits, `JSON`
|
|
182
|
+
// lowercases), so the indexed title is the one the page shows.
|
|
183
|
+
const fence = normalizeFence(node.lang, node.meta) ?? node;
|
|
184
|
+
const title = parseCodeTitle(
|
|
185
|
+
fence.meta ?? undefined,
|
|
186
|
+
fence.lang ?? undefined
|
|
187
|
+
);
|
|
181
188
|
if (title) {
|
|
182
189
|
out.push(title, " ");
|
|
183
190
|
}
|
|
@@ -504,7 +511,8 @@ export const buildSearchDocuments = async (
|
|
|
504
511
|
return false;
|
|
505
512
|
}
|
|
506
513
|
const page = pageById.get(route.id);
|
|
507
|
-
|
|
514
|
+
const { config, graph } = project;
|
|
515
|
+
return page ? contentIndexable(page, config, graph) : false;
|
|
508
516
|
});
|
|
509
517
|
|
|
510
518
|
// Built once — `downlevelComponents` rebuilds its registry per call
|
|
@@ -7,12 +7,37 @@ import { DEFAULT_CONTENT_GLOB, sharedSourceOptionsSchema } from "./shared.ts";
|
|
|
7
7
|
|
|
8
8
|
/** What `include` defaults to: every Markdown/MDX file under the root. */
|
|
9
9
|
export const DEFAULT_CONTENT_INCLUDE = [DEFAULT_CONTENT_GLOB];
|
|
10
|
-
/** What `exclude`
|
|
10
|
+
/** What `exclude` always holds: underscore- and dot-prefixed paths. */
|
|
11
11
|
export const DEFAULT_CONTENT_EXCLUDE = ["**/_*", "**/.*"];
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* A source's `exclude` as the scan applies it: the defaults, plus the
|
|
15
|
+
* author's patterns. A `!pattern` entry takes that exact pattern back out, a
|
|
16
|
+
* default included, so `["!**\/_*"]` publishes `_`-prefixed files. The glob
|
|
17
|
+
* library can't negate an ignore pattern itself.
|
|
18
|
+
*/
|
|
19
|
+
export const resolveContentExclude = (
|
|
20
|
+
patterns: readonly string[]
|
|
21
|
+
): string[] => {
|
|
22
|
+
const kept = new Set(
|
|
23
|
+
patterns.flatMap((pattern) =>
|
|
24
|
+
pattern.startsWith("!") ? [pattern.slice(1)] : []
|
|
25
|
+
)
|
|
26
|
+
);
|
|
27
|
+
return [
|
|
28
|
+
...new Set([
|
|
29
|
+
...DEFAULT_CONTENT_EXCLUDE,
|
|
30
|
+
...patterns.filter((pattern) => !pattern.startsWith("!")),
|
|
31
|
+
]),
|
|
32
|
+
].filter((pattern) => !kept.has(pattern));
|
|
33
|
+
};
|
|
34
|
+
|
|
13
35
|
/** Options for {@link filesystem}. */
|
|
14
36
|
export interface FilesystemOptions extends SharedSourceOptions {
|
|
15
|
-
/**
|
|
37
|
+
/**
|
|
38
|
+
* Glob patterns to ignore, on top of `["**\/_*", "**\/.*"]`. A `!pattern`
|
|
39
|
+
* entry stops ignoring that pattern, a default included.
|
|
40
|
+
*/
|
|
16
41
|
exclude?: string[];
|
|
17
42
|
/** Glob patterns to include. Defaults to `["**\/*.{md,mdx}"]`. */
|
|
18
43
|
include?: string[];
|
|
@@ -21,7 +46,7 @@ export interface FilesystemOptions extends SharedSourceOptions {
|
|
|
21
46
|
}
|
|
22
47
|
|
|
23
48
|
export const filesystemOptionsSchema = sharedSourceOptionsSchema.extend({
|
|
24
|
-
exclude: z.array(z.string()).default(
|
|
49
|
+
exclude: z.array(z.string()).default([]).transform(resolveContentExclude),
|
|
25
50
|
include: z.array(z.string()).default(DEFAULT_CONTENT_INCLUDE),
|
|
26
51
|
root: z.string().default("docs"),
|
|
27
52
|
});
|
|
@@ -50,27 +50,19 @@ export const mdxRemoteAdapterSchema = adapterDescriptorSchema(
|
|
|
50
50
|
mdxRemoteOptionsSchema
|
|
51
51
|
);
|
|
52
52
|
|
|
53
|
-
// The hosts the source ever sends `GITHUB_TOKEN` to (the same set the fetch
|
|
54
|
-
// in core/sources/mdx-remote.ts checks), so only an adapter reading from
|
|
55
|
-
// GitHub declares the variable.
|
|
56
|
-
const GITHUB_HOSTS = new Set(["api.github.com", "raw.githubusercontent.com"]);
|
|
57
|
-
|
|
58
|
-
const readsFromGithub = (options: MdxRemoteOptions): boolean =>
|
|
59
|
-
options.github !== undefined ||
|
|
60
|
-
(options.url !== undefined &&
|
|
61
|
-
URL.canParse(options.url) &&
|
|
62
|
-
GITHUB_HOSTS.has(new URL(options.url).hostname));
|
|
63
|
-
|
|
64
53
|
/**
|
|
65
54
|
* Remote Markdown/MDX fetched over HTTP. Enumerate files explicitly against a
|
|
66
55
|
* raw `url` base, or from a GitHub repo subtree via `github`. A private repo's
|
|
67
|
-
* token comes from `GITHUB_TOKEN` — never inline it here.
|
|
68
|
-
* the variable
|
|
69
|
-
*
|
|
56
|
+
* token comes from `GITHUB_TOKEN` — never inline it here. Only `github`
|
|
57
|
+
* declares the variable: it lists files through GitHub's API, whose
|
|
58
|
+
* unauthenticated rate limit a build can run into even for a public
|
|
59
|
+
* repository. A raw `url` needs no token for a public repository, so a fetch
|
|
60
|
+
* that fails for want of one names the variable instead (see
|
|
61
|
+
* core/sources/mdx-remote.ts).
|
|
70
62
|
*/
|
|
71
63
|
export const mdxRemote = (options: MdxRemoteOptions): MdxRemoteAdapter => ({
|
|
72
64
|
kind: "mdx-remote",
|
|
73
65
|
options,
|
|
74
|
-
requiredSecrets:
|
|
66
|
+
requiredSecrets: options.github ? ["GITHUB_TOKEN"] : [],
|
|
75
67
|
runtimeDeps: [],
|
|
76
68
|
});
|
package/src/theme/color.ts
CHANGED
|
@@ -470,6 +470,20 @@ export const parseColor = (value: string): Rgba | null => {
|
|
|
470
470
|
: null;
|
|
471
471
|
};
|
|
472
472
|
|
|
473
|
+
// Color syntax `parseColor` leaves unread but a browser takes: a custom
|
|
474
|
+
// property, `color-mix()`, `color()`, `light-dark()`, a relative color
|
|
475
|
+
// (`oklch(from var(--x) l c h)`), and the `currentcolor` keyword.
|
|
476
|
+
const UNREAD_COLOR =
|
|
477
|
+
/^(?:currentcolor|(?:color|color-mix|hsla?|hwb|lab|lch|light-dark|oklab|oklch|rgba?|var)\(.*\))$/isu;
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* Whether `value` is a CSS color: one `parseColor` reads, or a color function
|
|
481
|
+
* or keyword it leaves unread. Words that name no color (`deep purple`), and
|
|
482
|
+
* hex values with a wrong digit count or no `#`, are not.
|
|
483
|
+
*/
|
|
484
|
+
export const isCssColor = (value: string): boolean =>
|
|
485
|
+
parseColor(value) !== null || UNREAD_COLOR.test(value.trim());
|
|
486
|
+
|
|
473
487
|
/** `color` painted over an opaque `backdrop`. */
|
|
474
488
|
export const composite = (color: Rgba, backdrop: Rgba): Rgba => {
|
|
475
489
|
const mix = (top: number, bottom: number): number =>
|
package/src/theme/entry.ts
CHANGED
|
@@ -63,13 +63,18 @@ const TOKEN_DEFAULTS = `:root {
|
|
|
63
63
|
--blume-action: var(--blume-accent);
|
|
64
64
|
--blume-action-foreground: var(--blume-accent-foreground);
|
|
65
65
|
--blume-code-background: oklch(0.99 0 0);
|
|
66
|
-
/* Shiki notation transformers: line/word highlight, diff add/remove
|
|
66
|
+
/* Shiki notation transformers: line/word highlight, diff add/remove, and
|
|
67
|
+
error/warning lines. */
|
|
67
68
|
--blume-code-highlight: oklch(0.55 0.16 255 / 0.1);
|
|
68
69
|
--blume-code-highlight-border: oklch(0.55 0.16 255 / 0.55);
|
|
69
70
|
--blume-code-add: oklch(0.72 0.16 150 / 0.16);
|
|
70
71
|
--blume-code-add-border: oklch(0.52 0.15 150 / 0.7);
|
|
71
72
|
--blume-code-remove: oklch(0.66 0.21 22 / 0.16);
|
|
72
73
|
--blume-code-remove-border: oklch(0.55 0.2 22 / 0.7);
|
|
74
|
+
--blume-code-error: oklch(0.66 0.21 22 / 0.16);
|
|
75
|
+
--blume-code-error-border: oklch(0.55 0.2 22 / 0.7);
|
|
76
|
+
--blume-code-warning: oklch(0.8 0.16 80 / 0.2);
|
|
77
|
+
--blume-code-warning-border: oklch(0.66 0.15 70 / 0.75);
|
|
73
78
|
--blume-code-word: oklch(0.55 0.16 255 / 0.16);
|
|
74
79
|
--blume-code-word-border: oklch(0.55 0.16 255 / 0.5);
|
|
75
80
|
--blume-radius: 0.75rem;
|
|
@@ -129,6 +134,10 @@ const TOKEN_DEFAULTS = `:root {
|
|
|
129
134
|
--blume-code-add-border: oklch(0.72 0.16 150 / 0.7);
|
|
130
135
|
--blume-code-remove: oklch(0.72 0.21 22 / 0.22);
|
|
131
136
|
--blume-code-remove-border: oklch(0.7 0.2 22 / 0.7);
|
|
137
|
+
--blume-code-error: oklch(0.72 0.21 22 / 0.22);
|
|
138
|
+
--blume-code-error-border: oklch(0.7 0.2 22 / 0.7);
|
|
139
|
+
--blume-code-warning: oklch(0.82 0.16 80 / 0.18);
|
|
140
|
+
--blume-code-warning-border: oklch(0.82 0.16 80 / 0.7);
|
|
132
141
|
--blume-code-word: oklch(0.7 0.14 255 / 0.22);
|
|
133
142
|
--blume-code-word-border: oklch(0.7 0.14 255 / 0.55);
|
|
134
143
|
}`;
|
|
@@ -866,6 +875,18 @@ pre[data-line-numbers] .line::before {
|
|
|
866
875
|
box-shadow: inset 2px 0 0 0 var(--blume-code-remove-border);
|
|
867
876
|
}
|
|
868
877
|
|
|
878
|
+
/* Error and warning lines (\`// [!code error]\`, \`// [!code warning]\`) are
|
|
879
|
+
highlighted lines with a level class, tinted red and amber. */
|
|
880
|
+
.line.highlighted.error {
|
|
881
|
+
background-color: var(--blume-code-error) !important;
|
|
882
|
+
box-shadow: inset 2px 0 0 0 var(--blume-code-error-border);
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
.line.highlighted.warning {
|
|
886
|
+
background-color: var(--blume-code-warning) !important;
|
|
887
|
+
box-shadow: inset 2px 0 0 0 var(--blume-code-warning-border);
|
|
888
|
+
}
|
|
889
|
+
|
|
869
890
|
/* Word highlight (\`// [!code word:x]\`) wraps matches in an inline span. The
|
|
870
891
|
element selector keeps it ahead of the transparent token-span rule. */
|
|
871
892
|
span.highlighted-word {
|
package/src/theme/palette.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ResolvedConfig } from "../core/schema.ts";
|
|
2
|
-
import { composite, contrastRatio, parseColor } from "./color.ts";
|
|
2
|
+
import { composite, contrastRatio, isCssColor, parseColor } from "./color.ts";
|
|
3
3
|
import type { Rgba } from "./color.ts";
|
|
4
4
|
|
|
5
5
|
/** Per-mode CSS colors. */
|
|
@@ -243,3 +243,76 @@ ${root}
|
|
|
243
243
|
}
|
|
244
244
|
${dark}`;
|
|
245
245
|
};
|
|
246
|
+
|
|
247
|
+
/** A configured color: where the config sets it, and its value. */
|
|
248
|
+
export interface ColorSetting {
|
|
249
|
+
/** The config path, e.g. `["theme", "accent", "dark"]`. */
|
|
250
|
+
path: string[];
|
|
251
|
+
/** Whether the field also takes an accent preset name (`teal`). */
|
|
252
|
+
presets: boolean;
|
|
253
|
+
value: string;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const MODES = ["light", "dark"] as const;
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* A per-mode field's settings. Both modes holding one value (a string, which
|
|
260
|
+
* the schema copies into each) is one setting at the field itself, so a
|
|
261
|
+
* mistake is reported once, at the key that set it.
|
|
262
|
+
*/
|
|
263
|
+
const modeSettings = (
|
|
264
|
+
path: string[],
|
|
265
|
+
value: { dark?: string; light?: string } | undefined,
|
|
266
|
+
presets: boolean
|
|
267
|
+
): ColorSetting[] => {
|
|
268
|
+
if (value?.light !== undefined && value.light === value.dark) {
|
|
269
|
+
return [{ path, presets, value: value.light }];
|
|
270
|
+
}
|
|
271
|
+
return MODES.flatMap((mode) => {
|
|
272
|
+
const color = value?.[mode];
|
|
273
|
+
return color === undefined
|
|
274
|
+
? []
|
|
275
|
+
: [{ path: [...path, mode], presets, value: color }];
|
|
276
|
+
});
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
const OG_PALETTE_KEYS = [
|
|
280
|
+
"accent",
|
|
281
|
+
"background",
|
|
282
|
+
"border",
|
|
283
|
+
"foreground",
|
|
284
|
+
"muted",
|
|
285
|
+
] as const;
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* The configured colors that aren't CSS colors (`"deep purple"`, a hex value
|
|
289
|
+
* missing its `#`): `theme.accent`, `theme.action`, and `theme.background`,
|
|
290
|
+
* and the OG card's `seo.og.palette`. The schema takes any string, so a
|
|
291
|
+
* mistake would otherwise reach the stylesheet, where browsers drop it, or
|
|
292
|
+
* the card renderer, which rejects it. Preset names are CSS color names too.
|
|
293
|
+
*/
|
|
294
|
+
export const invalidColorSettings = (
|
|
295
|
+
config: ResolvedConfig
|
|
296
|
+
): ColorSetting[] => {
|
|
297
|
+
const { theme } = config;
|
|
298
|
+
const palette = config.seo.og.palette ?? {};
|
|
299
|
+
return [
|
|
300
|
+
...modeSettings(["theme", "accent"], theme.accent, true),
|
|
301
|
+
...(theme.action === undefined
|
|
302
|
+
? []
|
|
303
|
+
: [{ path: ["theme", "action"], presets: true, value: theme.action }]),
|
|
304
|
+
...modeSettings(["theme", "background"], theme.background, false),
|
|
305
|
+
...OG_PALETTE_KEYS.flatMap((key) => {
|
|
306
|
+
const value = palette[key];
|
|
307
|
+
return value === undefined
|
|
308
|
+
? []
|
|
309
|
+
: [
|
|
310
|
+
{
|
|
311
|
+
path: ["seo", "og", "palette", key],
|
|
312
|
+
presets: key === "accent",
|
|
313
|
+
value,
|
|
314
|
+
},
|
|
315
|
+
];
|
|
316
|
+
}),
|
|
317
|
+
].filter((setting) => !isCssColor(setting.value));
|
|
318
|
+
};
|