blume 2.1.0 → 2.1.2
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/CHANGELOG.md +110 -0
- package/dist/cli/{chunk-ga0pf4aj.js → chunk-0n9xkp3d.js} +12 -3
- package/dist/cli/{chunk-ga0pf4aj.js.map → chunk-0n9xkp3d.js.map} +3 -3
- package/dist/cli/{chunk-43zcf4gz.js → chunk-0pmb4tr4.js} +541 -368
- package/dist/cli/chunk-0pmb4tr4.js.map +35 -0
- package/dist/cli/{chunk-9geymqns.js → chunk-0w6hs479.js} +15 -15
- package/dist/cli/{chunk-xkz5xbtv.js → chunk-124fvmzq.js} +2802 -1422
- package/dist/cli/chunk-124fvmzq.js.map +220 -0
- package/dist/cli/chunk-150jk7km.js +52 -0
- package/dist/cli/chunk-150jk7km.js.map +10 -0
- package/dist/cli/{chunk-y4ykbark.js → chunk-1f882900.js} +2 -2
- package/dist/cli/{chunk-5ffywsmb.js → chunk-297ajdcv.js} +8 -6
- package/dist/cli/{chunk-5ffywsmb.js.map → chunk-297ajdcv.js.map} +3 -3
- package/dist/cli/{chunk-h2a48yhd.js → chunk-32khwcb6.js} +120 -16
- package/dist/cli/{chunk-h2a48yhd.js.map → chunk-32khwcb6.js.map} +10 -10
- package/dist/cli/{chunk-5cg2rzgf.js → chunk-36bxs9c7.js} +20 -49
- package/dist/cli/{chunk-5cg2rzgf.js.map → chunk-36bxs9c7.js.map} +4 -5
- package/dist/cli/{chunk-py62fewh.js → chunk-53jqw8z0.js} +3 -3
- package/dist/cli/{chunk-5wj2qwn2.js → chunk-58bt3hag.js} +4 -4
- package/dist/cli/{chunk-e7vvk5ya.js → chunk-5cmts6dv.js} +3 -3
- package/dist/cli/{chunk-y5h4r2y0.js → chunk-60hz265r.js} +15 -5
- package/dist/cli/chunk-60hz265r.js.map +10 -0
- package/dist/cli/chunk-74wfhv79.js +65 -0
- package/dist/cli/chunk-74wfhv79.js.map +10 -0
- package/dist/cli/{chunk-g2z9x01v.js → chunk-9qzgg6mj.js} +3 -3
- package/dist/cli/{chunk-q3wxxq39.js → chunk-a57yh0h9.js} +5 -5
- package/dist/cli/{chunk-713mngdq.js → chunk-ave1wcbr.js} +76 -10
- package/dist/cli/chunk-ave1wcbr.js.map +14 -0
- package/dist/cli/{chunk-2n4ps1b3.js → chunk-bqxaqn5p.js} +40 -22
- package/dist/cli/chunk-bqxaqn5p.js.map +15 -0
- package/dist/cli/{chunk-jnwj5kjj.js → chunk-bxwhtvw8.js} +20 -7
- package/dist/cli/{chunk-jnwj5kjj.js.map → chunk-bxwhtvw8.js.map} +3 -3
- package/dist/cli/chunk-ckrcm08h.js +324 -0
- package/dist/cli/chunk-ckrcm08h.js.map +14 -0
- package/dist/cli/{chunk-2f3ndkpw.js → chunk-desvm72z.js} +3 -3
- package/dist/cli/{chunk-gp84za0h.js → chunk-dhwtqnnd.js} +2 -2
- package/dist/cli/{chunk-4h8z9vv5.js → chunk-dpy8qdjf.js} +93 -47
- package/dist/cli/chunk-dpy8qdjf.js.map +17 -0
- package/dist/cli/{chunk-2f7n4qzt.js → chunk-dqhg54mr.js} +1 -1
- package/dist/cli/{chunk-0gz36akr.js → chunk-dv2z0rzf.js} +21 -5
- package/dist/cli/chunk-dv2z0rzf.js.map +12 -0
- package/dist/cli/{chunk-cm89scdv.js → chunk-es8h0v3j.js} +9 -11
- package/dist/cli/{chunk-cm89scdv.js.map → chunk-es8h0v3j.js.map} +3 -3
- package/dist/cli/{chunk-zhvd6adm.js → chunk-gfc5fqvf.js} +14 -14
- package/dist/cli/{chunk-nd1821sk.js → chunk-gxtg6ed2.js} +33 -19
- package/dist/cli/chunk-gxtg6ed2.js.map +10 -0
- package/dist/cli/{chunk-p804f3pe.js → chunk-hvcxng5f.js} +6 -6
- package/dist/cli/{chunk-ta27feev.js → chunk-j1x92mx9.js} +21 -2
- package/dist/cli/chunk-j1x92mx9.js.map +10 -0
- package/dist/cli/{chunk-rekqz4qg.js → chunk-k3gr1nm9.js} +19 -16
- package/dist/cli/chunk-k3gr1nm9.js.map +10 -0
- package/dist/cli/{chunk-1n228xqb.js → chunk-kdpzw38a.js} +2 -2
- package/dist/cli/{chunk-cy5bm0j0.js → chunk-ms9z66nz.js} +2 -2
- package/dist/cli/{chunk-cy5bm0j0.js.map → chunk-ms9z66nz.js.map} +2 -2
- package/dist/cli/{chunk-zf748avv.js → chunk-nbyvgnnm.js} +193 -286
- package/dist/cli/chunk-nbyvgnnm.js.map +36 -0
- package/dist/cli/{chunk-6bm0xpgd.js → chunk-s0bdnc7v.js} +2 -2
- package/dist/cli/{chunk-yxmk4pec.js → chunk-sc93apfs.js} +17 -16
- package/dist/cli/{chunk-yxmk4pec.js.map → chunk-sc93apfs.js.map} +3 -3
- package/dist/cli/{chunk-cmtcnh9f.js → chunk-tfycddbt.js} +2 -2
- package/dist/cli/{chunk-9xr4dgee.js → chunk-twy7psdz.js} +29 -16
- package/dist/cli/chunk-twy7psdz.js.map +10 -0
- package/dist/cli/{chunk-ntv4qrt7.js → chunk-y4msrwm9.js} +15 -15
- package/dist/cli/{chunk-yj17vs39.js → chunk-ydp3065p.js} +5 -5
- package/dist/cli/index.js +24 -19
- package/dist/cli/index.js.map +3 -3
- package/dist/types/ai/ask-context.d.ts +6 -2
- package/dist/types/ai/ask.d.ts +24 -5
- package/dist/types/ai/component-markdown.d.ts +2 -0
- package/dist/types/ai/openapi-components.d.ts +4 -1
- package/dist/types/analytics/clics.d.ts +37 -0
- package/dist/types/analytics/index.d.ts +2 -0
- package/dist/types/analytics/schema.d.ts +18 -0
- package/dist/types/astro/integration.d.ts +11 -4
- package/dist/types/astro/markdown-negotiation.d.ts +3 -0
- package/dist/types/astro/pages.d.ts +10 -0
- package/dist/types/cli/init/scaffold.d.ts +1 -1
- package/dist/types/components/content/api-field.d.ts +4 -1
- package/dist/types/components/content/api-page.d.ts +6 -1
- package/dist/types/components/openapi/code-samples.d.ts +29 -0
- package/dist/types/components/openapi/helpers.d.ts +22 -1
- package/dist/types/components/openapi/security.d.ts +10 -0
- package/dist/types/components/openapi/snippets.d.ts +60 -0
- package/dist/types/core/changelog-index.d.ts +8 -0
- package/dist/types/core/config-input.d.ts +37 -6
- package/dist/types/core/data.d.ts +4 -0
- package/dist/types/core/i18n-ui.d.ts +2 -0
- package/dist/types/core/links.d.ts +8 -0
- package/dist/types/core/powered-by.d.ts +12 -0
- package/dist/types/core/probe.d.ts +2 -0
- package/dist/types/core/project-graph.d.ts +6 -0
- package/dist/types/core/redirect-patterns.d.ts +11 -3
- package/dist/types/core/schema.d.ts +228 -3
- package/dist/types/core/sources/cache.d.ts +3 -0
- package/dist/types/core/sources/contentful-rich-text.d.ts +11 -2
- package/dist/types/core/sources/contentful.d.ts +17 -1
- package/dist/types/core/sources/lexical.d.ts +5 -0
- package/dist/types/core/sources/lower.d.ts +10 -2
- package/dist/types/core/sources/normalize.d.ts +20 -1
- package/dist/types/core/sources/notion.d.ts +8 -0
- package/dist/types/core/sources/remote.d.ts +37 -10
- package/dist/types/core/sources/sanity.d.ts +1 -1
- package/dist/types/core/types.d.ts +17 -0
- package/dist/types/deploy/adapter-output.d.ts +2 -1
- package/dist/types/deploy/adapters/cloudflare.d.ts +7 -5
- package/dist/types/deploy/adapters/node.d.ts +58 -23
- package/dist/types/deploy/adapters/registry.d.ts +10 -0
- package/dist/types/deploy/adapters/types.d.ts +3 -2
- package/dist/types/deploy/cloudflare-negotiation.d.ts +5 -2
- package/dist/types/deploy/node-headers.d.ts +12 -4
- package/dist/types/deploy/platforms/cloudflare.d.ts +10 -7
- package/dist/types/deploy/platforms/node.d.ts +3 -1
- package/dist/types/deploy/platforms/types.d.ts +18 -7
- package/dist/types/deploy/platforms/vercel.d.ts +21 -2
- package/dist/types/deploy/redirects.d.ts +17 -1
- package/dist/types/deploy/sitemap.d.ts +2 -1
- package/dist/types/deploy/vercel-negotiation.d.ts +44 -21
- package/dist/types/narration/build.d.ts +34 -12
- package/dist/types/narration/provider.d.ts +96 -8
- package/dist/types/openapi/checks.d.ts +27 -0
- package/dist/types/openapi/graphql.d.ts +6 -0
- package/dist/types/openapi/model.d.ts +15 -4
- package/dist/types/openapi/parse.d.ts +3 -0
- package/dist/types/openapi/references.d.ts +16 -0
- package/dist/types/openapi/sentence.d.ts +11 -1
- package/dist/types/ratelimit/index.d.ts +1 -1
- package/dist/types/ratelimit/schema.d.ts +8 -0
- package/dist/types/ratelimit/upstash.d.ts +39 -14
- package/dist/types/reference/graphql.d.ts +76 -1
- package/dist/types/reference/index.d.ts +1 -1
- package/dist/types/reference/openapi.d.ts +2 -2
- package/dist/types/reference/options.d.ts +37 -1
- package/dist/types/reference/schema.d.ts +84 -0
- package/dist/types/search/adapters/registry.d.ts +3 -0
- package/dist/types/search/adapters/typesense.d.ts +14 -4
- package/dist/types/search/build.d.ts +3 -1
- package/dist/types/search/orama-index.d.ts +9 -9
- package/dist/types/search/sync/algolia.d.ts +5 -2
- package/dist/types/search/sync/index.d.ts +3 -1
- package/dist/types/search/sync/typesense.d.ts +11 -7
- package/dist/types/seo/jsonld.d.ts +11 -6
- package/dist/types/sources/contentful.d.ts +16 -0
- package/dist/types/sources/github-releases.d.ts +8 -1
- package/dist/types/sources/notion.d.ts +8 -0
- package/dist/types/sources/payload.d.ts +2 -0
- package/dist/types/sources/registry.d.ts +63 -0
- package/dist/types/sources/shared.d.ts +3 -0
- package/dist/types/sources/strapi.d.ts +2 -0
- package/docs/01-quickstart.mdx +4 -2
- package/docs/02-deployment.mdx +59 -13
- package/docs/03-upgrading.mdx +2 -1
- package/docs/04-migrating.mdx +9 -9
- package/docs/08-faq.mdx +12 -12
- package/docs/advanced/changelog.mdx +30 -2
- package/docs/advanced/custom-pages.mdx +1 -1
- package/docs/advanced/skills.mdx +1 -1
- package/docs/cli/audit.mdx +30 -7
- package/docs/cli/doctor.mdx +6 -2
- package/docs/cli/evals.mdx +4 -4
- package/docs/cli/translate.mdx +1 -0
- package/docs/cli/validate.mdx +4 -3
- package/docs/configuration/analytics.mdx +19 -1
- package/docs/configuration/assistant.mdx +6 -2
- package/docs/configuration/customization.mdx +4 -2
- package/docs/configuration/export.mdx +5 -3
- package/docs/configuration/index.mdx +4 -2
- package/docs/configuration/narration.mdx +43 -6
- package/docs/configuration/rate-limiting.mdx +23 -2
- package/docs/configuration/search.mdx +37 -14
- package/docs/content/components.mdx +2 -2
- package/docs/content/frontmatter.mdx +5 -3
- package/docs/content/i18n.mdx +2 -2
- package/docs/content/includes.mdx +1 -1
- package/docs/content/navigation.mdx +8 -6
- package/docs/content/sources/contentful.mdx +9 -4
- package/docs/content/sources/custom.mdx +7 -3
- package/docs/content/sources/github-releases.mdx +12 -2
- package/docs/content/sources/index.mdx +3 -3
- package/docs/content/sources/notion.mdx +17 -2
- package/docs/content/sources/obsidian.mdx +3 -1
- package/docs/content/sources/payload.mdx +5 -2
- package/docs/content/sources/remote-mdx.mdx +6 -0
- package/docs/content/sources/sanity.mdx +4 -2
- package/docs/content/sources/strapi.mdx +5 -2
- package/docs/content/syntax.mdx +2 -2
- package/docs/discoverability/agent-discovery.mdx +1 -1
- package/docs/discoverability/index.mdx +1 -1
- package/docs/discoverability/json-api.mdx +2 -0
- package/docs/discoverability/llms-txt.mdx +1 -1
- package/docs/discoverability/markdown.mdx +3 -1
- package/docs/discoverability/mcp.mdx +6 -0
- package/docs/discoverability/sitemap-and-robots.mdx +1 -1
- package/docs/discoverability/structured-data.mdx +8 -6
- package/docs/references/api-pages.mdx +1 -1
- package/docs/references/asyncapi.mdx +5 -1
- package/docs/references/graphql.mdx +15 -1
- package/docs/references/openapi.mdx +64 -8
- package/package.json +9 -9
- package/skills/blume/SKILL.md +1 -1
- package/skills/blume-migrate/SKILL.md +2 -2
- package/skills/blume-migrate/assets/{oxfmt@0.67.0.patch → oxfmt@0.71.0.patch} +7 -7
- package/skills/blume-migrate/references/docusaurus.md +4 -4
- package/skills/blume-migrate/references/fumadocs.md +17 -13
- package/skills/blume-migrate/references/monorepo.md +5 -5
- package/skills/blume-migrate/references/nextra.md +8 -5
- package/skills/blume-migrate/references/starlight.md +9 -7
- package/src/ai/ask-context.ts +33 -3
- package/src/ai/ask-limits.ts +13 -0
- package/src/ai/ask.ts +24 -6
- package/src/ai/changelog-markdown.ts +11 -6
- package/src/ai/component-markdown.ts +1 -1
- package/src/ai/cors.ts +12 -3
- package/src/ai/mcp/query.ts +14 -6
- package/src/ai/openapi-components.ts +28 -4
- package/src/ai/relative-links.ts +4 -38
- package/src/analytics/clics.ts +58 -0
- package/src/analytics/head.ts +5 -0
- package/src/analytics/index.ts +2 -0
- package/src/analytics/schema.ts +2 -0
- package/src/astro/generate.ts +91 -56
- package/src/astro/integration.ts +72 -22
- package/src/astro/markdown-negotiation.ts +3 -0
- package/src/astro/module-types.ts +3 -1
- package/src/astro/pages.ts +23 -0
- package/src/astro/render-deps.ts +10 -5
- package/src/astro/runtime-deps.ts +23 -2
- package/src/astro/templates.ts +129 -81
- package/src/audit/catalog.ts +19 -3
- package/src/audit/checks/links.ts +14 -1
- package/src/audit/checks/network.ts +110 -6
- package/src/audit/checks/redirects.ts +6 -4
- package/src/audit/checks/robots.ts +58 -2
- package/src/audit/run.ts +3 -0
- package/src/audit/types.ts +2 -0
- package/src/audit/url.ts +14 -5
- package/src/blume-modules.d.ts +5 -1
- package/src/cli/args.ts +51 -0
- package/src/cli/build-failure.ts +23 -0
- package/src/cli/commands/audit.ts +10 -1
- package/src/cli/commands/dev.ts +18 -2
- package/src/cli/commands/doctor.ts +45 -12
- package/src/cli/commands/eval.ts +36 -4
- package/src/cli/commands/init.ts +6 -4
- package/src/cli/commands/validate.ts +10 -1
- package/src/cli/init/scaffold.ts +9 -6
- package/src/cli/prepare.ts +6 -3
- package/src/cli/required-secrets.ts +3 -2
- package/src/components/content/ApiPlayground.astro +6 -2
- package/src/components/content/api-field.ts +4 -1
- package/src/components/content/api-page.ts +31 -7
- package/src/components/content/mermaid-element.ts +15 -1
- package/src/components/content/view-switcher.ts +7 -4
- package/src/components/islands/hooks.ts +27 -1
- package/src/components/layout/NavTree.astro +49 -5
- package/src/components/layout/NavTreeScript.astro +18 -0
- package/src/components/layout/PageActions.astro +139 -24
- package/src/components/layout/PageLayout.astro +13 -3
- package/src/components/layout/RootLayout.astro +27 -14
- package/src/components/layout/Search.astro +17 -3
- package/src/components/layout/TableOfContents.astro +24 -17
- package/src/components/layout/analytics-client.ts +8 -8
- package/src/components/layout/head-scripts.ts +6 -1
- package/src/components/layout/search/algolia.ts +10 -1
- package/src/components/layout/search/analytics.ts +42 -14
- package/src/components/layout/search/endpoint.ts +48 -5
- package/src/components/layout/search/pagefind.ts +114 -5
- package/src/components/layout/search/types.ts +12 -0
- package/src/components/layout/search/typesense.ts +18 -6
- package/src/components/openapi/AsyncApiOperation.astro +14 -7
- package/src/components/openapi/Authorization.astro +10 -0
- package/src/components/openapi/GraphqlOperation.astro +5 -0
- package/src/components/openapi/Operation.astro +24 -1
- package/src/components/openapi/ParametersTable.astro +8 -4
- package/src/components/openapi/Playground.astro +7 -1
- package/src/components/openapi/RequestBody.astro +19 -2
- package/src/components/openapi/Responses.astro +1 -0
- package/src/components/openapi/SchemaTable.astro +15 -3
- package/src/components/openapi/async-snippets.ts +61 -5
- package/src/components/openapi/async.ts +123 -29
- package/src/components/openapi/graphql-helpers.ts +35 -12
- package/src/components/openapi/helpers.ts +36 -2
- package/src/components/openapi/message-model.ts +54 -11
- package/src/components/openapi/message.ts +14 -4
- package/src/components/openapi/operation-model.ts +16 -7
- package/src/components/openapi/playground-client.ts +77 -58
- package/src/components/openapi/playground-schema.ts +1 -1
- package/src/components/openapi/schema-tree.ts +44 -14
- package/src/components/openapi/security.ts +10 -0
- package/src/components/openapi/snippets.ts +5 -3
- package/src/components/openapi/validate-json.ts +4 -3
- package/src/components/powered-by-middleware.ts +33 -0
- package/src/core/changelog-index.ts +31 -1
- package/src/core/component-diagnostics.ts +53 -0
- package/src/core/component-overrides.ts +32 -0
- package/src/core/config-input.ts +42 -6
- package/src/core/data.ts +2 -0
- package/src/core/diagnostics.ts +5 -0
- package/src/core/i18n-ui.ts +2 -0
- package/src/core/includes.ts +1 -1
- package/src/core/links.ts +47 -17
- package/src/core/powered-by.ts +12 -0
- package/src/core/probe.ts +26 -6
- package/src/core/project-graph.ts +59 -18
- package/src/core/redirect-patterns.ts +36 -7
- package/src/core/schema.ts +26 -6
- package/src/core/sources/cache.ts +6 -0
- package/src/core/sources/contentful-rich-text.ts +29 -6
- package/src/core/sources/contentful.ts +135 -25
- package/src/core/sources/filesystem.ts +26 -4
- package/src/core/sources/github-releases.ts +12 -1
- package/src/core/sources/lexical.ts +15 -10
- package/src/core/sources/lower.ts +19 -3
- package/src/core/sources/mdx-remote.ts +62 -10
- package/src/core/sources/normalize.ts +227 -41
- package/src/core/sources/notion.ts +34 -10
- package/src/core/sources/obsidian.ts +16 -3
- package/src/core/sources/payload.ts +38 -15
- package/src/core/sources/remote.ts +72 -15
- package/src/core/sources/resolve.ts +11 -1
- package/src/core/sources/sanity.ts +43 -25
- package/src/core/sources/strapi.ts +2 -2
- package/src/core/types.ts +18 -0
- package/src/core/ui-packs/ar.ts +1 -0
- package/src/core/ui-packs/bg.ts +1 -0
- package/src/core/ui-packs/bn.ts +1 -0
- package/src/core/ui-packs/ca.ts +1 -0
- package/src/core/ui-packs/cs.ts +1 -0
- package/src/core/ui-packs/da.ts +1 -0
- package/src/core/ui-packs/de.ts +1 -0
- package/src/core/ui-packs/el.ts +1 -0
- package/src/core/ui-packs/es.ts +1 -0
- package/src/core/ui-packs/fa.ts +1 -0
- package/src/core/ui-packs/fi.ts +1 -0
- package/src/core/ui-packs/fr.ts +1 -0
- package/src/core/ui-packs/he.ts +1 -0
- package/src/core/ui-packs/hi.ts +1 -0
- package/src/core/ui-packs/hr.ts +1 -0
- package/src/core/ui-packs/hu.ts +1 -0
- package/src/core/ui-packs/id.ts +1 -0
- package/src/core/ui-packs/it.ts +1 -0
- package/src/core/ui-packs/ja.ts +1 -0
- package/src/core/ui-packs/ko.ts +1 -0
- package/src/core/ui-packs/nl.ts +1 -0
- package/src/core/ui-packs/no.ts +1 -0
- package/src/core/ui-packs/pl.ts +1 -0
- package/src/core/ui-packs/pt-br.ts +1 -0
- package/src/core/ui-packs/pt.ts +1 -0
- package/src/core/ui-packs/ro.ts +1 -0
- package/src/core/ui-packs/ru.ts +1 -0
- package/src/core/ui-packs/sk.ts +1 -0
- package/src/core/ui-packs/sr.ts +1 -0
- package/src/core/ui-packs/sv.ts +1 -0
- package/src/core/ui-packs/th.ts +1 -0
- package/src/core/ui-packs/tr.ts +1 -0
- package/src/core/ui-packs/uk.ts +1 -0
- package/src/core/ui-packs/vi.ts +1 -0
- package/src/core/ui-packs/zh-tw.ts +1 -0
- package/src/core/ui-packs/zh.ts +1 -0
- package/src/deploy/adapter-output.ts +7 -2
- package/src/deploy/adapters/cloudflare.ts +7 -5
- package/src/deploy/adapters/node.ts +47 -9
- package/src/deploy/adapters/types.ts +7 -3
- package/src/deploy/artifacts.ts +2 -1
- package/src/deploy/cloudflare-negotiation.ts +36 -7
- package/src/deploy/headers.ts +15 -1
- package/src/deploy/node-headers.ts +32 -20
- package/src/deploy/platforms/cloudflare.ts +14 -9
- package/src/deploy/platforms/netlify.ts +2 -1
- package/src/deploy/platforms/node.ts +12 -2
- package/src/deploy/platforms/types.ts +21 -7
- package/src/deploy/platforms/vercel.ts +115 -17
- package/src/deploy/redirects.ts +66 -6
- package/src/deploy/rss.ts +3 -1
- package/src/deploy/sitemap.ts +39 -5
- package/src/deploy/vercel-negotiation.ts +325 -103
- package/src/eval/agents.ts +18 -1
- package/src/eval/prompts.ts +6 -3
- package/src/eval/report.ts +34 -13
- package/src/eval/run.ts +5 -0
- package/src/markdown/base-links.ts +15 -14
- package/src/markdown/package-commands.ts +9 -8
- package/src/markdown/relative-links.ts +3 -2
- package/src/narration/build.ts +218 -40
- package/src/narration/provider.ts +89 -9
- package/src/openapi/checks.ts +273 -0
- package/src/openapi/graphql-build.ts +21 -0
- package/src/openapi/graphql.ts +11 -0
- package/src/openapi/model.ts +15 -3
- package/src/openapi/parse.ts +127 -2
- package/src/openapi/references.ts +43 -3
- package/src/openapi/render-mdx.ts +68 -8
- package/src/openapi/sentence.ts +29 -2
- package/src/openapi/source.ts +39 -14
- package/src/ratelimit/index.ts +1 -1
- package/src/ratelimit/runtime.ts +37 -19
- package/src/ratelimit/upstash.ts +40 -10
- package/src/reference/graphql.ts +15 -1
- package/src/reference/index.ts +1 -0
- package/src/reference/openapi.ts +2 -2
- package/src/reference/options.ts +29 -1
- package/src/registry/eject.ts +8 -2
- package/src/search/adapters/locale-scope.ts +30 -0
- package/src/search/adapters/typesense.ts +14 -4
- package/src/search/build.ts +21 -3
- package/src/search/orama-index.ts +163 -31
- package/src/search/source-pages.ts +29 -0
- package/src/search/sync/algolia.ts +99 -9
- package/src/search/sync/index.ts +52 -13
- package/src/search/sync/typesense.ts +72 -27
- package/src/seo/jsonld.ts +38 -20
- package/src/sources/contentful.ts +12 -0
- package/src/sources/github-releases.ts +7 -1
- package/src/sources/notion.ts +7 -0
- package/src/sources/shared.ts +3 -0
- package/src/theme/color.ts +9 -10
- package/src/theme/entry.ts +43 -6
- package/src/translate/validate.ts +23 -1
- package/dist/cli/chunk-0gz36akr.js.map +0 -12
- package/dist/cli/chunk-2n4ps1b3.js.map +0 -15
- package/dist/cli/chunk-43zcf4gz.js.map +0 -36
- package/dist/cli/chunk-4ejxbzee.js +0 -39
- package/dist/cli/chunk-4ejxbzee.js.map +0 -10
- package/dist/cli/chunk-4h8z9vv5.js.map +0 -16
- package/dist/cli/chunk-713mngdq.js.map +0 -14
- package/dist/cli/chunk-9xr4dgee.js.map +0 -10
- package/dist/cli/chunk-amrb6hgh.js +0 -145
- package/dist/cli/chunk-amrb6hgh.js.map +0 -11
- package/dist/cli/chunk-nd1821sk.js.map +0 -10
- package/dist/cli/chunk-rekqz4qg.js.map +0 -10
- package/dist/cli/chunk-ta27feev.js.map +0 -10
- package/dist/cli/chunk-xkz5xbtv.js.map +0 -213
- package/dist/cli/chunk-y5h4r2y0.js.map +0 -10
- package/dist/cli/chunk-zf748avv.js.map +0 -37
- /package/dist/cli/{chunk-9geymqns.js.map → chunk-0w6hs479.js.map} +0 -0
- /package/dist/cli/{chunk-y4ykbark.js.map → chunk-1f882900.js.map} +0 -0
- /package/dist/cli/{chunk-py62fewh.js.map → chunk-53jqw8z0.js.map} +0 -0
- /package/dist/cli/{chunk-5wj2qwn2.js.map → chunk-58bt3hag.js.map} +0 -0
- /package/dist/cli/{chunk-e7vvk5ya.js.map → chunk-5cmts6dv.js.map} +0 -0
- /package/dist/cli/{chunk-g2z9x01v.js.map → chunk-9qzgg6mj.js.map} +0 -0
- /package/dist/cli/{chunk-q3wxxq39.js.map → chunk-a57yh0h9.js.map} +0 -0
- /package/dist/cli/{chunk-2f3ndkpw.js.map → chunk-desvm72z.js.map} +0 -0
- /package/dist/cli/{chunk-gp84za0h.js.map → chunk-dhwtqnnd.js.map} +0 -0
- /package/dist/cli/{chunk-2f7n4qzt.js.map → chunk-dqhg54mr.js.map} +0 -0
- /package/dist/cli/{chunk-zhvd6adm.js.map → chunk-gfc5fqvf.js.map} +0 -0
- /package/dist/cli/{chunk-p804f3pe.js.map → chunk-hvcxng5f.js.map} +0 -0
- /package/dist/cli/{chunk-1n228xqb.js.map → chunk-kdpzw38a.js.map} +0 -0
- /package/dist/cli/{chunk-6bm0xpgd.js.map → chunk-s0bdnc7v.js.map} +0 -0
- /package/dist/cli/{chunk-cmtcnh9f.js.map → chunk-tfycddbt.js.map} +0 -0
- /package/dist/cli/{chunk-ntv4qrt7.js.map → chunk-y4msrwm9.js.map} +0 -0
- /package/dist/cli/{chunk-yj17vs39.js.map → chunk-ydp3065p.js.map} +0 -0
package/src/astro/templates.ts
CHANGED
|
@@ -4,13 +4,17 @@ import { pathToFileURL } from "node:url";
|
|
|
4
4
|
import { dirname, isAbsolute, join, relative } from "pathe";
|
|
5
5
|
|
|
6
6
|
import type { AskRetrievalOptions } from "../ai/ask-context.ts";
|
|
7
|
+
import { ASK_MAX_MESSAGES, ASK_MAX_MESSAGES_CHARS } from "../ai/ask-limits.ts";
|
|
7
8
|
import type { AskBackend } from "../ai/ask.ts";
|
|
8
9
|
import { buildHomeLinkHeader } from "../ai/link-headers.ts";
|
|
9
10
|
import type { CaptchaAdapter } from "../captcha/schema.ts";
|
|
10
11
|
import { CONSENT_CLIENT_MODULES } from "../consent/clients.ts";
|
|
11
12
|
import { normalizeBasePath } from "../core/base-path.ts";
|
|
12
13
|
import { TOC_HIDDEN_KEY } from "../core/heading-markers.ts";
|
|
13
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
compileEveryRedirect,
|
|
16
|
+
isPatternPath,
|
|
17
|
+
} from "../core/redirect-patterns.ts";
|
|
14
18
|
import type { CompiledRedirect } from "../core/redirect-patterns.ts";
|
|
15
19
|
import type { ResolvedConfig } from "../core/schema.ts";
|
|
16
20
|
import { resolveDocsCollection } from "../core/sources/collection.ts";
|
|
@@ -22,7 +26,10 @@ import { deployPassthrough } from "../deploy/adapters/types.ts";
|
|
|
22
26
|
import { SVG_ASSET_HEADERS } from "../deploy/headers.ts";
|
|
23
27
|
import { deployPlatform } from "../deploy/platforms/index.ts";
|
|
24
28
|
import { adapterRoot, distDir } from "../deploy/platforms/paths.ts";
|
|
25
|
-
import {
|
|
29
|
+
import {
|
|
30
|
+
applyBaseToAstroRedirects,
|
|
31
|
+
withMirrorRedirects,
|
|
32
|
+
} from "../deploy/redirects.ts";
|
|
26
33
|
import { API_RAIL_KEY } from "../markdown/api-rail.ts";
|
|
27
34
|
import { VIEWS_KEY } from "../markdown/views.ts";
|
|
28
35
|
import type { OgCache } from "../og/cache.ts";
|
|
@@ -34,6 +41,7 @@ import type {
|
|
|
34
41
|
ResolvedSearchAdapter,
|
|
35
42
|
SearchAdapterKind,
|
|
36
43
|
} from "../search/adapters/registry.ts";
|
|
44
|
+
import type { SourcePage } from "../search/source-pages.ts";
|
|
37
45
|
import { buildFontEntries, fontLocaleCodes } from "../theme/fonts.ts";
|
|
38
46
|
import { importSpecifier, wrapperPropsType } from "./component-slots.ts";
|
|
39
47
|
import type { ExampleSpec } from "./examples.ts";
|
|
@@ -122,7 +130,7 @@ const renderAstroAdapter = (
|
|
|
122
130
|
const { astro } = platform;
|
|
123
131
|
const args = {
|
|
124
132
|
...astro.options(context),
|
|
125
|
-
...deployPassthrough(deployment.options),
|
|
133
|
+
...deployPassthrough(deployment.options, astro.configOptions),
|
|
126
134
|
};
|
|
127
135
|
const argsLiteral = Object.keys(args).length > 0 ? JSON.stringify(args) : "";
|
|
128
136
|
const construct = `adapter(${argsLiteral})`;
|
|
@@ -133,7 +141,7 @@ const renderAstroAdapter = (
|
|
|
133
141
|
? `withAdapterRoot(${construct}, ${JSON.stringify(adapterRoot(context))})`
|
|
134
142
|
: construct;
|
|
135
143
|
return {
|
|
136
|
-
configEntries: Object.entries(astro.config)
|
|
144
|
+
configEntries: Object.entries(astro.config(deployment.options))
|
|
137
145
|
.map(([key, value]) => `\n ${key}: ${JSON.stringify(value)},`)
|
|
138
146
|
.join(""),
|
|
139
147
|
importLine: `import adapter from "${astro.package}";\n`,
|
|
@@ -283,18 +291,14 @@ const renderUserAliases = (
|
|
|
283
291
|
.join("");
|
|
284
292
|
|
|
285
293
|
/**
|
|
286
|
-
* Excludes
|
|
287
|
-
* react()
|
|
288
|
-
*
|
|
289
|
-
*
|
|
290
|
-
* re-
|
|
291
|
-
*
|
|
292
|
-
* resolve under `node_modules/blume/src`, and exclude beats include in the
|
|
293
|
-
* plugin's filter), so only the pre-bundle cache is excluded. The hidden runtime
|
|
294
|
-
* relocates that cache to `<runtime>/.cache/vite` (see `cacheOptions`), so both
|
|
295
|
-
* the default and the relocated path are excluded.
|
|
294
|
+
* Excludes the hidden runtime's pre-bundled dep cache from @vitejs/plugin-react.
|
|
295
|
+
* Astro's react() already excludes `/node_modules/`, which covers Vite's
|
|
296
|
+
* default `node_modules/.vite` cache, but the hidden runtime relocates that
|
|
297
|
+
* cache to `<runtime>/.cache/vite` (see `cacheOptions`). Without this the React
|
|
298
|
+
* Compiler re-transforms every optimized dep chunk served from there — a 500KB+
|
|
299
|
+
* vendor bundle per chunk, re-done on each re-optimization.
|
|
296
300
|
*/
|
|
297
|
-
const REACT_EXCLUDE = String.raw`exclude: [
|
|
301
|
+
const REACT_EXCLUDE = String.raw`exclude: [/\/\.cache\/vite\//]`;
|
|
298
302
|
|
|
299
303
|
/**
|
|
300
304
|
* The `cacheDir` entries for the generated config's top level and its `vite`
|
|
@@ -324,17 +328,14 @@ const runtimeCacheOptions = (
|
|
|
324
328
|
};
|
|
325
329
|
|
|
326
330
|
/**
|
|
327
|
-
* The `react()` integration call.
|
|
328
|
-
*
|
|
329
|
-
*
|
|
330
|
-
*
|
|
331
|
-
* specifier wouldn't resolve in a user project. `target: "19"` matches Blume's
|
|
332
|
-
* React pin. `null`/`undefined` (compiler off or unresolvable) omits the babel
|
|
333
|
-
* block. Both variants carry the pre-bundle exclude above.
|
|
331
|
+
* The `react()` integration call. `compiler` turns on @astrojs/react's React
|
|
332
|
+
* Compiler, which runs on `oxc-transform-react` and targets the installed
|
|
333
|
+
* React major; false/absent (compiler off or unresolvable) leaves it out. Both
|
|
334
|
+
* variants carry the pre-bundle exclude above.
|
|
334
335
|
*/
|
|
335
|
-
const reactIntegration = (
|
|
336
|
-
|
|
337
|
-
? `react({
|
|
336
|
+
const reactIntegration = (compiler: boolean | undefined): string =>
|
|
337
|
+
compiler
|
|
338
|
+
? `react({ compiler: true, ${REACT_EXCLUDE} })`
|
|
338
339
|
: `react({ ${REACT_EXCLUDE} })`;
|
|
339
340
|
|
|
340
341
|
interface IntegrationBridgeOptions {
|
|
@@ -388,11 +389,10 @@ interface OptimizeDepsConfig {
|
|
|
388
389
|
* the Vite root is the generated runtime, so user pages, convention islands,
|
|
389
390
|
* and alias-reachable components all live outside it and are otherwise only
|
|
390
391
|
* crawled when first requested. The compiler runtime rides the include list
|
|
391
|
-
* because
|
|
392
|
-
*
|
|
393
|
-
*
|
|
394
|
-
*
|
|
395
|
-
* the optimizeDeps comment in the generated config for the failure this prevents.
|
|
392
|
+
* because the compiler injects its import and no source scan can see it. The
|
|
393
|
+
* compiler plugin in `@vitejs/plugin-react` lists it too; Blume keeps it
|
|
394
|
+
* explicit so the guard doesn't hinge on that plugin's internals. See the
|
|
395
|
+
* optimizeDeps comment in the generated config for the failure this prevents.
|
|
396
396
|
*/
|
|
397
397
|
/**
|
|
398
398
|
* The client-side libraries a site needs, decided at generation time. A
|
|
@@ -432,7 +432,7 @@ const resolveOptimizeDeps = (options: {
|
|
|
432
432
|
context: ProjectContext;
|
|
433
433
|
features: ClientFeatures;
|
|
434
434
|
needsReact: boolean;
|
|
435
|
-
|
|
435
|
+
reactCompiler: boolean | undefined;
|
|
436
436
|
searchKind: SearchAdapterKind;
|
|
437
437
|
}): OptimizeDepsConfig => {
|
|
438
438
|
const { context, features } = options;
|
|
@@ -456,7 +456,7 @@ const resolveOptimizeDeps = (options: {
|
|
|
456
456
|
// (__PREFETCH_PREFETCH_ALL__ and friends) that a pre-bundled copy loses,
|
|
457
457
|
// throwing ReferenceError on every page. Astro manages their optimization
|
|
458
458
|
// itself, without a mid-session reload.
|
|
459
|
-
...(options.needsReact && options.
|
|
459
|
+
...(options.needsReact && options.reactCompiler
|
|
460
460
|
? ["react/compiler-runtime"]
|
|
461
461
|
: []),
|
|
462
462
|
];
|
|
@@ -567,7 +567,10 @@ const blumeIntegrationOptions = (options: {
|
|
|
567
567
|
pages: BlumePageRoute[];
|
|
568
568
|
redirects: CompiledRedirect[];
|
|
569
569
|
}): BlumeIntegrationOptions => {
|
|
570
|
-
const shared: BlumeIntegrationOptions = {
|
|
570
|
+
const shared: BlumeIntegrationOptions = {
|
|
571
|
+
pages: options.pages,
|
|
572
|
+
poweredBy: options.config.poweredBy,
|
|
573
|
+
};
|
|
571
574
|
if (options.redirects.length > 0) {
|
|
572
575
|
shared.redirects = options.redirects;
|
|
573
576
|
}
|
|
@@ -612,11 +615,10 @@ export const astroConfigTemplate = (options: {
|
|
|
612
615
|
*/
|
|
613
616
|
generatedModulesDir?: string;
|
|
614
617
|
/**
|
|
615
|
-
*
|
|
616
|
-
*
|
|
617
|
-
* disables the compiler and emits a bare `react()`.
|
|
618
|
+
* Turn on the React Compiler (the caller checked that `oxc-transform-react`
|
|
619
|
+
* resolves); false/absent emits `react()` without it.
|
|
618
620
|
*/
|
|
619
|
-
|
|
621
|
+
reactCompiler?: boolean;
|
|
620
622
|
/** Project tsconfig path aliases (`find` -> absolute dir), e.g. `@` -> src. */
|
|
621
623
|
aliases?: Record<string, string>;
|
|
622
624
|
/**
|
|
@@ -664,7 +666,7 @@ export const astroConfigTemplate = (options: {
|
|
|
664
666
|
context,
|
|
665
667
|
features,
|
|
666
668
|
needsReact,
|
|
667
|
-
|
|
669
|
+
reactCompiler: options.reactCompiler,
|
|
668
670
|
searchKind: config.search.provider.kind,
|
|
669
671
|
});
|
|
670
672
|
|
|
@@ -700,11 +702,17 @@ export const astroConfigTemplate = (options: {
|
|
|
700
702
|
// Base the redirect paths the same way routes are based, so a redirect lands
|
|
701
703
|
// under `basePath` too. Astro layers its own `base` (deployment.base) onto
|
|
702
704
|
// `from` when matching, but never onto `to` — see applyBaseToAstroRedirects.
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
705
|
+
// A moved page's Markdown copies move with it (see withMirrorRedirects).
|
|
706
|
+
const redirectPages = new Set(contentRoutes);
|
|
707
|
+
const basedRedirects = withMirrorRedirects(
|
|
708
|
+
applyBaseToAstroRedirects(
|
|
709
|
+
config.redirects,
|
|
710
|
+
config.basePath,
|
|
711
|
+
deployment.options.base ?? "",
|
|
712
|
+
redirectPages
|
|
713
|
+
),
|
|
714
|
+
redirectPages,
|
|
715
|
+
{ from: "", to: normalizeBasePath(deployment.options.base) }
|
|
708
716
|
);
|
|
709
717
|
// Only exact redirects: Astro can't prerender a pattern's redirect pages
|
|
710
718
|
// (it would need every path the pattern covers), so a pattern reaches the
|
|
@@ -837,7 +845,7 @@ export const astroConfigTemplate = (options: {
|
|
|
837
845
|
`mdx({ processor: blumeMdxProcessor(${processorOptions}) })`,
|
|
838
846
|
];
|
|
839
847
|
if (needsReact) {
|
|
840
|
-
integrations.push(reactIntegration(options.
|
|
848
|
+
integrations.push(reactIntegration(options.reactCompiler));
|
|
841
849
|
}
|
|
842
850
|
if (needsVue) {
|
|
843
851
|
integrations.push("vue()");
|
|
@@ -855,7 +863,7 @@ export const astroConfigTemplate = (options: {
|
|
|
855
863
|
contentRoutes,
|
|
856
864
|
ejected,
|
|
857
865
|
pages,
|
|
858
|
-
redirects:
|
|
866
|
+
redirects: compileEveryRedirect(basedRedirects),
|
|
859
867
|
})
|
|
860
868
|
)})`
|
|
861
869
|
);
|
|
@@ -931,8 +939,8 @@ ${userConfigSetup}export default defineConfig({
|
|
|
931
939
|
// Everything hydration can reach must be part of the dev dep optimizer's
|
|
932
940
|
// FIRST run. The Vite root is the generated runtime, so user pages,
|
|
933
941
|
// islands, and aliased components live outside it and are only crawled
|
|
934
|
-
// when first requested — and \`react/compiler-runtime\` is
|
|
935
|
-
// so no source scan can ever see it. A dependency discovered after
|
|
942
|
+
// when first requested — and \`react/compiler-runtime\` is injected by the
|
|
943
|
+
// React Compiler, so no source scan can ever see it. A dependency discovered after
|
|
936
944
|
// hydration begins triggers a mid-session re-optimization whose new
|
|
937
945
|
// generation imports React through new \`?v=\` URLs; the browser then
|
|
938
946
|
// evaluates a second React copy and every island tears down with
|
|
@@ -1270,8 +1278,8 @@ const askCaptchaTemplate = (adapter?: CaptchaAdapter): RateLimitTemplate => {
|
|
|
1270
1278
|
|
|
1271
1279
|
/**
|
|
1272
1280
|
* Largest request body the assistant route reads: 64 KB, well above the
|
|
1273
|
-
*
|
|
1274
|
-
* never meets it.
|
|
1281
|
+
* message budget it validates next (`ai/ask-limits.ts`), so a real
|
|
1282
|
+
* conversation never meets it.
|
|
1275
1283
|
*/
|
|
1276
1284
|
const ASK_BODY_LIMIT_BYTES = 65_536;
|
|
1277
1285
|
|
|
@@ -1380,7 +1388,7 @@ ${limit.check} const text = await readCappedText(request, ${ASK_BODY_LIMIT_BYTE
|
|
|
1380
1388
|
const valid =
|
|
1381
1389
|
Array.isArray(raw) &&
|
|
1382
1390
|
raw.length > 0 &&
|
|
1383
|
-
raw.length <=
|
|
1391
|
+
raw.length <= ${ASK_MAX_MESSAGES} &&
|
|
1384
1392
|
raw.every(
|
|
1385
1393
|
(m: unknown) =>
|
|
1386
1394
|
typeof m === "object" &&
|
|
@@ -1388,10 +1396,10 @@ ${limit.check} const text = await readCappedText(request, ${ASK_BODY_LIMIT_BYTE
|
|
|
1388
1396
|
("role" in m && (m.role === "user" || m.role === "assistant")) &&
|
|
1389
1397
|
("content" in m && typeof m.content === "string")
|
|
1390
1398
|
) &&
|
|
1391
|
-
JSON.stringify(raw).length <=
|
|
1399
|
+
JSON.stringify(raw).length <= ${ASK_MAX_MESSAGES_CHARS};
|
|
1392
1400
|
if (!valid) {
|
|
1393
1401
|
return new Response(
|
|
1394
|
-
"Invalid request: send 1
|
|
1402
|
+
"Invalid request: send 1-${ASK_MAX_MESSAGES} user/assistant messages with string content.",
|
|
1395
1403
|
{ status: 400 }
|
|
1396
1404
|
);
|
|
1397
1405
|
}
|
|
@@ -1649,10 +1657,12 @@ export const searchClientTemplate = (config: ResolvedConfig): string => {
|
|
|
1649
1657
|
return hostedSearchClient(provider);
|
|
1650
1658
|
}
|
|
1651
1659
|
case "server": {
|
|
1652
|
-
|
|
1660
|
+
// The dialog passes `typing`, which paces its queries (see endpoint.ts).
|
|
1661
|
+
return `${SEARCH_CLIENT_HEADER}${searchClientImport("endpoint")}${SEARCH_BASE_IMPORT}import type { SearchClientOptions } from "blume/components/layout/search/types.ts";
|
|
1653
1662
|
const api = joinBase(import.meta.env.BASE_URL, "api/search");
|
|
1654
1663
|
|
|
1655
|
-
export const createSearch = (
|
|
1664
|
+
export const createSearch = (options: SearchClientOptions = {}) =>
|
|
1665
|
+
create({ ...options, api });
|
|
1656
1666
|
`;
|
|
1657
1667
|
}
|
|
1658
1668
|
case "pagefind": {
|
|
@@ -1674,14 +1684,17 @@ export const createSearch = () => create({ url });
|
|
|
1674
1684
|
/**
|
|
1675
1685
|
* Generate the Mixedbread search endpoint (`/api/search`). It holds the secret
|
|
1676
1686
|
* key server-side and proxies semantic queries to the configured store. The
|
|
1677
|
-
* adapter's options are inlined as
|
|
1678
|
-
* config.
|
|
1679
|
-
*
|
|
1687
|
+
* adapter's options are inlined as literals so the route never imports the
|
|
1688
|
+
* config. `pages` (see `sourcePages`) maps each source file to its page: a
|
|
1689
|
+
* chunk links to the page whose file `mxbai store sync` uploaded it from,
|
|
1690
|
+
* found by the longest trailing run of the path the CLI recorded.
|
|
1680
1691
|
*/
|
|
1681
1692
|
export const mixedbreadSearchEndpointTemplate = (
|
|
1682
1693
|
options: MixedbreadOptions,
|
|
1694
|
+
pages: [string, SourcePage][],
|
|
1683
1695
|
rateLimit?: RateLimitAdapter | null
|
|
1684
1696
|
): string => {
|
|
1697
|
+
const { search_options: tuning, storeId, ...searchOptions } = options;
|
|
1685
1698
|
const limit = rateLimitTemplate(rateLimit, "search");
|
|
1686
1699
|
const imports = [
|
|
1687
1700
|
'import type { APIRoute } from "astro";',
|
|
@@ -1696,9 +1709,26 @@ ${imports.join("\n")}
|
|
|
1696
1709
|
export const prerender = false;
|
|
1697
1710
|
|
|
1698
1711
|
const client = new Mixedbread({ apiKey: getSecret("MIXEDBREAD_API_KEY") ?? "" });
|
|
1699
|
-
const
|
|
1700
|
-
// Every option
|
|
1701
|
-
const
|
|
1712
|
+
const STORE_ID = ${JSON.stringify(storeId)};
|
|
1713
|
+
// Every other option reaches the search call verbatim.
|
|
1714
|
+
const SEARCH_OPTIONS = ${JSON.stringify(searchOptions)};
|
|
1715
|
+
const SEARCH_TUNING = ${JSON.stringify(tuning ?? {})};
|
|
1716
|
+
// Each page's source file, relative to the project root, and the page it renders.
|
|
1717
|
+
const PAGES = new Map<string, { title: string; url: string }>(${JSON.stringify(pages)});
|
|
1718
|
+
|
|
1719
|
+
// The page a synced file renders. \`mxbai store sync\` records the path
|
|
1720
|
+
// relative to where it ran (the project root, or a monorepo root above it), so
|
|
1721
|
+
// the longest trailing run of that path that names a page's file wins.
|
|
1722
|
+
const pageFor = (path: string) => {
|
|
1723
|
+
const segments = path.replaceAll("\\\\", "/").split("/");
|
|
1724
|
+
for (let start = 0; start < segments.length; start += 1) {
|
|
1725
|
+
const page = PAGES.get(segments.slice(start).join("/"));
|
|
1726
|
+
if (page) {
|
|
1727
|
+
return page;
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
return undefined;
|
|
1731
|
+
};
|
|
1702
1732
|
${limit.setup}
|
|
1703
1733
|
export const POST: APIRoute = async (context) => {
|
|
1704
1734
|
const { request } = context;
|
|
@@ -1724,23 +1754,32 @@ ${limit.check} // A search body is one short query: read it under a 16 KB cap,
|
|
|
1724
1754
|
});
|
|
1725
1755
|
}
|
|
1726
1756
|
// \`top_k\` defaults to 8 unless an option sets it; the query and store
|
|
1727
|
-
// always come from the request and \`storeId\`.
|
|
1757
|
+
// always come from the request and \`storeId\`. File metadata is always
|
|
1758
|
+
// returned: it holds the path \`mxbai store sync\` recorded for the file.
|
|
1728
1759
|
const response = await client.stores.search({
|
|
1729
1760
|
top_k: 8,
|
|
1730
1761
|
...SEARCH_OPTIONS,
|
|
1731
1762
|
query,
|
|
1763
|
+
search_options: { ...SEARCH_TUNING, return_metadata: true },
|
|
1732
1764
|
store_identifiers: [STORE_ID],
|
|
1733
1765
|
});
|
|
1734
|
-
const
|
|
1766
|
+
const seen = new Set<string>();
|
|
1767
|
+
const hits = (response.data ?? []).flatMap((chunk) => {
|
|
1768
|
+
const { file_path: path } = (chunk.metadata ?? {}) as { file_path?: unknown };
|
|
1769
|
+
const page = typeof path === "string" ? pageFor(path) : undefined;
|
|
1770
|
+
// A file no page renders has nowhere to link, and a page's later chunks
|
|
1771
|
+
// would repeat it: one hit per page, at its best chunk.
|
|
1772
|
+
if (!page || seen.has(page.url)) {
|
|
1773
|
+
return [];
|
|
1774
|
+
}
|
|
1775
|
+
seen.add(page.url);
|
|
1735
1776
|
const meta = chunk.generated_metadata ?? {};
|
|
1736
1777
|
// Only a text chunk carries \`text\`; image, audio, and video chunks fall
|
|
1737
1778
|
// back to the excerpt the store generated for them.
|
|
1738
1779
|
const text = "text" in chunk ? chunk.text : undefined;
|
|
1739
|
-
return
|
|
1740
|
-
excerpt: text ?? meta.excerpt ?? "",
|
|
1741
|
-
|
|
1742
|
-
url: meta.url ?? "",
|
|
1743
|
-
};
|
|
1780
|
+
return [
|
|
1781
|
+
{ excerpt: text ?? meta.excerpt ?? "", title: page.title, url: page.url },
|
|
1782
|
+
];
|
|
1744
1783
|
});
|
|
1745
1784
|
return new Response(JSON.stringify(hits), {
|
|
1746
1785
|
headers: { "Content-Type": "application/json" },
|
|
@@ -2417,6 +2456,7 @@ import type { CollectionKey } from "astro:content";
|
|
|
2417
2456
|
import RootLayout from "blume/components/layout/RootLayout.astro";
|
|
2418
2457
|
import { withBase, withMountedBase } from "blume/components/islands/base-path.ts";
|
|
2419
2458
|
import { mountBasePath, stripBasePath } from "blume/core/base-path.ts";
|
|
2459
|
+
import { routeSetFor, servesRoute } from "blume/core/locale-links.ts";
|
|
2420
2460
|
import { resolveSlot } from "blume/components/layout/overrides.ts";
|
|
2421
2461
|
${componentImports}
|
|
2422
2462
|
import data from "blume:data";
|
|
@@ -2620,18 +2660,24 @@ const logicalRoute = i18n
|
|
|
2620
2660
|
? stripLocale(stripBasePath(data.config.basePath, route), locale)
|
|
2621
2661
|
: route;
|
|
2622
2662
|
// A page from a one-language source (GitHub Releases) gets no switcher: every
|
|
2623
|
-
// other locale would only repeat the same text.
|
|
2663
|
+
// other locale would only repeat the same text. A locale with no real
|
|
2664
|
+
// translation links the page's fallback copy, which exists only while
|
|
2665
|
+
// fallbacks are on; where nothing is served at that URL (\`fallbackLocale:
|
|
2666
|
+
// null\`), the locale is left out rather than linked to a 404.
|
|
2624
2667
|
const localeSwitch = i18n && !monolingual
|
|
2625
|
-
? i18n.locales.
|
|
2668
|
+
? i18n.locales.flatMap((l) => {
|
|
2626
2669
|
const alt = (alternates ?? []).find((x) => x.locale === l.code);
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2670
|
+
const href = alt ? alt.path : mountLocalized(logicalRoute, l.code);
|
|
2671
|
+
return alt || servesRoute(routeSetFor(data.routes), href)
|
|
2672
|
+
? [{
|
|
2673
|
+
code: l.code,
|
|
2674
|
+
current: l.code === locale,
|
|
2675
|
+
dir: l.dir,
|
|
2676
|
+
href,
|
|
2677
|
+
label: l.label,
|
|
2678
|
+
untranslated: !alt,
|
|
2679
|
+
}]
|
|
2680
|
+
: [];
|
|
2635
2681
|
})
|
|
2636
2682
|
: [];
|
|
2637
2683
|
|
|
@@ -2958,13 +3004,15 @@ const canonical = base ? base + basedRoute : null;
|
|
|
2958
3004
|
const ogPath = data.config.og.enabled ? withMountedBase("/og/changelog.png") : null;
|
|
2959
3005
|
const ogImage = ogPath && base ? base + ogPath : ogPath;
|
|
2960
3006
|
|
|
2961
|
-
// The page chrome (h1, title, description) comes from the
|
|
2962
|
-
// \`changelog\` group
|
|
2963
|
-
//
|
|
3007
|
+
// The page chrome (h1, title, description, empty state) comes from the
|
|
3008
|
+
// translatable \`changelog\` group, which carries the \`changelog\` config's title and
|
|
3009
|
+
// description when it sets them; optional chaining tolerates a
|
|
3010
|
+
// not-yet-regenerated data snapshot from before these keys existed.
|
|
2964
3011
|
const changelogTitle = data.ui.changelog?.title ?? "Changelog";
|
|
2965
3012
|
const changelogDescription =
|
|
2966
3013
|
data.ui.changelog?.description ??
|
|
2967
3014
|
"Product updates, new features, and fixes from every release.";
|
|
3015
|
+
const changelogEmpty = data.ui.changelog?.empty ?? "No changelog entries yet.";
|
|
2968
3016
|
// The layout suffixes "- {site title}" itself, so the page title is just the
|
|
2969
3017
|
// changelog's own name — prefixing the site title too would double it
|
|
2970
3018
|
// ("Acme Changelog - Acme").
|
|
@@ -3017,7 +3065,7 @@ const LayoutComponent = resolveSlot(layoutOverrides.Layout, RootLayout);
|
|
|
3017
3065
|
<p class="text-lg text-muted-foreground">{changelogDescription}</p>
|
|
3018
3066
|
{
|
|
3019
3067
|
items.length === 0 ? (
|
|
3020
|
-
<p>
|
|
3068
|
+
<p>{changelogEmpty}</p>
|
|
3021
3069
|
) : (
|
|
3022
3070
|
<div class="not-prose mt-10 divide-y divide-border border-border border-y">
|
|
3023
3071
|
{groups.map((group) => (
|
package/src/audit/catalog.ts
CHANGED
|
@@ -161,7 +161,7 @@ export const CHECKS = [
|
|
|
161
161
|
},
|
|
162
162
|
{
|
|
163
163
|
category: "duplicates",
|
|
164
|
-
fix: "Merge the pages, or
|
|
164
|
+
fix: "Merge the pages, or point `seo.canonical` on all but one at the page to index.",
|
|
165
165
|
id: "BLUME_AUDIT_DUPLICATE_CONTENT",
|
|
166
166
|
severity: "warning",
|
|
167
167
|
tier: "static",
|
|
@@ -359,7 +359,7 @@ export const CHECKS = [
|
|
|
359
359
|
},
|
|
360
360
|
{
|
|
361
361
|
category: "redirects",
|
|
362
|
-
fix: "Remove the redirect, or delete the page it shadows —
|
|
362
|
+
fix: "Remove the redirect, or delete the page it shadows — a path can't be both, and which one readers get depends on the host.",
|
|
363
363
|
id: "BLUME_AUDIT_REDIRECT_SOURCE_IS_PAGE",
|
|
364
364
|
severity: "error",
|
|
365
365
|
tier: "static",
|
|
@@ -373,6 +373,14 @@ export const CHECKS = [
|
|
|
373
373
|
tier: "network",
|
|
374
374
|
title: "HTTPS to HTTP redirect",
|
|
375
375
|
},
|
|
376
|
+
{
|
|
377
|
+
category: "redirects",
|
|
378
|
+
fix: "Deploy the redirect file your host reads (see Redirects in the deployment docs), or name the host in `deployment`.",
|
|
379
|
+
id: "BLUME_AUDIT_REDIRECT_NOT_SERVED",
|
|
380
|
+
severity: "error",
|
|
381
|
+
tier: "network",
|
|
382
|
+
title: "Live site doesn't redirect as configured",
|
|
383
|
+
},
|
|
376
384
|
|
|
377
385
|
// Social
|
|
378
386
|
{
|
|
@@ -570,7 +578,7 @@ export const CHECKS = [
|
|
|
570
578
|
// Sitemap
|
|
571
579
|
{
|
|
572
580
|
category: "sitemap",
|
|
573
|
-
fix: "Remove `draft`/`hidden`/`noindex` from the page's frontmatter if it should be indexed.",
|
|
581
|
+
fix: "Remove `draft`/`hidden`/`noindex` from the page's frontmatter if it should be indexed. A `public/sitemap.xml` replaces the generated sitemap, so add the page there or delete that file.",
|
|
574
582
|
id: "BLUME_AUDIT_INDEXABLE_PAGE_NOT_IN_SITEMAP",
|
|
575
583
|
severity: "warning",
|
|
576
584
|
tier: "static",
|
|
@@ -666,6 +674,14 @@ export const CHECKS = [
|
|
|
666
674
|
tier: "static",
|
|
667
675
|
title: "robots.txt disallows a page that is in the sitemap",
|
|
668
676
|
},
|
|
677
|
+
{
|
|
678
|
+
category: "robots",
|
|
679
|
+
fix: "Narrow or remove the rule in that crawler's `User-agent` group if it should read these pages. Blocking an AI crawler on purpose is fine; skip this check.",
|
|
680
|
+
id: "BLUME_AUDIT_ROBOTS_BLOCKS_CRAWLER",
|
|
681
|
+
severity: "warning",
|
|
682
|
+
tier: "static",
|
|
683
|
+
title: "robots.txt blocks one crawler from pages in the sitemap",
|
|
684
|
+
},
|
|
669
685
|
{
|
|
670
686
|
category: "robots",
|
|
671
687
|
fix: "Set `deployment.site` so robots.txt can reference the sitemap.",
|
|
@@ -101,6 +101,12 @@ export const linkChecks: CheckModule = {
|
|
|
101
101
|
return;
|
|
102
102
|
}
|
|
103
103
|
if (resolved.kind === "outside-base") {
|
|
104
|
+
// A full URL on this host outside the base names another app there
|
|
105
|
+
// (the navigation docs say to link one that way), not a page of this
|
|
106
|
+
// build that lost its base.
|
|
107
|
+
if (resolved.absolute) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
104
110
|
if (link.content) {
|
|
105
111
|
found.push(
|
|
106
112
|
finding(
|
|
@@ -215,11 +221,18 @@ export const linkChecks: CheckModule = {
|
|
|
215
221
|
|
|
216
222
|
const homeUrl = normalizeBasePath(context.project.config.basePath) || "/";
|
|
217
223
|
for (const page of orphanPages(context.pages, context.graph, homeUrl)) {
|
|
224
|
+
// A `sidebar.hidden` page is in no other page's navigation either, so
|
|
225
|
+
// it isn't reachable from the sidebar at all.
|
|
226
|
+
const fromNavigation = [
|
|
227
|
+
...(context.graph.chromeIn.get(page.url) ?? []),
|
|
228
|
+
].some((from) => from !== page.url);
|
|
218
229
|
found.push(
|
|
219
230
|
finding(
|
|
220
231
|
"BLUME_AUDIT_ORPHAN_PAGE",
|
|
221
232
|
pageSite(context, page),
|
|
222
|
-
|
|
233
|
+
fromNavigation
|
|
234
|
+
? "No other page's body links here — it is reachable only from the sidebar."
|
|
235
|
+
: "No page links here, from its body or from navigation, so readers and crawlers can't reach it."
|
|
223
236
|
)
|
|
224
237
|
);
|
|
225
238
|
}
|