blume 1.7.3 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +19 -0
- package/CHANGELOG.md +217 -0
- package/README.md +34 -21
- package/dist/cli/chunk-11j0384y.js +148 -0
- package/dist/cli/chunk-11j0384y.js.map +10 -0
- package/dist/cli/{chunk-rqy0s5wh.js → chunk-1w8dp3qb.js} +17 -16
- package/dist/cli/{chunk-rqy0s5wh.js.map → chunk-1w8dp3qb.js.map} +3 -3
- package/dist/cli/chunk-2q1dwty4.js +75 -0
- package/dist/cli/chunk-2q1dwty4.js.map +11 -0
- package/dist/cli/chunk-41za066z.js +122 -0
- package/dist/cli/chunk-41za066z.js.map +11 -0
- package/dist/cli/chunk-5a2z0198.js +133 -0
- package/dist/cli/chunk-5a2z0198.js.map +10 -0
- package/dist/cli/{chunk-5g0w1e2c.js → chunk-6k8vp3ta.js} +25 -13
- package/dist/cli/{chunk-5g0w1e2c.js.map → chunk-6k8vp3ta.js.map} +4 -4
- package/dist/cli/{chunk-5qk08vmp.js → chunk-79njf86q.js} +133 -54
- package/dist/cli/chunk-79njf86q.js.map +11 -0
- package/dist/cli/{chunk-e7f42gdj.js → chunk-7ez8ny0t.js} +2 -2
- package/dist/cli/{chunk-nn13znc2.js → chunk-88cpgt6h.js} +1 -1
- package/dist/cli/chunk-a9kptbw5.js +361 -0
- package/dist/cli/chunk-a9kptbw5.js.map +14 -0
- package/dist/cli/chunk-abh8yjkn.js +31 -0
- package/dist/cli/chunk-abh8yjkn.js.map +10 -0
- package/dist/cli/chunk-b5aj94ah.js +91 -0
- package/dist/cli/chunk-b5aj94ah.js.map +10 -0
- package/dist/cli/{chunk-b27xqwn9.js → chunk-bctazmbk.js} +9 -5
- package/dist/cli/chunk-bctazmbk.js.map +10 -0
- package/dist/cli/chunk-beat36xx.js +279 -0
- package/dist/cli/chunk-beat36xx.js.map +10 -0
- package/dist/cli/chunk-bnbmcwfb.js +145 -0
- package/dist/cli/chunk-bnbmcwfb.js.map +11 -0
- package/dist/cli/{chunk-0xjyb285.js → chunk-bw22s759.js} +15 -5
- package/dist/cli/{chunk-0xjyb285.js.map → chunk-bw22s759.js.map} +4 -4
- package/dist/cli/chunk-by2290sx.js +39 -0
- package/dist/cli/chunk-by2290sx.js.map +10 -0
- package/dist/cli/chunk-d1tadaw7.js +79 -0
- package/dist/cli/chunk-d1tadaw7.js.map +10 -0
- package/dist/cli/{chunk-ahnw3kxw.js → chunk-d80hr03s.js} +24 -19
- package/dist/cli/chunk-d80hr03s.js.map +15 -0
- package/dist/cli/chunk-ernrthtr.js +97 -0
- package/dist/cli/chunk-ernrthtr.js.map +10 -0
- package/dist/cli/chunk-f2972sbt.js +374 -0
- package/dist/cli/chunk-f2972sbt.js.map +10 -0
- package/dist/cli/{chunk-vacwm2hv.js → chunk-f7t03s3g.js} +2 -2
- package/dist/cli/{chunk-2z47ypj8.js → chunk-fa25z98p.js} +16 -3
- package/dist/cli/chunk-fa25z98p.js.map +11 -0
- package/dist/cli/{chunk-cjtn640a.js → chunk-fh5hj5jt.js} +43 -20
- package/dist/cli/chunk-fh5hj5jt.js.map +10 -0
- package/dist/cli/{chunk-yg63d42r.js → chunk-j8mw0za6.js} +86 -57
- package/dist/cli/chunk-j8mw0za6.js.map +35 -0
- package/dist/cli/{chunk-ct47dqpx.js → chunk-jts8mvcz.js} +67 -7
- package/dist/cli/{chunk-2mzebbbz.js.map → chunk-jts8mvcz.js.map} +6 -4
- package/dist/cli/{chunk-ps4m1xh4.js → chunk-mnqj32sj.js} +505 -542
- package/dist/cli/chunk-mnqj32sj.js.map +12 -0
- package/dist/cli/{chunk-8cjtbafj.js → chunk-mwt1k8n7.js} +100 -374
- package/dist/cli/chunk-mwt1k8n7.js.map +10 -0
- package/dist/cli/chunk-nk3ts2xk.js +51 -0
- package/dist/cli/chunk-nk3ts2xk.js.map +10 -0
- package/dist/cli/{chunk-3r45185y.js → chunk-pat2zzwc.js} +9 -11
- package/dist/cli/{chunk-3r45185y.js.map → chunk-pat2zzwc.js.map} +2 -2
- package/dist/cli/chunk-pnnvybbk.js +176 -0
- package/dist/cli/chunk-pnnvybbk.js.map +11 -0
- package/dist/cli/{chunk-4x36ddpw.js → chunk-sqn5t4q0.js} +81 -87
- package/dist/cli/chunk-sqn5t4q0.js.map +10 -0
- package/dist/cli/{chunk-bvwwhd84.js → chunk-tzne8qfq.js} +15 -15
- package/dist/cli/{chunk-bvwwhd84.js.map → chunk-tzne8qfq.js.map} +1 -1
- package/dist/cli/chunk-xaz13gwg.js +12449 -0
- package/dist/cli/chunk-xaz13gwg.js.map +182 -0
- package/dist/cli/chunk-y3e45rc8.js +102 -0
- package/dist/cli/chunk-y3e45rc8.js.map +10 -0
- package/dist/cli/chunk-z01ze5c1.js +261 -0
- package/dist/cli/chunk-z01ze5c1.js.map +10 -0
- package/dist/cli/{chunk-k79xp7av.js → chunk-z1f5arsg.js} +219 -689
- package/dist/cli/chunk-z1f5arsg.js.map +36 -0
- package/dist/cli/{chunk-1jefwnfs.js → chunk-zg2gtj10.js} +1076 -2592
- package/dist/cli/chunk-zg2gtj10.js.map +35 -0
- package/dist/cli/{chunk-dwgcp5sm.js → chunk-zxccj738.js} +1 -1
- package/dist/cli/index.js +214 -57
- package/dist/cli/index.js.map +8 -7
- package/dist/types/ai/agent-readability.d.ts +52 -0
- package/dist/types/ai/ai-catalog.d.ts +42 -0
- package/dist/types/ai/api/paths.d.ts +17 -0
- package/dist/types/ai/api-catalog.d.ts +18 -0
- package/dist/types/ai/ask.d.ts +368 -0
- package/dist/types/ai/changelog-markdown.d.ts +2 -0
- package/dist/types/ai/component-markdown.d.ts +2 -2
- package/dist/types/ai/index.d.ts +24 -0
- package/dist/types/ai/link-headers.d.ts +24 -0
- package/dist/types/ai/llms.d.ts +25 -0
- package/dist/types/ai/markdown.d.ts +45 -0
- package/dist/types/ai/mcp/discovery.d.ts +68 -0
- package/dist/types/ai/mcp/tools.d.ts +16 -0
- package/dist/types/ai/openapi-components.d.ts +43 -0
- package/dist/types/ai/relative-links.d.ts +26 -0
- package/dist/types/ai/serializers.d.ts +15 -0
- package/dist/types/ai/skills.d.ts +42 -0
- package/dist/types/ai/tar.d.ts +25 -0
- package/dist/types/ai/visibility.d.ts +17 -0
- package/dist/types/ai/web-bot-auth.d.ts +16 -0
- package/dist/types/analytics/adobe.d.ts +35 -0
- package/dist/types/analytics/amplitude.d.ts +50 -0
- package/dist/types/analytics/clarity.d.ts +31 -0
- package/dist/types/analytics/clearbit.d.ts +29 -0
- package/dist/types/analytics/cloudflare.d.ts +41 -0
- package/dist/types/analytics/fathom.d.ts +41 -0
- package/dist/types/analytics/google-analytics.d.ts +44 -0
- package/dist/types/analytics/google-tag-manager.d.ts +40 -0
- package/dist/types/analytics/head.d.ts +30 -0
- package/dist/types/analytics/heap.d.ts +40 -0
- package/dist/types/analytics/hightouch.d.ts +44 -0
- package/dist/types/analytics/hotjar.d.ts +33 -0
- package/dist/types/analytics/index.d.ts +61 -0
- package/dist/types/analytics/inline.d.ts +17 -0
- package/dist/types/analytics/logrocket.d.ts +44 -0
- package/dist/types/analytics/mixpanel.d.ts +67 -0
- package/dist/types/analytics/pirsch.d.ts +42 -0
- package/dist/types/analytics/plausible.d.ts +56 -0
- package/dist/types/analytics/posthog.d.ts +45 -0
- package/dist/types/analytics/schema.d.ts +320 -0
- package/dist/types/analytics/script.d.ts +46 -0
- package/dist/types/analytics/segment.d.ts +50 -0
- package/dist/types/analytics/vercel.d.ts +48 -0
- package/dist/types/astro/integration.d.ts +76 -0
- package/dist/types/astro/markdown-negotiation.d.ts +23 -0
- package/dist/types/astro/module-types.d.ts +14 -0
- package/dist/types/astro/pages.d.ts +44 -0
- package/dist/types/cli/env.d.ts +12 -0
- package/dist/types/cli/init/scaffold.d.ts +154 -0
- package/dist/types/components/layout/nav-utils.d.ts +11 -0
- package/dist/types/core/adapter.d.ts +47 -0
- package/dist/types/core/api-name.d.ts +7 -0
- package/dist/types/core/changelog-index.d.ts +13 -0
- package/dist/types/core/config-input.d.ts +186 -515
- package/dist/types/core/config.d.ts +60 -34
- package/dist/types/core/content-assets.d.ts +76 -0
- package/dist/types/core/custom-pages.d.ts +33 -0
- package/dist/types/core/data.d.ts +27 -12
- package/dist/types/core/define-components.d.ts +12 -9
- package/dist/types/core/deployment-env.d.ts +6 -11
- package/dist/types/core/frontmatter.d.ts +10 -0
- package/dist/types/core/graph.d.ts +18 -0
- package/dist/types/core/heading-markers.d.ts +54 -0
- package/dist/types/core/i18n-ui.d.ts +6 -2
- package/dist/types/core/i18n.d.ts +87 -0
- package/dist/types/core/includes.d.ts +138 -0
- package/dist/types/core/last-modified.d.ts +47 -0
- package/dist/types/core/links.d.ts +95 -0
- package/dist/types/core/locale-links.d.ts +60 -0
- package/dist/types/core/manifest.d.ts +17 -0
- package/dist/types/core/meta.d.ts +38 -0
- package/dist/types/core/nav-diagnostics.d.ts +26 -0
- package/dist/types/core/navigation.d.ts +6 -0
- package/dist/types/core/node-require.d.ts +19 -0
- package/dist/types/core/package-json.d.ts +13 -0
- package/dist/types/core/probe.d.ts +42 -0
- package/dist/types/core/project-graph.d.ts +51 -0
- package/dist/types/core/project.d.ts +2 -0
- package/dist/types/core/safe-href.d.ts +2 -0
- package/dist/types/core/safe-links.d.ts +26 -0
- package/dist/types/core/schema.d.ts +2282 -452
- package/dist/types/core/site-url.d.ts +16 -0
- package/dist/types/core/sources/assets.d.ts +36 -0
- package/dist/types/core/sources/cache.d.ts +37 -0
- package/dist/types/core/sources/collection.d.ts +28 -0
- package/dist/types/core/sources/contentful-rich-text.d.ts +31 -0
- package/dist/types/core/sources/contentful.d.ts +40 -0
- package/dist/types/core/sources/filesystem.d.ts +24 -0
- package/dist/types/core/sources/github-releases.d.ts +31 -0
- package/dist/types/core/sources/json.d.ts +30 -0
- package/dist/types/core/sources/lexical.d.ts +19 -0
- package/dist/types/core/sources/lower.d.ts +75 -0
- package/dist/types/core/sources/mdx-remote.d.ts +28 -0
- package/dist/types/core/sources/normalize.d.ts +147 -0
- package/dist/types/core/sources/notion.d.ts +131 -0
- package/dist/types/core/sources/obsidian.d.ts +46 -0
- package/dist/types/core/sources/payload.d.ts +39 -0
- package/dist/types/core/sources/portable-text.d.ts +42 -0
- package/dist/types/core/sources/read.d.ts +23 -0
- package/dist/types/core/sources/remote.d.ts +74 -0
- package/dist/types/core/sources/resolve.d.ts +19 -0
- package/dist/types/core/sources/sanity.d.ts +43 -0
- package/dist/types/core/sources/strapi-blocks.d.ts +12 -0
- package/dist/types/core/sources/strapi.d.ts +33 -0
- package/dist/types/core/sources/types.d.ts +7 -0
- package/dist/types/core/sources/watch.d.ts +45 -0
- package/dist/types/core/text-width.d.ts +11 -0
- package/dist/types/core/types.d.ts +15 -1
- package/dist/types/core/unrecognized-keys.d.ts +7 -0
- package/dist/types/core/versions.d.ts +72 -0
- package/dist/types/core/yaml.d.ts +9 -0
- package/dist/types/deploy/adapter-output.d.ts +45 -0
- package/dist/types/deploy/adapters/cloudflare.d.ts +40 -0
- package/dist/types/deploy/adapters/index.d.ts +29 -0
- package/dist/types/deploy/adapters/netlify.d.ts +37 -0
- package/dist/types/deploy/adapters/node.d.ts +37 -0
- package/dist/types/deploy/adapters/registry.d.ts +133 -0
- package/dist/types/deploy/adapters/types.d.ts +71 -0
- package/dist/types/deploy/adapters/vercel.d.ts +38 -0
- package/dist/types/deploy/artifacts.d.ts +65 -0
- package/dist/types/deploy/cloudflare-negotiation.d.ts +196 -0
- package/dist/types/deploy/function-bundle.d.ts +80 -0
- package/dist/types/deploy/headers.d.ts +50 -0
- package/dist/types/deploy/node-headers.d.ts +42 -0
- package/dist/types/deploy/platforms/cloudflare.d.ts +40 -0
- package/dist/types/deploy/platforms/index.d.ts +18 -0
- package/dist/types/deploy/platforms/netlify.d.ts +13 -0
- package/dist/types/deploy/platforms/node.d.ts +11 -0
- package/dist/types/deploy/platforms/paths.d.ts +27 -0
- package/dist/types/deploy/platforms/static.d.ts +10 -0
- package/dist/types/deploy/platforms/types.d.ts +104 -0
- package/dist/types/deploy/platforms/vercel.d.ts +32 -0
- package/dist/types/deploy/redirects.d.ts +53 -0
- package/dist/types/deploy/robots.d.ts +8 -0
- package/dist/types/deploy/rss.d.ts +31 -0
- package/dist/types/deploy/sitemap.d.ts +21 -0
- package/dist/types/deploy/vercel-negotiation.d.ts +109 -0
- package/dist/types/markdown/code-title.d.ts +32 -0
- package/dist/types/markdown/fence-meta.d.ts +23 -0
- package/dist/types/markdown/themes.d.ts +3 -3
- package/dist/types/openapi/asyncapi.d.ts +129 -0
- package/dist/types/openapi/graphql-build.d.ts +8 -0
- package/dist/types/openapi/graphql.d.ts +122 -0
- package/dist/types/openapi/model.d.ts +158 -0
- package/dist/types/openapi/parse.d.ts +57 -0
- package/dist/types/openapi/references.d.ts +37 -25
- package/dist/types/openapi/render-mdx.d.ts +33 -0
- package/dist/types/openapi/sentence.d.ts +7 -0
- package/dist/types/openapi/signature.d.ts +10 -0
- package/dist/types/openapi/source.d.ts +22 -0
- package/dist/types/openapi/spec-dependency-error.d.ts +10 -0
- package/dist/types/reference/asyncapi.d.ts +166 -0
- package/dist/types/reference/graphql.d.ts +181 -0
- package/dist/types/reference/index.d.ts +32 -0
- package/dist/types/reference/openapi.d.ts +165 -0
- package/dist/types/reference/options.d.ts +157 -0
- package/dist/types/reference/scalar.d.ts +136 -0
- package/dist/types/reference/schema.d.ts +630 -0
- package/dist/types/search/adapters/algolia.d.ts +32 -0
- package/dist/types/search/adapters/flexsearch.d.ts +12 -0
- package/dist/types/search/adapters/index.d.ts +31 -0
- package/dist/types/search/adapters/mixedbread.d.ts +22 -0
- package/dist/types/search/adapters/orama-cloud.d.ts +33 -0
- package/dist/types/search/adapters/orama.d.ts +13 -0
- package/dist/types/search/adapters/pagefind.d.ts +12 -0
- package/dist/types/search/adapters/registry.d.ts +228 -0
- package/dist/types/search/adapters/types.d.ts +34 -0
- package/dist/types/search/adapters/typesense.d.ts +42 -0
- package/dist/types/search/build.d.ts +23 -0
- package/dist/types/search/documents.d.ts +90 -0
- package/dist/types/search/facets.d.ts +3 -0
- package/dist/types/search/sync/algolia.d.ts +14 -0
- package/dist/types/search/sync/index.d.ts +14 -0
- package/dist/types/search/sync/orama-cloud.d.ts +10 -0
- package/dist/types/search/sync/typesense.d.ts +14 -0
- package/dist/types/sources/contentful.d.ts +68 -0
- package/dist/types/sources/custom.d.ts +20 -0
- package/dist/types/sources/filesystem.d.ts +42 -0
- package/dist/types/sources/github-releases.d.ts +46 -0
- package/dist/types/sources/index.d.ts +48 -0
- package/dist/types/sources/mdx-remote.d.ts +63 -0
- package/dist/types/sources/notion.d.ts +65 -0
- package/dist/types/sources/obsidian.d.ts +34 -0
- package/dist/types/sources/payload.d.ts +68 -0
- package/dist/types/sources/registry.d.ts +1414 -0
- package/dist/types/sources/sanity.d.ts +69 -0
- package/dist/types/sources/shared.d.ts +46 -0
- package/dist/types/sources/strapi.d.ts +66 -0
- package/dist/types/theme/icon-kind.d.ts +11 -0
- package/dist/types/theme/icons.d.ts +20 -0
- package/docs/01-quickstart.mdx +18 -18
- package/docs/02-deployment.mdx +50 -26
- package/docs/03-upgrading.mdx +351 -0
- package/docs/04-migrating.mdx +58 -0
- package/docs/08-faq.mdx +3 -3
- package/docs/advanced/blog.mdx +13 -6
- package/docs/advanced/changelog.mdx +23 -35
- package/docs/advanced/custom-pages.mdx +20 -8
- package/docs/advanced/meta.ts +1 -8
- package/docs/advanced/skills.mdx +8 -0
- package/docs/cli/audit.mdx +646 -0
- package/docs/cli/doctor.mdx +29 -0
- package/docs/{reference/eval.mdx → cli/evals.mdx} +9 -8
- package/docs/cli/index.mdx +105 -0
- package/docs/cli/meta.ts +7 -0
- package/docs/{reference → cli}/translate.mdx +1 -1
- package/docs/cli/validate.mdx +41 -0
- package/docs/cli/version.mdx +40 -0
- package/docs/configuration/analytics.mdx +350 -59
- package/docs/configuration/ask-ai.mdx +162 -61
- package/docs/configuration/customization.mdx +15 -9
- package/docs/configuration/index.mdx +50 -31
- package/docs/configuration/search.mdx +75 -54
- package/docs/configuration/theming.mdx +24 -15
- package/docs/content/components.mdx +21 -5
- package/docs/{reference → content}/frontmatter.mdx +35 -1
- package/docs/content/i18n.mdx +8 -6
- package/docs/content/includes.mdx +2 -4
- package/docs/content/index.mdx +1 -1
- package/docs/content/islands.mdx +10 -5
- package/docs/content/meta.mdx +1 -1
- package/docs/content/meta.ts +1 -0
- package/docs/content/navigation.mdx +9 -7
- package/docs/content/sources.mdx +145 -50
- package/docs/content/syntax.mdx +16 -12
- package/docs/content/versioning.mdx +3 -3
- package/docs/discoverability/agent-discovery.mdx +11 -11
- package/docs/discoverability/index.mdx +4 -4
- package/docs/discoverability/json-api.mdx +4 -4
- package/docs/discoverability/llms-txt.mdx +6 -6
- package/docs/discoverability/markdown.mdx +4 -4
- package/docs/discoverability/mcp.mdx +11 -11
- package/docs/discoverability/sitemap-and-robots.mdx +3 -3
- package/docs/index.mdx +2 -2
- package/docs/references/asyncapi.mdx +59 -0
- package/docs/{advanced → references}/graphql.mdx +45 -32
- package/docs/{reference → references}/meta.ts +2 -2
- package/docs/references/openapi.mdx +171 -0
- package/docs/references/scalar.mdx +64 -0
- package/package.json +42 -8
- package/skills/blume/SKILL.md +21 -8
- package/skills/blume-migrate/SKILL.md +22 -21
- package/skills/blume-migrate/assets/oxfmt@0.67.0.patch +49 -0
- package/skills/blume-migrate/references/docusaurus.md +5 -4
- package/skills/blume-migrate/references/fumadocs.md +4 -4
- package/skills/blume-migrate/references/mintlify.md +23 -8
- package/skills/blume-migrate/references/monorepo.md +6 -6
- package/skills/blume-migrate/references/starlight.md +4 -4
- package/src/ai/agent-readability.ts +21 -22
- package/src/ai/ai-catalog.ts +50 -32
- package/src/ai/api/handlers.ts +46 -11
- package/src/ai/api-catalog.ts +8 -8
- package/src/ai/ask-data.ts +1 -1
- package/src/ai/ask.ts +624 -100
- package/src/ai/changelog-markdown.ts +91 -0
- package/src/ai/component-markdown.ts +328 -12
- package/src/ai/index.ts +45 -0
- package/src/ai/link-headers.ts +7 -6
- package/src/ai/llms.ts +20 -15
- package/src/ai/markdown.ts +35 -5
- package/src/ai/mcp/data.ts +9 -5
- package/src/ai/openapi-components.ts +4 -1
- package/src/ai/relative-links.ts +170 -0
- package/src/ai/serializers.ts +2 -2
- package/src/ai/skills.ts +1 -1
- package/src/ai/web-bot-auth.ts +2 -2
- package/src/analytics/adobe.ts +46 -0
- package/src/analytics/amplitude.ts +79 -0
- package/src/analytics/clarity.ts +46 -0
- package/src/analytics/clearbit.ts +47 -0
- package/src/analytics/cloudflare.ts +67 -0
- package/src/analytics/fathom.ts +64 -0
- package/src/analytics/google-analytics.ts +84 -0
- package/src/analytics/google-tag-manager.ts +61 -0
- package/src/analytics/head.ts +130 -0
- package/src/analytics/heap.ts +65 -0
- package/src/analytics/hightouch.ts +77 -0
- package/src/analytics/hotjar.ts +47 -0
- package/src/analytics/index.ts +71 -0
- package/src/analytics/inline.ts +21 -0
- package/src/analytics/logrocket.ts +71 -0
- package/src/analytics/mixpanel.ts +92 -0
- package/src/analytics/pirsch.ts +66 -0
- package/src/analytics/plausible.ts +83 -0
- package/src/analytics/posthog.ts +78 -0
- package/src/analytics/schema.ts +60 -0
- package/src/analytics/script.ts +60 -0
- package/src/analytics/segment.ts +85 -0
- package/src/analytics/vercel.ts +50 -0
- package/src/astro/adapter-root.ts +7 -9
- package/src/astro/component-slots.ts +131 -91
- package/src/astro/generate.ts +112 -345
- package/src/astro/integration.ts +2 -6
- package/src/astro/pages.ts +13 -101
- package/src/astro/render-deps.ts +379 -0
- package/src/astro/runtime-deps.ts +201 -0
- package/src/astro/templates.ts +554 -541
- package/src/audit/agent.ts +24 -0
- package/src/audit/catalog.ts +2 -2
- package/src/audit/checks/assets.ts +2 -2
- package/src/audit/checks/dns-aid.ts +1 -1
- package/src/audit/checks/duplicates.ts +3 -1
- package/src/audit/checks/i18n.ts +1 -1
- package/src/audit/checks/indexability.ts +7 -7
- package/src/audit/checks/links.ts +2 -2
- package/src/audit/checks/llms.ts +6 -6
- package/src/audit/checks/network.ts +3 -3
- package/src/audit/checks/og-image.ts +2 -2
- package/src/audit/checks/robots.ts +1 -1
- package/src/audit/checks/sitemap.ts +2 -2
- package/src/audit/checks/social.ts +1 -1
- package/src/audit/run.ts +4 -3
- package/src/audit/terms.ts +31 -0
- package/src/audit/url.ts +13 -13
- package/src/cli/command-meta.ts +10 -0
- package/src/cli/commands/audit.ts +39 -20
- package/src/cli/commands/build.ts +71 -316
- package/src/cli/commands/check.ts +1 -0
- package/src/cli/commands/dev.ts +40 -1
- package/src/cli/commands/doctor.ts +90 -14
- package/src/cli/commands/eject.ts +44 -7
- package/src/cli/commands/eval.ts +2 -2
- package/src/cli/commands/init.ts +161 -41
- package/src/cli/commands/migrate.ts +121 -0
- package/src/cli/commands/preview.ts +7 -1
- package/src/cli/commands/translate.ts +2 -2
- package/src/cli/commands/upgrade.ts +141 -0
- package/src/cli/commands/version.ts +57 -44
- package/src/cli/eject-scripts.ts +121 -6
- package/src/cli/index.ts +11 -1
- package/src/cli/init/install.ts +70 -0
- package/src/cli/init/questions.ts +7 -0
- package/src/cli/init/scaffold.ts +459 -75
- package/src/cli/lazy-command.ts +37 -1
- package/src/cli/prepare.ts +40 -6
- package/src/cli/required-secrets.ts +38 -11
- package/src/cli/unknown-flags.ts +266 -0
- package/src/cli/yarn-pnp.ts +52 -0
- package/src/components/content/AccordionItem.astro +7 -1
- package/src/components/content/Card.astro +4 -3
- package/src/components/content/ColorItem.astro +22 -4
- package/src/components/content/GithubInfo.astro +2 -2
- package/src/components/content/Prompt.astro +25 -25
- package/src/components/content/Tabs.astro +3 -1
- package/src/components/content/Tile.astro +2 -3
- package/src/components/content/Tooltip.astro +57 -9
- package/src/components/content/content-strings.ts +34 -0
- package/src/components/content/diff.ts +1 -1
- package/src/components/content/mermaid-element.ts +13 -2
- package/src/components/content/prompt-markdown.ts +292 -0
- package/src/components/content/tooltip-id.ts +41 -0
- package/src/components/islands/hooks.ts +25 -2
- package/src/components/layout/Analytics.astro +21 -79
- package/src/components/layout/Banner.astro +3 -1
- package/src/components/layout/DiscoveryLinks.astro +69 -0
- package/src/components/layout/Header.astro +83 -20
- package/src/components/layout/LanguageSwitcher.astro +4 -1
- package/src/components/layout/Logo.astro +23 -2
- package/src/components/layout/NavSelector.astro +13 -2
- package/src/components/layout/NavTree.astro +12 -3
- package/src/components/layout/NavTreeScript.astro +17 -3
- package/src/components/layout/PageActions.astro +3 -3
- package/src/components/layout/PageFeedback.astro +11 -1
- package/src/components/layout/PageLayout.astro +52 -5
- package/src/components/layout/ReferenceLayout.astro +21 -12
- package/src/components/layout/RootLayout.astro +69 -66
- package/src/components/layout/Search.astro +30 -6
- package/src/components/layout/WebMcp.astro +1 -1
- package/src/components/layout/analytics-client.ts +72 -15
- package/src/components/layout/drawer-inert.ts +113 -15
- package/src/components/layout/dropdown-clamp.ts +105 -0
- package/src/components/layout/head-scripts.ts +15 -6
- package/src/components/layout/nav-utils.ts +17 -0
- package/src/components/layout/search/algolia.ts +8 -8
- package/src/components/layout/search/orama-cloud.ts +9 -7
- package/src/components/layout/search/typesense.ts +11 -17
- package/src/components/openapi/MessageComposer.astro +2 -2
- package/src/components/openapi/Playground.astro +2 -2
- package/src/components/openapi/playground-client.ts +79 -10
- package/src/core/changelog-index.ts +24 -0
- package/src/core/component-overrides.ts +399 -154
- package/src/core/config-input.ts +188 -553
- package/src/core/config.ts +130 -41
- package/src/core/custom-pages.ts +105 -0
- package/src/core/data.ts +31 -12
- package/src/core/define-components.ts +12 -9
- package/src/core/deployment-env.ts +18 -74
- package/src/core/diagnostics.ts +14 -7
- package/src/core/graph.ts +69 -25
- package/src/core/i18n-ui.ts +6 -2
- package/src/core/i18n.ts +17 -0
- package/src/core/includes.ts +156 -38
- package/src/core/last-modified.ts +6 -11
- package/src/core/links.ts +166 -2
- package/src/core/manifest.ts +10 -3
- package/src/core/navigation.ts +115 -16
- package/src/core/new-tab.ts +35 -0
- package/src/core/node-require.ts +21 -0
- package/src/core/project-graph.ts +42 -26
- package/src/core/project.ts +9 -4
- package/src/core/request-body.ts +61 -0
- package/src/core/safe-href.ts +28 -0
- package/src/core/safe-links.ts +68 -0
- package/src/core/schema.ts +517 -739
- package/src/core/server-features.ts +8 -9
- package/src/core/sources/assets.ts +47 -11
- package/src/core/sources/collection.ts +67 -0
- package/src/core/sources/contentful-rich-text.ts +285 -0
- package/src/core/sources/contentful.ts +173 -0
- package/src/core/sources/github-releases.ts +51 -1
- package/src/core/sources/json.ts +71 -0
- package/src/core/sources/lexical.ts +195 -0
- package/src/core/sources/lower.ts +226 -0
- package/src/core/sources/normalize.ts +52 -2
- package/src/core/sources/notion.ts +39 -28
- package/src/core/sources/payload.ts +135 -0
- package/src/core/sources/portable-text.ts +11 -16
- package/src/core/sources/remote.ts +226 -0
- package/src/core/sources/resolve.ts +104 -166
- package/src/core/sources/sanity.ts +16 -49
- package/src/core/sources/strapi-blocks.ts +124 -0
- package/src/core/sources/strapi.ts +191 -0
- package/src/core/sources/types.ts +12 -1
- package/src/core/types.ts +15 -1
- package/src/core/ui-packs/ar.ts +6 -2
- package/src/core/ui-packs/bg.ts +6 -2
- package/src/core/ui-packs/bn.ts +6 -2
- package/src/core/ui-packs/ca.ts +3 -1
- package/src/core/ui-packs/cs.ts +6 -2
- package/src/core/ui-packs/da.ts +6 -2
- package/src/core/ui-packs/de.ts +6 -2
- package/src/core/ui-packs/el.ts +3 -1
- package/src/core/ui-packs/es.ts +3 -1
- package/src/core/ui-packs/fa.ts +6 -2
- package/src/core/ui-packs/fi.ts +6 -2
- package/src/core/ui-packs/fr.ts +3 -1
- package/src/core/ui-packs/he.ts +6 -2
- package/src/core/ui-packs/hi.ts +6 -2
- package/src/core/ui-packs/hr.ts +6 -2
- package/src/core/ui-packs/hu.ts +6 -2
- package/src/core/ui-packs/id.ts +6 -2
- package/src/core/ui-packs/it.ts +3 -1
- package/src/core/ui-packs/ja.ts +3 -1
- package/src/core/ui-packs/ko.ts +3 -1
- package/src/core/ui-packs/nl.ts +6 -2
- package/src/core/ui-packs/no.ts +6 -2
- package/src/core/ui-packs/pl.ts +6 -2
- package/src/core/ui-packs/pt-br.ts +3 -1
- package/src/core/ui-packs/pt.ts +3 -1
- package/src/core/ui-packs/ro.ts +6 -2
- package/src/core/ui-packs/ru.ts +6 -2
- package/src/core/ui-packs/sk.ts +6 -2
- package/src/core/ui-packs/sr.ts +6 -2
- package/src/core/ui-packs/sv.ts +6 -2
- package/src/core/ui-packs/th.ts +3 -1
- package/src/core/ui-packs/tr.ts +6 -2
- package/src/core/ui-packs/uk.ts +6 -2
- package/src/core/ui-packs/vi.ts +3 -1
- package/src/core/ui-packs/zh-tw.ts +3 -1
- package/src/core/ui-packs/zh.ts +3 -1
- package/src/core/unrecognized-keys.ts +10 -0
- package/src/core/version-cut.ts +116 -8
- package/src/deploy/adapter-output.ts +57 -97
- package/src/deploy/adapters/cloudflare.ts +39 -0
- package/src/deploy/adapters/index.ts +41 -0
- package/src/deploy/adapters/netlify.ts +34 -0
- package/src/deploy/adapters/node.ts +34 -0
- package/src/deploy/adapters/registry.ts +127 -0
- package/src/deploy/adapters/types.ts +92 -0
- package/src/deploy/adapters/vercel.ts +35 -0
- package/src/deploy/artifacts.ts +55 -27
- package/src/deploy/cloudflare-negotiation.ts +179 -100
- package/src/deploy/function-bundle.ts +18 -3
- package/src/deploy/headers.ts +124 -23
- package/src/deploy/node-headers.ts +198 -0
- package/src/deploy/platforms/cloudflare.ts +312 -0
- package/src/deploy/platforms/index.ts +67 -0
- package/src/deploy/platforms/netlify.ts +52 -0
- package/src/deploy/platforms/node.ts +40 -0
- package/src/deploy/platforms/paths.ts +42 -0
- package/src/deploy/platforms/static.ts +29 -0
- package/src/deploy/platforms/types.ts +112 -0
- package/src/deploy/platforms/vercel.ts +193 -0
- package/src/deploy/redirects.ts +30 -18
- package/src/deploy/robots.ts +3 -3
- package/src/deploy/rss.ts +2 -2
- package/src/deploy/sitemap.ts +2 -2
- package/src/deploy/vercel-negotiation.ts +2 -2
- package/src/eval/agents.ts +32 -1
- package/src/eval/findings.ts +19 -11
- package/src/eval/report.ts +10 -2
- package/src/markdown/external-links.ts +65 -0
- package/src/markdown/include.ts +45 -27
- package/src/markdown/index.ts +34 -9
- package/src/markdown/inline-code.ts +12 -6
- package/src/markdown/relative-links.ts +324 -0
- package/src/markdown/themes.ts +3 -3
- package/src/migrate/migrate.ts +149 -0
- package/src/openapi/parse.ts +64 -16
- package/src/openapi/proxy.ts +62 -10
- package/src/openapi/references.ts +147 -147
- package/src/openapi/render-mdx.ts +32 -10
- package/src/openapi/scalar.ts +15 -13
- package/src/openapi/sentence.ts +14 -0
- package/src/openapi/source.ts +37 -21
- package/src/openapi/spec-dependency-error.ts +15 -0
- package/src/reference/asyncapi.ts +83 -0
- package/src/reference/graphql.ts +89 -0
- package/src/reference/index.ts +40 -0
- package/src/reference/openapi.ts +83 -0
- package/src/reference/options.ts +201 -0
- package/src/reference/scalar.ts +136 -0
- package/src/reference/schema.ts +88 -0
- package/src/registry/eject.ts +97 -42
- package/src/search/adapters/algolia.ts +46 -0
- package/src/search/adapters/flexsearch.ts +29 -0
- package/src/search/adapters/index.ts +39 -0
- package/src/search/adapters/mixedbread.ts +39 -0
- package/src/search/adapters/orama-cloud.ts +51 -0
- package/src/search/adapters/orama.ts +24 -0
- package/src/search/adapters/pagefind.ts +27 -0
- package/src/search/adapters/registry.ts +131 -0
- package/src/search/adapters/types.ts +46 -0
- package/src/search/adapters/typesense.ts +57 -0
- package/src/search/build.ts +8 -4
- package/src/search/documents.ts +6 -0
- package/src/search/sync/algolia.ts +12 -11
- package/src/search/sync/index.ts +35 -20
- package/src/search/sync/orama-cloud.ts +12 -9
- package/src/search/sync/typesense.ts +15 -13
- package/src/sources/contentful.ts +63 -0
- package/src/sources/custom.ts +38 -0
- package/src/sources/filesystem.ts +51 -0
- package/src/sources/github-releases.ts +52 -0
- package/src/sources/index.ts +60 -0
- package/src/sources/mdx-remote.ts +76 -0
- package/src/sources/notion.ts +63 -0
- package/src/sources/obsidian.ts +38 -0
- package/src/sources/payload.ts +60 -0
- package/src/sources/registry.ts +182 -0
- package/src/sources/sanity.ts +66 -0
- package/src/sources/shared.ts +52 -0
- package/src/sources/strapi.ts +58 -0
- package/src/theme/entry.ts +24 -2
- package/src/translate/report.ts +40 -7
- package/src/upgrade/upgrade.ts +499 -0
- package/dist/cli/chunk-0qymqwzz.js +0 -164
- package/dist/cli/chunk-0qymqwzz.js.map +0 -15
- package/dist/cli/chunk-1jefwnfs.js.map +0 -48
- package/dist/cli/chunk-2mzebbbz.js +0 -69
- package/dist/cli/chunk-2z47ypj8.js.map +0 -11
- package/dist/cli/chunk-4x36ddpw.js.map +0 -11
- package/dist/cli/chunk-5093q3n7.js +0 -68
- package/dist/cli/chunk-5093q3n7.js.map +0 -10
- package/dist/cli/chunk-5qk08vmp.js.map +0 -11
- package/dist/cli/chunk-7s8hm3b6.js +0 -5347
- package/dist/cli/chunk-7s8hm3b6.js.map +0 -58
- package/dist/cli/chunk-8cjtbafj.js.map +0 -13
- package/dist/cli/chunk-97r59kpr.js +0 -381
- package/dist/cli/chunk-97r59kpr.js.map +0 -12
- package/dist/cli/chunk-ahnw3kxw.js.map +0 -15
- package/dist/cli/chunk-b27xqwn9.js.map +0 -10
- package/dist/cli/chunk-bf6bt1xt.js +0 -185
- package/dist/cli/chunk-bf6bt1xt.js.map +0 -11
- package/dist/cli/chunk-cjtn640a.js.map +0 -10
- package/dist/cli/chunk-ct47dqpx.js.map +0 -11
- package/dist/cli/chunk-esphfr8p.js +0 -107
- package/dist/cli/chunk-esphfr8p.js.map +0 -11
- package/dist/cli/chunk-ex56aa81.js +0 -1016
- package/dist/cli/chunk-ex56aa81.js.map +0 -13
- package/dist/cli/chunk-garjf5z9.js +0 -30
- package/dist/cli/chunk-garjf5z9.js.map +0 -10
- package/dist/cli/chunk-js7saxwm.js +0 -1045
- package/dist/cli/chunk-js7saxwm.js.map +0 -22
- package/dist/cli/chunk-k79xp7av.js.map +0 -39
- package/dist/cli/chunk-ps4m1xh4.js.map +0 -15
- package/dist/cli/chunk-q4rae3bg.js +0 -60
- package/dist/cli/chunk-q4rae3bg.js.map +0 -10
- package/dist/cli/chunk-rz9jmfhz.js +0 -108
- package/dist/cli/chunk-rz9jmfhz.js.map +0 -10
- package/dist/cli/chunk-vh9w1sgp.js +0 -73
- package/dist/cli/chunk-vh9w1sgp.js.map +0 -10
- package/dist/cli/chunk-vrfp10qk.js +0 -81
- package/dist/cli/chunk-vrfp10qk.js.map +0 -10
- package/dist/cli/chunk-yg63d42r.js.map +0 -34
- package/docs/advanced/api-reference.mdx +0 -240
- package/docs/reference/cli.mdx +0 -197
- package/skills/blume-migrate/assets/oxfmt@0.55.0.patch +0 -20
- package/src/components/content/changelog-element.ts +0 -69
- package/src/search/providers.ts +0 -91
- /package/dist/cli/{chunk-e7f42gdj.js.map → chunk-7ez8ny0t.js.map} +0 -0
- /package/dist/cli/{chunk-nn13znc2.js.map → chunk-88cpgt6h.js.map} +0 -0
- /package/dist/cli/{chunk-vacwm2hv.js.map → chunk-f7t03s3g.js.map} +0 -0
- /package/dist/cli/{chunk-dwgcp5sm.js.map → chunk-zxccj738.js.map} +0 -0
package/src/core/links.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
|
|
3
|
-
import { basename, dirname, join, relative, resolve } from "pathe";
|
|
3
|
+
import { basename, dirname, join, normalize, relative, resolve } from "pathe";
|
|
4
4
|
|
|
5
5
|
import { stripBasePath, withBasePath } from "./base-path.ts";
|
|
6
6
|
import {
|
|
@@ -80,6 +80,8 @@ interface LinkContext {
|
|
|
80
80
|
/** Servable routes outside the graph (custom pages, generated routes); their
|
|
81
81
|
* headings are unknown, so anchors there are accepted unchecked. */
|
|
82
82
|
extraRoutes: Set<string>;
|
|
83
|
+
/** Where content files publish, for file links (`./setup.mdx`). */
|
|
84
|
+
fileRoutes: FileRouteIndex;
|
|
83
85
|
/** Locale routing, when the site is multi-locale; drives served-route resolution. */
|
|
84
86
|
i18n: LocaleRouting | null;
|
|
85
87
|
publicDir: string | null;
|
|
@@ -156,6 +158,81 @@ const toRoute = (path: string): string => {
|
|
|
156
158
|
return route === "" ? "/" : route;
|
|
157
159
|
};
|
|
158
160
|
|
|
161
|
+
/** The page a relative link is written on, as the resolver sees it. */
|
|
162
|
+
export interface RelativeLinkBase {
|
|
163
|
+
/** Whether the page is its folder's index (its route is its directory). */
|
|
164
|
+
isIndex: boolean;
|
|
165
|
+
/** The page's own route, base path included. */
|
|
166
|
+
route: string;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/** A root-relative path, a bare `#fragment` or `?query`, or any scheme. */
|
|
170
|
+
const NOT_RELATIVE = /^(?:[#?/]|[a-z][a-z0-9+.-]*:)/iu;
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Where a relative page link written on `from` lands: a root-relative route
|
|
174
|
+
* with the authored `?query#hash` kept — or `undefined` when `href` isn't a
|
|
175
|
+
* relative page link (a root-relative path, a bare `#fragment` or `?query`,
|
|
176
|
+
* an external URL or other scheme, or a relative asset like `./diagram.png`).
|
|
177
|
+
*
|
|
178
|
+
* The one reading `blume validate` checks links against and the Markdown
|
|
179
|
+
* pipeline rewrites them to, so the built `href`, the link check, and the
|
|
180
|
+
* browser agree. Relative paths resolve file-style: a leaf page's links
|
|
181
|
+
* resolve against its parent directory, while an index page's route already is
|
|
182
|
+
* its directory — `./install` on `guides/index.mdx` (`/guides`) lands on
|
|
183
|
+
* `/guides/install`, where a browser reading the slashless URL would go to
|
|
184
|
+
* `/install`. A `.md`/`.mdx` target is a file link: `resolveFile` maps its
|
|
185
|
+
* decoded path, relative to the linking file, to the route that file
|
|
186
|
+
* publishes at, so a target with its own `slug` or an ordering prefix still
|
|
187
|
+
* lands on its page instead of on its raw Markdown source. Without
|
|
188
|
+
* `resolveFile`, or for a file it doesn't know, the target resolves
|
|
189
|
+
* route-relative with the extension dropped.
|
|
190
|
+
*
|
|
191
|
+
* Any other extension (`./diagram.png`) marks an asset, except where a page
|
|
192
|
+
* publishes at the resolved path: `hasRoute` answers that, so a dotted page
|
|
193
|
+
* name (`./node.js` for `node.js.mdx`, `./v1.2`) is still a page link.
|
|
194
|
+
*/
|
|
195
|
+
export const resolveRelativeHref = (
|
|
196
|
+
href: string,
|
|
197
|
+
from: RelativeLinkBase,
|
|
198
|
+
resolveFile?: (path: string) => string | undefined,
|
|
199
|
+
hasRoute?: (route: string) => boolean
|
|
200
|
+
): string | undefined => {
|
|
201
|
+
if (href === "" || NOT_RELATIVE.test(href)) {
|
|
202
|
+
return undefined;
|
|
203
|
+
}
|
|
204
|
+
const suffixAt = href.search(/[?#]/u);
|
|
205
|
+
const path = suffixAt === -1 ? href : href.slice(0, suffixAt);
|
|
206
|
+
const suffix = suffixAt === -1 ? "" : href.slice(suffixAt);
|
|
207
|
+
if (FILE_EXT.test(path) && !DOC_EXT.test(path)) {
|
|
208
|
+
const route = toRoute(resolveRelative(from.route, path, from.isIndex));
|
|
209
|
+
return hasRoute?.(decodePercent(route)) ? `${route}${suffix}` : undefined;
|
|
210
|
+
}
|
|
211
|
+
const fileRoute = DOC_EXT.test(path)
|
|
212
|
+
? resolveFile?.(decodePercent(path))
|
|
213
|
+
: undefined;
|
|
214
|
+
return `${fileRoute ?? toRoute(resolveRelative(from.route, path, from.isIndex))}${suffix}`;
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Whether a content file is its folder's index, from its name as written on
|
|
219
|
+
* disk: `index.md(x)` after an ordering prefix, optionally carrying one of
|
|
220
|
+
* `localeTokens` before the extension (`index.fr.mdx` under the `dot` locale
|
|
221
|
+
* parser, `index.$.mdx` for a file shared by every locale).
|
|
222
|
+
*/
|
|
223
|
+
export const isIndexFileName = (
|
|
224
|
+
name: string,
|
|
225
|
+
localeTokens: readonly string[] = []
|
|
226
|
+
): boolean => {
|
|
227
|
+
const stem = basename(name).replace(NUMERIC_PREFIX, "");
|
|
228
|
+
const match = /^index(?:\.(?<token>[^./]+))?\.(?:md|mdx)$/iu.exec(stem);
|
|
229
|
+
if (!match) {
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
232
|
+
const token = match.groups?.token;
|
|
233
|
+
return token === undefined || localeTokens.includes(token);
|
|
234
|
+
};
|
|
235
|
+
|
|
159
236
|
/** Build a map of route -> set of heading anchor slugs. */
|
|
160
237
|
const buildAnchorIndex = (pages: PageRecord[]): Map<string, Set<string>> => {
|
|
161
238
|
const anchors = new Map<string, Set<string>>();
|
|
@@ -329,6 +406,92 @@ const checkExternalLinks = async (
|
|
|
329
406
|
return diagnostics;
|
|
330
407
|
};
|
|
331
408
|
|
|
409
|
+
/** Where content files publish, for resolving file links (`./setup.mdx`). */
|
|
410
|
+
export interface FileRouteIndex {
|
|
411
|
+
/**
|
|
412
|
+
* Absolute source path → the route that file publishes at. A file shared by
|
|
413
|
+
* every locale publishes once per locale; the default locale's route stands
|
|
414
|
+
* for it (a link from a localized page moves into that locale afterwards,
|
|
415
|
+
* exactly as the rendered link does). Fallback copies render another
|
|
416
|
+
* locale's file, so they never stand for it.
|
|
417
|
+
*/
|
|
418
|
+
bySource: Map<string, string>;
|
|
419
|
+
/**
|
|
420
|
+
* A default-locale page's locale-stripped path (`navPath`) → its route. A
|
|
421
|
+
* page in a locale folder that links a sibling not translated yet
|
|
422
|
+
* (`fr/guides/setup.mdx` missing) means the default tree's file
|
|
423
|
+
* (`guides/setup.mdx`), whose route — its own `slug` included — then moves
|
|
424
|
+
* into the reader's locale onto the fallback copy.
|
|
425
|
+
*/
|
|
426
|
+
byDefaultNavPath: Map<string, string>;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/** The linking side of a file link: where the page's source lives. */
|
|
430
|
+
export interface FileLinkBase {
|
|
431
|
+
navPath: string;
|
|
432
|
+
sourcePath: string;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
export const buildFileRouteIndex = (
|
|
436
|
+
pages: readonly PageRecord[],
|
|
437
|
+
i18n: LocaleRouting | null
|
|
438
|
+
): FileRouteIndex => {
|
|
439
|
+
const bySource = new Map<string, string>();
|
|
440
|
+
const byDefaultNavPath = new Map<string, string>();
|
|
441
|
+
for (const page of pages) {
|
|
442
|
+
const { sourcePath } = page;
|
|
443
|
+
if (!sourcePath || page.fallback) {
|
|
444
|
+
continue;
|
|
445
|
+
}
|
|
446
|
+
const isDefault = page.locale === i18n?.defaultLocale;
|
|
447
|
+
if (!bySource.has(sourcePath) || isDefault) {
|
|
448
|
+
bySource.set(sourcePath, page.route);
|
|
449
|
+
}
|
|
450
|
+
if (isDefault) {
|
|
451
|
+
byDefaultNavPath.set(normalize(page.navPath), page.route);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
return { byDefaultNavPath, bySource };
|
|
455
|
+
};
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* The route a file link written on `from` lands on: the linked file's own
|
|
459
|
+
* route, or — when a locale folder doesn't have that file yet — the default
|
|
460
|
+
* tree's file at the same place.
|
|
461
|
+
*/
|
|
462
|
+
export const routeOfLinkedFile = (
|
|
463
|
+
index: FileRouteIndex,
|
|
464
|
+
from: FileLinkBase,
|
|
465
|
+
path: string
|
|
466
|
+
): string | undefined =>
|
|
467
|
+
index.bySource.get(resolve(dirname(from.sourcePath), path)) ??
|
|
468
|
+
index.byDefaultNavPath.get(normalize(join(dirname(from.navPath), path)));
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* The path a relative link on `page` resolves to — the same reading the
|
|
472
|
+
* Markdown pipeline rewrites the rendered `href` to (see
|
|
473
|
+
* {@link resolveRelativeHref}), so what's checked is what ships. A relative
|
|
474
|
+
* asset (`./diagram.png`) isn't a page link; it resolves against the route's
|
|
475
|
+
* directory for the public-dir probe.
|
|
476
|
+
*/
|
|
477
|
+
const relativeTarget = (
|
|
478
|
+
page: PageRecord,
|
|
479
|
+
rawPath: string,
|
|
480
|
+
ctx: LinkContext
|
|
481
|
+
): string => {
|
|
482
|
+
const base = { isIndex: isIndexPage(page), route: page.route };
|
|
483
|
+
const { navPath, sourcePath } = page;
|
|
484
|
+
const resolveFile = sourcePath
|
|
485
|
+
? (path: string) =>
|
|
486
|
+
routeOfLinkedFile(ctx.fileRoutes, { navPath, sourcePath }, path)
|
|
487
|
+
: undefined;
|
|
488
|
+
return (
|
|
489
|
+
resolveRelativeHref(rawPath, base, resolveFile, (route) =>
|
|
490
|
+
ctx.routes.has(route)
|
|
491
|
+
) ?? resolveRelative(page.route, rawPath, base.isIndex)
|
|
492
|
+
);
|
|
493
|
+
};
|
|
494
|
+
|
|
332
495
|
/** Classify a single link, queueing external refs via `onExternal`. */
|
|
333
496
|
const classifyLink = (
|
|
334
497
|
page: PageRecord,
|
|
@@ -382,7 +545,7 @@ const classifyLink = (
|
|
|
382
545
|
|
|
383
546
|
const resolved = rawPath.startsWith("/")
|
|
384
547
|
? rawPath
|
|
385
|
-
:
|
|
548
|
+
: relativeTarget(page, rawPath, ctx);
|
|
386
549
|
return checkPathLink(resolved, fragment, page, link, site, ctx, via);
|
|
387
550
|
};
|
|
388
551
|
|
|
@@ -416,6 +579,7 @@ export const validateLinks = async (
|
|
|
416
579
|
anchors: buildAnchorIndex(graph.pages),
|
|
417
580
|
basePath,
|
|
418
581
|
extraRoutes: new Set((options.extraRoutes ?? []).map(toRoute)),
|
|
582
|
+
fileRoutes: buildFileRouteIndex(graph.pages, options.i18n ?? null),
|
|
419
583
|
i18n: options.i18n ?? null,
|
|
420
584
|
publicDir: options.publicDir,
|
|
421
585
|
redirects: new Set(
|
package/src/core/manifest.ts
CHANGED
|
@@ -82,9 +82,14 @@ const buildFallbackRoutes = (
|
|
|
82
82
|
if (!fallback) {
|
|
83
83
|
return [];
|
|
84
84
|
}
|
|
85
|
+
// A monolingual page (a GitHub release) publishes in one language only, so it
|
|
86
|
+
// gets no copy at every other locale's URL: those would be duplicates of the
|
|
87
|
+
// same text under a translated chrome.
|
|
85
88
|
const fallbackPages = new Map(
|
|
86
89
|
graph.pages.flatMap((page) =>
|
|
87
|
-
page.locale === fallback
|
|
90
|
+
page.locale === fallback && !page.monolingual
|
|
91
|
+
? [[page.translationKey, page] as const]
|
|
92
|
+
: []
|
|
88
93
|
)
|
|
89
94
|
);
|
|
90
95
|
const routes: RouteManifestEntry[] = [];
|
|
@@ -126,6 +131,7 @@ const buildFallbackRoutes = (
|
|
|
126
131
|
indexable: false,
|
|
127
132
|
lastModified: source.lastModified,
|
|
128
133
|
locale: code,
|
|
134
|
+
monolingual: source.monolingual,
|
|
129
135
|
path,
|
|
130
136
|
source: source.source,
|
|
131
137
|
sourcePath: source.sourcePath,
|
|
@@ -145,7 +151,7 @@ export const buildManifest = (options: {
|
|
|
145
151
|
graph: ContentGraph;
|
|
146
152
|
}): BlumeManifest => {
|
|
147
153
|
const { context, config, graph } = options;
|
|
148
|
-
const searchEnabled = config.search.provider !== "none";
|
|
154
|
+
const searchEnabled = config.search.provider.mode !== "none";
|
|
149
155
|
const { i18n } = config;
|
|
150
156
|
|
|
151
157
|
// Real translations per logical page, for `hreflang` and the switcher. Built
|
|
@@ -189,6 +195,7 @@ export const buildManifest = (options: {
|
|
|
189
195
|
indexable: searchEnabled && contentIndexable(page, config),
|
|
190
196
|
lastModified: page.lastModified,
|
|
191
197
|
locale: page.locale,
|
|
198
|
+
monolingual: page.monolingual,
|
|
192
199
|
path: page.route,
|
|
193
200
|
source: page.source,
|
|
194
201
|
sourcePath: page.sourcePath,
|
|
@@ -234,7 +241,7 @@ export const buildManifest = (options: {
|
|
|
234
241
|
return {
|
|
235
242
|
blumeVersion: getBlumeVersion(),
|
|
236
243
|
contentRoot: context.contentRoot,
|
|
237
|
-
output: config.deployment.output,
|
|
244
|
+
output: config.deployment.options.output,
|
|
238
245
|
projectRoot: context.root,
|
|
239
246
|
routes,
|
|
240
247
|
version: MANIFEST_VERSION,
|
package/src/core/navigation.ts
CHANGED
|
@@ -43,12 +43,66 @@ export const isUnderPath = (route: string, base: string): boolean =>
|
|
|
43
43
|
export const isRootTab = (tab: NavTab, root: string): boolean =>
|
|
44
44
|
isUnderPath(root, tab.path);
|
|
45
45
|
|
|
46
|
+
/**
|
|
47
|
+
* A page's sidebar icon: `sidebar.icon`, or the top-level `icon` shorthand
|
|
48
|
+
* (the Mintlify-style spelling) when the nested key is unset.
|
|
49
|
+
*/
|
|
50
|
+
const sidebarIcon = (page: PageRecord): string | undefined =>
|
|
51
|
+
page.meta.sidebar.icon ?? page.meta.icon;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Words a folder name spells in lowercase that read wrong capitalized: the
|
|
55
|
+
* acronyms and brand casings docs folders are named after (`api-reference`
|
|
56
|
+
* is "API Reference", not "Api Reference").
|
|
57
|
+
*/
|
|
58
|
+
const WORD_FORMS = new Map([
|
|
59
|
+
["ai", "AI"],
|
|
60
|
+
["api", "API"],
|
|
61
|
+
["apis", "APIs"],
|
|
62
|
+
["asyncapi", "AsyncAPI"],
|
|
63
|
+
["cli", "CLI"],
|
|
64
|
+
["css", "CSS"],
|
|
65
|
+
["faq", "FAQ"],
|
|
66
|
+
["faqs", "FAQs"],
|
|
67
|
+
["graphql", "GraphQL"],
|
|
68
|
+
["html", "HTML"],
|
|
69
|
+
["http", "HTTP"],
|
|
70
|
+
["https", "HTTPS"],
|
|
71
|
+
["id", "ID"],
|
|
72
|
+
["ids", "IDs"],
|
|
73
|
+
["ios", "iOS"],
|
|
74
|
+
["js", "JS"],
|
|
75
|
+
["json", "JSON"],
|
|
76
|
+
["jwt", "JWT"],
|
|
77
|
+
["llm", "LLM"],
|
|
78
|
+
["llms", "LLMs"],
|
|
79
|
+
["macos", "macOS"],
|
|
80
|
+
["mcp", "MCP"],
|
|
81
|
+
["oauth", "OAuth"],
|
|
82
|
+
["openapi", "OpenAPI"],
|
|
83
|
+
["rss", "RSS"],
|
|
84
|
+
["sdk", "SDK"],
|
|
85
|
+
["sdks", "SDKs"],
|
|
86
|
+
["seo", "SEO"],
|
|
87
|
+
["sql", "SQL"],
|
|
88
|
+
["sso", "SSO"],
|
|
89
|
+
["ts", "TS"],
|
|
90
|
+
["ui", "UI"],
|
|
91
|
+
["url", "URL"],
|
|
92
|
+
["urls", "URLs"],
|
|
93
|
+
["xml", "XML"],
|
|
94
|
+
["yaml", "YAML"],
|
|
95
|
+
]);
|
|
96
|
+
|
|
46
97
|
const humanize = (segment: string): string =>
|
|
47
98
|
segment
|
|
48
99
|
.replace(NUMERIC_PREFIX, "")
|
|
49
100
|
.split(WORD_SPLIT)
|
|
50
101
|
.filter(Boolean)
|
|
51
|
-
.map(
|
|
102
|
+
.map(
|
|
103
|
+
(word) =>
|
|
104
|
+
WORD_FORMS.get(word) ?? word.charAt(0).toUpperCase() + word.slice(1)
|
|
105
|
+
)
|
|
52
106
|
.join(" ");
|
|
53
107
|
|
|
54
108
|
const numericOrder = (segment: string): number => {
|
|
@@ -276,6 +330,12 @@ const applyFolderMeta = (
|
|
|
276
330
|
* update the folder's `meta.ts` and forget the index page's own frontmatter
|
|
277
331
|
* (or vice versa), and a correct-looking sidebar hides the mismatch.
|
|
278
332
|
*
|
|
333
|
+
* Only fires when the index page's own sidebar row is hidden
|
|
334
|
+
* (`sidebar.hidden`), so the linked group header is the only sidebar label the
|
|
335
|
+
* page has. A visible index row shows the page's own label beneath the header,
|
|
336
|
+
* so the sidebar already carries both titles and a divergence there is a
|
|
337
|
+
* deliberate pairing ("CLI" over "Overview"), not drift.
|
|
338
|
+
*
|
|
279
339
|
* Only fires when the page has an explicit frontmatter `title` of its own:
|
|
280
340
|
* when it's absent, `page.title` is derived from the first heading or the
|
|
281
341
|
* filename, so it almost never coincidentally matches a custom folder title —
|
|
@@ -298,7 +358,11 @@ const indexTitleMismatchDiagnostic = (
|
|
|
298
358
|
metaPrefix: string,
|
|
299
359
|
sharedMetaPrefix: string
|
|
300
360
|
): Diagnostic | undefined => {
|
|
301
|
-
if (
|
|
361
|
+
if (
|
|
362
|
+
!(page.meta.title && page.meta.sidebar.hidden) ||
|
|
363
|
+
page.fallback ||
|
|
364
|
+
folderPath === ""
|
|
365
|
+
) {
|
|
302
366
|
return undefined;
|
|
303
367
|
}
|
|
304
368
|
const meta =
|
|
@@ -552,8 +616,9 @@ const buildFileSystemSidebar = (
|
|
|
552
616
|
const stem = stemOf(filename);
|
|
553
617
|
const dirs = parts.slice(0, -1);
|
|
554
618
|
|
|
555
|
-
// Checked before the hidden filter:
|
|
556
|
-
//
|
|
619
|
+
// Checked before the hidden filter: the title check fires only for a
|
|
620
|
+
// sidebar-hidden index page, whose own <title> the header label stands in
|
|
621
|
+
// for, so it must see the pages the filter drops.
|
|
557
622
|
if (isIndexStem(stem)) {
|
|
558
623
|
const diagnostic = indexTitleMismatchDiagnostic(
|
|
559
624
|
page,
|
|
@@ -612,7 +677,7 @@ const buildFileSystemSidebar = (
|
|
|
612
677
|
deprecated: page.meta.deprecated || undefined,
|
|
613
678
|
description: page.description,
|
|
614
679
|
file: page.sourcePath,
|
|
615
|
-
icon: page
|
|
680
|
+
icon: sidebarIcon(page),
|
|
616
681
|
key: segmentKey(stem),
|
|
617
682
|
kind: "page",
|
|
618
683
|
label: page.meta.sidebar.label ?? page.title,
|
|
@@ -691,7 +756,7 @@ const configItemToNode = (
|
|
|
691
756
|
badge: page.meta.sidebar.badge,
|
|
692
757
|
deprecated: page.meta.deprecated || undefined,
|
|
693
758
|
description: page.description,
|
|
694
|
-
icon: page
|
|
759
|
+
icon: sidebarIcon(page),
|
|
695
760
|
kind: "page",
|
|
696
761
|
label: page.meta.sidebar.label ?? page.title,
|
|
697
762
|
pageId: page.id,
|
|
@@ -760,10 +825,26 @@ const buildConfigSidebar = (
|
|
|
760
825
|
/**
|
|
761
826
|
* Resolve a tab's clickable target. A tab's `path` scopes its sidebar section
|
|
762
827
|
* but need not be a real route — a section with no index page would 404 if the
|
|
763
|
-
* tab linked straight to it. Prefer
|
|
764
|
-
*
|
|
828
|
+
* tab linked straight to it. Prefer the path itself when it's served outside
|
|
829
|
+
* the content tree (the generated changelog index) or is a page/group in the
|
|
830
|
+
* tree; otherwise fall back to the first linkable route in the section
|
|
831
|
+
* (sidebar order).
|
|
832
|
+
*
|
|
833
|
+
* Routes outside the content tree are served at their own path, not under
|
|
834
|
+
* `basePath` (`pages/changelog.astro` answers `/changelog` on a `/docs`-based
|
|
835
|
+
* site), while tab paths arrive based (`/docs/changelog`). So when the based
|
|
836
|
+
* path is neither an outside route nor a tree node, the base-less path is
|
|
837
|
+
* checked against the outside routes before the section's first page wins.
|
|
765
838
|
*/
|
|
766
|
-
const resolveTabHref = (
|
|
839
|
+
const resolveTabHref = (
|
|
840
|
+
sidebar: NavNode[],
|
|
841
|
+
path: string,
|
|
842
|
+
extraRoutes: ReadonlySet<string>,
|
|
843
|
+
basePath: string
|
|
844
|
+
): string => {
|
|
845
|
+
if (extraRoutes.has(path)) {
|
|
846
|
+
return path;
|
|
847
|
+
}
|
|
767
848
|
let first: string | undefined;
|
|
768
849
|
const walk = (nodes: NavNode[]): boolean => {
|
|
769
850
|
for (const node of nodes) {
|
|
@@ -784,19 +865,30 @@ const resolveTabHref = (sidebar: NavNode[], path: string): string => {
|
|
|
784
865
|
}
|
|
785
866
|
return false;
|
|
786
867
|
};
|
|
787
|
-
|
|
868
|
+
if (walk(sidebar)) {
|
|
869
|
+
return path;
|
|
870
|
+
}
|
|
871
|
+
const bare = stripBasePath(basePath, path);
|
|
872
|
+
return extraRoutes.has(bare) ? bare : (first ?? path);
|
|
788
873
|
};
|
|
789
874
|
|
|
790
875
|
/**
|
|
791
876
|
* Attach a resolved `href` to each tab whose section has no index page. An
|
|
792
877
|
* author-declared `href` is the tab's stated target, so it's kept as-is —
|
|
793
878
|
* resolution only fills in the tabs that didn't declare one. That's what lets a
|
|
794
|
-
* tab point at a route outside the content tree (a
|
|
795
|
-
*
|
|
879
|
+
* tab point at a route outside the content tree that resolution can't see (a
|
|
880
|
+
* custom `.astro` page); the generated changelog index arrives in
|
|
881
|
+
* `extraRoutes`, so a `/changelog` tab needs no `href`.
|
|
796
882
|
*/
|
|
797
|
-
const withTabHrefs = (
|
|
883
|
+
const withTabHrefs = (
|
|
884
|
+
tabs: NavTab[],
|
|
885
|
+
sidebar: NavNode[],
|
|
886
|
+
extraRoutes: ReadonlySet<string>,
|
|
887
|
+
basePath: string
|
|
888
|
+
): NavTab[] =>
|
|
798
889
|
tabs.map((tab) => {
|
|
799
|
-
const href =
|
|
890
|
+
const href =
|
|
891
|
+
tab.href ?? resolveTabHref(sidebar, tab.path, extraRoutes, basePath);
|
|
800
892
|
return href === tab.path ? tab : { ...tab, href };
|
|
801
893
|
});
|
|
802
894
|
|
|
@@ -913,6 +1005,12 @@ export const buildNavigation = (
|
|
|
913
1005
|
* into in place; omit to discard.
|
|
914
1006
|
*/
|
|
915
1007
|
diagnostics?: Diagnostic[];
|
|
1008
|
+
/**
|
|
1009
|
+
* Routes served outside the content tree that a tab `path` may name
|
|
1010
|
+
* directly (the generated changelog index), so the tab links there instead
|
|
1011
|
+
* of falling back to its section's first page.
|
|
1012
|
+
*/
|
|
1013
|
+
extraRoutes?: ReadonlySet<string>;
|
|
916
1014
|
}
|
|
917
1015
|
): Navigation => {
|
|
918
1016
|
const basePath = options.basePath ?? "";
|
|
@@ -920,6 +1018,7 @@ export const buildNavigation = (
|
|
|
920
1018
|
const metaPrefix = options.metaPrefix ?? "";
|
|
921
1019
|
const sharedMetaPrefix = options.sharedMetaPrefix ?? "";
|
|
922
1020
|
const sharedFolderMeta = options.sharedFolderMeta ?? new Map();
|
|
1021
|
+
const extraRoutes = options.extraRoutes ?? new Set<string>();
|
|
923
1022
|
|
|
924
1023
|
// Content-derived sidebar routes are already based via `page.route`; the
|
|
925
1024
|
// based tab paths also feed tab-scoping below, so they must agree with the
|
|
@@ -981,7 +1080,7 @@ export const buildNavigation = (
|
|
|
981
1080
|
root: rootTabPath,
|
|
982
1081
|
selectors,
|
|
983
1082
|
sidebar,
|
|
984
|
-
tabs: withTabHrefs(tabs, sidebar),
|
|
1083
|
+
tabs: withTabHrefs(tabs, sidebar, extraRoutes, basePath),
|
|
985
1084
|
};
|
|
986
1085
|
}
|
|
987
1086
|
|
|
@@ -1004,6 +1103,6 @@ export const buildNavigation = (
|
|
|
1004
1103
|
root: rootTabPath,
|
|
1005
1104
|
selectors,
|
|
1006
1105
|
sidebar,
|
|
1007
|
-
tabs: withTabHrefs(tabs, sidebar),
|
|
1106
|
+
tabs: withTabHrefs(tabs, sidebar, extraRoutes, basePath),
|
|
1008
1107
|
};
|
|
1009
1108
|
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Links that open in a new tab. Every such link Blume renders — chrome (header
|
|
3
|
+
* actions, featured sidebar links, page actions), content components (Card,
|
|
4
|
+
* Tile, Tooltip), and Markdown links under `markdown.externalLinks` — points
|
|
5
|
+
* `aria-describedby` at one hidden, localized "Opens in a new tab" element each
|
|
6
|
+
* layout renders once per page, so screen-reader users hear the same warning
|
|
7
|
+
* sighted readers get from the arrow icon or the new tab itself.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { isExternalUrl } from "./base-path.ts";
|
|
11
|
+
|
|
12
|
+
/** The id of the layout's hidden "Opens in a new tab" description. */
|
|
13
|
+
export const NEW_TAB_HINT_ID = "blume-new-tab-hint";
|
|
14
|
+
|
|
15
|
+
/** The attributes a new-tab link carries (spread onto an `<a>`). */
|
|
16
|
+
export interface NewTabAttrs {
|
|
17
|
+
"aria-describedby"?: string;
|
|
18
|
+
rel?: string;
|
|
19
|
+
target?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** A link that always opens in a new tab (a repo link, an edit link). */
|
|
23
|
+
export const NEW_TAB_ATTRS: NewTabAttrs = {
|
|
24
|
+
"aria-describedby": NEW_TAB_HINT_ID,
|
|
25
|
+
rel: "noreferrer",
|
|
26
|
+
target: "_blank",
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* {@link NEW_TAB_ATTRS} for an external href (the shared `isExternalUrl`
|
|
31
|
+
* predicate), and nothing for a site route, fragment, or `mailto:` link, which
|
|
32
|
+
* stay in the current tab.
|
|
33
|
+
*/
|
|
34
|
+
export const newTabAttrs = (href?: string): NewTabAttrs =>
|
|
35
|
+
href !== undefined && isExternalUrl(href) ? NEW_TAB_ATTRS : {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Node's own `require`, for the SDKs and heavy modules Blume loads only when a
|
|
5
|
+
* feature needs them. Resolution starts from this file, inside the installed
|
|
6
|
+
* package, exactly like the `import()` it stands in for, and Node 22.12+ loads
|
|
7
|
+
* ES modules through it too.
|
|
8
|
+
*
|
|
9
|
+
* Never `import()` in their place. When Node can't import the generated Astro
|
|
10
|
+
* config itself — it refuses to strip types from TypeScript under
|
|
11
|
+
* `node_modules`, which is where an installed Blume's runtime source lives —
|
|
12
|
+
* Astro evaluates the config, and every Blume module it reaches, in a Vite
|
|
13
|
+
* module runner that it closes as soon as the config has loaded. A dynamic
|
|
14
|
+
* `import()` in one of those modules resolves through that runner, so a call
|
|
15
|
+
* made any later (an `astro:build:done` hook, a Markdown plugin) throws "Vite
|
|
16
|
+
* module runner has been closed". `require` is Node's, so it works however the
|
|
17
|
+
* calling module was evaluated. The repo itself never sees the failure: its
|
|
18
|
+
* workspace link puts Blume outside `node_modules`, so Node imports the config
|
|
19
|
+
* natively.
|
|
20
|
+
*/
|
|
21
|
+
export const nodeRequire = createRequire(import.meta.url);
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { isAbsolute, relative } from "pathe";
|
|
2
2
|
|
|
3
|
+
import { CHANGELOG_INDEX_ROUTE, hasChangelogIndex } from "./changelog-index.ts";
|
|
3
4
|
import { loadConfig } from "./config.ts";
|
|
4
|
-
import {
|
|
5
|
+
import { customStaticRoutes, discoverPages } from "./custom-pages.ts";
|
|
5
6
|
import { buildContentGraph } from "./graph.ts";
|
|
6
7
|
import { i18nDiagnostics } from "./i18n.ts";
|
|
7
8
|
import { expandIncludes, hasIncludeStatements } from "./includes.ts";
|
|
@@ -36,12 +37,6 @@ export type BuildMode = "dev" | "build";
|
|
|
36
37
|
export interface ConfigOverrides {
|
|
37
38
|
/** Override `content.root` (`blume dev --content-dir`). */
|
|
38
39
|
contentRoot?: string;
|
|
39
|
-
/** Override `deployment.adapter` (`blume build --adapter`). */
|
|
40
|
-
adapter?: ResolvedConfig["deployment"]["adapter"];
|
|
41
|
-
/** Override `deployment.base` (`blume build --base`). */
|
|
42
|
-
base?: string;
|
|
43
|
-
/** Override `deployment.output` (`blume build --output`). */
|
|
44
|
-
output?: ResolvedConfig["deployment"]["output"];
|
|
45
40
|
}
|
|
46
41
|
|
|
47
42
|
/**
|
|
@@ -61,18 +56,20 @@ const applyConfigOverrides = (
|
|
|
61
56
|
if (!overrides) {
|
|
62
57
|
return config;
|
|
63
58
|
}
|
|
59
|
+
// `--content-dir` re-roots every filesystem source: with one (the
|
|
60
|
+
// zero-config case) it is exactly the old `content.root` override, and
|
|
61
|
+
// several must share a root anyway (see `resolveDocsCollection`).
|
|
62
|
+
const { contentRoot } = overrides;
|
|
63
|
+
const sources = contentRoot
|
|
64
|
+
? config.content.sources.map((source) =>
|
|
65
|
+
source.kind === "filesystem"
|
|
66
|
+
? { ...source, options: { ...source.options, root: contentRoot } }
|
|
67
|
+
: source
|
|
68
|
+
)
|
|
69
|
+
: config.content.sources;
|
|
64
70
|
return {
|
|
65
71
|
...config,
|
|
66
|
-
content: {
|
|
67
|
-
...config.content,
|
|
68
|
-
root: overrides.contentRoot ?? config.content.root,
|
|
69
|
-
},
|
|
70
|
-
deployment: {
|
|
71
|
-
...config.deployment,
|
|
72
|
-
adapter: overrides.adapter ?? config.deployment.adapter,
|
|
73
|
-
base: overrides.base ?? config.deployment.base,
|
|
74
|
-
output: overrides.output ?? config.deployment.output,
|
|
75
|
-
},
|
|
72
|
+
content: { ...config.content, sources },
|
|
76
73
|
};
|
|
77
74
|
};
|
|
78
75
|
|
|
@@ -138,7 +135,7 @@ const entryIdDiagnostics = (
|
|
|
138
135
|
message: `Content source "${page.source.name}" is rooted outside the docs collection base, so ${page.route} resolves entry id "${entryId}" but the collection would generate "${expected}" — the page would 404 at runtime.`,
|
|
139
136
|
severity: "error",
|
|
140
137
|
suggestion:
|
|
141
|
-
"Use a single filesystem source (the docs collection roots at it), or
|
|
138
|
+
"Use a single filesystem() source (the docs collection roots at it), or give every filesystem() source the same root and partition them with include globs — a root at a subdirectory of the first source's root still mismatches.",
|
|
142
139
|
});
|
|
143
140
|
}
|
|
144
141
|
}
|
|
@@ -185,6 +182,7 @@ const normalizeLoadedEntries = (
|
|
|
185
182
|
frontmatterExtend,
|
|
186
183
|
i18n: config.i18n,
|
|
187
184
|
source: {
|
|
185
|
+
monolingual: source.monolingual,
|
|
188
186
|
name: source.name,
|
|
189
187
|
prefix: source.prefix,
|
|
190
188
|
staged: source.staged,
|
|
@@ -208,6 +206,15 @@ const normalizeLoadedEntries = (
|
|
|
208
206
|
* Collects all diagnostics without throwing on content-level problems so
|
|
209
207
|
* callers can decide how strict to be.
|
|
210
208
|
*/
|
|
209
|
+
/** Narrows the logo config's image shorthand from its object form. */
|
|
210
|
+
const isLogoShorthand = (
|
|
211
|
+
logo: NonNullable<ResolvedConfig["logo"]>
|
|
212
|
+
): logo is string => typeof logo === "string";
|
|
213
|
+
|
|
214
|
+
/** The configured brand link: `logo.href`, else the site root. */
|
|
215
|
+
const logoHref = (logo: ResolvedConfig["logo"]): string =>
|
|
216
|
+
logo === undefined || isLogoShorthand(logo) ? "/" : (logo.href ?? "/");
|
|
217
|
+
|
|
211
218
|
export const scanProject = async (
|
|
212
219
|
root: string,
|
|
213
220
|
options: {
|
|
@@ -226,13 +233,7 @@ export const scanProject = async (
|
|
|
226
233
|
const configResult = await loadConfig(root, {
|
|
227
234
|
devServerUrl: options.devServerUrl,
|
|
228
235
|
});
|
|
229
|
-
|
|
230
|
-
// but adapter inference keys off `deployment.output`, which `--output server`
|
|
231
|
-
// only sets here. Idempotent for already-resolved fields — `deployment.site`
|
|
232
|
-
// keeps loadConfig's explicit > platform env > devServerUrl precedence.
|
|
233
|
-
const config = applyDeploymentEnv(
|
|
234
|
-
applyConfigOverrides(configResult.config, options.overrides)
|
|
235
|
-
);
|
|
236
|
+
const config = applyConfigOverrides(configResult.config, options.overrides);
|
|
236
237
|
const context = resolveProjectContext(root, config, {
|
|
237
238
|
runtimeDir: options.runtimeDir,
|
|
238
239
|
});
|
|
@@ -373,8 +374,20 @@ export const scanProject = async (
|
|
|
373
374
|
);
|
|
374
375
|
}
|
|
375
376
|
|
|
377
|
+
// Custom `.astro` pages and the generated changelog index aren't content
|
|
378
|
+
// pages, so name them for navigation: a `/changelog` tab should open the
|
|
379
|
+
// timeline, not the newest entry, and a tab or brand link to a custom page
|
|
380
|
+
// must stay on its route in every locale.
|
|
381
|
+
const customPages = context.pagesRoot
|
|
382
|
+
? await discoverPages(context.pagesRoot)
|
|
383
|
+
: [];
|
|
376
384
|
const graph = buildContentGraph(pages, {
|
|
377
385
|
basePath: config.basePath,
|
|
386
|
+
brandHref: logoHref(config.logo),
|
|
387
|
+
extraRoutes: new Set([
|
|
388
|
+
...customStaticRoutes(customPages),
|
|
389
|
+
...(hasChangelogIndex(pages, config) ? [CHANGELOG_INDEX_ROUTE] : []),
|
|
390
|
+
]),
|
|
378
391
|
folderMeta: folderMeta.meta,
|
|
379
392
|
i18n: config.i18n,
|
|
380
393
|
navigation: config.navigation,
|
|
@@ -397,7 +410,10 @@ export const scanProject = async (
|
|
|
397
410
|
...contentDiagnostics,
|
|
398
411
|
...includeDiagnostics,
|
|
399
412
|
...folderMeta.diagnostics,
|
|
400
|
-
...entryIdDiagnostics(
|
|
413
|
+
...entryIdDiagnostics(
|
|
414
|
+
pages,
|
|
415
|
+
resolveDocsCollection(config, context.root).base
|
|
416
|
+
),
|
|
401
417
|
...graph.diagnostics,
|
|
402
418
|
...i18nWarnings,
|
|
403
419
|
...versionWarnings,
|