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
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
3
|
+
|
|
4
|
+
import { join } from "pathe";
|
|
5
|
+
|
|
6
|
+
import { crossOriginDiscoveryPaths } from "../../ai/ai-catalog.ts";
|
|
7
|
+
import {
|
|
8
|
+
API_CATALOG_PATH,
|
|
9
|
+
API_CATALOG_TYPE,
|
|
10
|
+
hasApiCatalog,
|
|
11
|
+
} from "../../ai/api-catalog.ts";
|
|
12
|
+
import { buildHomeLinkHeader } from "../../ai/link-headers.ts";
|
|
13
|
+
import {
|
|
14
|
+
agentMarkdown,
|
|
15
|
+
buildRawMarkdown,
|
|
16
|
+
markdownRoutePaths,
|
|
17
|
+
markdownTokenCount,
|
|
18
|
+
} from "../../ai/markdown.ts";
|
|
19
|
+
import {
|
|
20
|
+
SIGNATURES_DIRECTORY_PATH,
|
|
21
|
+
SIGNATURES_DIRECTORY_TYPE,
|
|
22
|
+
} from "../../ai/web-bot-auth.ts";
|
|
23
|
+
import type { BlumeProject } from "../../core/project-graph.ts";
|
|
24
|
+
import type { ProjectContext } from "../../core/types.ts";
|
|
25
|
+
import { VERCEL_ADAPTER_PACKAGE } from "../adapters/vercel.ts";
|
|
26
|
+
import {
|
|
27
|
+
addDevDependencyCommand,
|
|
28
|
+
auditVercelFunctions,
|
|
29
|
+
blumeDependencyNames,
|
|
30
|
+
functionBundleVerdict,
|
|
31
|
+
} from "../function-bundle.ts";
|
|
32
|
+
import { buildVercelConfig } from "../redirects.ts";
|
|
33
|
+
import { injectNegotiationRoutes } from "../vercel-negotiation.ts";
|
|
34
|
+
import { adapterRoot, toSiteUrl } from "./paths.ts";
|
|
35
|
+
import type { BuildLog, DeployPlatform, RedirectFile } from "./types.ts";
|
|
36
|
+
|
|
37
|
+
/** `vercel.json` with a `redirects` array, for a static deploy of `dist/`. */
|
|
38
|
+
export const VERCEL_JSON_FILE: RedirectFile = {
|
|
39
|
+
build: buildVercelConfig,
|
|
40
|
+
name: "vercel.json",
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The Build Output tree. The adapter is shown the project root (see
|
|
45
|
+
* `hiddenRuntime.showProjectRoot`), so for a real build this is
|
|
46
|
+
* `<project>/.vercel/output`; an isolated build keeps it under the relocated
|
|
47
|
+
* runtime.
|
|
48
|
+
*/
|
|
49
|
+
const buildOutputDir = (context: ProjectContext): string =>
|
|
50
|
+
join(adapterRoot(context), ".vercel", "output");
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Refuse to ship a function bundle that would crash at runtime: a bare import
|
|
54
|
+
* the adapter's dependency trace silently dropped (see
|
|
55
|
+
* `deploy/function-bundle.ts`). A missing package that is one of Blume's own
|
|
56
|
+
* dependencies is fatal — the generated runtime imports it, so every request
|
|
57
|
+
* would die; a project's own external import is reported as a warning and
|
|
58
|
+
* left to the author. Resolves to whether the bundle may ship.
|
|
59
|
+
*/
|
|
60
|
+
export const checkVercelFunctionBundles = async (
|
|
61
|
+
outputDir: string,
|
|
62
|
+
root: string,
|
|
63
|
+
log: BuildLog
|
|
64
|
+
): Promise<boolean> => {
|
|
65
|
+
const audits = await auditVercelFunctions(outputDir);
|
|
66
|
+
const own = blumeDependencyNames();
|
|
67
|
+
// The remedy names the project's own package manager (`pnpm add -D`, …).
|
|
68
|
+
const addDevCommand = await addDevDependencyCommand(root);
|
|
69
|
+
let fatal = false;
|
|
70
|
+
for (const audit of audits) {
|
|
71
|
+
const verdict = functionBundleVerdict(audit, root, own, addDevCommand);
|
|
72
|
+
if (verdict.fatal) {
|
|
73
|
+
fatal = true;
|
|
74
|
+
log.error(verdict.message);
|
|
75
|
+
} else {
|
|
76
|
+
log.warn(verdict.message);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return !fatal;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Splice `Accept: text/markdown` negotiation routes into the adapter's Build
|
|
84
|
+
* Output config, so a content-page request that prefers Markdown gets the
|
|
85
|
+
* page's prerendered `.md` mirror (content pages are prerendered even in
|
|
86
|
+
* server output, so Astro middleware never sees them — the routing layer is
|
|
87
|
+
* the only request-time hook). The adapter writes the config straight to the
|
|
88
|
+
* root it was shown.
|
|
89
|
+
*/
|
|
90
|
+
export const emitVercelNegotiation = async (
|
|
91
|
+
project: BlumeProject,
|
|
92
|
+
log: BuildLog
|
|
93
|
+
): Promise<void> => {
|
|
94
|
+
const { config, context } = project;
|
|
95
|
+
const outputDir = buildOutputDir(context);
|
|
96
|
+
const configPath = join(outputDir, "config.json");
|
|
97
|
+
if (!existsSync(configPath)) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const routePaths = markdownRoutePaths(project);
|
|
101
|
+
const overrides: Record<string, string> = {};
|
|
102
|
+
if (hasApiCatalog(config)) {
|
|
103
|
+
overrides[API_CATALOG_PATH.slice(1)] = API_CATALOG_TYPE;
|
|
104
|
+
}
|
|
105
|
+
if (config.agents.webBotAuth.keys.length > 0) {
|
|
106
|
+
overrides[SIGNATURES_DIRECTORY_PATH.slice(1)] = SIGNATURES_DIRECTORY_TYPE;
|
|
107
|
+
}
|
|
108
|
+
// The homepage rewrite serves `/index.md` from the static layer, so its
|
|
109
|
+
// `x-markdown-tokens` estimate has to ride the routing config; the runtime
|
|
110
|
+
// endpoint stamps it on dev/server-rendered responses itself.
|
|
111
|
+
const rawMarkdown = await buildRawMarkdown(project);
|
|
112
|
+
const home = rawMarkdown["/"];
|
|
113
|
+
// The Markdown and JSON 404 routes point at the prerendered twins; only
|
|
114
|
+
// wire each when the build actually emitted it (a project that owns `/404`
|
|
115
|
+
// gets none).
|
|
116
|
+
const staticDir = join(outputDir, "static");
|
|
117
|
+
const injected = injectNegotiationRoutes(
|
|
118
|
+
await readFile(configPath, "utf-8"),
|
|
119
|
+
routePaths,
|
|
120
|
+
buildHomeLinkHeader(config, routePaths),
|
|
121
|
+
overrides,
|
|
122
|
+
home ? markdownTokenCount(agentMarkdown(home)) : undefined,
|
|
123
|
+
{
|
|
124
|
+
json: existsSync(join(staticDir, "404.json")),
|
|
125
|
+
markdown: existsSync(join(staticDir, "404.md")),
|
|
126
|
+
},
|
|
127
|
+
crossOriginDiscoveryPaths(config)
|
|
128
|
+
);
|
|
129
|
+
if (injected === null) {
|
|
130
|
+
log.warn(
|
|
131
|
+
"Could not wire Accept: text/markdown negotiation into .vercel/output/config.json — raw Markdown stays available at the .md URLs."
|
|
132
|
+
);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
await writeFile(configPath, injected, "utf-8");
|
|
136
|
+
log.success(
|
|
137
|
+
"Wired Accept: text/markdown negotiation into the Vercel routing config"
|
|
138
|
+
);
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Vercel. A server build's Build Output tree lands at `.vercel/output` — at
|
|
143
|
+
* the project root, because the adapter is handed that root up front: its
|
|
144
|
+
* `@vercel/nft` dependency trace is rooted there too, and tracing from the
|
|
145
|
+
* hidden runtime silently drops the function's chunks and `node_modules`.
|
|
146
|
+
* Static assets are served from the tree's `static/` half, so the deploy
|
|
147
|
+
* artifacts are written there; headers arrive through the routing config
|
|
148
|
+
* rather than a `_headers` file, which Vercel never reads.
|
|
149
|
+
*/
|
|
150
|
+
export const vercelPlatform: DeployPlatform = {
|
|
151
|
+
astro: {
|
|
152
|
+
config: {},
|
|
153
|
+
options: () => ({}),
|
|
154
|
+
package: VERCEL_ADAPTER_PACKAGE,
|
|
155
|
+
},
|
|
156
|
+
env: {
|
|
157
|
+
detect: (env) => Boolean(env.VERCEL),
|
|
158
|
+
// The stable production domain wins over the per-deployment preview URL
|
|
159
|
+
// so the inferred origin (sitemap, OG, RSS) stays put across deploys;
|
|
160
|
+
// the chain falls through per resolved value, so an empty
|
|
161
|
+
// VERCEL_PROJECT_PRODUCTION_URL doesn't dead-end it.
|
|
162
|
+
site: (env) =>
|
|
163
|
+
toSiteUrl(env.VERCEL_PROJECT_PRODUCTION_URL) ?? toSiteUrl(env.VERCEL_URL),
|
|
164
|
+
},
|
|
165
|
+
finalizeBuild: async ({ isolated, log, project }) => {
|
|
166
|
+
const { context } = project;
|
|
167
|
+
const ok = await checkVercelFunctionBundles(
|
|
168
|
+
buildOutputDir(context),
|
|
169
|
+
context.root,
|
|
170
|
+
log
|
|
171
|
+
);
|
|
172
|
+
if (!ok) {
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
// An isolated verify only proves the bundle would ship; the routing
|
|
176
|
+
// config is a deploy artifact and stays untouched.
|
|
177
|
+
if (!isolated) {
|
|
178
|
+
await emitVercelNegotiation(project, log);
|
|
179
|
+
}
|
|
180
|
+
return true;
|
|
181
|
+
},
|
|
182
|
+
hiddenRuntime: {
|
|
183
|
+
ignoreDir: ".vercel/",
|
|
184
|
+
showProjectRoot: true,
|
|
185
|
+
surfacePath: null,
|
|
186
|
+
},
|
|
187
|
+
kind: "vercel",
|
|
188
|
+
negotiatesMarkdown: true,
|
|
189
|
+
readsHeaderFiles: { server: false, static: false },
|
|
190
|
+
redirectFiles: [VERCEL_JSON_FILE],
|
|
191
|
+
serverOutputDir: buildOutputDir,
|
|
192
|
+
serverStaticDir: (context) => join(buildOutputDir(context), "static"),
|
|
193
|
+
};
|
package/src/deploy/redirects.ts
CHANGED
|
@@ -4,13 +4,14 @@ import {
|
|
|
4
4
|
withComposedBasePath,
|
|
5
5
|
} from "../core/base-path.ts";
|
|
6
6
|
import type { ResolvedConfig } from "../core/schema.ts";
|
|
7
|
+
import type { VercelHeader } from "./headers.ts";
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Platform redirect files for a static build. Astro already emits redirect HTML
|
|
10
|
-
* (meta-refresh) pages for
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* (meta-refresh) pages for static output, but that's a soft client redirect.
|
|
12
|
+
* These give the host a real HTTP 3xx: Netlify/Cloudflare read `_redirects`,
|
|
13
|
+
* Vercel reads `vercel.json`, and `blume-redirects.json` is a structured
|
|
14
|
+
* manifest for anything else (Apache/nginx rules, an edge worker).
|
|
14
15
|
*/
|
|
15
16
|
|
|
16
17
|
type Redirect = ResolvedConfig["redirects"][number];
|
|
@@ -78,7 +79,7 @@ export const platformRedirects = (config: ResolvedConfig): Redirect[] =>
|
|
|
78
79
|
applyBaseToPlatformRedirects(
|
|
79
80
|
config.redirects,
|
|
80
81
|
config.basePath,
|
|
81
|
-
config.deployment.base ?? ""
|
|
82
|
+
config.deployment.options.base ?? ""
|
|
82
83
|
);
|
|
83
84
|
|
|
84
85
|
/** `_redirects` text (Netlify + Cloudflare Pages): `from to status` per line. */
|
|
@@ -87,24 +88,35 @@ export const buildNetlifyRedirects = (redirects: Redirect[]): string =>
|
|
|
87
88
|
.map((redirect) => `${redirect.from} ${redirect.to} ${redirect.status}`)
|
|
88
89
|
.join("\n")}\n`;
|
|
89
90
|
|
|
91
|
+
/** The `vercel.json` Blume writes for a static deploy of `dist/`. */
|
|
92
|
+
interface VercelConfig {
|
|
93
|
+
headers?: readonly VercelHeader[];
|
|
94
|
+
redirects: { destination: string; source: string; statusCode: number }[];
|
|
95
|
+
}
|
|
96
|
+
|
|
90
97
|
/**
|
|
91
|
-
* `vercel.json` contents with a `redirects` array
|
|
98
|
+
* `vercel.json` contents with a `redirects` array, and a `headers` array when
|
|
99
|
+
* header rules are given (see `buildVercelHeaders`). Uses `statusCode` (Vercel's
|
|
92
100
|
* alternative to the boolean `permanent`) so the configured code ships exactly:
|
|
93
101
|
* `permanent` would silently coerce a 301 to 308 and a 302 to 307, diverging
|
|
94
102
|
* from the `_redirects` file, which preserves exact codes.
|
|
95
103
|
*/
|
|
96
|
-
export const buildVercelConfig = (
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
)
|
|
104
|
+
export const buildVercelConfig = (
|
|
105
|
+
redirects: Redirect[],
|
|
106
|
+
headers: readonly VercelHeader[] = []
|
|
107
|
+
): string => {
|
|
108
|
+
const config: VercelConfig = {
|
|
109
|
+
redirects: redirects.map((redirect) => ({
|
|
110
|
+
destination: redirect.to,
|
|
111
|
+
source: redirect.from,
|
|
112
|
+
statusCode: redirect.status,
|
|
113
|
+
})),
|
|
114
|
+
};
|
|
115
|
+
if (headers.length > 0) {
|
|
116
|
+
config.headers = headers;
|
|
117
|
+
}
|
|
118
|
+
return `${JSON.stringify(config, null, 2)}\n`;
|
|
119
|
+
};
|
|
108
120
|
|
|
109
121
|
/** Structured manifest for hosts that need manual wiring. */
|
|
110
122
|
export const buildRedirectManifest = (redirects: Redirect[]): string =>
|
package/src/deploy/robots.ts
CHANGED
|
@@ -41,16 +41,16 @@ export const buildRobots = (project: BlumeProject): string | null => {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
const lines = ["User-agent: *"];
|
|
44
|
-
const signal = contentSignalLine(config.
|
|
44
|
+
const signal = contentSignalLine(config.agents.contentSignals);
|
|
45
45
|
if (signal) {
|
|
46
46
|
lines.push(signal);
|
|
47
47
|
}
|
|
48
48
|
lines.push("Allow: /");
|
|
49
49
|
|
|
50
|
-
const { site } = config.deployment;
|
|
50
|
+
const { site } = config.deployment.options;
|
|
51
51
|
if (site && config.seo.sitemap) {
|
|
52
52
|
const sitemapPath = withBasePath(
|
|
53
|
-
normalizeBasePath(config.deployment.base),
|
|
53
|
+
normalizeBasePath(config.deployment.options.base),
|
|
54
54
|
"/sitemap.xml"
|
|
55
55
|
);
|
|
56
56
|
lines.push("", `Sitemap: ${absoluteUrl(site, sitemapPath)}`);
|
package/src/deploy/rss.ts
CHANGED
|
@@ -52,7 +52,7 @@ const pageDate = (page: PageRecord): Date | undefined => {
|
|
|
52
52
|
export const buildRssFeeds = (project: BlumeProject): RssFeed[] => {
|
|
53
53
|
const { config } = project;
|
|
54
54
|
const { rss } = config.seo;
|
|
55
|
-
const { site } = config.deployment;
|
|
55
|
+
const { site } = config.deployment.options;
|
|
56
56
|
if (!(rss.enabled && site)) {
|
|
57
57
|
return [];
|
|
58
58
|
}
|
|
@@ -60,7 +60,7 @@ export const buildRssFeeds = (project: BlumeProject): RssFeed[] => {
|
|
|
60
60
|
// Routes carry `basePath`; a `deployment.base` subdirectory is layered on top.
|
|
61
61
|
// The feed's own `link`/self URL points at the docs root under that base, while
|
|
62
62
|
// `path` stays base-less (it's also the on-disk output location).
|
|
63
|
-
const deployBase = normalizeBasePath(config.deployment.base);
|
|
63
|
+
const deployBase = normalizeBasePath(config.deployment.options.base);
|
|
64
64
|
const rootLink = `${base}${deployBase}`;
|
|
65
65
|
|
|
66
66
|
const feeds: RssFeed[] = [];
|
package/src/deploy/sitemap.ts
CHANGED
|
@@ -72,14 +72,14 @@ ${urls.join("\n")}
|
|
|
72
72
|
export const buildSitemapFiles = (
|
|
73
73
|
project: BlumeProject
|
|
74
74
|
): SitemapFile[] | null => {
|
|
75
|
-
const { site } = project.config.deployment;
|
|
75
|
+
const { site } = project.config.deployment.options;
|
|
76
76
|
if (!(site && project.config.seo.sitemap)) {
|
|
77
77
|
return null;
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
const base = siteRoot(site);
|
|
81
81
|
// Routes carry `basePath`; a `deployment.base` subdirectory is layered on top.
|
|
82
|
-
const deployBase = normalizeBasePath(project.config.deployment.base);
|
|
82
|
+
const deployBase = normalizeBasePath(project.config.deployment.options.base);
|
|
83
83
|
|
|
84
84
|
// Archived-version pages leave the sitemap when the version is noindexed,
|
|
85
85
|
// or when their canonical points at a still-existing latest equivalent —
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `Accept: text/markdown` content negotiation for Vercel server builds.
|
|
3
3
|
*
|
|
4
|
-
* Blume prerenders every content page — even
|
|
5
|
-
*
|
|
4
|
+
* Blume prerenders every content page — even in a server build (`deployment:
|
|
5
|
+
* vercel()`) — so a page request never reaches Astro middleware: Vercel serves
|
|
6
6
|
* the prerendered HTML straight from its static layer. Request-time negotiation
|
|
7
7
|
* therefore has to live in the platform's routing config. The Vercel adapter
|
|
8
8
|
* emits a Build Output API `config.json`; these helpers splice extra routes
|
package/src/eval/agents.ts
CHANGED
|
@@ -48,6 +48,8 @@ export interface HeadlessResult {
|
|
|
48
48
|
|
|
49
49
|
export interface HeadlessOptions {
|
|
50
50
|
cwd: string;
|
|
51
|
+
/** How long the SIGTERM gets before SIGKILL follows (default 5s). */
|
|
52
|
+
killGraceMs?: number;
|
|
51
53
|
prompt: string;
|
|
52
54
|
timeoutMs: number;
|
|
53
55
|
}
|
|
@@ -89,10 +91,14 @@ export const runAgentHeadless = (
|
|
|
89
91
|
stderr += chunk.toString("utf-8");
|
|
90
92
|
});
|
|
91
93
|
|
|
94
|
+
let hardKill: ReturnType<typeof setTimeout> | undefined;
|
|
92
95
|
const deadline = setTimeout(() => {
|
|
93
96
|
timedOut = true;
|
|
94
97
|
child.kill("SIGTERM");
|
|
95
|
-
|
|
98
|
+
hardKill = setTimeout(
|
|
99
|
+
() => child.kill("SIGKILL"),
|
|
100
|
+
options.killGraceMs ?? KILL_GRACE_MS
|
|
101
|
+
);
|
|
96
102
|
hardKill.unref();
|
|
97
103
|
}, options.timeoutMs);
|
|
98
104
|
deadline.unref();
|
|
@@ -109,6 +115,9 @@ export const runAgentHeadless = (
|
|
|
109
115
|
// (an MCP server, a shell) can hold open past the SIGTERM. A timed-out
|
|
110
116
|
// run's output is discarded anyway, so the process dying is enough.
|
|
111
117
|
child.once("exit", (code) => {
|
|
118
|
+
// Once the process is gone the SIGKILL follow-up has nothing to do, and
|
|
119
|
+
// firing it later could signal an unrelated process that reused the pid.
|
|
120
|
+
clearTimeout(hardKill);
|
|
112
121
|
if (timedOut) {
|
|
113
122
|
clearTimeout(deadline);
|
|
114
123
|
resolve({ code: code ?? 1, stderr, stdout, timedOut });
|
|
@@ -197,6 +206,27 @@ const claudeArgs = (context: InvocationContext): string[] => {
|
|
|
197
206
|
];
|
|
198
207
|
};
|
|
199
208
|
|
|
209
|
+
/**
|
|
210
|
+
* Codex config overrides that leave an eval run nothing but its prompt and the
|
|
211
|
+
* docs MCP tools. `--sandbox read-only` blocks writes and the network but still
|
|
212
|
+
* lets the shell tool read any file the user can, and the docs a reader
|
|
213
|
+
* searches — or the answer a judge grades — can come from a remote source, so
|
|
214
|
+
* an instruction planted there could otherwise pull a local secret into the
|
|
215
|
+
* transcript sent to the model provider. With both command tools and the
|
|
216
|
+
* local-image tool off, and any subprocess started with no inherited
|
|
217
|
+
* environment, there is nothing on the machine for a run to read.
|
|
218
|
+
*/
|
|
219
|
+
const CODEX_LOCKDOWN = [
|
|
220
|
+
"-c",
|
|
221
|
+
"features.shell_tool=false",
|
|
222
|
+
"-c",
|
|
223
|
+
"features.unified_exec=false",
|
|
224
|
+
"-c",
|
|
225
|
+
"tools.view_image=false",
|
|
226
|
+
"-c",
|
|
227
|
+
'shell_environment_policy.inherit="none"',
|
|
228
|
+
];
|
|
229
|
+
|
|
200
230
|
const codexArgs = (context: InvocationContext): string[] => {
|
|
201
231
|
const base = [
|
|
202
232
|
"exec",
|
|
@@ -205,6 +235,7 @@ const codexArgs = (context: InvocationContext): string[] => {
|
|
|
205
235
|
"--ephemeral",
|
|
206
236
|
"--sandbox",
|
|
207
237
|
"read-only",
|
|
238
|
+
...CODEX_LOCKDOWN,
|
|
208
239
|
"--output-last-message",
|
|
209
240
|
context.lastMessagePath,
|
|
210
241
|
];
|
package/src/eval/findings.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { Diagnostic } from "../core/types.ts";
|
|
|
3
3
|
import { locateQuestion } from "./schema.ts";
|
|
4
4
|
import type { EvalQuestion } from "./schema.ts";
|
|
5
5
|
|
|
6
|
-
const DOCS_URL = "https://useblume.dev/docs/
|
|
6
|
+
const DOCS_URL = "https://useblume.dev/docs/cli/evals";
|
|
7
7
|
|
|
8
8
|
/** Where a finding should anchor when no route hint matches a page. */
|
|
9
9
|
export interface EvalsAnchor {
|
|
@@ -58,9 +58,12 @@ export interface QuestionOutcome {
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
/**
|
|
61
|
-
* The diagnostic for a failed or errored question
|
|
62
|
-
* should have answered it (via the first matching route hint)
|
|
63
|
-
* that, to the question's line in the evals file.
|
|
61
|
+
* The diagnostic for a failed or errored question. A failure is anchored to
|
|
62
|
+
* the page that should have answered it (via the first matching route hint)
|
|
63
|
+
* or, failing that, to the question's line in the evals file. An errored run —
|
|
64
|
+
* the agent crashed, timed out, or answered in a shape Blume couldn't read —
|
|
65
|
+
* says nothing about the docs, so it always points at the question instead of
|
|
66
|
+
* a page there's nothing to fix in.
|
|
64
67
|
*/
|
|
65
68
|
export const questionFinding = (
|
|
66
69
|
question: EvalQuestion,
|
|
@@ -68,25 +71,30 @@ export const questionFinding = (
|
|
|
68
71
|
project: BlumeProject,
|
|
69
72
|
anchor: EvalsAnchor
|
|
70
73
|
): Diagnostic => {
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
74
|
+
const questionSite = {
|
|
75
|
+
file: anchor.path,
|
|
76
|
+
line: locateQuestion(anchor.raw, question.id),
|
|
77
|
+
};
|
|
75
78
|
|
|
76
79
|
if (outcome.status === "error") {
|
|
77
80
|
return {
|
|
78
81
|
code: "BLUME_EVAL_QUESTION_ERROR",
|
|
79
82
|
docsUrl: DOCS_URL,
|
|
80
|
-
message: `
|
|
83
|
+
message: `The agent run failed for "${question.question}"${
|
|
81
84
|
outcome.detail ? ` — ${outcome.detail}` : ""
|
|
82
|
-
}.`,
|
|
85
|
+
}, so the docs weren't graded.`,
|
|
83
86
|
severity: question.severity,
|
|
84
87
|
suggestion:
|
|
85
88
|
"Rerun `blume eval`; if it persists, check the agent CLI installation and the failure detail.",
|
|
86
|
-
...
|
|
89
|
+
...questionSite,
|
|
87
90
|
};
|
|
88
91
|
}
|
|
89
92
|
|
|
93
|
+
const route = hintedRoute(question, project);
|
|
94
|
+
const site = route
|
|
95
|
+
? { file: route.sourcePath, url: route.path }
|
|
96
|
+
: questionSite;
|
|
97
|
+
|
|
90
98
|
const missing =
|
|
91
99
|
outcome.missing.length > 0
|
|
92
100
|
? ` — missing: ${outcome.missing.join("; ")}`
|
package/src/eval/report.ts
CHANGED
|
@@ -94,7 +94,11 @@ export const headerLine = (total: number, agent: EvalResult["agent"]): string =>
|
|
|
94
94
|
export const startLine = (id: string, index: number, total: number): string =>
|
|
95
95
|
` ${colors.dim(`▸ ${id} (${index + 1}/${total})`)}`;
|
|
96
96
|
|
|
97
|
-
/**
|
|
97
|
+
/**
|
|
98
|
+
* `fix:` pointers for failed questions, naming the file that resolves each. A
|
|
99
|
+
* question whose agent run errored gets a `run failed:` line pointing at the
|
|
100
|
+
* question instead: the run never graded the docs, so there's no page to fix.
|
|
101
|
+
*/
|
|
98
102
|
export const fixLines = (result: EvalResult, root: string): string[] =>
|
|
99
103
|
result.diagnostics
|
|
100
104
|
.filter((diagnostic) => diagnostic.code !== "BLUME_EVAL_ROUTE_UNKNOWN")
|
|
@@ -102,7 +106,11 @@ export const fixLines = (result: EvalResult, root: string): string[] =>
|
|
|
102
106
|
const site = finding.file
|
|
103
107
|
? `${relative(root, finding.file)}${finding.line ? `:${finding.line}` : ""}`
|
|
104
108
|
: "";
|
|
105
|
-
|
|
109
|
+
const label =
|
|
110
|
+
finding.code === "BLUME_EVAL_QUESTION_ERROR"
|
|
111
|
+
? colors.red("run failed:")
|
|
112
|
+
: colors.cyan("fix:");
|
|
113
|
+
return ` ${label} ${site} ${colors.dim(finding.message)}`;
|
|
106
114
|
});
|
|
107
115
|
|
|
108
116
|
/** Dim warnings for route hints that no longer match a page. */
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opens external Markdown links in a new tab (`markdown.externalLinks`). A
|
|
3
|
+
* Satteri hast plugin: every `<a>` whose href passes the shared
|
|
4
|
+
* `isExternalUrl` predicate — the one behind the header actions and featured
|
|
5
|
+
* sidebar links — gets `target="_blank"`, `rel="noreferrer"`, an
|
|
6
|
+
* `aria-describedby` pointing at the layout's hidden "Opens in a new tab"
|
|
7
|
+
* element, and a `data-blume-external` marker the theme draws the arrow icon
|
|
8
|
+
* from. So a Markdown link and a chrome link to the same place behave alike.
|
|
9
|
+
*
|
|
10
|
+
* Site routes, fragments, relative paths, and other schemes (`mailto:`,
|
|
11
|
+
* `tel:`) stay in the current tab. Raw `<a>` tags written in Markdown, and JSX
|
|
12
|
+
* or components in MDX, keep whatever attributes their author gave them. Only
|
|
13
|
+
* constructed when the option is on (see `markdown/index.ts`).
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { isExternalUrl } from "../core/base-path.ts";
|
|
17
|
+
import { NEW_TAB_HINT_ID } from "../core/new-tab.ts";
|
|
18
|
+
|
|
19
|
+
/** A hast property value: an attribute primitive or a token list. */
|
|
20
|
+
type HastPropertyValue = string | number | boolean | (string | number)[];
|
|
21
|
+
|
|
22
|
+
/** A minimal hast node (avoids a hast type dependency). */
|
|
23
|
+
interface HastNode {
|
|
24
|
+
properties?: Record<string, HastPropertyValue>;
|
|
25
|
+
tagName?: string;
|
|
26
|
+
type: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The slice of Satteri's hast visitor context this plugin needs. Satteri
|
|
31
|
+
* serializes an unchanged node by identity, so attributes are recorded via
|
|
32
|
+
* `setProperty` rather than by mutating `node.properties`.
|
|
33
|
+
*/
|
|
34
|
+
interface HastContext {
|
|
35
|
+
setProperty: (node: HastNode, key: string, value: HastPropertyValue) => void;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** A Satteri hast plugin, typed structurally to avoid a Satteri dep. */
|
|
39
|
+
export interface ExternalLinksPlugin {
|
|
40
|
+
name: string;
|
|
41
|
+
element: {
|
|
42
|
+
filter: string[];
|
|
43
|
+
visit: (node: HastNode, ctx: HastContext) => void;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Only a string href can be tested; hast allows numbers and token lists. */
|
|
48
|
+
const isHref = (value: HastPropertyValue | undefined): value is string =>
|
|
49
|
+
typeof value === "string";
|
|
50
|
+
|
|
51
|
+
export const externalLinksPlugin = (): ExternalLinksPlugin => ({
|
|
52
|
+
element: {
|
|
53
|
+
filter: ["a"],
|
|
54
|
+
visit(node, ctx) {
|
|
55
|
+
const href = node.properties?.href;
|
|
56
|
+
if (isHref(href) && isExternalUrl(href)) {
|
|
57
|
+
ctx.setProperty(node, "target", "_blank");
|
|
58
|
+
ctx.setProperty(node, "rel", ["noreferrer"]);
|
|
59
|
+
ctx.setProperty(node, "ariaDescribedBy", [NEW_TAB_HINT_ID]);
|
|
60
|
+
ctx.setProperty(node, "dataBlumeExternal", "");
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
name: "blume:external-links",
|
|
65
|
+
});
|
package/src/markdown/include.ts
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
advanceHtmlCommentState,
|
|
8
8
|
expandIncludeTarget,
|
|
9
9
|
hasIncludeStatements,
|
|
10
|
-
|
|
10
|
+
matchIncludeStatement,
|
|
11
11
|
} from "../core/includes.ts";
|
|
12
12
|
import type { MdastNode, MdastValue } from "./mdast.ts";
|
|
13
13
|
|
|
@@ -151,32 +151,42 @@ export const includePlugin = (options: IncludePluginOptions = {}) => {
|
|
|
151
151
|
};
|
|
152
152
|
|
|
153
153
|
/**
|
|
154
|
-
* Splice every statement
|
|
155
|
-
* Statement detection
|
|
156
|
-
*
|
|
157
|
-
* indexed/mirrored surfaces agree on
|
|
158
|
-
* `<!-- -->` or indented like code stays verbatim on both sides
|
|
154
|
+
* Splice every statement in a text block; `null` when none matched.
|
|
155
|
+
* Statement detection is the string-level scanner's (`matchIncludeStatement`
|
|
156
|
+
* with its `.md` rules, plus HTML comment tracking), so the rendered page and
|
|
157
|
+
* the indexed/mirrored surfaces agree on what splices: a statement inside
|
|
158
|
+
* `<!-- -->` or indented like code stays verbatim on both sides, and a
|
|
159
|
+
* wrapped statement splices whole on both.
|
|
159
160
|
*/
|
|
160
161
|
const spliceLines = async (
|
|
161
162
|
node: MdastNode,
|
|
162
163
|
text: string,
|
|
163
164
|
ctx: IncludeVisitorContext
|
|
164
165
|
): Promise<string | null> => {
|
|
166
|
+
const source = text.split("\n");
|
|
167
|
+
const pieces: (string | Promise<string>)[] = [];
|
|
165
168
|
let matched = false;
|
|
166
169
|
let inComment = false;
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
|
|
170
|
+
for (let index = 0; index < source.length; index += 1) {
|
|
171
|
+
const line = source[index] ?? "";
|
|
172
|
+
const wasInComment = inComment;
|
|
173
|
+
inComment = advanceHtmlCommentState(line, inComment);
|
|
174
|
+
const match = wasInComment
|
|
175
|
+
? null
|
|
176
|
+
: matchIncludeStatement(source, index, "md");
|
|
177
|
+
if (match?.kind !== "statement") {
|
|
178
|
+
pieces.push(line);
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
matched = true;
|
|
182
|
+
pieces.push(splice(node, match.statement, ctx));
|
|
183
|
+
index = match.end;
|
|
184
|
+
}
|
|
185
|
+
if (!matched) {
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
const spliced = await Promise.all(pieces);
|
|
189
|
+
return spliced.join("\n");
|
|
180
190
|
};
|
|
181
191
|
|
|
182
192
|
return {
|
|
@@ -195,17 +205,25 @@ export const includePlugin = (options: IncludePluginOptions = {}) => {
|
|
|
195
205
|
if (node.name !== "include") {
|
|
196
206
|
return;
|
|
197
207
|
}
|
|
198
|
-
//
|
|
199
|
-
// graph)
|
|
200
|
-
// would render content those surfaces
|
|
201
|
-
// instead of
|
|
208
|
+
// A wrapped element splices only when the string-level scanner (search,
|
|
209
|
+
// mirrors, llms-full.txt, the HMR graph) reads the same lines as one
|
|
210
|
+
// statement; anything it can't read would render content those surfaces
|
|
211
|
+
// never see, so it's rejected loudly instead of spliced invisibly.
|
|
202
212
|
const start = node.position?.start?.line;
|
|
203
213
|
const end = node.position?.end?.line;
|
|
204
214
|
if (start !== undefined && end !== undefined && start !== end) {
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
215
|
+
const lines = ctx.source.split("\n").slice(start - 1, end);
|
|
216
|
+
const match = matchIncludeStatement(lines, 0, "mdx");
|
|
217
|
+
if (match.kind !== "statement" || match.end !== lines.length - 1) {
|
|
218
|
+
const message =
|
|
219
|
+
"<include> must sit on a line of its own, or wrap with the path on its own line and no blank lines: <include>./path.mdx</include>.";
|
|
220
|
+
ctx.report({ message, node, severity: "warning" });
|
|
221
|
+
ctx.replaceNode(node, { raw: errorBlock(message) });
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
ctx.replaceNode(node, {
|
|
225
|
+
raw: await splice(node, match.statement, ctx),
|
|
226
|
+
});
|
|
209
227
|
return;
|
|
210
228
|
}
|
|
211
229
|
ctx.replaceNode(node, {
|