blume 1.7.3 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +19 -0
- package/CHANGELOG.md +245 -0
- package/README.md +34 -21
- package/dist/cli/{chunk-vacwm2hv.js → chunk-27g6wdth.js} +2 -2
- package/dist/cli/{chunk-ps4m1xh4.js → chunk-2hn4b8z7.js} +513 -550
- package/dist/cli/chunk-2hn4b8z7.js.map +12 -0
- package/dist/cli/chunk-5shv93fd.js +39 -0
- package/dist/cli/chunk-5shv93fd.js.map +10 -0
- package/dist/cli/chunk-6crbhc3x.js +361 -0
- package/dist/cli/chunk-6crbhc3x.js.map +14 -0
- package/dist/cli/{chunk-8cjtbafj.js → chunk-6hsn950k.js} +109 -383
- package/dist/cli/chunk-6hsn950k.js.map +10 -0
- package/dist/cli/chunk-6vm74dry.js +148 -0
- package/dist/cli/chunk-6vm74dry.js.map +10 -0
- package/dist/cli/{chunk-yg63d42r.js → chunk-79jhk4py.js} +87 -58
- package/dist/cli/chunk-79jhk4py.js.map +35 -0
- package/dist/cli/chunk-82bbrxdn.js +51 -0
- package/dist/cli/chunk-82bbrxdn.js.map +10 -0
- package/dist/cli/chunk-abh8yjkn.js +31 -0
- package/dist/cli/chunk-abh8yjkn.js.map +10 -0
- package/dist/cli/chunk-ah61y8py.js +75 -0
- package/dist/cli/chunk-ah61y8py.js.map +11 -0
- package/dist/cli/{chunk-dwgcp5sm.js → chunk-ce574jw2.js} +1 -1
- package/dist/cli/chunk-ch6g3ar0.js +102 -0
- package/dist/cli/chunk-ch6g3ar0.js.map +10 -0
- package/dist/cli/chunk-dh8cwk36.js +279 -0
- package/dist/cli/chunk-dh8cwk36.js.map +10 -0
- package/dist/cli/{chunk-rqy0s5wh.js → chunk-epjnccmv.js} +17 -16
- package/dist/cli/{chunk-rqy0s5wh.js.map → chunk-epjnccmv.js.map} +3 -3
- package/dist/cli/chunk-f2z5v128.js +97 -0
- package/dist/cli/chunk-f2z5v128.js.map +10 -0
- package/dist/cli/{chunk-2z47ypj8.js → chunk-fa25z98p.js} +16 -3
- package/dist/cli/chunk-fa25z98p.js.map +11 -0
- package/dist/cli/{chunk-1jefwnfs.js → chunk-fs23ddbb.js} +1076 -2592
- package/dist/cli/chunk-fs23ddbb.js.map +35 -0
- package/dist/cli/{chunk-e7f42gdj.js → chunk-fxypxtvm.js} +2 -2
- package/dist/cli/{chunk-bvwwhd84.js → chunk-fz5wtpmh.js} +15 -15
- package/dist/cli/{chunk-bvwwhd84.js.map → chunk-fz5wtpmh.js.map} +1 -1
- package/dist/cli/chunk-hdpx1tax.js +91 -0
- package/dist/cli/chunk-hdpx1tax.js.map +10 -0
- package/dist/cli/{chunk-ct47dqpx.js → chunk-jts8mvcz.js} +67 -7
- package/dist/cli/{chunk-2mzebbbz.js.map → chunk-jts8mvcz.js.map} +6 -4
- package/dist/cli/{chunk-ahnw3kxw.js → chunk-jwyddg7y.js} +27 -22
- package/dist/cli/chunk-jwyddg7y.js.map +15 -0
- package/dist/cli/{chunk-cjtn640a.js → chunk-kdp5q7ke.js} +43 -20
- package/dist/cli/chunk-kdp5q7ke.js.map +10 -0
- package/dist/cli/{chunk-5g0w1e2c.js → chunk-kpf8rrjc.js} +28 -16
- package/dist/cli/{chunk-5g0w1e2c.js.map → chunk-kpf8rrjc.js.map} +4 -4
- package/dist/cli/chunk-m3vmjgmq.js +133 -0
- package/dist/cli/chunk-m3vmjgmq.js.map +10 -0
- package/dist/cli/{chunk-b27xqwn9.js → chunk-mb2919y2.js} +9 -5
- package/dist/cli/chunk-mb2919y2.js.map +10 -0
- package/dist/cli/{chunk-5qk08vmp.js → chunk-q5163e60.js} +133 -54
- package/dist/cli/chunk-q5163e60.js.map +11 -0
- package/dist/cli/chunk-qkqwkpte.js +12437 -0
- package/dist/cli/chunk-qkqwkpte.js.map +182 -0
- package/dist/cli/{chunk-4x36ddpw.js → chunk-qs4q5p4e.js} +81 -87
- package/dist/cli/chunk-qs4q5p4e.js.map +10 -0
- package/dist/cli/{chunk-0xjyb285.js → chunk-qwsrynx5.js} +15 -5
- package/dist/cli/{chunk-0xjyb285.js.map → chunk-qwsrynx5.js.map} +4 -4
- package/dist/cli/chunk-s1p84fyh.js +261 -0
- package/dist/cli/chunk-s1p84fyh.js.map +10 -0
- package/dist/cli/chunk-s6jhgk0q.js +176 -0
- package/dist/cli/chunk-s6jhgk0q.js.map +11 -0
- package/dist/cli/chunk-vtk4a6dg.js +374 -0
- package/dist/cli/chunk-vtk4a6dg.js.map +10 -0
- package/dist/cli/{chunk-k79xp7av.js → chunk-wgm7m9qk.js} +230 -700
- package/dist/cli/chunk-wgm7m9qk.js.map +36 -0
- package/dist/cli/chunk-wm7js3j9.js +145 -0
- package/dist/cli/chunk-wm7js3j9.js.map +11 -0
- package/dist/cli/chunk-yt5n7ppj.js +79 -0
- package/dist/cli/chunk-yt5n7ppj.js.map +10 -0
- package/dist/cli/{chunk-3r45185y.js → chunk-yw7dm696.js} +9 -11
- package/dist/cli/{chunk-3r45185y.js.map → chunk-yw7dm696.js.map} +3 -3
- package/dist/cli/{chunk-nn13znc2.js → chunk-zxcczpyx.js} +1 -1
- package/dist/cli/chunk-zxh4d9vy.js +122 -0
- package/dist/cli/chunk-zxh4d9vy.js.map +11 -0
- package/dist/cli/index.js +214 -57
- package/dist/cli/index.js.map +8 -7
- package/dist/types/ai/agent-readability.d.ts +52 -0
- package/dist/types/ai/ai-catalog.d.ts +42 -0
- package/dist/types/ai/api/paths.d.ts +17 -0
- package/dist/types/ai/api-catalog.d.ts +18 -0
- package/dist/types/ai/ask-context.d.ts +7 -7
- package/dist/types/ai/ask.d.ts +368 -0
- package/dist/types/ai/changelog-markdown.d.ts +2 -0
- package/dist/types/ai/component-markdown.d.ts +2 -2
- package/dist/types/ai/index.d.ts +24 -0
- package/dist/types/ai/link-headers.d.ts +24 -0
- package/dist/types/ai/llms.d.ts +25 -0
- package/dist/types/ai/markdown.d.ts +45 -0
- package/dist/types/ai/mcp/discovery.d.ts +68 -0
- package/dist/types/ai/mcp/tools.d.ts +16 -0
- package/dist/types/ai/openapi-components.d.ts +43 -0
- package/dist/types/ai/relative-links.d.ts +26 -0
- package/dist/types/ai/serializers.d.ts +15 -0
- package/dist/types/ai/skills.d.ts +42 -0
- package/dist/types/ai/tar.d.ts +25 -0
- package/dist/types/ai/visibility.d.ts +17 -0
- package/dist/types/ai/web-bot-auth.d.ts +16 -0
- package/dist/types/analytics/adobe.d.ts +35 -0
- package/dist/types/analytics/amplitude.d.ts +50 -0
- package/dist/types/analytics/clarity.d.ts +31 -0
- package/dist/types/analytics/clearbit.d.ts +29 -0
- package/dist/types/analytics/cloudflare.d.ts +41 -0
- package/dist/types/analytics/fathom.d.ts +41 -0
- package/dist/types/analytics/google-analytics.d.ts +44 -0
- package/dist/types/analytics/google-tag-manager.d.ts +40 -0
- package/dist/types/analytics/head.d.ts +30 -0
- package/dist/types/analytics/heap.d.ts +40 -0
- package/dist/types/analytics/hightouch.d.ts +44 -0
- package/dist/types/analytics/hotjar.d.ts +33 -0
- package/dist/types/analytics/index.d.ts +61 -0
- package/dist/types/analytics/inline.d.ts +17 -0
- package/dist/types/analytics/logrocket.d.ts +44 -0
- package/dist/types/analytics/mixpanel.d.ts +67 -0
- package/dist/types/analytics/pirsch.d.ts +42 -0
- package/dist/types/analytics/plausible.d.ts +56 -0
- package/dist/types/analytics/posthog.d.ts +45 -0
- package/dist/types/analytics/schema.d.ts +320 -0
- package/dist/types/analytics/script.d.ts +46 -0
- package/dist/types/analytics/segment.d.ts +50 -0
- package/dist/types/analytics/vercel.d.ts +48 -0
- package/dist/types/astro/integration.d.ts +76 -0
- package/dist/types/astro/markdown-negotiation.d.ts +23 -0
- package/dist/types/astro/module-types.d.ts +14 -0
- package/dist/types/astro/pages.d.ts +44 -0
- package/dist/types/cli/env.d.ts +12 -0
- package/dist/types/cli/init/scaffold.d.ts +154 -0
- package/dist/types/components/layout/nav-utils.d.ts +11 -0
- package/dist/types/core/adapter.d.ts +47 -0
- package/dist/types/core/api-name.d.ts +7 -0
- package/dist/types/core/changelog-index.d.ts +13 -0
- package/dist/types/core/config-input.d.ts +197 -526
- package/dist/types/core/config.d.ts +61 -35
- package/dist/types/core/content-assets.d.ts +76 -0
- package/dist/types/core/custom-pages.d.ts +33 -0
- package/dist/types/core/data.d.ts +30 -15
- package/dist/types/core/define-components.d.ts +12 -9
- package/dist/types/core/deployment-env.d.ts +6 -11
- package/dist/types/core/frontmatter.d.ts +10 -0
- package/dist/types/core/graph.d.ts +18 -0
- package/dist/types/core/heading-markers.d.ts +54 -0
- package/dist/types/core/i18n-ui.d.ts +12 -10
- package/dist/types/core/i18n.d.ts +87 -0
- package/dist/types/core/includes.d.ts +138 -0
- package/dist/types/core/last-modified.d.ts +47 -0
- package/dist/types/core/links.d.ts +95 -0
- package/dist/types/core/locale-links.d.ts +60 -0
- package/dist/types/core/manifest.d.ts +17 -0
- package/dist/types/core/meta.d.ts +38 -0
- package/dist/types/core/nav-diagnostics.d.ts +26 -0
- package/dist/types/core/navigation.d.ts +6 -0
- package/dist/types/core/node-require.d.ts +19 -0
- package/dist/types/core/package-json.d.ts +13 -0
- package/dist/types/core/probe.d.ts +42 -0
- package/dist/types/core/project-graph.d.ts +51 -0
- package/dist/types/core/project.d.ts +2 -0
- package/dist/types/core/safe-href.d.ts +2 -0
- package/dist/types/core/safe-links.d.ts +26 -0
- package/dist/types/core/schema.d.ts +2284 -454
- package/dist/types/core/site-url.d.ts +16 -0
- package/dist/types/core/sources/assets.d.ts +36 -0
- package/dist/types/core/sources/cache.d.ts +37 -0
- package/dist/types/core/sources/collection.d.ts +28 -0
- package/dist/types/core/sources/contentful-rich-text.d.ts +31 -0
- package/dist/types/core/sources/contentful.d.ts +40 -0
- package/dist/types/core/sources/filesystem.d.ts +24 -0
- package/dist/types/core/sources/github-releases.d.ts +31 -0
- package/dist/types/core/sources/json.d.ts +30 -0
- package/dist/types/core/sources/lexical.d.ts +19 -0
- package/dist/types/core/sources/lower.d.ts +75 -0
- package/dist/types/core/sources/mdx-remote.d.ts +28 -0
- package/dist/types/core/sources/normalize.d.ts +147 -0
- package/dist/types/core/sources/notion.d.ts +131 -0
- package/dist/types/core/sources/obsidian.d.ts +46 -0
- package/dist/types/core/sources/payload.d.ts +39 -0
- package/dist/types/core/sources/portable-text.d.ts +42 -0
- package/dist/types/core/sources/read.d.ts +23 -0
- package/dist/types/core/sources/remote.d.ts +74 -0
- package/dist/types/core/sources/resolve.d.ts +19 -0
- package/dist/types/core/sources/sanity.d.ts +43 -0
- package/dist/types/core/sources/strapi-blocks.d.ts +12 -0
- package/dist/types/core/sources/strapi.d.ts +33 -0
- package/dist/types/core/sources/types.d.ts +7 -0
- package/dist/types/core/sources/watch.d.ts +45 -0
- package/dist/types/core/text-width.d.ts +11 -0
- package/dist/types/core/types.d.ts +15 -1
- package/dist/types/core/unrecognized-keys.d.ts +7 -0
- package/dist/types/core/versions.d.ts +72 -0
- package/dist/types/core/yaml.d.ts +9 -0
- package/dist/types/deploy/adapter-output.d.ts +45 -0
- package/dist/types/deploy/adapters/cloudflare.d.ts +40 -0
- package/dist/types/deploy/adapters/index.d.ts +29 -0
- package/dist/types/deploy/adapters/netlify.d.ts +37 -0
- package/dist/types/deploy/adapters/node.d.ts +37 -0
- package/dist/types/deploy/adapters/registry.d.ts +133 -0
- package/dist/types/deploy/adapters/types.d.ts +71 -0
- package/dist/types/deploy/adapters/vercel.d.ts +38 -0
- package/dist/types/deploy/artifacts.d.ts +65 -0
- package/dist/types/deploy/cloudflare-negotiation.d.ts +196 -0
- package/dist/types/deploy/function-bundle.d.ts +80 -0
- package/dist/types/deploy/headers.d.ts +50 -0
- package/dist/types/deploy/node-headers.d.ts +42 -0
- package/dist/types/deploy/platforms/cloudflare.d.ts +40 -0
- package/dist/types/deploy/platforms/index.d.ts +18 -0
- package/dist/types/deploy/platforms/netlify.d.ts +13 -0
- package/dist/types/deploy/platforms/node.d.ts +11 -0
- package/dist/types/deploy/platforms/paths.d.ts +27 -0
- package/dist/types/deploy/platforms/static.d.ts +10 -0
- package/dist/types/deploy/platforms/types.d.ts +104 -0
- package/dist/types/deploy/platforms/vercel.d.ts +32 -0
- package/dist/types/deploy/redirects.d.ts +53 -0
- package/dist/types/deploy/robots.d.ts +8 -0
- package/dist/types/deploy/rss.d.ts +31 -0
- package/dist/types/deploy/sitemap.d.ts +21 -0
- package/dist/types/deploy/vercel-negotiation.d.ts +109 -0
- package/dist/types/markdown/code-title.d.ts +32 -0
- package/dist/types/markdown/fence-meta.d.ts +23 -0
- package/dist/types/markdown/themes.d.ts +3 -3
- package/dist/types/openapi/asyncapi.d.ts +129 -0
- package/dist/types/openapi/graphql-build.d.ts +8 -0
- package/dist/types/openapi/graphql.d.ts +122 -0
- package/dist/types/openapi/model.d.ts +158 -0
- package/dist/types/openapi/parse.d.ts +57 -0
- package/dist/types/openapi/references.d.ts +37 -25
- package/dist/types/openapi/render-mdx.d.ts +33 -0
- package/dist/types/openapi/sentence.d.ts +7 -0
- package/dist/types/openapi/signature.d.ts +10 -0
- package/dist/types/openapi/source.d.ts +22 -0
- package/dist/types/openapi/spec-dependency-error.d.ts +10 -0
- package/dist/types/reference/asyncapi.d.ts +166 -0
- package/dist/types/reference/graphql.d.ts +181 -0
- package/dist/types/reference/index.d.ts +32 -0
- package/dist/types/reference/openapi.d.ts +165 -0
- package/dist/types/reference/options.d.ts +157 -0
- package/dist/types/reference/scalar.d.ts +136 -0
- package/dist/types/reference/schema.d.ts +630 -0
- package/dist/types/search/adapters/algolia.d.ts +32 -0
- package/dist/types/search/adapters/flexsearch.d.ts +12 -0
- package/dist/types/search/adapters/index.d.ts +31 -0
- package/dist/types/search/adapters/mixedbread.d.ts +22 -0
- package/dist/types/search/adapters/orama-cloud.d.ts +33 -0
- package/dist/types/search/adapters/orama.d.ts +13 -0
- package/dist/types/search/adapters/pagefind.d.ts +12 -0
- package/dist/types/search/adapters/registry.d.ts +228 -0
- package/dist/types/search/adapters/types.d.ts +34 -0
- package/dist/types/search/adapters/typesense.d.ts +42 -0
- package/dist/types/search/build.d.ts +23 -0
- package/dist/types/search/documents.d.ts +90 -0
- package/dist/types/search/facets.d.ts +3 -0
- package/dist/types/search/orama-index.d.ts +1 -1
- package/dist/types/search/sync/algolia.d.ts +14 -0
- package/dist/types/search/sync/index.d.ts +14 -0
- package/dist/types/search/sync/orama-cloud.d.ts +10 -0
- package/dist/types/search/sync/typesense.d.ts +14 -0
- package/dist/types/sources/contentful.d.ts +68 -0
- package/dist/types/sources/custom.d.ts +20 -0
- package/dist/types/sources/filesystem.d.ts +42 -0
- package/dist/types/sources/github-releases.d.ts +46 -0
- package/dist/types/sources/index.d.ts +48 -0
- package/dist/types/sources/mdx-remote.d.ts +63 -0
- package/dist/types/sources/notion.d.ts +65 -0
- package/dist/types/sources/obsidian.d.ts +34 -0
- package/dist/types/sources/payload.d.ts +68 -0
- package/dist/types/sources/registry.d.ts +1414 -0
- package/dist/types/sources/sanity.d.ts +69 -0
- package/dist/types/sources/shared.d.ts +46 -0
- package/dist/types/sources/strapi.d.ts +66 -0
- package/dist/types/theme/icon-kind.d.ts +11 -0
- package/dist/types/theme/icons.d.ts +20 -0
- package/docs/01-quickstart.mdx +18 -18
- package/docs/02-deployment.mdx +52 -28
- package/docs/03-upgrading.mdx +364 -0
- package/docs/04-migrating.mdx +58 -0
- package/docs/08-faq.mdx +5 -5
- package/docs/advanced/blog.mdx +13 -6
- package/docs/advanced/changelog.mdx +23 -35
- package/docs/advanced/custom-pages.mdx +22 -10
- package/docs/advanced/meta.ts +1 -8
- package/docs/advanced/skills.mdx +8 -0
- package/docs/cli/audit.mdx +646 -0
- package/docs/cli/doctor.mdx +29 -0
- package/docs/{reference/eval.mdx → cli/evals.mdx} +12 -11
- package/docs/cli/index.mdx +105 -0
- package/docs/cli/meta.ts +7 -0
- package/docs/{reference → cli}/translate.mdx +9 -9
- package/docs/cli/validate.mdx +41 -0
- package/docs/cli/version.mdx +40 -0
- package/docs/configuration/analytics.mdx +350 -59
- package/docs/configuration/assistant.mdx +357 -0
- package/docs/configuration/customization.mdx +16 -10
- package/docs/configuration/index.mdx +50 -31
- package/docs/configuration/meta.ts +1 -1
- package/docs/configuration/search.mdx +76 -55
- package/docs/configuration/theming.mdx +24 -15
- package/docs/content/components.mdx +21 -5
- package/docs/{reference → content}/frontmatter.mdx +35 -1
- package/docs/content/i18n.mdx +9 -7
- package/docs/content/includes.mdx +2 -4
- package/docs/content/index.mdx +1 -1
- package/docs/content/islands.mdx +11 -6
- package/docs/content/meta.mdx +1 -1
- package/docs/content/meta.ts +1 -0
- package/docs/content/navigation.mdx +9 -7
- package/docs/content/sources.mdx +145 -50
- package/docs/content/syntax.mdx +16 -12
- package/docs/content/versioning.mdx +3 -3
- package/docs/discoverability/agent-discovery.mdx +12 -12
- package/docs/discoverability/index.mdx +4 -4
- package/docs/discoverability/json-api.mdx +4 -4
- package/docs/discoverability/llms-txt.mdx +6 -6
- package/docs/discoverability/markdown.mdx +4 -4
- package/docs/discoverability/mcp.mdx +11 -11
- package/docs/discoverability/sitemap-and-robots.mdx +3 -3
- package/docs/index.mdx +4 -4
- package/docs/references/asyncapi.mdx +59 -0
- package/docs/{advanced → references}/graphql.mdx +45 -32
- package/docs/{reference → references}/meta.ts +2 -2
- package/docs/references/openapi.mdx +171 -0
- package/docs/references/scalar.mdx +64 -0
- package/package.json +42 -8
- package/skills/blume/SKILL.md +23 -10
- package/skills/blume-migrate/SKILL.md +22 -21
- package/skills/blume-migrate/assets/oxfmt@0.67.0.patch +49 -0
- package/skills/blume-migrate/references/docusaurus.md +5 -4
- package/skills/blume-migrate/references/fumadocs.md +4 -4
- package/skills/blume-migrate/references/mintlify.md +23 -8
- package/skills/blume-migrate/references/monorepo.md +6 -6
- package/skills/blume-migrate/references/starlight.md +4 -4
- package/src/ai/agent-readability.ts +25 -26
- package/src/ai/ai-catalog.ts +50 -32
- package/src/ai/api/handlers.ts +46 -11
- package/src/ai/api/paths.ts +1 -1
- package/src/ai/api-catalog.ts +8 -8
- package/src/ai/ask-context.ts +7 -7
- package/src/ai/ask-data.ts +3 -3
- package/src/ai/ask.ts +637 -100
- package/src/ai/changelog-markdown.ts +91 -0
- package/src/ai/component-markdown.ts +328 -12
- package/src/ai/cors.ts +3 -3
- package/src/ai/index.ts +45 -0
- package/src/ai/link-headers.ts +7 -6
- package/src/ai/llms.ts +20 -15
- package/src/ai/markdown.ts +35 -5
- package/src/ai/mcp/data.ts +9 -5
- package/src/ai/openapi-components.ts +5 -2
- package/src/ai/relative-links.ts +170 -0
- package/src/ai/serializers.ts +3 -3
- package/src/ai/skills.ts +1 -1
- package/src/ai/visibility.ts +1 -1
- package/src/ai/web-bot-auth.ts +2 -2
- package/src/analytics/adobe.ts +46 -0
- package/src/analytics/amplitude.ts +79 -0
- package/src/analytics/clarity.ts +46 -0
- package/src/analytics/clearbit.ts +47 -0
- package/src/analytics/cloudflare.ts +67 -0
- package/src/analytics/fathom.ts +64 -0
- package/src/analytics/google-analytics.ts +84 -0
- package/src/analytics/google-tag-manager.ts +61 -0
- package/src/analytics/head.ts +130 -0
- package/src/analytics/heap.ts +65 -0
- package/src/analytics/hightouch.ts +77 -0
- package/src/analytics/hotjar.ts +47 -0
- package/src/analytics/index.ts +71 -0
- package/src/analytics/inline.ts +21 -0
- package/src/analytics/logrocket.ts +71 -0
- package/src/analytics/mixpanel.ts +92 -0
- package/src/analytics/pirsch.ts +66 -0
- package/src/analytics/plausible.ts +83 -0
- package/src/analytics/posthog.ts +78 -0
- package/src/analytics/schema.ts +60 -0
- package/src/analytics/script.ts +60 -0
- package/src/analytics/segment.ts +85 -0
- package/src/analytics/vercel.ts +50 -0
- package/src/astro/adapter-root.ts +7 -9
- package/src/astro/component-slots.ts +131 -91
- package/src/astro/generate.ts +129 -361
- package/src/astro/integration.ts +2 -6
- package/src/astro/module-types.ts +1 -1
- package/src/astro/pages.ts +13 -101
- package/src/astro/render-deps.ts +379 -0
- package/src/astro/runtime-deps.ts +201 -0
- package/src/astro/templates.ts +575 -562
- package/src/audit/agent.ts +24 -0
- package/src/audit/catalog.ts +2 -2
- package/src/audit/checks/assets.ts +2 -2
- package/src/audit/checks/dns-aid.ts +1 -1
- package/src/audit/checks/duplicates.ts +3 -1
- package/src/audit/checks/i18n.ts +1 -1
- package/src/audit/checks/indexability.ts +7 -7
- package/src/audit/checks/links.ts +2 -2
- package/src/audit/checks/llms.ts +6 -6
- package/src/audit/checks/network.ts +3 -3
- package/src/audit/checks/og-image.ts +2 -2
- package/src/audit/checks/robots.ts +1 -1
- package/src/audit/checks/sitemap.ts +2 -2
- package/src/audit/checks/social.ts +1 -1
- package/src/audit/run.ts +4 -3
- package/src/audit/terms.ts +31 -0
- package/src/audit/url.ts +13 -13
- package/src/blume-modules.d.ts +2 -2
- package/src/cli/command-meta.ts +10 -0
- package/src/cli/commands/audit.ts +40 -21
- package/src/cli/commands/build.ts +71 -316
- package/src/cli/commands/check.ts +1 -0
- package/src/cli/commands/dev.ts +40 -1
- package/src/cli/commands/doctor.ts +92 -14
- package/src/cli/commands/eject.ts +44 -7
- package/src/cli/commands/eval.ts +5 -5
- package/src/cli/commands/init.ts +161 -41
- package/src/cli/commands/migrate.ts +121 -0
- package/src/cli/commands/preview.ts +7 -1
- package/src/cli/commands/translate.ts +5 -5
- package/src/cli/commands/upgrade.ts +141 -0
- package/src/cli/commands/version.ts +57 -44
- package/src/cli/eject-scripts.ts +121 -6
- package/src/cli/index.ts +11 -1
- package/src/cli/init/install.ts +70 -0
- package/src/cli/init/questions.ts +7 -0
- package/src/cli/init/scaffold.ts +459 -75
- package/src/cli/lazy-command.ts +37 -1
- package/src/cli/prepare.ts +40 -6
- package/src/cli/required-secrets.ts +39 -12
- package/src/cli/unknown-flags.ts +266 -0
- package/src/cli/yarn-pnp.ts +52 -0
- package/src/components/content/AccordionItem.astro +7 -1
- package/src/components/content/Card.astro +4 -3
- package/src/components/content/ColorItem.astro +22 -4
- package/src/components/content/GithubInfo.astro +2 -2
- package/src/components/content/Prompt.astro +25 -25
- package/src/components/content/Tabs.astro +3 -1
- package/src/components/content/Tile.astro +2 -3
- package/src/components/content/Tooltip.astro +57 -9
- package/src/components/content/content-strings.ts +34 -0
- package/src/components/content/diff.ts +1 -1
- package/src/components/content/mermaid-element.ts +13 -2
- package/src/components/content/prompt-markdown.ts +292 -0
- package/src/components/content/tooltip-id.ts +41 -0
- package/src/components/copy-feedback.ts +1 -1
- package/src/components/islands/{AskAI.astro → Assistant.astro} +10 -10
- package/src/components/islands/{ask-ai.tsx → assistant.tsx} +23 -23
- package/src/components/islands/hooks.ts +36 -11
- package/src/components/layout/Analytics.astro +21 -79
- package/src/components/layout/Banner.astro +3 -1
- package/src/components/layout/DiscoveryLinks.astro +69 -0
- package/src/components/layout/Header.astro +93 -30
- package/src/components/layout/LanguageSwitcher.astro +4 -1
- package/src/components/layout/Logo.astro +23 -2
- package/src/components/layout/NavSelector.astro +13 -2
- package/src/components/layout/NavTree.astro +12 -3
- package/src/components/layout/NavTreeScript.astro +17 -3
- package/src/components/layout/PageActions.astro +3 -3
- package/src/components/layout/PageFeedback.astro +11 -1
- package/src/components/layout/PageLayout.astro +58 -11
- package/src/components/layout/Pagination.astro +7 -7
- package/src/components/layout/ReferenceLayout.astro +22 -13
- package/src/components/layout/RootLayout.astro +75 -72
- package/src/components/layout/Search.astro +43 -19
- package/src/components/layout/WebMcp.astro +1 -1
- package/src/components/layout/analytics-client.ts +73 -16
- package/src/components/layout/drawer-inert.ts +113 -15
- package/src/components/layout/dropdown-clamp.ts +105 -0
- package/src/components/layout/head-scripts.ts +15 -6
- package/src/components/layout/nav-utils.ts +17 -0
- package/src/components/layout/search/algolia.ts +8 -8
- package/src/components/layout/search/orama-cloud.ts +9 -7
- package/src/components/layout/search/typesense.ts +11 -17
- package/src/components/openapi/MessageComposer.astro +2 -2
- package/src/components/openapi/Playground.astro +2 -2
- package/src/components/openapi/description.ts +2 -2
- package/src/components/openapi/playground-client.ts +79 -10
- package/src/core/changelog-index.ts +24 -0
- package/src/core/code-fences.ts +1 -1
- package/src/core/component-overrides.ts +399 -154
- package/src/core/config-input.ts +201 -566
- package/src/core/config.ts +131 -42
- package/src/core/custom-pages.ts +105 -0
- package/src/core/data.ts +34 -15
- package/src/core/define-components.ts +12 -9
- package/src/core/deployment-env.ts +18 -74
- package/src/core/diagnostics.ts +14 -7
- package/src/core/graph.ts +69 -25
- package/src/core/i18n-ui.ts +41 -11
- package/src/core/i18n.ts +17 -0
- package/src/core/includes.ts +156 -38
- package/src/core/last-modified.ts +6 -11
- package/src/core/links.ts +166 -2
- package/src/core/manifest.ts +10 -3
- package/src/core/navigation.ts +115 -16
- package/src/core/new-tab.ts +35 -0
- package/src/core/node-require.ts +21 -0
- package/src/core/project-graph.ts +42 -26
- package/src/core/project.ts +9 -4
- package/src/core/request-body.ts +61 -0
- package/src/core/safe-href.ts +28 -0
- package/src/core/safe-links.ts +68 -0
- package/src/core/schema.ts +528 -745
- package/src/core/server-features.ts +10 -11
- package/src/core/sources/assets.ts +47 -11
- package/src/core/sources/collection.ts +67 -0
- package/src/core/sources/contentful-rich-text.ts +285 -0
- package/src/core/sources/contentful.ts +173 -0
- package/src/core/sources/github-releases.ts +51 -1
- package/src/core/sources/json.ts +71 -0
- package/src/core/sources/lexical.ts +195 -0
- package/src/core/sources/lower.ts +226 -0
- package/src/core/sources/normalize.ts +52 -2
- package/src/core/sources/notion.ts +39 -28
- package/src/core/sources/payload.ts +135 -0
- package/src/core/sources/portable-text.ts +11 -16
- package/src/core/sources/remote.ts +226 -0
- package/src/core/sources/resolve.ts +104 -166
- package/src/core/sources/sanity.ts +16 -49
- package/src/core/sources/strapi-blocks.ts +124 -0
- package/src/core/sources/strapi.ts +191 -0
- package/src/core/sources/types.ts +12 -1
- package/src/core/types.ts +15 -1
- package/src/core/ui-packs/ar.ts +10 -7
- package/src/core/ui-packs/bg.ts +10 -7
- package/src/core/ui-packs/bn.ts +10 -7
- package/src/core/ui-packs/ca.ts +7 -6
- package/src/core/ui-packs/cs.ts +10 -7
- package/src/core/ui-packs/da.ts +10 -7
- package/src/core/ui-packs/de.ts +10 -7
- package/src/core/ui-packs/el.ts +7 -6
- package/src/core/ui-packs/es.ts +7 -6
- package/src/core/ui-packs/fa.ts +10 -7
- package/src/core/ui-packs/fi.ts +10 -7
- package/src/core/ui-packs/fr.ts +7 -6
- package/src/core/ui-packs/he.ts +10 -7
- package/src/core/ui-packs/hi.ts +10 -7
- package/src/core/ui-packs/hr.ts +10 -7
- package/src/core/ui-packs/hu.ts +10 -7
- package/src/core/ui-packs/id.ts +10 -7
- package/src/core/ui-packs/it.ts +7 -6
- package/src/core/ui-packs/ja.ts +7 -6
- package/src/core/ui-packs/ko.ts +7 -6
- package/src/core/ui-packs/nl.ts +10 -7
- package/src/core/ui-packs/no.ts +10 -7
- package/src/core/ui-packs/pl.ts +10 -7
- package/src/core/ui-packs/pt-br.ts +7 -6
- package/src/core/ui-packs/pt.ts +7 -6
- package/src/core/ui-packs/ro.ts +10 -7
- package/src/core/ui-packs/ru.ts +10 -7
- package/src/core/ui-packs/sk.ts +10 -7
- package/src/core/ui-packs/sr.ts +10 -7
- package/src/core/ui-packs/sv.ts +10 -7
- package/src/core/ui-packs/th.ts +7 -6
- package/src/core/ui-packs/tr.ts +10 -7
- package/src/core/ui-packs/uk.ts +10 -7
- package/src/core/ui-packs/vi.ts +7 -6
- package/src/core/ui-packs/zh-tw.ts +7 -6
- package/src/core/ui-packs/zh.ts +7 -6
- package/src/core/unrecognized-keys.ts +10 -0
- package/src/core/version-cut.ts +116 -8
- package/src/deploy/adapter-output.ts +57 -97
- package/src/deploy/adapters/cloudflare.ts +39 -0
- package/src/deploy/adapters/index.ts +41 -0
- package/src/deploy/adapters/netlify.ts +34 -0
- package/src/deploy/adapters/node.ts +34 -0
- package/src/deploy/adapters/registry.ts +127 -0
- package/src/deploy/adapters/types.ts +92 -0
- package/src/deploy/adapters/vercel.ts +35 -0
- package/src/deploy/artifacts.ts +55 -27
- package/src/deploy/cloudflare-negotiation.ts +179 -100
- package/src/deploy/function-bundle.ts +18 -3
- package/src/deploy/headers.ts +124 -23
- package/src/deploy/node-headers.ts +198 -0
- package/src/deploy/platforms/cloudflare.ts +312 -0
- package/src/deploy/platforms/index.ts +67 -0
- package/src/deploy/platforms/netlify.ts +52 -0
- package/src/deploy/platforms/node.ts +40 -0
- package/src/deploy/platforms/paths.ts +42 -0
- package/src/deploy/platforms/static.ts +29 -0
- package/src/deploy/platforms/types.ts +112 -0
- package/src/deploy/platforms/vercel.ts +193 -0
- package/src/deploy/redirects.ts +30 -18
- package/src/deploy/robots.ts +3 -3
- package/src/deploy/rss.ts +2 -2
- package/src/deploy/sitemap.ts +2 -2
- package/src/deploy/vercel-negotiation.ts +2 -2
- package/src/eval/agents.ts +32 -1
- package/src/eval/findings.ts +19 -11
- package/src/eval/report.ts +10 -2
- package/src/markdown/external-links.ts +65 -0
- package/src/markdown/include.ts +45 -27
- package/src/markdown/index.ts +34 -9
- package/src/markdown/inline-code.ts +12 -6
- package/src/markdown/relative-links.ts +324 -0
- package/src/markdown/themes.ts +3 -3
- package/src/migrate/migrate.ts +149 -0
- package/src/openapi/parse.ts +64 -16
- package/src/openapi/proxy.ts +62 -10
- package/src/openapi/references.ts +147 -147
- package/src/openapi/render-mdx.ts +32 -10
- package/src/openapi/scalar.ts +15 -13
- package/src/openapi/sentence.ts +14 -0
- package/src/openapi/source.ts +37 -21
- package/src/openapi/spec-dependency-error.ts +15 -0
- package/src/reference/asyncapi.ts +83 -0
- package/src/reference/graphql.ts +89 -0
- package/src/reference/index.ts +40 -0
- package/src/reference/openapi.ts +83 -0
- package/src/reference/options.ts +201 -0
- package/src/reference/scalar.ts +136 -0
- package/src/reference/schema.ts +88 -0
- package/src/registry/eject.ts +109 -53
- package/src/search/adapters/algolia.ts +46 -0
- package/src/search/adapters/flexsearch.ts +29 -0
- package/src/search/adapters/index.ts +39 -0
- package/src/search/adapters/mixedbread.ts +39 -0
- package/src/search/adapters/orama-cloud.ts +51 -0
- package/src/search/adapters/orama.ts +24 -0
- package/src/search/adapters/pagefind.ts +27 -0
- package/src/search/adapters/registry.ts +131 -0
- package/src/search/adapters/types.ts +46 -0
- package/src/search/adapters/typesense.ts +57 -0
- package/src/search/build.ts +8 -4
- package/src/search/documents.ts +8 -2
- package/src/search/orama-index.ts +1 -1
- package/src/search/sync/algolia.ts +12 -11
- package/src/search/sync/index.ts +35 -20
- package/src/search/sync/orama-cloud.ts +12 -9
- package/src/search/sync/typesense.ts +15 -13
- package/src/sources/contentful.ts +63 -0
- package/src/sources/custom.ts +38 -0
- package/src/sources/filesystem.ts +51 -0
- package/src/sources/github-releases.ts +52 -0
- package/src/sources/index.ts +60 -0
- package/src/sources/mdx-remote.ts +76 -0
- package/src/sources/notion.ts +63 -0
- package/src/sources/obsidian.ts +38 -0
- package/src/sources/payload.ts +60 -0
- package/src/sources/registry.ts +182 -0
- package/src/sources/sanity.ts +66 -0
- package/src/sources/shared.ts +52 -0
- package/src/sources/strapi.ts +58 -0
- package/src/theme/entry.ts +24 -2
- package/src/translate/report.ts +40 -7
- package/src/upgrade/upgrade.ts +499 -0
- package/dist/cli/chunk-0qymqwzz.js +0 -164
- package/dist/cli/chunk-0qymqwzz.js.map +0 -15
- package/dist/cli/chunk-1jefwnfs.js.map +0 -48
- package/dist/cli/chunk-2mzebbbz.js +0 -69
- package/dist/cli/chunk-2z47ypj8.js.map +0 -11
- package/dist/cli/chunk-4x36ddpw.js.map +0 -11
- package/dist/cli/chunk-5093q3n7.js +0 -68
- package/dist/cli/chunk-5093q3n7.js.map +0 -10
- package/dist/cli/chunk-5qk08vmp.js.map +0 -11
- package/dist/cli/chunk-7s8hm3b6.js +0 -5347
- package/dist/cli/chunk-7s8hm3b6.js.map +0 -58
- package/dist/cli/chunk-8cjtbafj.js.map +0 -13
- package/dist/cli/chunk-97r59kpr.js +0 -381
- package/dist/cli/chunk-97r59kpr.js.map +0 -12
- package/dist/cli/chunk-ahnw3kxw.js.map +0 -15
- package/dist/cli/chunk-b27xqwn9.js.map +0 -10
- package/dist/cli/chunk-bf6bt1xt.js +0 -185
- package/dist/cli/chunk-bf6bt1xt.js.map +0 -11
- package/dist/cli/chunk-cjtn640a.js.map +0 -10
- package/dist/cli/chunk-ct47dqpx.js.map +0 -11
- package/dist/cli/chunk-esphfr8p.js +0 -107
- package/dist/cli/chunk-esphfr8p.js.map +0 -11
- package/dist/cli/chunk-ex56aa81.js +0 -1016
- package/dist/cli/chunk-ex56aa81.js.map +0 -13
- package/dist/cli/chunk-garjf5z9.js +0 -30
- package/dist/cli/chunk-garjf5z9.js.map +0 -10
- package/dist/cli/chunk-js7saxwm.js +0 -1045
- package/dist/cli/chunk-js7saxwm.js.map +0 -22
- package/dist/cli/chunk-k79xp7av.js.map +0 -39
- package/dist/cli/chunk-ps4m1xh4.js.map +0 -15
- package/dist/cli/chunk-q4rae3bg.js +0 -60
- package/dist/cli/chunk-q4rae3bg.js.map +0 -10
- package/dist/cli/chunk-rz9jmfhz.js +0 -108
- package/dist/cli/chunk-rz9jmfhz.js.map +0 -10
- package/dist/cli/chunk-vh9w1sgp.js +0 -73
- package/dist/cli/chunk-vh9w1sgp.js.map +0 -10
- package/dist/cli/chunk-vrfp10qk.js +0 -81
- package/dist/cli/chunk-vrfp10qk.js.map +0 -10
- package/dist/cli/chunk-yg63d42r.js.map +0 -34
- package/docs/advanced/api-reference.mdx +0 -240
- package/docs/configuration/ask-ai.mdx +0 -256
- package/docs/reference/cli.mdx +0 -197
- package/skills/blume-migrate/assets/oxfmt@0.55.0.patch +0 -20
- package/src/components/content/changelog-element.ts +0 -69
- package/src/search/providers.ts +0 -91
- /package/dist/cli/{chunk-vacwm2hv.js.map → chunk-27g6wdth.js.map} +0 -0
- /package/dist/cli/{chunk-dwgcp5sm.js.map → chunk-ce574jw2.js.map} +0 -0
- /package/dist/cli/{chunk-e7f42gdj.js.map → chunk-fxypxtvm.js.map} +0 -0
- /package/dist/cli/{chunk-nn13znc2.js.map → chunk-zxcczpyx.js.map} +0 -0
|
@@ -1,25 +1,30 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
|
|
3
|
-
import { dirname, extname, isAbsolute, resolve } from "pathe";
|
|
3
|
+
import { basename, dirname, extname, isAbsolute, join, resolve } from "pathe";
|
|
4
4
|
import ts from "typescript";
|
|
5
5
|
|
|
6
|
+
import { BlumeError } from "./diagnostics.ts";
|
|
6
7
|
import type { HydrationMode } from "./schema.ts";
|
|
8
|
+
import type { Diagnostic } from "./types.ts";
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* Static analysis of a user `components.ts`/`.tsx`.
|
|
10
12
|
*
|
|
11
13
|
* Astro can only hydrate a component it imports *statically by path*, so to honor
|
|
12
|
-
* hydration on overrides
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* file with the TypeScript compiler API (never executing it, so `.astro`/React
|
|
14
|
+
* hydration on overrides Blume needs each override's source path and client mode
|
|
15
|
+
* at generate time — before Vite compiles anything. We read that here by parsing
|
|
16
|
+
* the file with the TypeScript compiler API (never executing it, so `.astro`/React
|
|
16
17
|
* imports don't need a Node loader).
|
|
17
18
|
*
|
|
18
|
-
* Only statically-analyzable authoring is
|
|
19
|
-
* object literal or a `defineComponents({ ... })` call,
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
19
|
+
* Only statically-analyzable authoring is accepted: a default export that is an
|
|
20
|
+
* object literal or a `defineComponents({ ... })` call, whose `mdx`/`layout`
|
|
21
|
+
* groups are object literals with entries that are imported identifiers, path
|
|
22
|
+
* strings, or `{ component, client, media }` object literals, and a relative
|
|
23
|
+
* or absolute path must name a file that exists. Anything else is a config
|
|
24
|
+
* error ({@link ComponentOverridesError}, `BLUME_COMPONENTS_INVALID`) naming the
|
|
25
|
+
* entry, its line, and the accepted forms — there is no runtime fallback, so an
|
|
26
|
+
* override that can't be planned never silently renders without hydration, and
|
|
27
|
+
* a missing file never surfaces as a bundler error inside the generated runtime.
|
|
23
28
|
*/
|
|
24
29
|
|
|
25
30
|
export type OverrideFramework = "react" | "svelte" | "vue";
|
|
@@ -38,35 +43,36 @@ export interface OverrideImport {
|
|
|
38
43
|
export interface NormalizedOverride {
|
|
39
44
|
/** Present when the override should hydrate; drives the `client:*` directive. */
|
|
40
45
|
client?: HydrationMode;
|
|
41
|
-
/**
|
|
42
|
-
* True when the value is a bare imported identifier, so the runtime overrides
|
|
43
|
-
* object already holds a usable component (no generated import needed for a
|
|
44
|
-
* non-hydrated entry). False for path strings and `{ component }` descriptors.
|
|
45
|
-
*/
|
|
46
|
-
identifier: boolean;
|
|
47
46
|
key: string;
|
|
48
47
|
/** Media query for `client: "media"`. */
|
|
49
48
|
media?: string;
|
|
50
|
-
/**
|
|
51
|
-
|
|
52
|
-
* so the runtime overrides object is used (static render only).
|
|
53
|
-
*/
|
|
54
|
-
source: OverrideImport | null;
|
|
49
|
+
/** How to obtain the component. */
|
|
50
|
+
source: OverrideImport;
|
|
55
51
|
}
|
|
56
52
|
|
|
57
53
|
export interface ComponentOverrideAnalysis {
|
|
58
|
-
islands: NormalizedOverride[];
|
|
59
54
|
layout: NormalizedOverride[];
|
|
60
55
|
mdx: NormalizedOverride[];
|
|
61
56
|
warnings: string[];
|
|
62
57
|
}
|
|
63
58
|
|
|
64
|
-
|
|
59
|
+
/** The analysis of a project with no `components.ts`. */
|
|
60
|
+
export const emptyComponentOverrides = (): ComponentOverrideAnalysis => ({
|
|
61
|
+
layout: [],
|
|
62
|
+
mdx: [],
|
|
63
|
+
warnings: [],
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const GROUPS = ["mdx", "layout"] as const;
|
|
65
67
|
const GROUP_SET = new Set<string>(GROUPS);
|
|
66
68
|
type Group = (typeof GROUPS)[number];
|
|
67
69
|
|
|
68
70
|
const isGroup = (name: string): name is Group => GROUP_SET.has(name);
|
|
69
71
|
|
|
72
|
+
/** The authoring forms an override accepts; the fix every rejection points at. */
|
|
73
|
+
export const ACCEPTED_OVERRIDE_FORMS =
|
|
74
|
+
"Each override must be an imported identifier, a path string, or a `{ component, client, media }` object literal whose `component` is an imported identifier or a path string.";
|
|
75
|
+
|
|
70
76
|
const FRAMEWORK_BY_EXT = new Map<string, OverrideFramework>([
|
|
71
77
|
["jsx", "react"],
|
|
72
78
|
["svelte", "svelte"],
|
|
@@ -100,29 +106,51 @@ const HYDRATION_MODES: ReadonlySet<string> = new Set<HydrationMode>([
|
|
|
100
106
|
"visible",
|
|
101
107
|
]);
|
|
102
108
|
|
|
109
|
+
const HYDRATION_MODE_LIST = '"load", "idle", "visible", "media", or "only"';
|
|
110
|
+
|
|
103
111
|
const isHydrationMode = (value: string): value is HydrationMode =>
|
|
104
112
|
HYDRATION_MODES.has(value);
|
|
105
113
|
|
|
106
114
|
interface ImportBinding {
|
|
107
115
|
/** Exported name: `"default"` or a named export. */
|
|
108
116
|
imported: string;
|
|
117
|
+
/** The import statement, where a missing file is reported. */
|
|
118
|
+
node: ts.ImportDeclaration;
|
|
109
119
|
specifier: string;
|
|
110
120
|
}
|
|
111
121
|
|
|
122
|
+
/** Why one entry was rejected, and the node it's about (for its line). */
|
|
123
|
+
interface Rejection {
|
|
124
|
+
message: string;
|
|
125
|
+
/** A path that names no file: the fix is the path, not the entry's form. */
|
|
126
|
+
missingFile?: boolean;
|
|
127
|
+
node?: ts.Node;
|
|
128
|
+
}
|
|
129
|
+
|
|
112
130
|
/** An override's declared component before framework/path resolution. */
|
|
113
131
|
interface RawDescriptor {
|
|
114
132
|
client?: HydrationMode;
|
|
115
|
-
hadComponent: boolean;
|
|
116
133
|
media?: string;
|
|
117
134
|
source: OverrideImport | null;
|
|
118
135
|
}
|
|
119
136
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
137
|
+
/** Everything one analysis pass needs to resolve and report an entry. */
|
|
138
|
+
interface AnalysisContext {
|
|
139
|
+
dir: string;
|
|
140
|
+
/** Rejections collected across the file; thrown together at the end. */
|
|
141
|
+
errors: Rejection[];
|
|
142
|
+
imports: Map<string, ImportBinding>;
|
|
143
|
+
warnings: string[];
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const reject = (
|
|
147
|
+
context: AnalysisContext,
|
|
148
|
+
message: string,
|
|
149
|
+
node?: ts.Node,
|
|
150
|
+
missingFile?: boolean
|
|
151
|
+
): void => {
|
|
152
|
+
context.errors.push({ message, missingFile, node });
|
|
153
|
+
};
|
|
126
154
|
|
|
127
155
|
const propName = (name: ts.PropertyName): string | undefined =>
|
|
128
156
|
ts.isIdentifier(name) || ts.isStringLiteral(name) ? name.text : undefined;
|
|
@@ -144,13 +172,18 @@ const addImportBindings = (
|
|
|
144
172
|
return;
|
|
145
173
|
}
|
|
146
174
|
if (clause.name) {
|
|
147
|
-
map.set(clause.name.text, {
|
|
175
|
+
map.set(clause.name.text, {
|
|
176
|
+
imported: "default",
|
|
177
|
+
node: statement,
|
|
178
|
+
specifier,
|
|
179
|
+
});
|
|
148
180
|
}
|
|
149
181
|
const named = clause.namedBindings;
|
|
150
182
|
if (named && ts.isNamedImports(named)) {
|
|
151
183
|
for (const element of named.elements) {
|
|
152
184
|
map.set(element.name.text, {
|
|
153
185
|
imported: (element.propertyName ?? element.name).text,
|
|
186
|
+
node: statement,
|
|
154
187
|
specifier,
|
|
155
188
|
});
|
|
156
189
|
}
|
|
@@ -188,16 +221,13 @@ const unwrapObject = (
|
|
|
188
221
|
return undefined;
|
|
189
222
|
};
|
|
190
223
|
|
|
191
|
-
const
|
|
224
|
+
const findDefaultExport = (
|
|
192
225
|
sourceFile: ts.SourceFile
|
|
193
|
-
): ts.
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}
|
|
199
|
-
return undefined;
|
|
200
|
-
};
|
|
226
|
+
): ts.ExportAssignment | undefined =>
|
|
227
|
+
sourceFile.statements.find(
|
|
228
|
+
(statement): statement is ts.ExportAssignment =>
|
|
229
|
+
ts.isExportAssignment(statement) && !statement.isExportEquals
|
|
230
|
+
);
|
|
201
231
|
|
|
202
232
|
const probeExtension = (base: string): string | null => {
|
|
203
233
|
for (const extension of COMPONENT_EXTS) {
|
|
@@ -209,6 +239,30 @@ const probeExtension = (base: string): string | null => {
|
|
|
209
239
|
return null;
|
|
210
240
|
};
|
|
211
241
|
|
|
242
|
+
// A `.js` specifier in a TypeScript file may name its `.ts`/`.tsx` source, as
|
|
243
|
+
// Vite resolves it; the same holds for `.jsx` and `.mjs`.
|
|
244
|
+
const SCRIPT_EXT = /\.(?:jsx?|mjs)$/u;
|
|
245
|
+
const TS_SOURCE_EXTS = ["ts", "tsx", "mts"];
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Whether a local path names something the bundler can import: the file
|
|
249
|
+
* itself, the file with a component extension added, a folder's `index`, or
|
|
250
|
+
* the TypeScript source a `.js` specifier stands for.
|
|
251
|
+
*/
|
|
252
|
+
const resolvesLocally = (absolute: string): boolean => {
|
|
253
|
+
if (existsSync(absolute) || probeExtension(absolute)) {
|
|
254
|
+
return true;
|
|
255
|
+
}
|
|
256
|
+
if (probeExtension(join(absolute, "index"))) {
|
|
257
|
+
return true;
|
|
258
|
+
}
|
|
259
|
+
const base = absolute.replace(SCRIPT_EXT, "");
|
|
260
|
+
return (
|
|
261
|
+
base !== absolute &&
|
|
262
|
+
TS_SOURCE_EXTS.some((extension) => existsSync(`${base}.${extension}`))
|
|
263
|
+
);
|
|
264
|
+
};
|
|
265
|
+
|
|
212
266
|
/** Resolve a module specifier to a wrapper-importable path + framework. */
|
|
213
267
|
const toImport = (
|
|
214
268
|
specifier: string,
|
|
@@ -237,88 +291,191 @@ const toImport = (
|
|
|
237
291
|
};
|
|
238
292
|
};
|
|
239
293
|
|
|
294
|
+
/**
|
|
295
|
+
* Resolve a specifier to its import, or record that the file it names doesn't
|
|
296
|
+
* exist. A bare package specifier is left to the bundler.
|
|
297
|
+
*/
|
|
298
|
+
const sourceFor = (
|
|
299
|
+
specifier: string,
|
|
300
|
+
imported: string,
|
|
301
|
+
label: string,
|
|
302
|
+
node: ts.Node,
|
|
303
|
+
context: AnalysisContext
|
|
304
|
+
): OverrideImport | null => {
|
|
305
|
+
const local = specifier.startsWith(".") || isAbsolute(specifier);
|
|
306
|
+
if (local && !resolvesLocally(resolve(context.dir, specifier))) {
|
|
307
|
+
reject(
|
|
308
|
+
context,
|
|
309
|
+
`${label} points at "${specifier}", but no file exists there; fix the path or restore the file.`,
|
|
310
|
+
node,
|
|
311
|
+
true
|
|
312
|
+
);
|
|
313
|
+
return null;
|
|
314
|
+
}
|
|
315
|
+
return toImport(specifier, imported, context.dir);
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Resolve an identifier to the import it names, or record why it can't be: a
|
|
320
|
+
* local binding (a `const`, a function declared in the file) has no source path
|
|
321
|
+
* a wrapper could import.
|
|
322
|
+
*/
|
|
240
323
|
const resolveIdentifier = (
|
|
241
324
|
name: string,
|
|
242
|
-
|
|
243
|
-
|
|
325
|
+
label: string,
|
|
326
|
+
node: ts.Node,
|
|
327
|
+
context: AnalysisContext
|
|
244
328
|
): OverrideImport | null => {
|
|
245
|
-
const binding = imports.get(name);
|
|
246
|
-
|
|
329
|
+
const binding = context.imports.get(name);
|
|
330
|
+
if (binding) {
|
|
331
|
+
return sourceFor(
|
|
332
|
+
binding.specifier,
|
|
333
|
+
binding.imported,
|
|
334
|
+
label,
|
|
335
|
+
binding.node,
|
|
336
|
+
context
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
reject(
|
|
340
|
+
context,
|
|
341
|
+
`${label} refers to "${name}", which isn't imported in this file; import the component from its file.`,
|
|
342
|
+
node
|
|
343
|
+
);
|
|
344
|
+
return null;
|
|
247
345
|
};
|
|
248
346
|
|
|
347
|
+
const ALLOWED_FIELDS =
|
|
348
|
+
"only `component`, `client`, and `media` are allowed in a descriptor.";
|
|
349
|
+
|
|
249
350
|
/** Fold one descriptor-object property into the accumulating descriptor. */
|
|
250
351
|
const applyDescriptorProperty = (
|
|
251
352
|
descriptor: RawDescriptor,
|
|
252
353
|
property: ts.ObjectLiteralElementLike,
|
|
253
|
-
|
|
254
|
-
|
|
354
|
+
label: string,
|
|
355
|
+
context: AnalysisContext
|
|
255
356
|
): void => {
|
|
256
357
|
if (ts.isShorthandPropertyAssignment(property)) {
|
|
257
358
|
if (property.name.text === "component") {
|
|
258
|
-
descriptor.
|
|
259
|
-
|
|
359
|
+
descriptor.source = resolveIdentifier(
|
|
360
|
+
property.name.text,
|
|
361
|
+
`${label}'s \`component\``,
|
|
362
|
+
property,
|
|
363
|
+
context
|
|
364
|
+
);
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
const shorthand = property.name.text;
|
|
368
|
+
if (shorthand === "client" || shorthand === "media") {
|
|
369
|
+
reject(
|
|
370
|
+
context,
|
|
371
|
+
`${label} writes \`${shorthand}\` as a shorthand property; only \`component\` may be shorthand, \`${shorthand}\` must be a string literal.`,
|
|
372
|
+
property
|
|
373
|
+
);
|
|
374
|
+
return;
|
|
260
375
|
}
|
|
376
|
+
reject(
|
|
377
|
+
context,
|
|
378
|
+
`${label} has a \`${shorthand}\` field; ${ALLOWED_FIELDS}`,
|
|
379
|
+
property
|
|
380
|
+
);
|
|
261
381
|
return;
|
|
262
382
|
}
|
|
263
383
|
if (!ts.isPropertyAssignment(property)) {
|
|
384
|
+
reject(
|
|
385
|
+
context,
|
|
386
|
+
`${label} contains a spread, method, or accessor; write it as a plain \`{ component, client, media }\` object literal.`,
|
|
387
|
+
property
|
|
388
|
+
);
|
|
264
389
|
return;
|
|
265
390
|
}
|
|
266
391
|
const name = propName(property.name);
|
|
267
392
|
const init = property.initializer;
|
|
268
393
|
if (name === "component") {
|
|
269
|
-
descriptor.hadComponent = true;
|
|
270
394
|
if (ts.isStringLiteral(init)) {
|
|
271
|
-
descriptor.source =
|
|
395
|
+
descriptor.source = sourceFor(
|
|
396
|
+
init.text,
|
|
397
|
+
"default",
|
|
398
|
+
`${label}'s \`component\``,
|
|
399
|
+
init,
|
|
400
|
+
context
|
|
401
|
+
);
|
|
272
402
|
} else if (ts.isIdentifier(init)) {
|
|
273
|
-
descriptor.source = resolveIdentifier(
|
|
403
|
+
descriptor.source = resolveIdentifier(
|
|
404
|
+
init.text,
|
|
405
|
+
`${label}'s \`component\``,
|
|
406
|
+
init,
|
|
407
|
+
context
|
|
408
|
+
);
|
|
409
|
+
} else {
|
|
410
|
+
reject(
|
|
411
|
+
context,
|
|
412
|
+
`${label}'s \`component\` must be an imported identifier or a path string.`,
|
|
413
|
+
init
|
|
414
|
+
);
|
|
274
415
|
}
|
|
275
|
-
} else if (
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
416
|
+
} else if (name === "client") {
|
|
417
|
+
if (ts.isStringLiteral(init) && isHydrationMode(init.text)) {
|
|
418
|
+
descriptor.client = init.text;
|
|
419
|
+
} else {
|
|
420
|
+
reject(
|
|
421
|
+
context,
|
|
422
|
+
`${label}'s \`client\` must be a string literal: ${HYDRATION_MODE_LIST}.`,
|
|
423
|
+
init
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
} else if (name === "media") {
|
|
427
|
+
if (ts.isStringLiteral(init)) {
|
|
428
|
+
descriptor.media = init.text;
|
|
429
|
+
} else {
|
|
430
|
+
reject(context, `${label}'s \`media\` must be a string literal.`, init);
|
|
431
|
+
}
|
|
432
|
+
} else {
|
|
433
|
+
reject(
|
|
434
|
+
context,
|
|
435
|
+
`${label} has a \`${name ?? property.name.getText()}\` field; ${ALLOWED_FIELDS}`,
|
|
436
|
+
property
|
|
437
|
+
);
|
|
283
438
|
}
|
|
284
439
|
};
|
|
285
440
|
|
|
441
|
+
/**
|
|
442
|
+
* Read a `{ component, client, media }` descriptor. Returns null (after
|
|
443
|
+
* recording the reason) when it can't be planned.
|
|
444
|
+
*/
|
|
286
445
|
const readDescriptor = (
|
|
287
446
|
object: ts.ObjectLiteralExpression,
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
): RawDescriptor => {
|
|
291
|
-
const descriptor: RawDescriptor = {
|
|
447
|
+
label: string,
|
|
448
|
+
context: AnalysisContext
|
|
449
|
+
): RawDescriptor | null => {
|
|
450
|
+
const descriptor: RawDescriptor = { source: null };
|
|
451
|
+
const before = context.errors.length;
|
|
452
|
+
let hadComponent = false;
|
|
292
453
|
for (const property of object.properties) {
|
|
293
|
-
|
|
454
|
+
if (property.name && propName(property.name) === "component") {
|
|
455
|
+
hadComponent = true;
|
|
456
|
+
}
|
|
457
|
+
applyDescriptorProperty(descriptor, property, label, context);
|
|
458
|
+
}
|
|
459
|
+
if (!hadComponent) {
|
|
460
|
+
reject(
|
|
461
|
+
context,
|
|
462
|
+
`${label} is an object literal without a \`component\` field.`,
|
|
463
|
+
object
|
|
464
|
+
);
|
|
294
465
|
}
|
|
295
|
-
return descriptor;
|
|
466
|
+
return context.errors.length === before ? descriptor : null;
|
|
296
467
|
};
|
|
297
468
|
|
|
298
469
|
/** Apply cross-cutting validation and produce the final normalized override. */
|
|
299
470
|
const finalize = (
|
|
300
471
|
key: string,
|
|
301
|
-
group: Group,
|
|
302
472
|
descriptor: RawDescriptor,
|
|
303
473
|
label: string,
|
|
304
|
-
identifier: boolean,
|
|
305
474
|
warnings: string[]
|
|
306
475
|
): NormalizedOverride | null => {
|
|
307
476
|
const { client, media, source } = descriptor;
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
if (!source) {
|
|
311
|
-
warnings.push(
|
|
312
|
-
`Island override "${key}" couldn't be resolved to a file. Reference it by an imported component or a path string with an extension.`
|
|
313
|
-
);
|
|
314
|
-
return null;
|
|
315
|
-
}
|
|
316
|
-
if (!source.framework) {
|
|
317
|
-
warnings.push(
|
|
318
|
-
`Island override "${key}" (${label}) is not a React, Vue, or Svelte component; only framework components can be islands.`
|
|
319
|
-
);
|
|
320
|
-
return null;
|
|
321
|
-
}
|
|
477
|
+
if (!source) {
|
|
478
|
+
return null;
|
|
322
479
|
}
|
|
323
480
|
|
|
324
481
|
if (client === "media" && !media) {
|
|
@@ -327,19 +484,19 @@ const finalize = (
|
|
|
327
484
|
);
|
|
328
485
|
}
|
|
329
486
|
|
|
330
|
-
if (client === "only" &&
|
|
487
|
+
if (client === "only" && !source.framework) {
|
|
331
488
|
warnings.push(
|
|
332
489
|
`Override "${key}" uses client: "only" but its framework couldn't be inferred; reference a .tsx/.jsx/.vue/.svelte file.`
|
|
333
490
|
);
|
|
334
491
|
}
|
|
335
492
|
|
|
336
|
-
if (!client && source
|
|
493
|
+
if (!client && source.framework) {
|
|
337
494
|
warnings.push(
|
|
338
495
|
`Override "${key}" points to a ${FRAMEWORK_LABEL[source.framework]} component (${label}) but has no hydration mode, so it renders as static HTML with no interactivity. Add one, e.g. \`${key}: { component: ${JSON.stringify(label)}, client: "load" }\`.`
|
|
339
496
|
);
|
|
340
497
|
}
|
|
341
498
|
|
|
342
|
-
const normalized: NormalizedOverride = {
|
|
499
|
+
const normalized: NormalizedOverride = { key, source };
|
|
343
500
|
if (client) {
|
|
344
501
|
normalized.client = client;
|
|
345
502
|
}
|
|
@@ -349,37 +506,48 @@ const finalize = (
|
|
|
349
506
|
return normalized;
|
|
350
507
|
};
|
|
351
508
|
|
|
509
|
+
/** Normalize one `key: value` entry of a group, or record why it's rejected. */
|
|
352
510
|
const normalizeEntry = (
|
|
353
511
|
entry: ts.ObjectLiteralElementLike,
|
|
354
512
|
group: Group,
|
|
355
|
-
|
|
356
|
-
dir: string,
|
|
357
|
-
warnings: string[]
|
|
513
|
+
context: AnalysisContext
|
|
358
514
|
): NormalizedOverride | null => {
|
|
359
|
-
const
|
|
360
|
-
group === "islands" ? "visible" : undefined;
|
|
515
|
+
const { warnings } = context;
|
|
361
516
|
|
|
362
517
|
if (ts.isShorthandPropertyAssignment(entry)) {
|
|
363
518
|
const name = entry.name.text;
|
|
364
519
|
return finalize(
|
|
365
520
|
name,
|
|
366
|
-
group,
|
|
367
|
-
{
|
|
368
|
-
client: defaultClient,
|
|
369
|
-
hadComponent: true,
|
|
370
|
-
source: resolveIdentifier(name, imports, dir),
|
|
371
|
-
},
|
|
521
|
+
{ source: resolveIdentifier(name, `${group}.${name}`, entry, context) },
|
|
372
522
|
name,
|
|
373
|
-
true,
|
|
374
523
|
warnings
|
|
375
524
|
);
|
|
376
525
|
}
|
|
377
526
|
|
|
378
|
-
if (
|
|
527
|
+
if (ts.isSpreadAssignment(entry)) {
|
|
528
|
+
reject(
|
|
529
|
+
context,
|
|
530
|
+
`${group} contains a spread (\`...${entry.expression.getText()}\`); list each override explicitly.`,
|
|
531
|
+
entry
|
|
532
|
+
);
|
|
379
533
|
return null;
|
|
380
534
|
}
|
|
381
535
|
const key = propName(entry.name);
|
|
382
536
|
if (!key) {
|
|
537
|
+
reject(
|
|
538
|
+
context,
|
|
539
|
+
`${group} has an entry with a computed key (\`${entry.name.getText()}\`); keys must be plain names.`,
|
|
540
|
+
entry
|
|
541
|
+
);
|
|
542
|
+
return null;
|
|
543
|
+
}
|
|
544
|
+
const label = `${group}.${key}`;
|
|
545
|
+
if (!ts.isPropertyAssignment(entry)) {
|
|
546
|
+
reject(
|
|
547
|
+
context,
|
|
548
|
+
`${label} is a method or accessor, which Blume can't analyze statically.`,
|
|
549
|
+
entry
|
|
550
|
+
);
|
|
383
551
|
return null;
|
|
384
552
|
}
|
|
385
553
|
const value = entry.initializer;
|
|
@@ -387,100 +555,155 @@ const normalizeEntry = (
|
|
|
387
555
|
if (ts.isIdentifier(value)) {
|
|
388
556
|
return finalize(
|
|
389
557
|
key,
|
|
390
|
-
|
|
391
|
-
{
|
|
392
|
-
client: defaultClient,
|
|
393
|
-
hadComponent: true,
|
|
394
|
-
source: resolveIdentifier(value.text, imports, dir),
|
|
395
|
-
},
|
|
558
|
+
{ source: resolveIdentifier(value.text, label, entry, context) },
|
|
396
559
|
value.text,
|
|
397
|
-
true,
|
|
398
560
|
warnings
|
|
399
561
|
);
|
|
400
562
|
}
|
|
401
563
|
if (ts.isStringLiteral(value)) {
|
|
402
564
|
return finalize(
|
|
403
565
|
key,
|
|
404
|
-
|
|
405
|
-
{
|
|
406
|
-
client: defaultClient,
|
|
407
|
-
hadComponent: true,
|
|
408
|
-
source: toImport(value.text, "default", dir),
|
|
409
|
-
},
|
|
566
|
+
{ source: sourceFor(value.text, "default", label, value, context) },
|
|
410
567
|
value.text,
|
|
411
|
-
false,
|
|
412
568
|
warnings
|
|
413
569
|
);
|
|
414
570
|
}
|
|
415
571
|
if (ts.isObjectLiteralExpression(value)) {
|
|
416
|
-
const descriptor = readDescriptor(value,
|
|
417
|
-
|
|
418
|
-
warnings.push(
|
|
419
|
-
`Override "${key}" is an object without a \`component\` field; expected \`{ component, client }\`.`
|
|
420
|
-
);
|
|
421
|
-
return null;
|
|
422
|
-
}
|
|
423
|
-
if (!descriptor.source) {
|
|
424
|
-
warnings.push(
|
|
425
|
-
`Override "${key}"'s \`component\` couldn't be resolved to a file. Reference an imported component or a path string with an extension.`
|
|
426
|
-
);
|
|
427
|
-
return null;
|
|
428
|
-
}
|
|
429
|
-
return finalize(
|
|
430
|
-
key,
|
|
431
|
-
group,
|
|
432
|
-
{ ...descriptor, client: descriptor.client ?? defaultClient },
|
|
433
|
-
key,
|
|
434
|
-
false,
|
|
435
|
-
warnings
|
|
436
|
-
);
|
|
572
|
+
const descriptor = readDescriptor(value, label, context);
|
|
573
|
+
return descriptor ? finalize(key, descriptor, key, warnings) : null;
|
|
437
574
|
}
|
|
438
575
|
|
|
439
|
-
|
|
440
|
-
|
|
576
|
+
reject(
|
|
577
|
+
context,
|
|
578
|
+
`${label} is an inline expression, which Blume can't analyze statically.`,
|
|
579
|
+
entry
|
|
580
|
+
);
|
|
581
|
+
return null;
|
|
441
582
|
};
|
|
442
583
|
|
|
443
|
-
/** Normalize one top-level `{ mdx | layout
|
|
584
|
+
/** Normalize one top-level `{ mdx | layout }` group into `result`. */
|
|
444
585
|
const collectGroupOverrides = (
|
|
445
586
|
property: ts.ObjectLiteralElementLike,
|
|
446
|
-
|
|
447
|
-
dir: string,
|
|
587
|
+
context: AnalysisContext,
|
|
448
588
|
result: ComponentOverrideAnalysis
|
|
449
589
|
): void => {
|
|
450
|
-
if (
|
|
590
|
+
if (ts.isSpreadAssignment(property)) {
|
|
591
|
+
reject(
|
|
592
|
+
context,
|
|
593
|
+
`The top-level object contains a spread (\`...${property.expression.getText()}\`); list \`mdx\` and \`layout\` explicitly.`,
|
|
594
|
+
property
|
|
595
|
+
);
|
|
451
596
|
return;
|
|
452
597
|
}
|
|
453
598
|
const name = propName(property.name);
|
|
599
|
+
if (name === "islands") {
|
|
600
|
+
reject(
|
|
601
|
+
context,
|
|
602
|
+
'The `islands` group was folded into `mdx`: move each entry there and give it a `client` mode, e.g. `mdx: { Counter: { component: Counter, client: "visible" } }`.',
|
|
603
|
+
property
|
|
604
|
+
);
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
if (!(name && isGroup(name))) {
|
|
608
|
+
reject(
|
|
609
|
+
context,
|
|
610
|
+
`\`${name ?? property.name.getText()}\` isn't an override group; use \`mdx\` or \`layout\`.`,
|
|
611
|
+
property
|
|
612
|
+
);
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
454
615
|
if (
|
|
455
|
-
!(
|
|
616
|
+
!ts.isPropertyAssignment(property) ||
|
|
456
617
|
!ts.isObjectLiteralExpression(property.initializer)
|
|
457
618
|
) {
|
|
619
|
+
reject(
|
|
620
|
+
context,
|
|
621
|
+
`\`${name}\` must be an object literal of overrides.`,
|
|
622
|
+
property
|
|
623
|
+
);
|
|
458
624
|
return;
|
|
459
625
|
}
|
|
460
626
|
for (const entry of property.initializer.properties) {
|
|
461
|
-
const normalized = normalizeEntry(
|
|
462
|
-
entry,
|
|
463
|
-
name,
|
|
464
|
-
imports,
|
|
465
|
-
dir,
|
|
466
|
-
result.warnings
|
|
467
|
-
);
|
|
627
|
+
const normalized = normalizeEntry(entry, name, context);
|
|
468
628
|
if (normalized) {
|
|
469
629
|
result[name].push(normalized);
|
|
470
630
|
}
|
|
471
631
|
}
|
|
472
632
|
};
|
|
473
633
|
|
|
634
|
+
/**
|
|
635
|
+
* A `components.ts` Blume can't plan. The diagnostic lists every rejected entry
|
|
636
|
+
* at once (at the first one's line); `issues` holds each on its own, with its
|
|
637
|
+
* line, for a caller that reports them one by one (`blume upgrade`).
|
|
638
|
+
*/
|
|
639
|
+
export class ComponentOverridesError extends BlumeError {
|
|
640
|
+
readonly issues: Diagnostic[];
|
|
641
|
+
|
|
642
|
+
constructor(diagnostic: Diagnostic, issues: Diagnostic[]) {
|
|
643
|
+
super(diagnostic);
|
|
644
|
+
this.name = "ComponentOverridesError";
|
|
645
|
+
this.issues = issues;
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
/** A rejection as a diagnostic, at its node's line when it has one. */
|
|
650
|
+
const rejectionDiagnostic = (
|
|
651
|
+
filePath: string,
|
|
652
|
+
sourceFile: ts.SourceFile,
|
|
653
|
+
rejection: Rejection
|
|
654
|
+
): Diagnostic => {
|
|
655
|
+
const position = rejection.node
|
|
656
|
+
? sourceFile.getLineAndCharacterOfPosition(
|
|
657
|
+
rejection.node.getStart(sourceFile)
|
|
658
|
+
)
|
|
659
|
+
: undefined;
|
|
660
|
+
return {
|
|
661
|
+
code: "BLUME_COMPONENTS_INVALID",
|
|
662
|
+
column: position && position.character + 1,
|
|
663
|
+
file: filePath,
|
|
664
|
+
line: position && position.line + 1,
|
|
665
|
+
message: rejection.message,
|
|
666
|
+
severity: "error",
|
|
667
|
+
suggestion: rejection.missingFile ? undefined : ACCEPTED_OVERRIDE_FORMS,
|
|
668
|
+
};
|
|
669
|
+
};
|
|
670
|
+
|
|
671
|
+
const invalidOverrides = (
|
|
672
|
+
filePath: string,
|
|
673
|
+
sourceFile: ts.SourceFile,
|
|
674
|
+
rejections: Rejection[]
|
|
675
|
+
): ComponentOverridesError => {
|
|
676
|
+
const issues = rejections.map((rejection) =>
|
|
677
|
+
rejectionDiagnostic(filePath, sourceFile, rejection)
|
|
678
|
+
);
|
|
679
|
+
const first = issues.find((issue) => issue.line !== undefined);
|
|
680
|
+
return new ComponentOverridesError(
|
|
681
|
+
{
|
|
682
|
+
code: "BLUME_COMPONENTS_INVALID",
|
|
683
|
+
column: first?.column,
|
|
684
|
+
file: filePath,
|
|
685
|
+
line: first?.line,
|
|
686
|
+
message: `${basename(filePath)} has ${rejections.length} override(s) Blume can't plan:\n${rejections.map((rejection) => ` - ${rejection.message}`).join("\n")}`,
|
|
687
|
+
severity: "error",
|
|
688
|
+
suggestion: rejections.every((rejection) => rejection.missingFile)
|
|
689
|
+
? undefined
|
|
690
|
+
: ACCEPTED_OVERRIDE_FORMS,
|
|
691
|
+
},
|
|
692
|
+
issues
|
|
693
|
+
);
|
|
694
|
+
};
|
|
695
|
+
|
|
474
696
|
/**
|
|
475
697
|
* Parse a user `components.ts`/`.tsx` and return its normalized overrides. Never
|
|
476
|
-
* executes the file.
|
|
477
|
-
*
|
|
698
|
+
* executes the file. Throws a `BLUME_COMPONENTS_INVALID`
|
|
699
|
+
* {@link ComponentOverridesError} listing every entry that isn't one of the
|
|
700
|
+
* accepted forms or points at a file that doesn't exist.
|
|
478
701
|
*/
|
|
479
702
|
export const analyzeComponentOverrides = (
|
|
480
703
|
source: string,
|
|
481
704
|
filePath: string
|
|
482
705
|
): ComponentOverrideAnalysis => {
|
|
483
|
-
const result =
|
|
706
|
+
const result = emptyComponentOverrides();
|
|
484
707
|
const sourceFile = ts.createSourceFile(
|
|
485
708
|
filePath,
|
|
486
709
|
source,
|
|
@@ -489,17 +712,39 @@ export const analyzeComponentOverrides = (
|
|
|
489
712
|
filePath.endsWith("tsx") ? ts.ScriptKind.TSX : ts.ScriptKind.TS
|
|
490
713
|
);
|
|
491
714
|
|
|
492
|
-
const
|
|
715
|
+
const exported = findDefaultExport(sourceFile);
|
|
716
|
+
if (!exported) {
|
|
717
|
+
throw invalidOverrides(filePath, sourceFile, [
|
|
718
|
+
{
|
|
719
|
+
message:
|
|
720
|
+
"No default export was found; export `defineComponents({ mdx, layout })` (or a plain object literal) as the default.",
|
|
721
|
+
},
|
|
722
|
+
]);
|
|
723
|
+
}
|
|
724
|
+
const object = unwrapObject(exported.expression);
|
|
493
725
|
if (!object) {
|
|
494
|
-
|
|
726
|
+
throw invalidOverrides(filePath, sourceFile, [
|
|
727
|
+
{
|
|
728
|
+
message:
|
|
729
|
+
"The default export isn't an object literal or a `defineComponents({ ... })` call.",
|
|
730
|
+
node: exported,
|
|
731
|
+
},
|
|
732
|
+
]);
|
|
495
733
|
}
|
|
496
734
|
|
|
497
|
-
const
|
|
498
|
-
|
|
735
|
+
const context: AnalysisContext = {
|
|
736
|
+
dir: dirname(filePath),
|
|
737
|
+
errors: [],
|
|
738
|
+
imports: collectImports(sourceFile),
|
|
739
|
+
warnings: result.warnings,
|
|
740
|
+
};
|
|
499
741
|
|
|
500
742
|
for (const property of object.properties) {
|
|
501
|
-
collectGroupOverrides(property,
|
|
743
|
+
collectGroupOverrides(property, context, result);
|
|
502
744
|
}
|
|
503
745
|
|
|
746
|
+
if (context.errors.length > 0) {
|
|
747
|
+
throw invalidOverrides(filePath, sourceFile, context.errors);
|
|
748
|
+
}
|
|
504
749
|
return result;
|
|
505
750
|
};
|