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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
|
-
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
3
3
|
|
|
4
|
-
import { join } from "pathe";
|
|
4
|
+
import { dirname, join } from "pathe";
|
|
5
5
|
|
|
6
6
|
import { crossOriginDiscoveryPaths } from "../../ai/ai-catalog.ts";
|
|
7
7
|
import {
|
|
@@ -20,7 +20,10 @@ import {
|
|
|
20
20
|
SIGNATURES_DIRECTORY_PATH,
|
|
21
21
|
SIGNATURES_DIRECTORY_TYPE,
|
|
22
22
|
} from "../../ai/web-bot-auth.ts";
|
|
23
|
+
import { mountBasePath, normalizeBasePath } from "../../core/base-path.ts";
|
|
23
24
|
import type { BlumeProject } from "../../core/project-graph.ts";
|
|
25
|
+
import { isPatternPath, regexRedirect } from "../../core/redirect-patterns.ts";
|
|
26
|
+
import type { ResolvedConfig } from "../../core/schema.ts";
|
|
24
27
|
import type { ProjectContext } from "../../core/types.ts";
|
|
25
28
|
import { VERCEL_ADAPTER_PACKAGE } from "../adapters/vercel.ts";
|
|
26
29
|
import {
|
|
@@ -37,7 +40,9 @@ import {
|
|
|
37
40
|
import {
|
|
38
41
|
injectNegotiationRoutes,
|
|
39
42
|
injectRedirectRoutes,
|
|
43
|
+
rebaseAdapterRoutes,
|
|
40
44
|
} from "../vercel-negotiation.ts";
|
|
45
|
+
import type { VercelRoute } from "../vercel-negotiation.ts";
|
|
41
46
|
import { adapterRoot, toSiteUrl } from "./paths.ts";
|
|
42
47
|
import type { BuildLog, DeployPlatform, RedirectFile } from "./types.ts";
|
|
43
48
|
|
|
@@ -56,6 +61,14 @@ export const VERCEL_JSON_FILE: RedirectFile = {
|
|
|
56
61
|
const buildOutputDir = (context: ProjectContext): string =>
|
|
57
62
|
join(adapterRoot(context), ".vercel", "output");
|
|
58
63
|
|
|
64
|
+
/** The static files a server build serves, under the base's directory. */
|
|
65
|
+
const staticDir = (context: ProjectContext, base: string): string =>
|
|
66
|
+
join(buildOutputDir(context), "static", base);
|
|
67
|
+
|
|
68
|
+
/** The project's normalized `deployment.base`, `""` for none. */
|
|
69
|
+
const deploymentBase = (project: BlumeProject): string =>
|
|
70
|
+
normalizeBasePath(project.config.deployment.options.base);
|
|
71
|
+
|
|
59
72
|
/**
|
|
60
73
|
* Refuse to ship a function bundle that would crash at runtime: a bare import
|
|
61
74
|
* the adapter's dependency trace silently dropped (see
|
|
@@ -99,18 +112,21 @@ export const emitVercelNegotiation = async (
|
|
|
99
112
|
log: BuildLog
|
|
100
113
|
): Promise<void> => {
|
|
101
114
|
const { config, context } = project;
|
|
102
|
-
const
|
|
103
|
-
const configPath = join(outputDir, "config.json");
|
|
115
|
+
const configPath = join(buildOutputDir(context), "config.json");
|
|
104
116
|
if (!existsSync(configPath)) {
|
|
105
117
|
return;
|
|
106
118
|
}
|
|
119
|
+
const base = deploymentBase(project);
|
|
107
120
|
const routePaths = markdownRoutePaths(project);
|
|
121
|
+
// Keyed by the file's path in `static/`, under the base's directory.
|
|
108
122
|
const overrides: Record<string, string> = {};
|
|
109
123
|
if (hasApiCatalog(config)) {
|
|
110
|
-
overrides[API_CATALOG_PATH.slice(1)] =
|
|
124
|
+
overrides[mountBasePath(base, API_CATALOG_PATH).slice(1)] =
|
|
125
|
+
API_CATALOG_TYPE;
|
|
111
126
|
}
|
|
112
127
|
if (config.agents.webBotAuth.keys.length > 0) {
|
|
113
|
-
overrides[SIGNATURES_DIRECTORY_PATH.slice(1)] =
|
|
128
|
+
overrides[mountBasePath(base, SIGNATURES_DIRECTORY_PATH).slice(1)] =
|
|
129
|
+
SIGNATURES_DIRECTORY_TYPE;
|
|
114
130
|
}
|
|
115
131
|
// The homepage rewrite serves `/index.md` from the static layer, so its
|
|
116
132
|
// `x-markdown-tokens` estimate has to ride the routing config; the runtime
|
|
@@ -120,7 +136,7 @@ export const emitVercelNegotiation = async (
|
|
|
120
136
|
// The Markdown and JSON 404 routes point at the prerendered twins; only
|
|
121
137
|
// wire each when the build actually emitted it (a project that owns `/404`
|
|
122
138
|
// gets none).
|
|
123
|
-
const
|
|
139
|
+
const builtDir = staticDir(context, base);
|
|
124
140
|
const injected = injectNegotiationRoutes(
|
|
125
141
|
await readFile(configPath, "utf-8"),
|
|
126
142
|
routePaths,
|
|
@@ -128,13 +144,15 @@ export const emitVercelNegotiation = async (
|
|
|
128
144
|
overrides,
|
|
129
145
|
home ? markdownTokenCount(agentMarkdown(home)) : undefined,
|
|
130
146
|
{
|
|
131
|
-
json: existsSync(join(
|
|
132
|
-
markdown: existsSync(join(
|
|
147
|
+
json: existsSync(join(builtDir, "404.json")),
|
|
148
|
+
markdown: existsSync(join(builtDir, "404.md")),
|
|
133
149
|
},
|
|
134
150
|
crossOriginDiscoveryPaths(config),
|
|
135
151
|
// Downloaded content assets are prerendered static files; only a build
|
|
136
152
|
// that has them needs the SVG sandbox route.
|
|
137
|
-
existsSync(join(
|
|
153
|
+
existsSync(join(builtDir, "blume-assets")),
|
|
154
|
+
base,
|
|
155
|
+
config.poweredBy
|
|
138
156
|
);
|
|
139
157
|
if (injected === null) {
|
|
140
158
|
log.warn(
|
|
@@ -175,6 +193,76 @@ export const emitVercelPatternRedirects = async (
|
|
|
175
193
|
await writeFile(configPath, injected, "utf-8");
|
|
176
194
|
};
|
|
177
195
|
|
|
196
|
+
type Redirect = ResolvedConfig["redirects"][number];
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* The exact redirects as Build Output routes, matched the way the pattern ones
|
|
200
|
+
* are (see `regexRedirect`): the served path, a trailing slash optional.
|
|
201
|
+
*/
|
|
202
|
+
const exactRedirectRoutes = (redirects: Redirect[]): VercelRoute[] =>
|
|
203
|
+
redirects
|
|
204
|
+
.filter((redirect) => !isPatternPath(redirect.from))
|
|
205
|
+
.map(({ from, status, to }) => ({
|
|
206
|
+
headers: { Location: encodeURI(to) },
|
|
207
|
+
src: regexRedirect({ parts: [{ kind: "text", text: from }], status, to })
|
|
208
|
+
.source,
|
|
209
|
+
status,
|
|
210
|
+
}));
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Move a server build's static files under `deployment.base`.
|
|
214
|
+
* `@astrojs/vercel` copies them to the root of the Build Output tree's
|
|
215
|
+
* `static/`, while the pages request `<base>/_astro/…` and link to
|
|
216
|
+
* `<base>/…`, so nothing the site asks for would be found. Moved to
|
|
217
|
+
* `static/<base>/`, they're served at the base, as the routes that
|
|
218
|
+
* {@link rebaseVercelRoutes} moves there expect.
|
|
219
|
+
*/
|
|
220
|
+
export const moveStaticUnderBase = async (
|
|
221
|
+
context: ProjectContext,
|
|
222
|
+
base: string
|
|
223
|
+
): Promise<void> => {
|
|
224
|
+
const root = staticDir(context, "");
|
|
225
|
+
if (!base || !existsSync(root)) {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
// Through a sibling, since the target lies inside the directory it moves.
|
|
229
|
+
const staging = join(buildOutputDir(context), "static-unbased");
|
|
230
|
+
await rename(root, staging);
|
|
231
|
+
const target = staticDir(context, base);
|
|
232
|
+
await mkdir(dirname(target), { recursive: true });
|
|
233
|
+
await rename(staging, target);
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Move the adapter's routing config under `deployment.base` to match the
|
|
238
|
+
* static files (see `rebaseAdapterRoutes`), its exact redirects rebuilt from
|
|
239
|
+
* the configured ones. Resolves to false when the config can't be read: the
|
|
240
|
+
* adapter's routes would then miss every path under the base.
|
|
241
|
+
*/
|
|
242
|
+
export const rebaseVercelRoutes = async (
|
|
243
|
+
project: BlumeProject,
|
|
244
|
+
log: BuildLog
|
|
245
|
+
): Promise<boolean> => {
|
|
246
|
+
const base = deploymentBase(project);
|
|
247
|
+
const configPath = join(buildOutputDir(project.context), "config.json");
|
|
248
|
+
if (!base || !existsSync(configPath)) {
|
|
249
|
+
return true;
|
|
250
|
+
}
|
|
251
|
+
const rebased = rebaseAdapterRoutes(
|
|
252
|
+
await readFile(configPath, "utf-8"),
|
|
253
|
+
base,
|
|
254
|
+
exactRedirectRoutes(platformRedirects(project))
|
|
255
|
+
);
|
|
256
|
+
if (rebased === null) {
|
|
257
|
+
log.error(
|
|
258
|
+
`Could not move the routes in .vercel/output/config.json under the deployment base "${base}", so the site would not be served there.`
|
|
259
|
+
);
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
await writeFile(configPath, rebased, "utf-8");
|
|
263
|
+
return true;
|
|
264
|
+
};
|
|
265
|
+
|
|
178
266
|
/**
|
|
179
267
|
* Vercel. A server build's Build Output tree lands at `.vercel/output` — at
|
|
180
268
|
* the project root, because the adapter is handed that root up front: its
|
|
@@ -182,12 +270,15 @@ export const emitVercelPatternRedirects = async (
|
|
|
182
270
|
* hidden runtime silently drops the function's chunks and `node_modules`.
|
|
183
271
|
* Static assets are served from the tree's `static/` half, so the deploy
|
|
184
272
|
* artifacts are written there; headers (the discovery files', the sandbox on
|
|
185
|
-
* downloaded SVGs) arrive through the routing config rather
|
|
186
|
-
* `_headers` file, which Vercel never reads.
|
|
273
|
+
* downloaded SVGs, `X-Powered-By`) arrive through the routing config rather
|
|
274
|
+
* than a `_headers` file, which Vercel never reads. The adapter ignores
|
|
275
|
+
* `deployment.base`, so under one the build moves the static files and the
|
|
276
|
+
* routes beneath it.
|
|
187
277
|
*/
|
|
188
278
|
export const vercelPlatform: DeployPlatform = {
|
|
189
279
|
astro: {
|
|
190
|
-
config: {},
|
|
280
|
+
config: () => ({}),
|
|
281
|
+
configOptions: [],
|
|
191
282
|
options: () => ({}),
|
|
192
283
|
package: VERCEL_ADAPTER_PACKAGE,
|
|
193
284
|
},
|
|
@@ -210,12 +301,19 @@ export const vercelPlatform: DeployPlatform = {
|
|
|
210
301
|
if (!ok) {
|
|
211
302
|
return false;
|
|
212
303
|
}
|
|
304
|
+
// A verify build moves its static files too, where the budget gate reads
|
|
305
|
+
// them (`serverStaticDir`).
|
|
306
|
+
await moveStaticUnderBase(context, deploymentBase(project));
|
|
213
307
|
// An isolated verify only proves the bundle would ship; the routing
|
|
214
308
|
// config is a deploy artifact and stays untouched.
|
|
215
|
-
if (
|
|
216
|
-
|
|
217
|
-
|
|
309
|
+
if (isolated) {
|
|
310
|
+
return true;
|
|
311
|
+
}
|
|
312
|
+
if (!(await rebaseVercelRoutes(project, log))) {
|
|
313
|
+
return false;
|
|
218
314
|
}
|
|
315
|
+
await emitVercelNegotiation(project, log);
|
|
316
|
+
await emitVercelPatternRedirects(project, log);
|
|
219
317
|
return true;
|
|
220
318
|
},
|
|
221
319
|
hiddenRuntime: {
|
|
@@ -231,5 +329,5 @@ export const vercelPlatform: DeployPlatform = {
|
|
|
231
329
|
redirectFiles: [VERCEL_JSON_FILE],
|
|
232
330
|
serverClientUnderBase: false,
|
|
233
331
|
serverOutputDir: buildOutputDir,
|
|
234
|
-
serverStaticDir:
|
|
332
|
+
serverStaticDir: staticDir,
|
|
235
333
|
};
|
package/src/deploy/redirects.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
normalizeBasePath,
|
|
3
|
+
normalizePath,
|
|
4
|
+
stripBasePath,
|
|
3
5
|
withAuthoredBasePath,
|
|
4
6
|
withBasePath,
|
|
5
7
|
withComposedBasePath,
|
|
@@ -11,6 +13,7 @@ import {
|
|
|
11
13
|
compileRedirects,
|
|
12
14
|
exactFirst,
|
|
13
15
|
expandRedirect,
|
|
16
|
+
isPatternPath,
|
|
14
17
|
underscoreRedirect,
|
|
15
18
|
vercelRedirect,
|
|
16
19
|
} from "../core/redirect-patterns.ts";
|
|
@@ -109,9 +112,60 @@ export const applyBaseToPlatformRedirects = (
|
|
|
109
112
|
: redirects;
|
|
110
113
|
};
|
|
111
114
|
|
|
115
|
+
/**
|
|
116
|
+
* The raw-Markdown copies Blume serves beside every page (`/guide.md`,
|
|
117
|
+
* `/guide.mdx`; see `rawMarkdownEndpointTemplate`).
|
|
118
|
+
*/
|
|
119
|
+
const MIRROR_EXTENSIONS = [".md", ".mdx"] as const;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Where a page's Markdown copy is served, from the page's served path and the
|
|
123
|
+
* deployment base that path carries: the endpoints name the root `index`.
|
|
124
|
+
*/
|
|
125
|
+
const mirrorPath = (path: string, base: string, extension: string): string => {
|
|
126
|
+
const route = stripBasePath(base, path);
|
|
127
|
+
return `${base}${route === "/" ? "/index" : route}${extension}`;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Based `redirects`, each exact one that moves a page followed by the same
|
|
132
|
+
* redirect for the page's Markdown copies: from a path no page is served at
|
|
133
|
+
* to one a page is, `/old.md` goes to `/new.md` (and `.mdx` alike), where it
|
|
134
|
+
* would otherwise 404 for an agent still reading the old URL. A pattern gets
|
|
135
|
+
* none; one that carries its capture over (`/beta/:slug*` → `/v2/:slug*`)
|
|
136
|
+
* already moves `/beta/guide.md` along. `pages` are the served page routes
|
|
137
|
+
* (carrying `basePath`, not `deployment.base`), and `bases` the deployment
|
|
138
|
+
* base each end carries: Astro's config leaves it off `from` (see
|
|
139
|
+
* {@link applyBaseToAstroRedirects}).
|
|
140
|
+
*/
|
|
141
|
+
export const withMirrorRedirects = (
|
|
142
|
+
redirects: Redirect[],
|
|
143
|
+
pages: RouteSet,
|
|
144
|
+
bases: { from: string; to: string }
|
|
145
|
+
): Redirect[] =>
|
|
146
|
+
redirects.flatMap((redirect) => {
|
|
147
|
+
const from = normalizePath(redirect.from);
|
|
148
|
+
const to = normalizePath(redirect.to);
|
|
149
|
+
const movesPage =
|
|
150
|
+
!isPatternPath(redirect.from) &&
|
|
151
|
+
servesRoute(pages, stripBasePath(bases.to, to)) &&
|
|
152
|
+
!servesRoute(pages, stripBasePath(bases.from, from));
|
|
153
|
+
return movesPage
|
|
154
|
+
? [
|
|
155
|
+
redirect,
|
|
156
|
+
...MIRROR_EXTENSIONS.map((extension) => ({
|
|
157
|
+
from: mirrorPath(from, bases.from, extension),
|
|
158
|
+
status: redirect.status,
|
|
159
|
+
to: mirrorPath(to, bases.to, extension),
|
|
160
|
+
})),
|
|
161
|
+
]
|
|
162
|
+
: [redirect];
|
|
163
|
+
});
|
|
164
|
+
|
|
112
165
|
/**
|
|
113
166
|
* The configured redirects as the host platform matches them, via
|
|
114
|
-
* {@link applyBaseToPlatformRedirects}
|
|
167
|
+
* {@link applyBaseToPlatformRedirects} plus the Markdown copies of each moved
|
|
168
|
+
* page ({@link withMirrorRedirects}), exact paths ahead of patterns: hosts
|
|
115
169
|
* try rules in order, and an exact redirect wins over a pattern that also
|
|
116
170
|
* covers its path. The one basing every consumer must share: the emitted
|
|
117
171
|
* redirect files and the server wrappers all compare these paths against
|
|
@@ -122,12 +176,18 @@ export const platformRedirects = (project: {
|
|
|
122
176
|
manifest: Pick<BlumeProject["manifest"], "routes">;
|
|
123
177
|
}): Redirect[] => {
|
|
124
178
|
const { config } = project;
|
|
179
|
+
const base = normalizeBasePath(config.deployment.options.base);
|
|
180
|
+
const pages = routeSetFor(project.manifest.routes);
|
|
125
181
|
return exactFirst(
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
182
|
+
withMirrorRedirects(
|
|
183
|
+
applyBaseToPlatformRedirects(
|
|
184
|
+
config.redirects,
|
|
185
|
+
config.basePath,
|
|
186
|
+
base,
|
|
187
|
+
pages
|
|
188
|
+
),
|
|
189
|
+
pages,
|
|
190
|
+
{ from: base, to: base }
|
|
131
191
|
)
|
|
132
192
|
);
|
|
133
193
|
};
|
package/src/deploy/rss.ts
CHANGED
|
@@ -78,7 +78,9 @@ export const buildRssFeeds = (project: BlumeProject): RssFeed[] => {
|
|
|
78
78
|
const items: RssItem[] = pages
|
|
79
79
|
.map((page) => ({
|
|
80
80
|
date: pageDate(page),
|
|
81
|
-
|
|
81
|
+
// A page with only a meta description (a GitHub release, whose
|
|
82
|
+
// summary goes in `seo.description`) still describes its item.
|
|
83
|
+
description: page.description ?? page.meta.seo.description,
|
|
82
84
|
// Encode like the sitemap does: a route with spaces or non-ASCII
|
|
83
85
|
// must still yield a valid <link>/<guid> URL after XML decoding.
|
|
84
86
|
link: encodeURI(`${base}${mountBasePath(deployBase, page.route)}`),
|
package/src/deploy/sitemap.ts
CHANGED
|
@@ -6,7 +6,11 @@ import {
|
|
|
6
6
|
discoverPagesSync,
|
|
7
7
|
hasGeneratedChangelog,
|
|
8
8
|
} from "../astro/pages.ts";
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
mountBasePath,
|
|
11
|
+
normalizeBasePath,
|
|
12
|
+
normalizePath,
|
|
13
|
+
} from "../core/base-path.ts";
|
|
10
14
|
import type { BlumeProject } from "../core/project-graph.ts";
|
|
11
15
|
import { siteRoot } from "../core/site-url.ts";
|
|
12
16
|
|
|
@@ -30,6 +34,30 @@ const lastmodTag = (value: string | undefined): string => {
|
|
|
30
34
|
: `<lastmod>${date.toISOString().slice(0, 10)}</lastmod>`;
|
|
31
35
|
};
|
|
32
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Whether a page's own `seo.canonical` names another URL. The sitemap lists
|
|
39
|
+
* canonical URLs only, so such a page stays out — `blume audit` reports a
|
|
40
|
+
* listed one as NON_CANONICAL_IN_SITEMAP and expects it unlisted. Compared by
|
|
41
|
+
* decoded path, as the audit does: `served` is the page's path with the
|
|
42
|
+
* deployment base mounted, which the canonical carries too.
|
|
43
|
+
*/
|
|
44
|
+
const canonicalElsewhere = (
|
|
45
|
+
canonical: string | undefined,
|
|
46
|
+
served: string
|
|
47
|
+
): boolean => {
|
|
48
|
+
if (!canonical) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
const { pathname } = new URL(canonical);
|
|
52
|
+
let path = pathname;
|
|
53
|
+
try {
|
|
54
|
+
path = decodeURI(pathname);
|
|
55
|
+
} catch {
|
|
56
|
+
// A malformed escape stays as written; it can't match the served path.
|
|
57
|
+
}
|
|
58
|
+
return normalizePath(path) !== normalizePath(served);
|
|
59
|
+
};
|
|
60
|
+
|
|
33
61
|
/** One emitted sitemap artifact: its dist-root filename and XML body. */
|
|
34
62
|
export interface SitemapFile {
|
|
35
63
|
name: string;
|
|
@@ -62,7 +90,8 @@ ${urls.join("\n")}
|
|
|
62
90
|
* can't see: custom `.astro` pages (most importantly a custom landing `/`) and
|
|
63
91
|
* the generated `/changelog` index. Returns null when the sitemap is disabled
|
|
64
92
|
* or no `site` is configured (absolute URLs are required for a valid sitemap).
|
|
65
|
-
* Drafts, hidden, and `noindex` pages are excluded
|
|
93
|
+
* Drafts, hidden, and `noindex` pages are excluded, and so is a page whose
|
|
94
|
+
* `seo.canonical` points elsewhere.
|
|
66
95
|
*
|
|
67
96
|
* Sites within the per-file URL cap get the single classic `sitemap.xml`;
|
|
68
97
|
* larger sites get `sitemap.xml` as a sitemap index over numbered
|
|
@@ -87,7 +116,9 @@ export const buildSitemapFiles = (
|
|
|
87
116
|
// or when their canonical points at a still-existing latest equivalent —
|
|
88
117
|
// listing a URL whose canonical says "index the other page" invites the
|
|
89
118
|
// noindexed-page-in-sitemap incoherence Docusaurus is known for. A page
|
|
90
|
-
// that exists only in an archived version stays listed (self-canonical)
|
|
119
|
+
// that exists only in an archived version stays listed (self-canonical),
|
|
120
|
+
// and a page's own `seo.canonical` wins over the version's default, as it
|
|
121
|
+
// does in the page head (see `canonicalElsewhere`).
|
|
91
122
|
const { versions } = project.config;
|
|
92
123
|
const archivedById = new Map(
|
|
93
124
|
(versions?.archived ?? []).map((version) => [version.id, version])
|
|
@@ -109,6 +140,7 @@ export const buildSitemapFiles = (
|
|
|
109
140
|
return Boolean(
|
|
110
141
|
archived?.noindex ||
|
|
111
142
|
(archived?.canonical === "latest" &&
|
|
143
|
+
!page.meta.seo.canonical &&
|
|
112
144
|
currentKeys?.has(`${page.versionKey}\u0000${page.locale}`))
|
|
113
145
|
);
|
|
114
146
|
};
|
|
@@ -128,16 +160,18 @@ export const buildSitemapFiles = (
|
|
|
128
160
|
urls.push(` <url><loc>${loc}</loc>${lastmodTag(lastModified)}</url>`);
|
|
129
161
|
};
|
|
130
162
|
for (const page of project.graph.pages) {
|
|
163
|
+
const served = mountBasePath(deployBase, page.route);
|
|
131
164
|
if (
|
|
132
165
|
page.meta.draft ||
|
|
133
166
|
page.meta.sidebar.hidden ||
|
|
134
167
|
page.meta.seo.noindex ||
|
|
135
168
|
ERROR_ROUTES.has(page.route) ||
|
|
136
|
-
archivedExcluded(page)
|
|
169
|
+
archivedExcluded(page) ||
|
|
170
|
+
canonicalElsewhere(page.meta.seo.canonical, served)
|
|
137
171
|
) {
|
|
138
172
|
continue;
|
|
139
173
|
}
|
|
140
|
-
pushUrl(
|
|
174
|
+
pushUrl(served, page.lastModified);
|
|
141
175
|
}
|
|
142
176
|
// Custom `.astro` pages and the generated changelog index mount outside
|
|
143
177
|
// `basePath` (they're injected at their pattern — see `blumeIntegration`), so
|