blume 1.7.3 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +19 -0
- package/CHANGELOG.md +245 -0
- package/README.md +34 -21
- package/dist/cli/{chunk-vacwm2hv.js → chunk-27g6wdth.js} +2 -2
- package/dist/cli/{chunk-ps4m1xh4.js → chunk-2hn4b8z7.js} +513 -550
- package/dist/cli/chunk-2hn4b8z7.js.map +12 -0
- package/dist/cli/chunk-5shv93fd.js +39 -0
- package/dist/cli/chunk-5shv93fd.js.map +10 -0
- package/dist/cli/chunk-6crbhc3x.js +361 -0
- package/dist/cli/chunk-6crbhc3x.js.map +14 -0
- package/dist/cli/{chunk-8cjtbafj.js → chunk-6hsn950k.js} +109 -383
- package/dist/cli/chunk-6hsn950k.js.map +10 -0
- package/dist/cli/chunk-6vm74dry.js +148 -0
- package/dist/cli/chunk-6vm74dry.js.map +10 -0
- package/dist/cli/{chunk-yg63d42r.js → chunk-79jhk4py.js} +87 -58
- package/dist/cli/chunk-79jhk4py.js.map +35 -0
- package/dist/cli/chunk-82bbrxdn.js +51 -0
- package/dist/cli/chunk-82bbrxdn.js.map +10 -0
- package/dist/cli/chunk-abh8yjkn.js +31 -0
- package/dist/cli/chunk-abh8yjkn.js.map +10 -0
- package/dist/cli/chunk-ah61y8py.js +75 -0
- package/dist/cli/chunk-ah61y8py.js.map +11 -0
- package/dist/cli/{chunk-dwgcp5sm.js → chunk-ce574jw2.js} +1 -1
- package/dist/cli/chunk-ch6g3ar0.js +102 -0
- package/dist/cli/chunk-ch6g3ar0.js.map +10 -0
- package/dist/cli/chunk-dh8cwk36.js +279 -0
- package/dist/cli/chunk-dh8cwk36.js.map +10 -0
- package/dist/cli/{chunk-rqy0s5wh.js → chunk-epjnccmv.js} +17 -16
- package/dist/cli/{chunk-rqy0s5wh.js.map → chunk-epjnccmv.js.map} +3 -3
- package/dist/cli/chunk-f2z5v128.js +97 -0
- package/dist/cli/chunk-f2z5v128.js.map +10 -0
- package/dist/cli/{chunk-2z47ypj8.js → chunk-fa25z98p.js} +16 -3
- package/dist/cli/chunk-fa25z98p.js.map +11 -0
- package/dist/cli/{chunk-1jefwnfs.js → chunk-fs23ddbb.js} +1076 -2592
- package/dist/cli/chunk-fs23ddbb.js.map +35 -0
- package/dist/cli/{chunk-e7f42gdj.js → chunk-fxypxtvm.js} +2 -2
- package/dist/cli/{chunk-bvwwhd84.js → chunk-fz5wtpmh.js} +15 -15
- package/dist/cli/{chunk-bvwwhd84.js.map → chunk-fz5wtpmh.js.map} +1 -1
- package/dist/cli/chunk-hdpx1tax.js +91 -0
- package/dist/cli/chunk-hdpx1tax.js.map +10 -0
- package/dist/cli/{chunk-ct47dqpx.js → chunk-jts8mvcz.js} +67 -7
- package/dist/cli/{chunk-2mzebbbz.js.map → chunk-jts8mvcz.js.map} +6 -4
- package/dist/cli/{chunk-ahnw3kxw.js → chunk-jwyddg7y.js} +27 -22
- package/dist/cli/chunk-jwyddg7y.js.map +15 -0
- package/dist/cli/{chunk-cjtn640a.js → chunk-kdp5q7ke.js} +43 -20
- package/dist/cli/chunk-kdp5q7ke.js.map +10 -0
- package/dist/cli/{chunk-5g0w1e2c.js → chunk-kpf8rrjc.js} +28 -16
- package/dist/cli/{chunk-5g0w1e2c.js.map → chunk-kpf8rrjc.js.map} +4 -4
- package/dist/cli/chunk-m3vmjgmq.js +133 -0
- package/dist/cli/chunk-m3vmjgmq.js.map +10 -0
- package/dist/cli/{chunk-b27xqwn9.js → chunk-mb2919y2.js} +9 -5
- package/dist/cli/chunk-mb2919y2.js.map +10 -0
- package/dist/cli/{chunk-5qk08vmp.js → chunk-q5163e60.js} +133 -54
- package/dist/cli/chunk-q5163e60.js.map +11 -0
- package/dist/cli/chunk-qkqwkpte.js +12437 -0
- package/dist/cli/chunk-qkqwkpte.js.map +182 -0
- package/dist/cli/{chunk-4x36ddpw.js → chunk-qs4q5p4e.js} +81 -87
- package/dist/cli/chunk-qs4q5p4e.js.map +10 -0
- package/dist/cli/{chunk-0xjyb285.js → chunk-qwsrynx5.js} +15 -5
- package/dist/cli/{chunk-0xjyb285.js.map → chunk-qwsrynx5.js.map} +4 -4
- package/dist/cli/chunk-s1p84fyh.js +261 -0
- package/dist/cli/chunk-s1p84fyh.js.map +10 -0
- package/dist/cli/chunk-s6jhgk0q.js +176 -0
- package/dist/cli/chunk-s6jhgk0q.js.map +11 -0
- package/dist/cli/chunk-vtk4a6dg.js +374 -0
- package/dist/cli/chunk-vtk4a6dg.js.map +10 -0
- package/dist/cli/{chunk-k79xp7av.js → chunk-wgm7m9qk.js} +230 -700
- package/dist/cli/chunk-wgm7m9qk.js.map +36 -0
- package/dist/cli/chunk-wm7js3j9.js +145 -0
- package/dist/cli/chunk-wm7js3j9.js.map +11 -0
- package/dist/cli/chunk-yt5n7ppj.js +79 -0
- package/dist/cli/chunk-yt5n7ppj.js.map +10 -0
- package/dist/cli/{chunk-3r45185y.js → chunk-yw7dm696.js} +9 -11
- package/dist/cli/{chunk-3r45185y.js.map → chunk-yw7dm696.js.map} +3 -3
- package/dist/cli/{chunk-nn13znc2.js → chunk-zxcczpyx.js} +1 -1
- package/dist/cli/chunk-zxh4d9vy.js +122 -0
- package/dist/cli/chunk-zxh4d9vy.js.map +11 -0
- package/dist/cli/index.js +214 -57
- package/dist/cli/index.js.map +8 -7
- package/dist/types/ai/agent-readability.d.ts +52 -0
- package/dist/types/ai/ai-catalog.d.ts +42 -0
- package/dist/types/ai/api/paths.d.ts +17 -0
- package/dist/types/ai/api-catalog.d.ts +18 -0
- package/dist/types/ai/ask-context.d.ts +7 -7
- package/dist/types/ai/ask.d.ts +368 -0
- package/dist/types/ai/changelog-markdown.d.ts +2 -0
- package/dist/types/ai/component-markdown.d.ts +2 -2
- package/dist/types/ai/index.d.ts +24 -0
- package/dist/types/ai/link-headers.d.ts +24 -0
- package/dist/types/ai/llms.d.ts +25 -0
- package/dist/types/ai/markdown.d.ts +45 -0
- package/dist/types/ai/mcp/discovery.d.ts +68 -0
- package/dist/types/ai/mcp/tools.d.ts +16 -0
- package/dist/types/ai/openapi-components.d.ts +43 -0
- package/dist/types/ai/relative-links.d.ts +26 -0
- package/dist/types/ai/serializers.d.ts +15 -0
- package/dist/types/ai/skills.d.ts +42 -0
- package/dist/types/ai/tar.d.ts +25 -0
- package/dist/types/ai/visibility.d.ts +17 -0
- package/dist/types/ai/web-bot-auth.d.ts +16 -0
- package/dist/types/analytics/adobe.d.ts +35 -0
- package/dist/types/analytics/amplitude.d.ts +50 -0
- package/dist/types/analytics/clarity.d.ts +31 -0
- package/dist/types/analytics/clearbit.d.ts +29 -0
- package/dist/types/analytics/cloudflare.d.ts +41 -0
- package/dist/types/analytics/fathom.d.ts +41 -0
- package/dist/types/analytics/google-analytics.d.ts +44 -0
- package/dist/types/analytics/google-tag-manager.d.ts +40 -0
- package/dist/types/analytics/head.d.ts +30 -0
- package/dist/types/analytics/heap.d.ts +40 -0
- package/dist/types/analytics/hightouch.d.ts +44 -0
- package/dist/types/analytics/hotjar.d.ts +33 -0
- package/dist/types/analytics/index.d.ts +61 -0
- package/dist/types/analytics/inline.d.ts +17 -0
- package/dist/types/analytics/logrocket.d.ts +44 -0
- package/dist/types/analytics/mixpanel.d.ts +67 -0
- package/dist/types/analytics/pirsch.d.ts +42 -0
- package/dist/types/analytics/plausible.d.ts +56 -0
- package/dist/types/analytics/posthog.d.ts +45 -0
- package/dist/types/analytics/schema.d.ts +320 -0
- package/dist/types/analytics/script.d.ts +46 -0
- package/dist/types/analytics/segment.d.ts +50 -0
- package/dist/types/analytics/vercel.d.ts +48 -0
- package/dist/types/astro/integration.d.ts +76 -0
- package/dist/types/astro/markdown-negotiation.d.ts +23 -0
- package/dist/types/astro/module-types.d.ts +14 -0
- package/dist/types/astro/pages.d.ts +44 -0
- package/dist/types/cli/env.d.ts +12 -0
- package/dist/types/cli/init/scaffold.d.ts +154 -0
- package/dist/types/components/layout/nav-utils.d.ts +11 -0
- package/dist/types/core/adapter.d.ts +47 -0
- package/dist/types/core/api-name.d.ts +7 -0
- package/dist/types/core/changelog-index.d.ts +13 -0
- package/dist/types/core/config-input.d.ts +197 -526
- package/dist/types/core/config.d.ts +61 -35
- package/dist/types/core/content-assets.d.ts +76 -0
- package/dist/types/core/custom-pages.d.ts +33 -0
- package/dist/types/core/data.d.ts +30 -15
- package/dist/types/core/define-components.d.ts +12 -9
- package/dist/types/core/deployment-env.d.ts +6 -11
- package/dist/types/core/frontmatter.d.ts +10 -0
- package/dist/types/core/graph.d.ts +18 -0
- package/dist/types/core/heading-markers.d.ts +54 -0
- package/dist/types/core/i18n-ui.d.ts +12 -10
- package/dist/types/core/i18n.d.ts +87 -0
- package/dist/types/core/includes.d.ts +138 -0
- package/dist/types/core/last-modified.d.ts +47 -0
- package/dist/types/core/links.d.ts +95 -0
- package/dist/types/core/locale-links.d.ts +60 -0
- package/dist/types/core/manifest.d.ts +17 -0
- package/dist/types/core/meta.d.ts +38 -0
- package/dist/types/core/nav-diagnostics.d.ts +26 -0
- package/dist/types/core/navigation.d.ts +6 -0
- package/dist/types/core/node-require.d.ts +19 -0
- package/dist/types/core/package-json.d.ts +13 -0
- package/dist/types/core/probe.d.ts +42 -0
- package/dist/types/core/project-graph.d.ts +51 -0
- package/dist/types/core/project.d.ts +2 -0
- package/dist/types/core/safe-href.d.ts +2 -0
- package/dist/types/core/safe-links.d.ts +26 -0
- package/dist/types/core/schema.d.ts +2284 -454
- package/dist/types/core/site-url.d.ts +16 -0
- package/dist/types/core/sources/assets.d.ts +36 -0
- package/dist/types/core/sources/cache.d.ts +37 -0
- package/dist/types/core/sources/collection.d.ts +28 -0
- package/dist/types/core/sources/contentful-rich-text.d.ts +31 -0
- package/dist/types/core/sources/contentful.d.ts +40 -0
- package/dist/types/core/sources/filesystem.d.ts +24 -0
- package/dist/types/core/sources/github-releases.d.ts +31 -0
- package/dist/types/core/sources/json.d.ts +30 -0
- package/dist/types/core/sources/lexical.d.ts +19 -0
- package/dist/types/core/sources/lower.d.ts +75 -0
- package/dist/types/core/sources/mdx-remote.d.ts +28 -0
- package/dist/types/core/sources/normalize.d.ts +147 -0
- package/dist/types/core/sources/notion.d.ts +131 -0
- package/dist/types/core/sources/obsidian.d.ts +46 -0
- package/dist/types/core/sources/payload.d.ts +39 -0
- package/dist/types/core/sources/portable-text.d.ts +42 -0
- package/dist/types/core/sources/read.d.ts +23 -0
- package/dist/types/core/sources/remote.d.ts +74 -0
- package/dist/types/core/sources/resolve.d.ts +19 -0
- package/dist/types/core/sources/sanity.d.ts +43 -0
- package/dist/types/core/sources/strapi-blocks.d.ts +12 -0
- package/dist/types/core/sources/strapi.d.ts +33 -0
- package/dist/types/core/sources/types.d.ts +7 -0
- package/dist/types/core/sources/watch.d.ts +45 -0
- package/dist/types/core/text-width.d.ts +11 -0
- package/dist/types/core/types.d.ts +15 -1
- package/dist/types/core/unrecognized-keys.d.ts +7 -0
- package/dist/types/core/versions.d.ts +72 -0
- package/dist/types/core/yaml.d.ts +9 -0
- package/dist/types/deploy/adapter-output.d.ts +45 -0
- package/dist/types/deploy/adapters/cloudflare.d.ts +40 -0
- package/dist/types/deploy/adapters/index.d.ts +29 -0
- package/dist/types/deploy/adapters/netlify.d.ts +37 -0
- package/dist/types/deploy/adapters/node.d.ts +37 -0
- package/dist/types/deploy/adapters/registry.d.ts +133 -0
- package/dist/types/deploy/adapters/types.d.ts +71 -0
- package/dist/types/deploy/adapters/vercel.d.ts +38 -0
- package/dist/types/deploy/artifacts.d.ts +65 -0
- package/dist/types/deploy/cloudflare-negotiation.d.ts +196 -0
- package/dist/types/deploy/function-bundle.d.ts +80 -0
- package/dist/types/deploy/headers.d.ts +50 -0
- package/dist/types/deploy/node-headers.d.ts +42 -0
- package/dist/types/deploy/platforms/cloudflare.d.ts +40 -0
- package/dist/types/deploy/platforms/index.d.ts +18 -0
- package/dist/types/deploy/platforms/netlify.d.ts +13 -0
- package/dist/types/deploy/platforms/node.d.ts +11 -0
- package/dist/types/deploy/platforms/paths.d.ts +27 -0
- package/dist/types/deploy/platforms/static.d.ts +10 -0
- package/dist/types/deploy/platforms/types.d.ts +104 -0
- package/dist/types/deploy/platforms/vercel.d.ts +32 -0
- package/dist/types/deploy/redirects.d.ts +53 -0
- package/dist/types/deploy/robots.d.ts +8 -0
- package/dist/types/deploy/rss.d.ts +31 -0
- package/dist/types/deploy/sitemap.d.ts +21 -0
- package/dist/types/deploy/vercel-negotiation.d.ts +109 -0
- package/dist/types/markdown/code-title.d.ts +32 -0
- package/dist/types/markdown/fence-meta.d.ts +23 -0
- package/dist/types/markdown/themes.d.ts +3 -3
- package/dist/types/openapi/asyncapi.d.ts +129 -0
- package/dist/types/openapi/graphql-build.d.ts +8 -0
- package/dist/types/openapi/graphql.d.ts +122 -0
- package/dist/types/openapi/model.d.ts +158 -0
- package/dist/types/openapi/parse.d.ts +57 -0
- package/dist/types/openapi/references.d.ts +37 -25
- package/dist/types/openapi/render-mdx.d.ts +33 -0
- package/dist/types/openapi/sentence.d.ts +7 -0
- package/dist/types/openapi/signature.d.ts +10 -0
- package/dist/types/openapi/source.d.ts +22 -0
- package/dist/types/openapi/spec-dependency-error.d.ts +10 -0
- package/dist/types/reference/asyncapi.d.ts +166 -0
- package/dist/types/reference/graphql.d.ts +181 -0
- package/dist/types/reference/index.d.ts +32 -0
- package/dist/types/reference/openapi.d.ts +165 -0
- package/dist/types/reference/options.d.ts +157 -0
- package/dist/types/reference/scalar.d.ts +136 -0
- package/dist/types/reference/schema.d.ts +630 -0
- package/dist/types/search/adapters/algolia.d.ts +32 -0
- package/dist/types/search/adapters/flexsearch.d.ts +12 -0
- package/dist/types/search/adapters/index.d.ts +31 -0
- package/dist/types/search/adapters/mixedbread.d.ts +22 -0
- package/dist/types/search/adapters/orama-cloud.d.ts +33 -0
- package/dist/types/search/adapters/orama.d.ts +13 -0
- package/dist/types/search/adapters/pagefind.d.ts +12 -0
- package/dist/types/search/adapters/registry.d.ts +228 -0
- package/dist/types/search/adapters/types.d.ts +34 -0
- package/dist/types/search/adapters/typesense.d.ts +42 -0
- package/dist/types/search/build.d.ts +23 -0
- package/dist/types/search/documents.d.ts +90 -0
- package/dist/types/search/facets.d.ts +3 -0
- package/dist/types/search/orama-index.d.ts +1 -1
- package/dist/types/search/sync/algolia.d.ts +14 -0
- package/dist/types/search/sync/index.d.ts +14 -0
- package/dist/types/search/sync/orama-cloud.d.ts +10 -0
- package/dist/types/search/sync/typesense.d.ts +14 -0
- package/dist/types/sources/contentful.d.ts +68 -0
- package/dist/types/sources/custom.d.ts +20 -0
- package/dist/types/sources/filesystem.d.ts +42 -0
- package/dist/types/sources/github-releases.d.ts +46 -0
- package/dist/types/sources/index.d.ts +48 -0
- package/dist/types/sources/mdx-remote.d.ts +63 -0
- package/dist/types/sources/notion.d.ts +65 -0
- package/dist/types/sources/obsidian.d.ts +34 -0
- package/dist/types/sources/payload.d.ts +68 -0
- package/dist/types/sources/registry.d.ts +1414 -0
- package/dist/types/sources/sanity.d.ts +69 -0
- package/dist/types/sources/shared.d.ts +46 -0
- package/dist/types/sources/strapi.d.ts +66 -0
- package/dist/types/theme/icon-kind.d.ts +11 -0
- package/dist/types/theme/icons.d.ts +20 -0
- package/docs/01-quickstart.mdx +18 -18
- package/docs/02-deployment.mdx +52 -28
- package/docs/03-upgrading.mdx +364 -0
- package/docs/04-migrating.mdx +58 -0
- package/docs/08-faq.mdx +5 -5
- package/docs/advanced/blog.mdx +13 -6
- package/docs/advanced/changelog.mdx +23 -35
- package/docs/advanced/custom-pages.mdx +22 -10
- package/docs/advanced/meta.ts +1 -8
- package/docs/advanced/skills.mdx +8 -0
- package/docs/cli/audit.mdx +646 -0
- package/docs/cli/doctor.mdx +29 -0
- package/docs/{reference/eval.mdx → cli/evals.mdx} +12 -11
- package/docs/cli/index.mdx +105 -0
- package/docs/cli/meta.ts +7 -0
- package/docs/{reference → cli}/translate.mdx +9 -9
- package/docs/cli/validate.mdx +41 -0
- package/docs/cli/version.mdx +40 -0
- package/docs/configuration/analytics.mdx +350 -59
- package/docs/configuration/assistant.mdx +357 -0
- package/docs/configuration/customization.mdx +16 -10
- package/docs/configuration/index.mdx +50 -31
- package/docs/configuration/meta.ts +1 -1
- package/docs/configuration/search.mdx +76 -55
- package/docs/configuration/theming.mdx +24 -15
- package/docs/content/components.mdx +21 -5
- package/docs/{reference → content}/frontmatter.mdx +35 -1
- package/docs/content/i18n.mdx +9 -7
- package/docs/content/includes.mdx +2 -4
- package/docs/content/index.mdx +1 -1
- package/docs/content/islands.mdx +11 -6
- package/docs/content/meta.mdx +1 -1
- package/docs/content/meta.ts +1 -0
- package/docs/content/navigation.mdx +9 -7
- package/docs/content/sources.mdx +145 -50
- package/docs/content/syntax.mdx +16 -12
- package/docs/content/versioning.mdx +3 -3
- package/docs/discoverability/agent-discovery.mdx +12 -12
- package/docs/discoverability/index.mdx +4 -4
- package/docs/discoverability/json-api.mdx +4 -4
- package/docs/discoverability/llms-txt.mdx +6 -6
- package/docs/discoverability/markdown.mdx +4 -4
- package/docs/discoverability/mcp.mdx +11 -11
- package/docs/discoverability/sitemap-and-robots.mdx +3 -3
- package/docs/index.mdx +4 -4
- package/docs/references/asyncapi.mdx +59 -0
- package/docs/{advanced → references}/graphql.mdx +45 -32
- package/docs/{reference → references}/meta.ts +2 -2
- package/docs/references/openapi.mdx +171 -0
- package/docs/references/scalar.mdx +64 -0
- package/package.json +42 -8
- package/skills/blume/SKILL.md +23 -10
- package/skills/blume-migrate/SKILL.md +22 -21
- package/skills/blume-migrate/assets/oxfmt@0.67.0.patch +49 -0
- package/skills/blume-migrate/references/docusaurus.md +5 -4
- package/skills/blume-migrate/references/fumadocs.md +4 -4
- package/skills/blume-migrate/references/mintlify.md +23 -8
- package/skills/blume-migrate/references/monorepo.md +6 -6
- package/skills/blume-migrate/references/starlight.md +4 -4
- package/src/ai/agent-readability.ts +25 -26
- package/src/ai/ai-catalog.ts +50 -32
- package/src/ai/api/handlers.ts +46 -11
- package/src/ai/api/paths.ts +1 -1
- package/src/ai/api-catalog.ts +8 -8
- package/src/ai/ask-context.ts +7 -7
- package/src/ai/ask-data.ts +3 -3
- package/src/ai/ask.ts +637 -100
- package/src/ai/changelog-markdown.ts +91 -0
- package/src/ai/component-markdown.ts +328 -12
- package/src/ai/cors.ts +3 -3
- package/src/ai/index.ts +45 -0
- package/src/ai/link-headers.ts +7 -6
- package/src/ai/llms.ts +20 -15
- package/src/ai/markdown.ts +35 -5
- package/src/ai/mcp/data.ts +9 -5
- package/src/ai/openapi-components.ts +5 -2
- package/src/ai/relative-links.ts +170 -0
- package/src/ai/serializers.ts +3 -3
- package/src/ai/skills.ts +1 -1
- package/src/ai/visibility.ts +1 -1
- package/src/ai/web-bot-auth.ts +2 -2
- package/src/analytics/adobe.ts +46 -0
- package/src/analytics/amplitude.ts +79 -0
- package/src/analytics/clarity.ts +46 -0
- package/src/analytics/clearbit.ts +47 -0
- package/src/analytics/cloudflare.ts +67 -0
- package/src/analytics/fathom.ts +64 -0
- package/src/analytics/google-analytics.ts +84 -0
- package/src/analytics/google-tag-manager.ts +61 -0
- package/src/analytics/head.ts +130 -0
- package/src/analytics/heap.ts +65 -0
- package/src/analytics/hightouch.ts +77 -0
- package/src/analytics/hotjar.ts +47 -0
- package/src/analytics/index.ts +71 -0
- package/src/analytics/inline.ts +21 -0
- package/src/analytics/logrocket.ts +71 -0
- package/src/analytics/mixpanel.ts +92 -0
- package/src/analytics/pirsch.ts +66 -0
- package/src/analytics/plausible.ts +83 -0
- package/src/analytics/posthog.ts +78 -0
- package/src/analytics/schema.ts +60 -0
- package/src/analytics/script.ts +60 -0
- package/src/analytics/segment.ts +85 -0
- package/src/analytics/vercel.ts +50 -0
- package/src/astro/adapter-root.ts +7 -9
- package/src/astro/component-slots.ts +131 -91
- package/src/astro/generate.ts +129 -361
- package/src/astro/integration.ts +2 -6
- package/src/astro/module-types.ts +1 -1
- package/src/astro/pages.ts +13 -101
- package/src/astro/render-deps.ts +379 -0
- package/src/astro/runtime-deps.ts +201 -0
- package/src/astro/templates.ts +575 -562
- package/src/audit/agent.ts +24 -0
- package/src/audit/catalog.ts +2 -2
- package/src/audit/checks/assets.ts +2 -2
- package/src/audit/checks/dns-aid.ts +1 -1
- package/src/audit/checks/duplicates.ts +3 -1
- package/src/audit/checks/i18n.ts +1 -1
- package/src/audit/checks/indexability.ts +7 -7
- package/src/audit/checks/links.ts +2 -2
- package/src/audit/checks/llms.ts +6 -6
- package/src/audit/checks/network.ts +3 -3
- package/src/audit/checks/og-image.ts +2 -2
- package/src/audit/checks/robots.ts +1 -1
- package/src/audit/checks/sitemap.ts +2 -2
- package/src/audit/checks/social.ts +1 -1
- package/src/audit/run.ts +4 -3
- package/src/audit/terms.ts +31 -0
- package/src/audit/url.ts +13 -13
- package/src/blume-modules.d.ts +2 -2
- package/src/cli/command-meta.ts +10 -0
- package/src/cli/commands/audit.ts +40 -21
- package/src/cli/commands/build.ts +71 -316
- package/src/cli/commands/check.ts +1 -0
- package/src/cli/commands/dev.ts +40 -1
- package/src/cli/commands/doctor.ts +92 -14
- package/src/cli/commands/eject.ts +44 -7
- package/src/cli/commands/eval.ts +5 -5
- package/src/cli/commands/init.ts +161 -41
- package/src/cli/commands/migrate.ts +121 -0
- package/src/cli/commands/preview.ts +7 -1
- package/src/cli/commands/translate.ts +5 -5
- package/src/cli/commands/upgrade.ts +141 -0
- package/src/cli/commands/version.ts +57 -44
- package/src/cli/eject-scripts.ts +121 -6
- package/src/cli/index.ts +11 -1
- package/src/cli/init/install.ts +70 -0
- package/src/cli/init/questions.ts +7 -0
- package/src/cli/init/scaffold.ts +459 -75
- package/src/cli/lazy-command.ts +37 -1
- package/src/cli/prepare.ts +40 -6
- package/src/cli/required-secrets.ts +39 -12
- package/src/cli/unknown-flags.ts +266 -0
- package/src/cli/yarn-pnp.ts +52 -0
- package/src/components/content/AccordionItem.astro +7 -1
- package/src/components/content/Card.astro +4 -3
- package/src/components/content/ColorItem.astro +22 -4
- package/src/components/content/GithubInfo.astro +2 -2
- package/src/components/content/Prompt.astro +25 -25
- package/src/components/content/Tabs.astro +3 -1
- package/src/components/content/Tile.astro +2 -3
- package/src/components/content/Tooltip.astro +57 -9
- package/src/components/content/content-strings.ts +34 -0
- package/src/components/content/diff.ts +1 -1
- package/src/components/content/mermaid-element.ts +13 -2
- package/src/components/content/prompt-markdown.ts +292 -0
- package/src/components/content/tooltip-id.ts +41 -0
- package/src/components/copy-feedback.ts +1 -1
- package/src/components/islands/{AskAI.astro → Assistant.astro} +10 -10
- package/src/components/islands/{ask-ai.tsx → assistant.tsx} +23 -23
- package/src/components/islands/hooks.ts +36 -11
- package/src/components/layout/Analytics.astro +21 -79
- package/src/components/layout/Banner.astro +3 -1
- package/src/components/layout/DiscoveryLinks.astro +69 -0
- package/src/components/layout/Header.astro +93 -30
- package/src/components/layout/LanguageSwitcher.astro +4 -1
- package/src/components/layout/Logo.astro +23 -2
- package/src/components/layout/NavSelector.astro +13 -2
- package/src/components/layout/NavTree.astro +12 -3
- package/src/components/layout/NavTreeScript.astro +17 -3
- package/src/components/layout/PageActions.astro +3 -3
- package/src/components/layout/PageFeedback.astro +11 -1
- package/src/components/layout/PageLayout.astro +58 -11
- package/src/components/layout/Pagination.astro +7 -7
- package/src/components/layout/ReferenceLayout.astro +22 -13
- package/src/components/layout/RootLayout.astro +75 -72
- package/src/components/layout/Search.astro +43 -19
- package/src/components/layout/WebMcp.astro +1 -1
- package/src/components/layout/analytics-client.ts +73 -16
- package/src/components/layout/drawer-inert.ts +113 -15
- package/src/components/layout/dropdown-clamp.ts +105 -0
- package/src/components/layout/head-scripts.ts +15 -6
- package/src/components/layout/nav-utils.ts +17 -0
- package/src/components/layout/search/algolia.ts +8 -8
- package/src/components/layout/search/orama-cloud.ts +9 -7
- package/src/components/layout/search/typesense.ts +11 -17
- package/src/components/openapi/MessageComposer.astro +2 -2
- package/src/components/openapi/Playground.astro +2 -2
- package/src/components/openapi/description.ts +2 -2
- package/src/components/openapi/playground-client.ts +79 -10
- package/src/core/changelog-index.ts +24 -0
- package/src/core/code-fences.ts +1 -1
- package/src/core/component-overrides.ts +399 -154
- package/src/core/config-input.ts +201 -566
- package/src/core/config.ts +131 -42
- package/src/core/custom-pages.ts +105 -0
- package/src/core/data.ts +34 -15
- package/src/core/define-components.ts +12 -9
- package/src/core/deployment-env.ts +18 -74
- package/src/core/diagnostics.ts +14 -7
- package/src/core/graph.ts +69 -25
- package/src/core/i18n-ui.ts +41 -11
- package/src/core/i18n.ts +17 -0
- package/src/core/includes.ts +156 -38
- package/src/core/last-modified.ts +6 -11
- package/src/core/links.ts +166 -2
- package/src/core/manifest.ts +10 -3
- package/src/core/navigation.ts +115 -16
- package/src/core/new-tab.ts +35 -0
- package/src/core/node-require.ts +21 -0
- package/src/core/project-graph.ts +42 -26
- package/src/core/project.ts +9 -4
- package/src/core/request-body.ts +61 -0
- package/src/core/safe-href.ts +28 -0
- package/src/core/safe-links.ts +68 -0
- package/src/core/schema.ts +528 -745
- package/src/core/server-features.ts +10 -11
- package/src/core/sources/assets.ts +47 -11
- package/src/core/sources/collection.ts +67 -0
- package/src/core/sources/contentful-rich-text.ts +285 -0
- package/src/core/sources/contentful.ts +173 -0
- package/src/core/sources/github-releases.ts +51 -1
- package/src/core/sources/json.ts +71 -0
- package/src/core/sources/lexical.ts +195 -0
- package/src/core/sources/lower.ts +226 -0
- package/src/core/sources/normalize.ts +52 -2
- package/src/core/sources/notion.ts +39 -28
- package/src/core/sources/payload.ts +135 -0
- package/src/core/sources/portable-text.ts +11 -16
- package/src/core/sources/remote.ts +226 -0
- package/src/core/sources/resolve.ts +104 -166
- package/src/core/sources/sanity.ts +16 -49
- package/src/core/sources/strapi-blocks.ts +124 -0
- package/src/core/sources/strapi.ts +191 -0
- package/src/core/sources/types.ts +12 -1
- package/src/core/types.ts +15 -1
- package/src/core/ui-packs/ar.ts +10 -7
- package/src/core/ui-packs/bg.ts +10 -7
- package/src/core/ui-packs/bn.ts +10 -7
- package/src/core/ui-packs/ca.ts +7 -6
- package/src/core/ui-packs/cs.ts +10 -7
- package/src/core/ui-packs/da.ts +10 -7
- package/src/core/ui-packs/de.ts +10 -7
- package/src/core/ui-packs/el.ts +7 -6
- package/src/core/ui-packs/es.ts +7 -6
- package/src/core/ui-packs/fa.ts +10 -7
- package/src/core/ui-packs/fi.ts +10 -7
- package/src/core/ui-packs/fr.ts +7 -6
- package/src/core/ui-packs/he.ts +10 -7
- package/src/core/ui-packs/hi.ts +10 -7
- package/src/core/ui-packs/hr.ts +10 -7
- package/src/core/ui-packs/hu.ts +10 -7
- package/src/core/ui-packs/id.ts +10 -7
- package/src/core/ui-packs/it.ts +7 -6
- package/src/core/ui-packs/ja.ts +7 -6
- package/src/core/ui-packs/ko.ts +7 -6
- package/src/core/ui-packs/nl.ts +10 -7
- package/src/core/ui-packs/no.ts +10 -7
- package/src/core/ui-packs/pl.ts +10 -7
- package/src/core/ui-packs/pt-br.ts +7 -6
- package/src/core/ui-packs/pt.ts +7 -6
- package/src/core/ui-packs/ro.ts +10 -7
- package/src/core/ui-packs/ru.ts +10 -7
- package/src/core/ui-packs/sk.ts +10 -7
- package/src/core/ui-packs/sr.ts +10 -7
- package/src/core/ui-packs/sv.ts +10 -7
- package/src/core/ui-packs/th.ts +7 -6
- package/src/core/ui-packs/tr.ts +10 -7
- package/src/core/ui-packs/uk.ts +10 -7
- package/src/core/ui-packs/vi.ts +7 -6
- package/src/core/ui-packs/zh-tw.ts +7 -6
- package/src/core/ui-packs/zh.ts +7 -6
- package/src/core/unrecognized-keys.ts +10 -0
- package/src/core/version-cut.ts +116 -8
- package/src/deploy/adapter-output.ts +57 -97
- package/src/deploy/adapters/cloudflare.ts +39 -0
- package/src/deploy/adapters/index.ts +41 -0
- package/src/deploy/adapters/netlify.ts +34 -0
- package/src/deploy/adapters/node.ts +34 -0
- package/src/deploy/adapters/registry.ts +127 -0
- package/src/deploy/adapters/types.ts +92 -0
- package/src/deploy/adapters/vercel.ts +35 -0
- package/src/deploy/artifacts.ts +55 -27
- package/src/deploy/cloudflare-negotiation.ts +179 -100
- package/src/deploy/function-bundle.ts +18 -3
- package/src/deploy/headers.ts +124 -23
- package/src/deploy/node-headers.ts +198 -0
- package/src/deploy/platforms/cloudflare.ts +312 -0
- package/src/deploy/platforms/index.ts +67 -0
- package/src/deploy/platforms/netlify.ts +52 -0
- package/src/deploy/platforms/node.ts +40 -0
- package/src/deploy/platforms/paths.ts +42 -0
- package/src/deploy/platforms/static.ts +29 -0
- package/src/deploy/platforms/types.ts +112 -0
- package/src/deploy/platforms/vercel.ts +193 -0
- package/src/deploy/redirects.ts +30 -18
- package/src/deploy/robots.ts +3 -3
- package/src/deploy/rss.ts +2 -2
- package/src/deploy/sitemap.ts +2 -2
- package/src/deploy/vercel-negotiation.ts +2 -2
- package/src/eval/agents.ts +32 -1
- package/src/eval/findings.ts +19 -11
- package/src/eval/report.ts +10 -2
- package/src/markdown/external-links.ts +65 -0
- package/src/markdown/include.ts +45 -27
- package/src/markdown/index.ts +34 -9
- package/src/markdown/inline-code.ts +12 -6
- package/src/markdown/relative-links.ts +324 -0
- package/src/markdown/themes.ts +3 -3
- package/src/migrate/migrate.ts +149 -0
- package/src/openapi/parse.ts +64 -16
- package/src/openapi/proxy.ts +62 -10
- package/src/openapi/references.ts +147 -147
- package/src/openapi/render-mdx.ts +32 -10
- package/src/openapi/scalar.ts +15 -13
- package/src/openapi/sentence.ts +14 -0
- package/src/openapi/source.ts +37 -21
- package/src/openapi/spec-dependency-error.ts +15 -0
- package/src/reference/asyncapi.ts +83 -0
- package/src/reference/graphql.ts +89 -0
- package/src/reference/index.ts +40 -0
- package/src/reference/openapi.ts +83 -0
- package/src/reference/options.ts +201 -0
- package/src/reference/scalar.ts +136 -0
- package/src/reference/schema.ts +88 -0
- package/src/registry/eject.ts +109 -53
- package/src/search/adapters/algolia.ts +46 -0
- package/src/search/adapters/flexsearch.ts +29 -0
- package/src/search/adapters/index.ts +39 -0
- package/src/search/adapters/mixedbread.ts +39 -0
- package/src/search/adapters/orama-cloud.ts +51 -0
- package/src/search/adapters/orama.ts +24 -0
- package/src/search/adapters/pagefind.ts +27 -0
- package/src/search/adapters/registry.ts +131 -0
- package/src/search/adapters/types.ts +46 -0
- package/src/search/adapters/typesense.ts +57 -0
- package/src/search/build.ts +8 -4
- package/src/search/documents.ts +8 -2
- package/src/search/orama-index.ts +1 -1
- package/src/search/sync/algolia.ts +12 -11
- package/src/search/sync/index.ts +35 -20
- package/src/search/sync/orama-cloud.ts +12 -9
- package/src/search/sync/typesense.ts +15 -13
- package/src/sources/contentful.ts +63 -0
- package/src/sources/custom.ts +38 -0
- package/src/sources/filesystem.ts +51 -0
- package/src/sources/github-releases.ts +52 -0
- package/src/sources/index.ts +60 -0
- package/src/sources/mdx-remote.ts +76 -0
- package/src/sources/notion.ts +63 -0
- package/src/sources/obsidian.ts +38 -0
- package/src/sources/payload.ts +60 -0
- package/src/sources/registry.ts +182 -0
- package/src/sources/sanity.ts +66 -0
- package/src/sources/shared.ts +52 -0
- package/src/sources/strapi.ts +58 -0
- package/src/theme/entry.ts +24 -2
- package/src/translate/report.ts +40 -7
- package/src/upgrade/upgrade.ts +499 -0
- package/dist/cli/chunk-0qymqwzz.js +0 -164
- package/dist/cli/chunk-0qymqwzz.js.map +0 -15
- package/dist/cli/chunk-1jefwnfs.js.map +0 -48
- package/dist/cli/chunk-2mzebbbz.js +0 -69
- package/dist/cli/chunk-2z47ypj8.js.map +0 -11
- package/dist/cli/chunk-4x36ddpw.js.map +0 -11
- package/dist/cli/chunk-5093q3n7.js +0 -68
- package/dist/cli/chunk-5093q3n7.js.map +0 -10
- package/dist/cli/chunk-5qk08vmp.js.map +0 -11
- package/dist/cli/chunk-7s8hm3b6.js +0 -5347
- package/dist/cli/chunk-7s8hm3b6.js.map +0 -58
- package/dist/cli/chunk-8cjtbafj.js.map +0 -13
- package/dist/cli/chunk-97r59kpr.js +0 -381
- package/dist/cli/chunk-97r59kpr.js.map +0 -12
- package/dist/cli/chunk-ahnw3kxw.js.map +0 -15
- package/dist/cli/chunk-b27xqwn9.js.map +0 -10
- package/dist/cli/chunk-bf6bt1xt.js +0 -185
- package/dist/cli/chunk-bf6bt1xt.js.map +0 -11
- package/dist/cli/chunk-cjtn640a.js.map +0 -10
- package/dist/cli/chunk-ct47dqpx.js.map +0 -11
- package/dist/cli/chunk-esphfr8p.js +0 -107
- package/dist/cli/chunk-esphfr8p.js.map +0 -11
- package/dist/cli/chunk-ex56aa81.js +0 -1016
- package/dist/cli/chunk-ex56aa81.js.map +0 -13
- package/dist/cli/chunk-garjf5z9.js +0 -30
- package/dist/cli/chunk-garjf5z9.js.map +0 -10
- package/dist/cli/chunk-js7saxwm.js +0 -1045
- package/dist/cli/chunk-js7saxwm.js.map +0 -22
- package/dist/cli/chunk-k79xp7av.js.map +0 -39
- package/dist/cli/chunk-ps4m1xh4.js.map +0 -15
- package/dist/cli/chunk-q4rae3bg.js +0 -60
- package/dist/cli/chunk-q4rae3bg.js.map +0 -10
- package/dist/cli/chunk-rz9jmfhz.js +0 -108
- package/dist/cli/chunk-rz9jmfhz.js.map +0 -10
- package/dist/cli/chunk-vh9w1sgp.js +0 -73
- package/dist/cli/chunk-vh9w1sgp.js.map +0 -10
- package/dist/cli/chunk-vrfp10qk.js +0 -81
- package/dist/cli/chunk-vrfp10qk.js.map +0 -10
- package/dist/cli/chunk-yg63d42r.js.map +0 -34
- package/docs/advanced/api-reference.mdx +0 -240
- package/docs/configuration/ask-ai.mdx +0 -256
- package/docs/reference/cli.mdx +0 -197
- package/skills/blume-migrate/assets/oxfmt@0.55.0.patch +0 -20
- package/src/components/content/changelog-element.ts +0 -69
- package/src/search/providers.ts +0 -91
- /package/dist/cli/{chunk-vacwm2hv.js.map → chunk-27g6wdth.js.map} +0 -0
- /package/dist/cli/{chunk-dwgcp5sm.js.map → chunk-ce574jw2.js.map} +0 -0
- /package/dist/cli/{chunk-e7f42gdj.js.map → chunk-fxypxtvm.js.map} +0 -0
- /package/dist/cli/{chunk-nn13znc2.js.map → chunk-zxcczpyx.js.map} +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import Ask from "blume:ask";
|
|
3
3
|
import data from "blume:data";
|
|
4
4
|
import { withBase } from "../islands/base-path.ts";
|
|
5
|
-
import {
|
|
5
|
+
import { NEW_TAB_ATTRS, newTabAttrs } from "../../core/new-tab.ts";
|
|
6
6
|
import type { ComponentOverride } from "../../core/define-components.ts";
|
|
7
7
|
import { EN_UI } from "../../core/i18n-ui.ts";
|
|
8
8
|
import type { UIStrings } from "../../core/i18n-ui.ts";
|
|
@@ -34,13 +34,18 @@ interface Props {
|
|
|
34
34
|
route: string;
|
|
35
35
|
searchEnabled: boolean;
|
|
36
36
|
/**
|
|
37
|
-
*
|
|
38
|
-
*
|
|
37
|
+
* Active locale of the page, forwarded to the `Logo` slot so the brand link
|
|
38
|
+
* resolves to the locale's root like the tabs beside it.
|
|
39
|
+
*/
|
|
40
|
+
locale?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Whether the search modal offers a hand-off to the assistant. Defaults to whether
|
|
43
|
+
* the assistant is configured, so no page has to pass it; a layout can still opt a
|
|
39
44
|
* shell out explicitly.
|
|
40
45
|
*/
|
|
41
|
-
|
|
42
|
-
/** Localized
|
|
43
|
-
|
|
46
|
+
assistantEnabled?: boolean;
|
|
47
|
+
/** Localized assistant strings for the active locale. */
|
|
48
|
+
assistantStrings?: UIStrings["assistant"];
|
|
44
49
|
// The mobile menu button toggles the docs sidebar drawer; custom pages
|
|
45
50
|
// without a sidebar (e.g. a landing page) pass `false` to hide it.
|
|
46
51
|
hasSidebar?: boolean;
|
|
@@ -71,6 +76,12 @@ interface Props {
|
|
|
71
76
|
* the whole header.
|
|
72
77
|
*/
|
|
73
78
|
layout?: Record<string, ComponentOverride>;
|
|
79
|
+
/**
|
|
80
|
+
* Start the header see-through, with its chrome in white, so it can sit over
|
|
81
|
+
* a dark hero at the top of the page; it returns to the frosted bar as soon
|
|
82
|
+
* as the page scrolls (`PageLayout`'s `transparentHeader`).
|
|
83
|
+
*/
|
|
84
|
+
transparent?: boolean;
|
|
74
85
|
}
|
|
75
86
|
|
|
76
87
|
const {
|
|
@@ -79,11 +90,12 @@ const {
|
|
|
79
90
|
navigation,
|
|
80
91
|
route,
|
|
81
92
|
searchEnabled,
|
|
82
|
-
|
|
93
|
+
locale,
|
|
94
|
+
// `config.assistant` is null whenever the assistant is off, so the header is the one place
|
|
83
95
|
// that has to know — the Ask trigger below and the search modal's hand-off to
|
|
84
96
|
// it both switch on this, and every page gets both for free.
|
|
85
|
-
|
|
86
|
-
|
|
97
|
+
assistantEnabled = Boolean(data.config.assistant),
|
|
98
|
+
assistantStrings,
|
|
87
99
|
hasSidebar = true,
|
|
88
100
|
hasDrawer = true,
|
|
89
101
|
searchStrings,
|
|
@@ -94,6 +106,7 @@ const {
|
|
|
94
106
|
searchLocale,
|
|
95
107
|
searchVersion = null,
|
|
96
108
|
layout = {},
|
|
109
|
+
transparent = false,
|
|
97
110
|
} = Astro.props;
|
|
98
111
|
|
|
99
112
|
// Merge over the English defaults so a label missing from a translation (or
|
|
@@ -143,6 +156,12 @@ const ctaClass = [
|
|
|
143
156
|
// for the swap (next-themes' disableTransitionOnChange trick), force a
|
|
144
157
|
// synchronous style flush, then restore them on the next tick.
|
|
145
158
|
//
|
|
159
|
+
// Both the theme toggle and the banner dismiss change the page first and only
|
|
160
|
+
// then remember the choice: localStorage throws where storage is blocked
|
|
161
|
+
// (Safari "Block All Cookies", sandboxed iframes), and a throw before the DOM
|
|
162
|
+
// change would leave the toggle dead with transitions switched off for good.
|
|
163
|
+
// There the choice simply isn't remembered.
|
|
164
|
+
//
|
|
146
165
|
// The mobile drawer sits below the sticky header, but the banner above the
|
|
147
166
|
// header has no fixed height (its text wraps), so the drawer's top offset can't
|
|
148
167
|
// be static: on open we measure the header's on-screen bottom edge into
|
|
@@ -150,16 +169,31 @@ const ctaClass = [
|
|
|
150
169
|
// so the offset can't drift while open, and re-measure when a banner dismiss or
|
|
151
170
|
// a resize/rotation moves the header. Crossing into the desktop breakpoint
|
|
152
171
|
// (64rem, Tailwind `lg`) closes the drawer so the scroll lock can't outlive it.
|
|
153
|
-
|
|
172
|
+
// The rest of the drawer's behavior — the toggle's `aria-expanded`, Escape to
|
|
173
|
+
// close, and the inert page behind it — follows the same attribute from the
|
|
174
|
+
// layouts' drawer-inert.ts.
|
|
175
|
+
// Transparent header: flag the bar as scrolled once the page moves off the
|
|
176
|
+
// top so the stylesheet below can swap it back to the frosted look. `sync`
|
|
177
|
+
// re-queries the header each time, so the one listener a real load installs
|
|
178
|
+
// keeps working across client-router swaps (and no-ops on pages without it).
|
|
179
|
+
// The router re-runs this inline script on every swap into a transparent-header
|
|
180
|
+
// page, so it syncs that page each time but installs the listeners only once
|
|
181
|
+
// per real load, behind a window flag.
|
|
182
|
+
const transparentScript = `(()=>{const sync=()=>{const h=document.querySelector("[data-blume-header-transparent]");if(h){h.toggleAttribute("data-blume-header-scrolled",scrollY>8);}};sync();if(window.__blumeTransparentHeader){return;}window.__blumeTransparentHeader=true;addEventListener("scroll",sync,{passive:true});document.addEventListener("astro:after-swap",sync);})();`;
|
|
183
|
+
|
|
184
|
+
const clickScript = `(()=>{const dr=()=>{const h=document.querySelector("[data-blume-header]");if(h){document.documentElement.style.setProperty("--blume-drawer-top",h.getBoundingClientRect().bottom+"px");}};const save=(k,v)=>{try{localStorage.setItem(k,v);}catch{}};document.addEventListener("click",(e)=>{const t=e.target.closest("[data-blume-theme-toggle]");if(t){const d=document.documentElement;const next=d.dataset.theme==="dark"?"light":"dark";const s=document.createElement("style");s.appendChild(document.createTextNode("*,*::before,*::after{transition:none!important}"));document.head.appendChild(s);d.dataset.theme=next;window.getComputedStyle(d).opacity;setTimeout(()=>document.head.removeChild(s),1);save("blume-theme",next);}const n=e.target.closest("[data-blume-nav-toggle]");if(n){const d=document.documentElement;const open=d.toggleAttribute("data-blume-nav-open");if(open){dr();}}const b=e.target.closest("[data-blume-banner-dismiss]");if(b){document.documentElement.setAttribute("data-blume-banner-hidden","");requestAnimationFrame(dr);const bar=b.closest("[data-blume-banner]");const k=bar&&bar.getAttribute("data-banner-key");if(k){save("blume-banner:"+k,"1");}}});addEventListener("resize",()=>{const d=document.documentElement;if(!d.hasAttribute("data-blume-nav-open")){return;}if(matchMedia("(min-width:64rem)").matches){d.removeAttribute("data-blume-nav-open");}else{dr();}});})();`;
|
|
154
185
|
---
|
|
155
186
|
|
|
156
187
|
<header
|
|
157
188
|
class="sticky top-0 z-40 flex h-16 items-center gap-3 bg-background/90 px-4 backdrop-blur md:px-6"
|
|
158
189
|
data-blume-header
|
|
190
|
+
data-blume-header-transparent={transparent ? "" : undefined}
|
|
159
191
|
>
|
|
160
192
|
{
|
|
161
193
|
showNavToggle && (
|
|
162
194
|
<button
|
|
195
|
+
aria-controls="blume-nav-drawer"
|
|
196
|
+
aria-expanded="false"
|
|
163
197
|
aria-label={n.toggleNavigation}
|
|
164
198
|
class={`${iconButton} lg:hidden`}
|
|
165
199
|
data-blume-nav-toggle
|
|
@@ -169,7 +203,7 @@ const clickScript = `(()=>{const dr=()=>{const h=document.querySelector("[data-b
|
|
|
169
203
|
</button>
|
|
170
204
|
)
|
|
171
205
|
}
|
|
172
|
-
<LogoSlot logo={logo} site={site} />
|
|
206
|
+
<LogoSlot locale={locale} logo={logo} site={site} />
|
|
173
207
|
{
|
|
174
208
|
navigation.selectors.length > 0 && (
|
|
175
209
|
<div class="flex items-center gap-1.5">
|
|
@@ -216,7 +250,7 @@ const clickScript = `(()=>{const dr=()=>{const h=document.querySelector("[data-b
|
|
|
216
250
|
{
|
|
217
251
|
searchEnabled && (
|
|
218
252
|
<SearchSlot
|
|
219
|
-
|
|
253
|
+
assistantEnabled={assistantEnabled}
|
|
220
254
|
locale={searchLocale}
|
|
221
255
|
navigation={navigation}
|
|
222
256
|
popularPages={data.config.search.popular}
|
|
@@ -229,27 +263,22 @@ const clickScript = `(()=>{const dr=()=>{const h=document.querySelector("[data-b
|
|
|
229
263
|
{
|
|
230
264
|
/* Plain links first, then the one filled button: the reader's eye lands
|
|
231
265
|
on the button because nothing beside it competes. */
|
|
232
|
-
(navigation.actions ?? []).map((action) =>
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
{action.label}
|
|
242
|
-
</a>
|
|
243
|
-
);
|
|
244
|
-
})
|
|
266
|
+
(navigation.actions ?? []).map((action) => (
|
|
267
|
+
<a
|
|
268
|
+
class={actionClass}
|
|
269
|
+
href={withBase(action.href)}
|
|
270
|
+
{...newTabAttrs(action.href)}
|
|
271
|
+
>
|
|
272
|
+
{action.label}
|
|
273
|
+
</a>
|
|
274
|
+
))
|
|
245
275
|
}
|
|
246
276
|
{
|
|
247
277
|
navigation.cta && (
|
|
248
278
|
<a
|
|
249
279
|
class={ctaClass}
|
|
250
280
|
href={withBase(navigation.cta.href)}
|
|
251
|
-
|
|
252
|
-
target={isExternalUrl(navigation.cta.href) ? "_blank" : undefined}
|
|
281
|
+
{...newTabAttrs(navigation.cta.href)}
|
|
253
282
|
>
|
|
254
283
|
{navigation.cta.label}
|
|
255
284
|
<Icon name="chevron-right" size={14} />
|
|
@@ -262,8 +291,7 @@ const clickScript = `(()=>{const dr=()=>{const h=document.querySelector("[data-b
|
|
|
262
291
|
aria-label={n.githubRepository}
|
|
263
292
|
class={iconButton}
|
|
264
293
|
href={navigation.repoUrl}
|
|
265
|
-
|
|
266
|
-
target="_blank"
|
|
294
|
+
{...NEW_TAB_ATTRS}
|
|
267
295
|
>
|
|
268
296
|
<svg
|
|
269
297
|
aria-hidden="true"
|
|
@@ -286,7 +314,42 @@ const clickScript = `(()=>{const dr=()=>{const h=document.querySelector("[data-b
|
|
|
286
314
|
<span class="inline-flex dark:hidden"><Icon name="sun" size={18} /></span>
|
|
287
315
|
<span class="hidden dark:inline-flex"><Icon name="moon" size={18} /></span>
|
|
288
316
|
</button>
|
|
289
|
-
{
|
|
317
|
+
{assistantEnabled && <Ask strings={assistantStrings} />}
|
|
290
318
|
</div>
|
|
291
319
|
</header>
|
|
292
320
|
<script is:inline set:html={clickScript} />
|
|
321
|
+
{transparent && <script is:inline set:html={transparentScript} />}
|
|
322
|
+
|
|
323
|
+
<style is:global>
|
|
324
|
+
/* Transparent header (PageLayout `transparentHeader`): at the top of the
|
|
325
|
+
page the bar has no background and its chrome renders in white so it can
|
|
326
|
+
sit over a dark hero; once scrolled it is the frosted bar again. The color
|
|
327
|
+
tokens are re-declared on the header so every utility inside follows, and
|
|
328
|
+
the search dialog gets the page's own values back so it isn't inverted. */
|
|
329
|
+
:root {
|
|
330
|
+
--blume-header-background: var(--blume-background);
|
|
331
|
+
--blume-header-foreground: var(--blume-foreground);
|
|
332
|
+
--blume-header-muted: var(--blume-muted);
|
|
333
|
+
--blume-header-muted-foreground: var(--blume-muted-foreground);
|
|
334
|
+
--blume-header-border: var(--blume-border);
|
|
335
|
+
}
|
|
336
|
+
[data-blume-header-transparent] {
|
|
337
|
+
transition: background-color 200ms;
|
|
338
|
+
}
|
|
339
|
+
[data-blume-header-transparent]:not([data-blume-header-scrolled]) {
|
|
340
|
+
--blume-background: transparent;
|
|
341
|
+
--blume-foreground: #fff;
|
|
342
|
+
--blume-muted: rgb(255 255 255 / 0.12);
|
|
343
|
+
--blume-muted-foreground: rgb(255 255 255 / 0.75);
|
|
344
|
+
--blume-border: rgb(255 255 255 / 0.25);
|
|
345
|
+
background-color: transparent;
|
|
346
|
+
backdrop-filter: none;
|
|
347
|
+
}
|
|
348
|
+
[data-blume-header-transparent]:not([data-blume-header-scrolled]) dialog {
|
|
349
|
+
--blume-background: var(--blume-header-background);
|
|
350
|
+
--blume-foreground: var(--blume-header-foreground);
|
|
351
|
+
--blume-muted: var(--blume-header-muted);
|
|
352
|
+
--blume-muted-foreground: var(--blume-header-muted-foreground);
|
|
353
|
+
--blume-border: var(--blume-header-border);
|
|
354
|
+
}
|
|
355
|
+
</style>
|
|
@@ -11,6 +11,9 @@ interface Props {
|
|
|
11
11
|
|
|
12
12
|
const { options, label, untranslatedLabel } = Astro.props;
|
|
13
13
|
const current = options.find((option) => option.current);
|
|
14
|
+
// The accessible name carries the visible language name too (WCAG 2.5.3,
|
|
15
|
+
// label in name), so a voice-control user can say "English" to open it.
|
|
16
|
+
const summaryLabel = current ? `${label}: ${current.label}` : label;
|
|
14
17
|
|
|
15
18
|
const iconButton =
|
|
16
19
|
"inline-flex h-9 cursor-pointer items-center gap-1.5 rounded-full border border-border bg-background px-3 text-muted-foreground text-sm transition-colors hover:border-foreground hover:text-foreground";
|
|
@@ -22,7 +25,7 @@ const menuRowClass =
|
|
|
22
25
|
options.length > 1 && (
|
|
23
26
|
<details class="group relative" data-blume-dropdown>
|
|
24
27
|
<summary
|
|
25
|
-
aria-label={
|
|
28
|
+
aria-label={summaryLabel}
|
|
26
29
|
class={`${iconButton} list-none [&::-webkit-details-marker]:hidden`}
|
|
27
30
|
>
|
|
28
31
|
<Icon name="globe" size={16} />
|
|
@@ -1,17 +1,26 @@
|
|
|
1
1
|
---
|
|
2
|
+
import data from "blume:data";
|
|
2
3
|
import { withBase } from "../islands/base-path.ts";
|
|
3
4
|
// The site brand: the logo mark (inline SVG so a `currentColor` mark follows the
|
|
4
5
|
// theme, or light/dark `<img>` variants) followed by the site title, wrapped in
|
|
5
6
|
// a link to the brand href. Extracted from the header so it can be replaced on
|
|
6
7
|
// its own through the `Logo` layout slot (`defineComponents({ layout: { Logo } })`).
|
|
7
8
|
import type { BlumeLogo } from "../../core/data.ts";
|
|
9
|
+
import { localizeInternalPath } from "../../core/i18n.ts";
|
|
8
10
|
|
|
9
11
|
interface Props {
|
|
10
12
|
site: { title: string };
|
|
11
13
|
logo?: BlumeLogo | null;
|
|
14
|
+
/**
|
|
15
|
+
* Active locale of the page. The brand link follows it the way the header
|
|
16
|
+
* tabs do (`/` -> `/en` under a prefixed locale), so clicking the logo never
|
|
17
|
+
* drops a reader out of the language they were reading. Absent, the link is
|
|
18
|
+
* emitted as configured.
|
|
19
|
+
*/
|
|
20
|
+
locale?: string;
|
|
12
21
|
}
|
|
13
22
|
|
|
14
|
-
const { site, logo } = Astro.props;
|
|
23
|
+
const { site, logo, locale } = Astro.props;
|
|
15
24
|
|
|
16
25
|
// The logo is resolved upstream: an inline `svg` (so a currentColor mark follows
|
|
17
26
|
// the theme) or image URL(s) for an <img>.
|
|
@@ -21,7 +30,19 @@ const logoDark = logo?.dark ?? logo?.light;
|
|
|
21
30
|
const logoLightDimensions = logo?.dimensions?.light;
|
|
22
31
|
const logoDarkDimensions = logo?.dimensions?.dark ?? logo?.dimensions?.light;
|
|
23
32
|
const logoAlt = logo?.alt ?? "";
|
|
24
|
-
|
|
33
|
+
// The configured `logo.href` (default `/`) is authored in the default locale's
|
|
34
|
+
// path space, like a tab path; localize it for the page's locale. The locale's
|
|
35
|
+
// navigation carries it resolved against the routes the build serves (a custom
|
|
36
|
+
// home page exists only at `/`, so it isn't moved to `/fr`). External and
|
|
37
|
+
// protocol-relative hrefs pass through, and `withBase` layers the deployment
|
|
38
|
+
// base on afterwards, so the locale prefix sits inside the base like every
|
|
39
|
+
// other localized route.
|
|
40
|
+
const configuredHref = logo?.href ?? "/";
|
|
41
|
+
const brandHref =
|
|
42
|
+
locale === undefined
|
|
43
|
+
? configuredHref
|
|
44
|
+
: (data.navigationByLocale[locale]?.brandHref ??
|
|
45
|
+
localizeInternalPath(configuredHref, locale, data.config.i18n));
|
|
25
46
|
// Wordmark beside the mark: the configured `logo.text`, or the site title when
|
|
26
47
|
// it's omitted. An explicit `""` hides it (an image-only logo whose mark already
|
|
27
48
|
// carries the wordmark).
|
|
@@ -33,6 +33,12 @@ const active =
|
|
|
33
33
|
.toSorted((a, b) => b.path.length - a.path.length)[0] ??
|
|
34
34
|
selector.items[0];
|
|
35
35
|
|
|
36
|
+
// The active label rides in the trigger on every screen when it's short (a
|
|
37
|
+
// version like "v2" or "Latest"): on a phone a bare chevron doesn't say what
|
|
38
|
+
// it switches. Longer product names still collapse to the icon there.
|
|
39
|
+
const label = active?.label ?? selector.label;
|
|
40
|
+
const labelClass = label.length <= 6 ? undefined : "max-sm:hidden";
|
|
41
|
+
|
|
36
42
|
const iconButton =
|
|
37
43
|
"inline-flex h-9 cursor-pointer items-center gap-1.5 rounded-full border border-border bg-background px-3 text-muted-foreground text-sm transition-colors hover:border-foreground hover:text-foreground";
|
|
38
44
|
const menuRowClass =
|
|
@@ -47,7 +53,7 @@ const menuRowClass =
|
|
|
47
53
|
class={`${iconButton} list-none [&::-webkit-details-marker]:hidden`}
|
|
48
54
|
>
|
|
49
55
|
{active?.icon && <Icon name={active.icon} size={16} />}
|
|
50
|
-
<span class=
|
|
56
|
+
<span class={labelClass}>{label}</span>
|
|
51
57
|
<Icon
|
|
52
58
|
class="transition-transform group-open:rotate-180"
|
|
53
59
|
name="chevron-down"
|
|
@@ -55,7 +61,8 @@ const menuRowClass =
|
|
|
55
61
|
/>
|
|
56
62
|
</summary>
|
|
57
63
|
<div
|
|
58
|
-
class={`absolute z-50 mt-2 min-w-56 rounded-blume border border-border bg-background p-1 shadow-xl ${align === "end" ? "end-0" : "start-0"}`}
|
|
64
|
+
class={`absolute z-50 mt-2 min-w-56 max-w-[calc(100vw-1rem)] rounded-blume border border-border bg-background p-1 shadow-xl ${align === "end" ? "end-0" : "start-0"}`}
|
|
65
|
+
data-blume-dropdown-panel
|
|
59
66
|
>
|
|
60
67
|
{selector.items.map((item) => (
|
|
61
68
|
<a
|
|
@@ -89,8 +96,12 @@ const menuRowClass =
|
|
|
89
96
|
|
|
90
97
|
<script>
|
|
91
98
|
import { installDropdownDismiss } from "../dropdown-dismiss.ts";
|
|
99
|
+
import { installDropdownClamp } from "./dropdown-clamp.ts";
|
|
92
100
|
|
|
93
101
|
// Outside-click / Escape / focus-out dismissal, shared with the language
|
|
94
102
|
// switcher and the page actions.
|
|
95
103
|
installDropdownDismiss();
|
|
104
|
+
// On a phone the trigger sits mid-header, so an edge-anchored panel can
|
|
105
|
+
// run off the screen; shift it back inside when it opens.
|
|
106
|
+
installDropdownClamp();
|
|
96
107
|
</script>
|
|
@@ -8,6 +8,7 @@ import { withBase } from "../islands/base-path.ts";
|
|
|
8
8
|
import Self from "./NavTree.astro";
|
|
9
9
|
import NavTreeCache from "./NavTreeCache.astro";
|
|
10
10
|
import NavTreeScript from "./NavTreeScript.astro";
|
|
11
|
+
import { isGroupRowCurrent } from "./nav-utils.ts";
|
|
11
12
|
|
|
12
13
|
interface PagePanel {
|
|
13
14
|
id: string;
|
|
@@ -180,7 +181,11 @@ const initialId =
|
|
|
180
181
|
<Icon class="rtl:-scale-x-100" name="arrow-left" size={16} />
|
|
181
182
|
</button>
|
|
182
183
|
<a
|
|
183
|
-
aria-current={
|
|
184
|
+
aria-current={
|
|
185
|
+
isGroupRowCurrent(panel.node, currentRoute)
|
|
186
|
+
? "page"
|
|
187
|
+
: undefined
|
|
188
|
+
}
|
|
184
189
|
class="flex-1 truncate rounded-[0.65rem] px-1 py-1 font-semibold text-foreground text-sm transition-colors hover:bg-muted"
|
|
185
190
|
href={withBase(panel.route)}
|
|
186
191
|
>
|
|
@@ -329,7 +334,9 @@ const initialId =
|
|
|
329
334
|
{item.route ? (
|
|
330
335
|
<a
|
|
331
336
|
aria-current={
|
|
332
|
-
item
|
|
337
|
+
isGroupRowCurrent(item, currentRoute)
|
|
338
|
+
? "page"
|
|
339
|
+
: undefined
|
|
333
340
|
}
|
|
334
341
|
class="blume-nav-summary-link"
|
|
335
342
|
href={withBase(item.route)}
|
|
@@ -412,7 +419,9 @@ const initialId =
|
|
|
412
419
|
<p class="blume-nav-heading">
|
|
413
420
|
{item.route ? (
|
|
414
421
|
<a
|
|
415
|
-
aria-current={
|
|
422
|
+
aria-current={
|
|
423
|
+
isGroupRowCurrent(item, currentRoute) ? "page" : undefined
|
|
424
|
+
}
|
|
416
425
|
class="blume-nav-heading-link"
|
|
417
426
|
href={withBase(item.route)}
|
|
418
427
|
>
|
|
@@ -77,7 +77,12 @@
|
|
|
77
77
|
}
|
|
78
78
|
const slot = deferredIn(details.querySelector(":scope > [data-nav-src]"));
|
|
79
79
|
if (slot) {
|
|
80
|
-
|
|
80
|
+
// A fragment that can't load (offline, a deploy that dropped it)
|
|
81
|
+
// closes the group again instead of leaving it open and empty; the
|
|
82
|
+
// slot keeps its `data-nav-src`, so the next open retries.
|
|
83
|
+
fillDeferred(slot).catch(() => {
|
|
84
|
+
details.open = false;
|
|
85
|
+
});
|
|
81
86
|
}
|
|
82
87
|
},
|
|
83
88
|
true
|
|
@@ -159,8 +164,17 @@
|
|
|
159
164
|
if (!next) {
|
|
160
165
|
return;
|
|
161
166
|
}
|
|
162
|
-
// A deferred panel loads its contents before it slides in.
|
|
163
|
-
|
|
167
|
+
// A deferred panel loads its contents before it slides in. When its
|
|
168
|
+
// fragment can't load (offline, a deploy that dropped it), the drill-in
|
|
169
|
+
// follows the section's own page link — the panel's title — instead of
|
|
170
|
+
// leaving the click dead. A section with no page stays put, and the next
|
|
171
|
+
// drill-in retries the fetch.
|
|
172
|
+
try {
|
|
173
|
+
await fillDeferred(next);
|
|
174
|
+
} catch {
|
|
175
|
+
next.querySelector<HTMLAnchorElement>("a[href]")?.click();
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
164
178
|
const prev = this.active;
|
|
165
179
|
if (prev === next) {
|
|
166
180
|
return;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
import { EN_UI } from "../../core/i18n-ui.ts";
|
|
3
3
|
import type { UIStrings } from "../../core/i18n-ui.ts";
|
|
4
|
+
import { NEW_TAB_ATTRS } from "../../core/new-tab.ts";
|
|
4
5
|
import { openInChatProviders } from "../../core/open-in-chat.ts";
|
|
5
6
|
import type { OpenInChatProvider } from "../../core/open-in-chat.ts";
|
|
6
7
|
import { GITHUB_MARK } from "../github-mark.ts";
|
|
@@ -112,7 +113,7 @@ const menuRowClass =
|
|
|
112
113
|
>
|
|
113
114
|
{
|
|
114
115
|
editUrl && (
|
|
115
|
-
<a class={rowClass} href={editUrl}
|
|
116
|
+
<a class={rowClass} href={editUrl} {...NEW_TAB_ATTRS}>
|
|
116
117
|
<span set:html={GITHUB_LOGO} />
|
|
117
118
|
{a.edit}
|
|
118
119
|
</a>
|
|
@@ -192,8 +193,7 @@ const menuRowClass =
|
|
|
192
193
|
<a
|
|
193
194
|
class={menuRowClass}
|
|
194
195
|
data-open-in={provider.key}
|
|
195
|
-
|
|
196
|
-
target="_blank"
|
|
196
|
+
{...NEW_TAB_ATTRS}
|
|
197
197
|
>
|
|
198
198
|
<span set:html={LOGOS[provider.key]} />
|
|
199
199
|
<span class="flex-1">{provider.label}</span>
|
|
@@ -34,7 +34,12 @@ const buttonClass =
|
|
|
34
34
|
{f.no}
|
|
35
35
|
</button>
|
|
36
36
|
</div>
|
|
37
|
-
<p
|
|
37
|
+
<p
|
|
38
|
+
class="hidden text-muted-foreground text-sm focus:outline-none"
|
|
39
|
+
data-feedback-thanks
|
|
40
|
+
role="status"
|
|
41
|
+
tabindex="-1"
|
|
42
|
+
>
|
|
38
43
|
{f.thanks}
|
|
39
44
|
</p>
|
|
40
45
|
</section>
|
|
@@ -61,6 +66,11 @@ const buttonClass =
|
|
|
61
66
|
});
|
|
62
67
|
actions?.classList.add("hidden");
|
|
63
68
|
thanks?.classList.remove("hidden");
|
|
69
|
+
// The clicked button just disappeared under focus; hand focus to the
|
|
70
|
+
// (live) thanks line so the reader isn't dropped at the top of the page.
|
|
71
|
+
if (thanks instanceof HTMLElement) {
|
|
72
|
+
thanks.focus();
|
|
73
|
+
}
|
|
64
74
|
});
|
|
65
75
|
}
|
|
66
76
|
};
|
|
@@ -23,10 +23,12 @@ import type {
|
|
|
23
23
|
BlumeDataConfig,
|
|
24
24
|
BlumeFavicon,
|
|
25
25
|
BlumeLogo,
|
|
26
|
+
DiscoveryHeadLinks,
|
|
26
27
|
} from "../../core/data.ts";
|
|
27
28
|
import data from "blume:data";
|
|
28
29
|
import { EN_UI } from "../../core/i18n-ui.ts";
|
|
29
30
|
import type { UIStrings } from "../../core/i18n-ui.ts";
|
|
31
|
+
import { NEW_TAB_HINT_ID } from "../../core/new-tab.ts";
|
|
30
32
|
import type { FontHead } from "../../theme/fonts.ts";
|
|
31
33
|
import type { LocaleSwitchOption, Navigation } from "../../core/types.ts";
|
|
32
34
|
import {
|
|
@@ -36,13 +38,14 @@ import {
|
|
|
36
38
|
} from "../../og/dimensions.ts";
|
|
37
39
|
import { buildStructuredData } from "../../seo/jsonld.ts";
|
|
38
40
|
import { normalizeXHandle } from "../../seo/x-handle.ts";
|
|
39
|
-
import { withBase } from "../islands/base-path.ts";
|
|
41
|
+
import { stripBase, withBase } from "../islands/base-path.ts";
|
|
40
42
|
import { pageDirection, pageLocale } from "./page-locale.ts";
|
|
41
43
|
import { searchLocaleFor } from "./search-locale.ts";
|
|
42
44
|
import "blume:theme";
|
|
43
45
|
import { ClientRouter } from "astro:transitions";
|
|
44
46
|
import Analytics from "./Analytics.astro";
|
|
45
47
|
import Banner from "./Banner.astro";
|
|
48
|
+
import DiscoveryLinks from "./DiscoveryLinks.astro";
|
|
46
49
|
import Favicon from "./Favicon.astro";
|
|
47
50
|
import Fonts from "./Fonts.astro";
|
|
48
51
|
import {
|
|
@@ -65,18 +68,28 @@ interface Props {
|
|
|
65
68
|
/**
|
|
66
69
|
* Title/description/route for `<title>`, `og:*`, and the header active link.
|
|
67
70
|
* Unlike RootLayout, `title` is used verbatim (no `- siteTitle` suffix), since
|
|
68
|
-
* marketing pages usually set their own complete document title.
|
|
71
|
+
* marketing pages usually set their own complete document title. An omitted
|
|
72
|
+
* `route` is read from the request URL (base-less), so a page that never
|
|
73
|
+
* passes one still gets its own canonical, OG card, and Markdown mirror
|
|
74
|
+
* rather than the homepage's.
|
|
69
75
|
*/
|
|
70
76
|
page?: { title?: string; description?: string; route?: string };
|
|
71
77
|
themeMode: "system" | "light" | "dark";
|
|
72
78
|
fontCssVars?: (string | FontHead)[];
|
|
73
79
|
searchEnabled: boolean;
|
|
74
80
|
/**
|
|
75
|
-
* Opt this page out of the header's
|
|
76
|
-
*
|
|
81
|
+
* Opt this page out of the header's assistant trigger. Defaults to whether the
|
|
82
|
+
* assistant is configured, so a custom page gets the same trigger the docs pages have
|
|
77
83
|
* without wiring anything up.
|
|
78
84
|
*/
|
|
79
|
-
|
|
85
|
+
assistantEnabled?: boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Start the header see-through, with its chrome in white, so it can sit over
|
|
88
|
+
* a dark hero at the top of the page; it returns to the frosted bar as soon
|
|
89
|
+
* as the page scrolls. The hero has to run under the header for this to
|
|
90
|
+
* show: pull it up by the header's height (`-mt-16`) and pad its top.
|
|
91
|
+
*/
|
|
92
|
+
transparentHeader?: boolean;
|
|
80
93
|
/**
|
|
81
94
|
* Absolute site URL (`data.config.site`). When set, `canonical` and the
|
|
82
95
|
* generated `og:image` for this route are derived from it automatically;
|
|
@@ -105,6 +118,14 @@ interface Props {
|
|
|
105
118
|
* matching RootLayout.
|
|
106
119
|
*/
|
|
107
120
|
structuredDataEnabled?: boolean;
|
|
121
|
+
/**
|
|
122
|
+
* Which agent-discovery resources exist, advertised as `describedby` head
|
|
123
|
+
* links plus the AI Catalog/ARD pair — the same `DiscoveryLinks` partial
|
|
124
|
+
* RootLayout renders. A custom page gets this from the `blume:data` snapshot
|
|
125
|
+
* without wiring anything up; pass it to override, or `null` to drop the
|
|
126
|
+
* links.
|
|
127
|
+
*/
|
|
128
|
+
discovery?: DiscoveryHeadLinks | null;
|
|
108
129
|
/**
|
|
109
130
|
* X (Twitter) attribution (`data.config.x`): the site's account and an author
|
|
110
131
|
* handle, emitted as `twitter:site`/`twitter:creator`.
|
|
@@ -142,7 +163,8 @@ const {
|
|
|
142
163
|
themeMode,
|
|
143
164
|
fontCssVars,
|
|
144
165
|
searchEnabled,
|
|
145
|
-
|
|
166
|
+
assistantEnabled,
|
|
167
|
+
transparentHeader,
|
|
146
168
|
siteUrl,
|
|
147
169
|
ogEnabled,
|
|
148
170
|
ogImage,
|
|
@@ -150,6 +172,7 @@ const {
|
|
|
150
172
|
ogImageSize,
|
|
151
173
|
canonical,
|
|
152
174
|
structuredDataEnabled,
|
|
175
|
+
discovery = data.config.discovery,
|
|
153
176
|
x,
|
|
154
177
|
noindex,
|
|
155
178
|
locale: localeProp,
|
|
@@ -180,14 +203,30 @@ const navStrings = { ...EN_UI.nav, ...strings.nav };
|
|
|
180
203
|
const searchLocale = searchLocaleFor(data.config.i18n, locale);
|
|
181
204
|
const pageTitle = page?.title ?? site.title;
|
|
182
205
|
const description = page?.description ?? site.description;
|
|
183
|
-
|
|
206
|
+
// An omitted `page.route` falls back to the request pathname with the
|
|
207
|
+
// deployment base stripped, not to `/`: a non-root page that copies the
|
|
208
|
+
// homepage example would otherwise claim the homepage's canonical, OG card,
|
|
209
|
+
// and `/index.md` mirror. `trailingSlash: "never"` keeps the pathname bare.
|
|
210
|
+
const route =
|
|
211
|
+
page?.route ??
|
|
212
|
+
stripBase(import.meta.env.BASE_URL ?? "/", Astro.url.pathname);
|
|
184
213
|
const activeTab = currentTabForRoute(navigation.tabs, route, navigation.root);
|
|
185
214
|
|
|
215
|
+
// A custom page has no raw-Markdown mirror — except the homepage: `/index.md`
|
|
216
|
+
// always exists (see `markdownRoutePaths`; a landing page gets the synthesized
|
|
217
|
+
// llms.txt index), and the homepage HTTP `Link` header already advertises it,
|
|
218
|
+
// so the head is its HTML counterpart on hosts that can't set that header.
|
|
219
|
+
// Advertising a mirror for any other custom route would 404.
|
|
220
|
+
const markdownMirror = route === "/" ? withBase("/index.md") : null;
|
|
221
|
+
|
|
186
222
|
// Derive canonical + og:image from the site URL the same way the catch-all does
|
|
187
223
|
// for content pages, so a custom page gets both for free. The matching OG card
|
|
188
224
|
// (`/og/<slug>.png`, `index` for the home) is generated for static custom pages
|
|
189
|
-
// when `og.enabled
|
|
225
|
+
// when `og.enabled` — not for a dynamic route (`[param]`), whose concrete URLs
|
|
226
|
+
// can't be enumerated up front, so such a page advertises no generated card
|
|
227
|
+
// rather than one that 404s. Explicit props still win.
|
|
190
228
|
const ogSlug = route === "/" ? "index" : route.slice(1);
|
|
229
|
+
const ogCardGenerated = !Astro.routePattern.includes("[");
|
|
191
230
|
// Absolute URLs carry the deployment base too (`site + base + route`), since the
|
|
192
231
|
// page is served under it. `withBase` handles a root base as a no-op.
|
|
193
232
|
const basedRoute = withBase(route);
|
|
@@ -211,7 +250,7 @@ const absolutizeOgImage = (value: string): string =>
|
|
|
211
250
|
value.startsWith("/") && siteBase ? `${siteBase}${withBase(value)}` : value;
|
|
212
251
|
const resolvedOgImage = ogImage
|
|
213
252
|
? absolutizeOgImage(ogImage)
|
|
214
|
-
: ogEnabled && siteBase
|
|
253
|
+
: ogEnabled && ogCardGenerated && siteBase
|
|
215
254
|
? `${siteBase}${encodeURI(withBase(`/og/${ogSlug}.png`))}`
|
|
216
255
|
: null;
|
|
217
256
|
// Only the generated card has a known size and format, so its dimensions are
|
|
@@ -321,6 +360,9 @@ createIconSprite(Astro.locals);
|
|
|
321
360
|
{description && <meta content={description} name="twitter:description" />}
|
|
322
361
|
{xSite && <meta content={xSite} name="twitter:site" />}
|
|
323
362
|
{xCreator && <meta content={xCreator} name="twitter:creator" />}
|
|
363
|
+
{/* Agent discovery on every page, so a custom page built on PageLayout is
|
|
364
|
+
covered without passing a prop, the same way the docs pages are. */}
|
|
365
|
+
<DiscoveryLinks discovery={discovery} markdownMirror={markdownMirror} />
|
|
324
366
|
{
|
|
325
367
|
structuredDataJson && (
|
|
326
368
|
<script
|
|
@@ -343,11 +385,14 @@ createIconSprite(Astro.locals);
|
|
|
343
385
|
class="absolute start-[-999px] top-0 z-[100] bg-accent px-4 py-2 text-accent-foreground focus:start-0"
|
|
344
386
|
href="#blume-content">{strings.page.skipToContent}</a
|
|
345
387
|
>
|
|
388
|
+
{/* Every new-tab link's aria-describedby target (see core/new-tab.ts). */}
|
|
389
|
+
<span hidden id={NEW_TAB_HINT_ID}>{navStrings.opensInNewTab}</span>
|
|
346
390
|
<Banner banner={banner} strings={strings.banner} />
|
|
347
391
|
<Header
|
|
348
|
-
|
|
349
|
-
|
|
392
|
+
assistantEnabled={assistantEnabled}
|
|
393
|
+
assistantStrings={strings.assistant}
|
|
350
394
|
hasSidebar={false}
|
|
395
|
+
locale={locale}
|
|
351
396
|
localeSwitch={localeSwitch}
|
|
352
397
|
logo={logo}
|
|
353
398
|
navStrings={navStrings}
|
|
@@ -358,6 +403,7 @@ createIconSprite(Astro.locals);
|
|
|
358
403
|
searchStrings={strings.search}
|
|
359
404
|
site={site}
|
|
360
405
|
switcherStrings={strings.languageSwitcher}
|
|
406
|
+
transparent={transparentHeader}
|
|
361
407
|
/>
|
|
362
408
|
<main id="blume-content"><slot /></main>
|
|
363
409
|
<slot name="footer" />
|
|
@@ -374,6 +420,7 @@ createIconSprite(Astro.locals);
|
|
|
374
420
|
aria-label={navStrings.navigation}
|
|
375
421
|
class="fixed top-[var(--blume-drawer-top,4rem)] start-0 z-[35] h-[calc(100dvh-var(--blume-drawer-top,4rem))] w-64 max-w-[80vw] -translate-x-[105%] overflow-y-auto border-border border-e bg-background px-5 pt-4 pb-6 transition-transform rtl:translate-x-[105%] [:where([data-blume-nav-open])_&]:translate-x-0! lg:hidden"
|
|
376
422
|
data-blume-nav-drawer
|
|
423
|
+
id="blume-nav-drawer"
|
|
377
424
|
>
|
|
378
425
|
<nav aria-label={navStrings.sections}>
|
|
379
426
|
<ul class="m-0 list-none p-0">
|