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
package/src/markdown/index.ts
CHANGED
|
@@ -12,6 +12,7 @@ import { codeToHtml } from "shiki";
|
|
|
12
12
|
import { baseLinksPlugin } from "./base-links.ts";
|
|
13
13
|
import { codeTitleTransformer } from "./code-title.ts";
|
|
14
14
|
import { directiveToCalloutPlugin } from "./directives.ts";
|
|
15
|
+
import { externalLinksPlugin } from "./external-links.ts";
|
|
15
16
|
import { MARKDOWN_FEATURES, MDX_FEATURES } from "./features.ts";
|
|
16
17
|
import { headingAnchorPlugin } from "./heading-anchors.ts";
|
|
17
18
|
import { includePlugin } from "./include.ts";
|
|
@@ -20,6 +21,7 @@ import { languageIconTransformer } from "./language-icon.ts";
|
|
|
20
21
|
import { mathPlugin } from "./math.ts";
|
|
21
22
|
import { mermaidPlugin } from "./mermaid.ts";
|
|
22
23
|
import { packageInstallPlugin } from "./package-install.ts";
|
|
24
|
+
import { relativeLinksPlugin } from "./relative-links.ts";
|
|
23
25
|
import { tableWrapPlugin } from "./table-wrap.ts";
|
|
24
26
|
import { DEFAULT_CODE_THEMES } from "./themes.ts";
|
|
25
27
|
import type { CodeThemes } from "./themes.ts";
|
|
@@ -87,12 +89,14 @@ const asShikiTransformer = (transformer: { name: string }): ShikiTransformer =>
|
|
|
87
89
|
* (`[#custom-id]`, `[!toc]`, `[toc]`), which must parse regardless of config —
|
|
88
90
|
* while `markdown.headingAnchors: false` only turns off the self-linking
|
|
89
91
|
* anchor wrap on `<h2>`–`<h6>`. Inline code runs first so the anchor wrap
|
|
90
|
-
* re-refs already-highlighted code.
|
|
92
|
+
* re-refs already-highlighted code. The external-link plugin is added only
|
|
93
|
+
* when `markdown.externalLinks` is on, so off stays today's exact output.
|
|
91
94
|
*/
|
|
92
95
|
const blumeHastPlugins = (options: BlumeMarkdownOptions): HastPlugin[] => [
|
|
93
96
|
asHastPlugin(inlineCodeHighlightPlugin(options.codeThemes)),
|
|
94
97
|
asHastPlugin(tableWrapPlugin()),
|
|
95
98
|
asHastPlugin(headingAnchorPlugin({ wrap: options.headingAnchors !== false })),
|
|
99
|
+
...(options.externalLinks ? [asHastPlugin(externalLinksPlugin())] : []),
|
|
96
100
|
];
|
|
97
101
|
|
|
98
102
|
/**
|
|
@@ -196,7 +200,7 @@ export interface HighlightCodeOptions extends BlumeShikiOptions {
|
|
|
196
200
|
/** Extra `<pre>` class names, e.g. `blume-source` for a height-capped pane. */
|
|
197
201
|
className?: string;
|
|
198
202
|
/**
|
|
199
|
-
* Light/dark Shiki themes (`markdown.
|
|
203
|
+
* Light/dark Shiki themes (`markdown.code.theme`). Defaults to the same
|
|
200
204
|
* github pair fenced code uses, so out-of-pipeline code stays in lockstep.
|
|
201
205
|
*/
|
|
202
206
|
themes?: CodeThemes;
|
|
@@ -248,9 +252,14 @@ export const highlightCode = async (
|
|
|
248
252
|
export interface BlumeMarkdownOptions {
|
|
249
253
|
/**
|
|
250
254
|
* Light/dark Shiki themes for inline `` `code`{:lang} `` highlighting
|
|
251
|
-
* (`markdown.
|
|
255
|
+
* (`markdown.code.theme`). Defaults to the github pair fenced code uses.
|
|
252
256
|
*/
|
|
253
257
|
codeThemes?: CodeThemes;
|
|
258
|
+
/**
|
|
259
|
+
* Open external links in a new tab, marked with an arrow icon and a
|
|
260
|
+
* screen-reader hint (`markdown.externalLinks`). Off unless `true`.
|
|
261
|
+
*/
|
|
262
|
+
externalLinks?: boolean;
|
|
254
263
|
/**
|
|
255
264
|
* Wrap `<h2>`–`<h6>` in self-linking anchors (`markdown.headingAnchors`).
|
|
256
265
|
* On unless explicitly `false`.
|
|
@@ -271,25 +280,41 @@ export interface BlumeMarkdownOptions {
|
|
|
271
280
|
/**
|
|
272
281
|
* The docs content root, bounding `<include>` target resolution (and
|
|
273
282
|
* anchoring `/`-leading include paths). When unset, relative includes still
|
|
274
|
-
* resolve from the including file.
|
|
283
|
+
* resolve from the including file. Also the base the `docs` collection's
|
|
284
|
+
* entry ids are relative to, which relative page links resolve through.
|
|
275
285
|
*/
|
|
276
286
|
contentRoot?: string;
|
|
287
|
+
/**
|
|
288
|
+
* The `blume:data` snapshot file an ejected app aliases. Relative page links
|
|
289
|
+
* resolve through the snapshot the CLI publishes; with no CLI in the
|
|
290
|
+
* process, they read this file instead.
|
|
291
|
+
*/
|
|
292
|
+
dataFile?: string;
|
|
277
293
|
}
|
|
278
294
|
|
|
279
295
|
/**
|
|
280
|
-
* MDAST plugins that apply to both `.md` and `.mdx`:
|
|
281
|
-
*
|
|
296
|
+
* MDAST plugins that apply to both `.md` and `.mdx`: relative page links
|
|
297
|
+
* rewritten to the root-relative route they mean, then the base-path link
|
|
298
|
+
* rewrite (added only when a `basePath` or `deployBase` is configured), which
|
|
299
|
+
* layers `deployment.base` over the rewritten routes.
|
|
282
300
|
*/
|
|
283
301
|
const blumeSharedMdastPlugins = (
|
|
284
302
|
options: BlumeMarkdownOptions
|
|
285
|
-
): MdastPlugin[] =>
|
|
286
|
-
|
|
303
|
+
): MdastPlugin[] => [
|
|
304
|
+
asMdastPlugin(
|
|
305
|
+
relativeLinksPlugin({
|
|
306
|
+
contentRoot: options.contentRoot,
|
|
307
|
+
dataFile: options.dataFile,
|
|
308
|
+
})
|
|
309
|
+
),
|
|
310
|
+
...(options.basePath || options.deployBase
|
|
287
311
|
? [
|
|
288
312
|
asMdastPlugin(
|
|
289
313
|
baseLinksPlugin(options.deployBase ?? "", options.basePath ?? "")
|
|
290
314
|
),
|
|
291
315
|
]
|
|
292
|
-
: []
|
|
316
|
+
: []),
|
|
317
|
+
];
|
|
293
318
|
|
|
294
319
|
/**
|
|
295
320
|
* The `<include>` splice. Always first: its mutations apply before the next
|
|
@@ -7,11 +7,14 @@
|
|
|
7
7
|
* marker and replaces the code's text with Shiki tokens (dual github-light/dark
|
|
8
8
|
* via CSS variables, like fenced blocks).
|
|
9
9
|
*
|
|
10
|
-
* Shiki is
|
|
10
|
+
* Shiki is loaded lazily, so it loads only on pages that actually use inline
|
|
11
11
|
* highlighting — and never when `markdown.code.inline` is off (the plugin is not
|
|
12
12
|
* added to the pipeline at all).
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
+
import type * as ShikiModule from "shiki";
|
|
16
|
+
|
|
17
|
+
import { nodeRequire } from "../core/node-require.ts";
|
|
15
18
|
import { DEFAULT_CODE_THEMES } from "./themes.ts";
|
|
16
19
|
import type { CodeThemes } from "./themes.ts";
|
|
17
20
|
|
|
@@ -77,13 +80,16 @@ type InlineHighlighter = (
|
|
|
77
80
|
}
|
|
78
81
|
) => Promise<{ children: HastNode[] }>;
|
|
79
82
|
|
|
80
|
-
// `
|
|
81
|
-
|
|
82
|
-
|
|
83
|
+
// `require` caches the module, so this dedupes Shiki across calls on its own.
|
|
84
|
+
// Not `import()`: the plugin runs after Astro has closed the module runner an
|
|
85
|
+
// installed Blume's config was evaluated in (see `core/node-require.ts`), so
|
|
86
|
+
// every inline snippet would silently lose its highlighting.
|
|
87
|
+
const loadHighlighter = (): InlineHighlighter => {
|
|
88
|
+
const { codeToHast }: typeof ShikiModule = nodeRequire("shiki");
|
|
83
89
|
// SAFETY: Shiki accepts arbitrary lang/theme strings at runtime (an unknown
|
|
84
90
|
// one rejects the promise, which the caller catches); only its bundled types
|
|
85
91
|
// constrain them to known ids, so the loose signature narrows nothing real.
|
|
86
|
-
return
|
|
92
|
+
return codeToHast as InlineHighlighter;
|
|
87
93
|
};
|
|
88
94
|
|
|
89
95
|
/** Build the plugin. Highlights inline `` `code{:lang}` `` snippets. */
|
|
@@ -102,7 +108,7 @@ export const inlineCodeHighlightPlugin = (
|
|
|
102
108
|
return;
|
|
103
109
|
}
|
|
104
110
|
try {
|
|
105
|
-
const codeToHast =
|
|
111
|
+
const codeToHast = loadHighlighter();
|
|
106
112
|
const root = await codeToHast(parsed.code, {
|
|
107
113
|
defaultColor: false,
|
|
108
114
|
lang: parsed.lang,
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
import { readFileSync, statSync } from "node:fs";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
|
|
4
|
+
import { dirname, normalize, relative, resolve } from "pathe";
|
|
5
|
+
|
|
6
|
+
import { readRuntimeModule } from "../astro/runtime-modules.ts";
|
|
7
|
+
import { isIndexFileName, resolveRelativeHref } from "../core/links.ts";
|
|
8
|
+
import type { RelativeLinkBase } from "../core/links.ts";
|
|
9
|
+
import type { MdastNode, MdastValue } from "./mdast.ts";
|
|
10
|
+
|
|
11
|
+
interface UrlNode extends MdastNode {
|
|
12
|
+
url?: string | null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** An MDX JSX attribute, as the plugin reads it. */
|
|
16
|
+
interface JsxAttribute {
|
|
17
|
+
[key: string]: MdastValue;
|
|
18
|
+
name?: string;
|
|
19
|
+
type?: string;
|
|
20
|
+
value?: MdastValue;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** An MDX JSX element (`<Card href="./install" />`), as the plugin reads it. */
|
|
24
|
+
interface JsxNode extends MdastNode {
|
|
25
|
+
attributes?: JsxAttribute[];
|
|
26
|
+
children?: MdastValue[];
|
|
27
|
+
name?: string | null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** The visitor-context slice this plugin uses (see `mdast.ts` for the model). */
|
|
31
|
+
interface RelativeLinksContext {
|
|
32
|
+
fileURL: URL | undefined;
|
|
33
|
+
replaceNode: (node: MdastNode, replacement: MdastNode) => void;
|
|
34
|
+
setProperty: (node: MdastNode, key: "url", value: string) => void;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** The slice of the `blume:data` snapshot the plugin reads. */
|
|
38
|
+
interface RouteData {
|
|
39
|
+
config: {
|
|
40
|
+
i18n?: { defaultLocale: string; locales: { code: string }[] } | null;
|
|
41
|
+
};
|
|
42
|
+
routes: {
|
|
43
|
+
collection: string;
|
|
44
|
+
entryId: string;
|
|
45
|
+
fallback: boolean;
|
|
46
|
+
locale: string;
|
|
47
|
+
path: string;
|
|
48
|
+
}[];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** What the plugin knows about where content files publish. */
|
|
52
|
+
interface RouteIndex {
|
|
53
|
+
/** `collection` + NUL + `entryId` → the route that entry publishes at. */
|
|
54
|
+
routes: Map<string, string>;
|
|
55
|
+
/** Every route the site serves, fallback copies included. */
|
|
56
|
+
paths: Set<string>;
|
|
57
|
+
/** Tokens an index file name may carry before its extension. */
|
|
58
|
+
localeTokens: string[];
|
|
59
|
+
/** The locale folders beside the default tree (every locale but the default). */
|
|
60
|
+
localeFolders: string[];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** A content file, located: its page, and how to find the files beside it. */
|
|
64
|
+
interface LocatedPage extends RelativeLinkBase {
|
|
65
|
+
/** The route a sibling file publishes at, from its path relative to `file`. */
|
|
66
|
+
routeOf: (path: string) => string | undefined;
|
|
67
|
+
/** Every route the site serves, for dotted page names (`./node.js`). */
|
|
68
|
+
routes: ReadonlySet<string>;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** A JSX component name (`Card`, `Tree.File`), as opposed to an HTML tag. */
|
|
72
|
+
const COMPONENT_NAME = /^[A-Z]/u;
|
|
73
|
+
|
|
74
|
+
/** A plain string attribute value; an expression value isn't a link target. */
|
|
75
|
+
const isStringValue = (value: MdastValue): value is string =>
|
|
76
|
+
typeof value === "string";
|
|
77
|
+
|
|
78
|
+
const entryKey = (collection: string, entryId: string): string =>
|
|
79
|
+
`${collection}\0${entryId}`;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Index the snapshot's routes by collection entry. A file shared by every
|
|
83
|
+
* locale publishes once per locale; the default locale's route stands for it,
|
|
84
|
+
* and the rendered link moves into the reader's locale afterwards (see
|
|
85
|
+
* `LocaleLinks.astro`). Fallback copies render another locale's file, so they
|
|
86
|
+
* never stand for it.
|
|
87
|
+
*/
|
|
88
|
+
const indexRoutes = (data: RouteData): RouteIndex => {
|
|
89
|
+
const defaultLocale = data.config.i18n?.defaultLocale;
|
|
90
|
+
const routes = new Map<string, string>();
|
|
91
|
+
for (const route of data.routes) {
|
|
92
|
+
if (route.fallback) {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
const key = entryKey(route.collection, route.entryId);
|
|
96
|
+
if (!routes.has(key) || route.locale === defaultLocale) {
|
|
97
|
+
routes.set(key, route.path);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const locales = data.config.i18n?.locales.map((locale) => locale.code) ?? [];
|
|
101
|
+
return {
|
|
102
|
+
localeFolders: locales.filter((code) => code !== defaultLocale),
|
|
103
|
+
localeTokens: data.config.i18n ? ["$", ...locales] : [],
|
|
104
|
+
paths: new Set(data.routes.map((route) => route.path)),
|
|
105
|
+
routes,
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* The same entry path in the default tree: a page in a locale folder that
|
|
111
|
+
* links a sibling not translated yet (`fr/guides/setup.mdx` missing) means
|
|
112
|
+
* the default tree's file (`guides/setup.mdx`), whose route — its own `slug`
|
|
113
|
+
* included — moves into the reader's locale afterwards, onto the fallback
|
|
114
|
+
* copy (see `LocaleLinks.astro`).
|
|
115
|
+
*/
|
|
116
|
+
const defaultTreePath = (
|
|
117
|
+
entryId: string,
|
|
118
|
+
localeFolders: readonly string[]
|
|
119
|
+
): string | undefined => {
|
|
120
|
+
const slash = entryId.indexOf("/");
|
|
121
|
+
return slash !== -1 && localeFolders.includes(entryId.slice(0, slash))
|
|
122
|
+
? entryId.slice(slash + 1)
|
|
123
|
+
: undefined;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
export interface RelativeLinksPluginOptions {
|
|
127
|
+
/** The `docs` collection's base directory, which entry ids are relative to. */
|
|
128
|
+
contentRoot?: string;
|
|
129
|
+
/**
|
|
130
|
+
* The `blume:data` JSON file, for an ejected app: with no CLI in the process
|
|
131
|
+
* to publish the snapshot, the plugin reads the file eject writes instead.
|
|
132
|
+
*/
|
|
133
|
+
dataFile?: string;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Satteri MDAST plugin that rewrites relative page links (`[Install](./install)`,
|
|
138
|
+
* `[Setup](../guides/setup.md)`) to the root-relative route they mean, using
|
|
139
|
+
* the same file-style reading `blume validate` checks them against
|
|
140
|
+
* (`resolveRelativeHref`). Left as written, the browser resolves them against
|
|
141
|
+
* the page's slashless URL — so `./install` on an index page (`/guides`) lands
|
|
142
|
+
* on `/install`, and a `.md` link opens the raw Markdown source instead of the
|
|
143
|
+
* page. The page's own route, and a linked file's, come from the `blume:data`
|
|
144
|
+
* snapshot the CLI publishes (or, ejected, the file eject writes), keyed by
|
|
145
|
+
* collection entry: `docs` entries by their path under `contentRoot`, staged
|
|
146
|
+
* entries (remote sources) by the longest trailing path that names one. A file
|
|
147
|
+
* the snapshot doesn't know keeps its links as written.
|
|
148
|
+
*
|
|
149
|
+
* Runs before the base-links plugin, whose `basePath` layering is idempotent,
|
|
150
|
+
* so a rewritten route (which already carries `basePath`) only gains the
|
|
151
|
+
* `deployment.base` prefix.
|
|
152
|
+
*/
|
|
153
|
+
export const relativeLinksPlugin = (
|
|
154
|
+
options: RelativeLinksPluginOptions = {}
|
|
155
|
+
) => {
|
|
156
|
+
const contentRoot = options.contentRoot
|
|
157
|
+
? resolve(options.contentRoot)
|
|
158
|
+
: undefined;
|
|
159
|
+
const dataFile = options.dataFile ? resolve(options.dataFile) : undefined;
|
|
160
|
+
|
|
161
|
+
// Parsed once per published snapshot: the CLI republishes on regeneration,
|
|
162
|
+
// and an unchanged snapshot is the same string, so every page compiled
|
|
163
|
+
// between regenerations reuses one index.
|
|
164
|
+
let cached: { index: RouteIndex; text: string } | undefined;
|
|
165
|
+
let fileStamp: number | undefined;
|
|
166
|
+
let fileText: string | undefined;
|
|
167
|
+
|
|
168
|
+
/** The ejected snapshot file's text, re-read only when it changes. */
|
|
169
|
+
const readDataFile = (path: string): string | undefined => {
|
|
170
|
+
let stamp: number;
|
|
171
|
+
try {
|
|
172
|
+
stamp = statSync(path).mtimeMs;
|
|
173
|
+
} catch {
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
if (stamp !== fileStamp) {
|
|
177
|
+
fileStamp = stamp;
|
|
178
|
+
fileText = readFileSync(path, "utf-8");
|
|
179
|
+
}
|
|
180
|
+
return fileText;
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
const routeIndex = (): RouteIndex | undefined => {
|
|
184
|
+
const text =
|
|
185
|
+
readRuntimeModule("blume:data") ??
|
|
186
|
+
(dataFile ? readDataFile(dataFile) : undefined);
|
|
187
|
+
if (text === undefined) {
|
|
188
|
+
return undefined;
|
|
189
|
+
}
|
|
190
|
+
if (cached?.text !== text) {
|
|
191
|
+
const data: RouteData = JSON.parse(text);
|
|
192
|
+
cached = { index: indexRoutes(data), text };
|
|
193
|
+
}
|
|
194
|
+
return cached.index;
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
/** The page `file` renders, with a resolver for the files beside it. */
|
|
198
|
+
const locate = (file: string, index: RouteIndex): LocatedPage | undefined => {
|
|
199
|
+
const locateIn = (
|
|
200
|
+
collection: string,
|
|
201
|
+
base: string
|
|
202
|
+
): LocatedPage | undefined => {
|
|
203
|
+
const entryId = relative(base, file);
|
|
204
|
+
const route = index.routes.get(entryKey(collection, entryId));
|
|
205
|
+
if (route === undefined) {
|
|
206
|
+
return undefined;
|
|
207
|
+
}
|
|
208
|
+
return {
|
|
209
|
+
isIndex: isIndexFileName(entryId, index.localeTokens),
|
|
210
|
+
route,
|
|
211
|
+
routeOf: (path) => {
|
|
212
|
+
const target = relative(base, resolve(dirname(file), path));
|
|
213
|
+
const inDefaultTree = defaultTreePath(target, index.localeFolders);
|
|
214
|
+
return (
|
|
215
|
+
index.routes.get(entryKey(collection, target)) ??
|
|
216
|
+
(inDefaultTree === undefined
|
|
217
|
+
? undefined
|
|
218
|
+
: index.routes.get(entryKey(collection, inDefaultTree)))
|
|
219
|
+
);
|
|
220
|
+
},
|
|
221
|
+
routes: index.paths,
|
|
222
|
+
};
|
|
223
|
+
};
|
|
224
|
+
if (contentRoot && !relative(contentRoot, file).startsWith("../")) {
|
|
225
|
+
return locateIn("docs", contentRoot);
|
|
226
|
+
}
|
|
227
|
+
// A staged entry's id is its path under the staging dir, which the plugin
|
|
228
|
+
// isn't told: the longest trailing path naming a staged entry wins.
|
|
229
|
+
const segments = file.split("/");
|
|
230
|
+
for (let start = 1; start < segments.length; start += 1) {
|
|
231
|
+
const staged = locateIn(
|
|
232
|
+
"staged",
|
|
233
|
+
segments.slice(0, start).join("/") || "/"
|
|
234
|
+
);
|
|
235
|
+
if (staged) {
|
|
236
|
+
return staged;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return undefined;
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
/** The route `url` means on the page at `fileURL`, when it's relative. */
|
|
243
|
+
const resolveUrl = (
|
|
244
|
+
url: string,
|
|
245
|
+
fileURL: URL | undefined
|
|
246
|
+
): string | undefined => {
|
|
247
|
+
// Cheap first: a target that can't be relative never needs the index. A
|
|
248
|
+
// dotted name (`./node.js`) passes, since only the index knows its route.
|
|
249
|
+
if (
|
|
250
|
+
!fileURL ||
|
|
251
|
+
resolveRelativeHref(
|
|
252
|
+
url,
|
|
253
|
+
{ isIndex: false, route: "/" },
|
|
254
|
+
undefined,
|
|
255
|
+
() => true
|
|
256
|
+
) === undefined
|
|
257
|
+
) {
|
|
258
|
+
return undefined;
|
|
259
|
+
}
|
|
260
|
+
const index = routeIndex();
|
|
261
|
+
const page = index && locate(normalize(fileURLToPath(fileURL)), index);
|
|
262
|
+
if (!page) {
|
|
263
|
+
return undefined;
|
|
264
|
+
}
|
|
265
|
+
const next = resolveRelativeHref(url, page, page.routeOf, (route) =>
|
|
266
|
+
page.routes.has(route)
|
|
267
|
+
);
|
|
268
|
+
return next === url ? undefined : next;
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
const rewrite = (node: UrlNode, ctx: RelativeLinksContext): void => {
|
|
272
|
+
const { url } = node;
|
|
273
|
+
const next = isStringValue(url) ? resolveUrl(url, ctx.fileURL) : undefined;
|
|
274
|
+
if (next !== undefined) {
|
|
275
|
+
ctx.setProperty(node, "url", next);
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
// A component's string `href` (`<Card href="./install">`) is the same kind
|
|
280
|
+
// of link, and `blume validate` reads it as one. Lowercase elements are
|
|
281
|
+
// raw HTML in a `.md` page, which neither rewrites nor checks, so only
|
|
282
|
+
// components are rewritten; an expression-valued `href={…}` is left alone.
|
|
283
|
+
const rewriteHref = (node: JsxNode, ctx: RelativeLinksContext): void => {
|
|
284
|
+
if (!node.name || !COMPONENT_NAME.test(node.name)) {
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
const attributes = node.attributes ?? [];
|
|
288
|
+
const at = attributes.findIndex(
|
|
289
|
+
(attribute) =>
|
|
290
|
+
attribute.type === "mdxJsxAttribute" &&
|
|
291
|
+
attribute.name === "href" &&
|
|
292
|
+
isStringValue(attribute.value)
|
|
293
|
+
);
|
|
294
|
+
const value = attributes[at]?.value;
|
|
295
|
+
const next = isStringValue(value)
|
|
296
|
+
? resolveUrl(value, ctx.fileURL)
|
|
297
|
+
: undefined;
|
|
298
|
+
if (next !== undefined) {
|
|
299
|
+
// Sätteri can't set a JSX element's attributes in place, so the element
|
|
300
|
+
// is swapped for a copy; its children carry over and are still visited.
|
|
301
|
+
ctx.replaceNode(node, {
|
|
302
|
+
attributes: attributes.map((attribute, position) =>
|
|
303
|
+
position === at
|
|
304
|
+
? { name: attribute.name, type: attribute.type, value: next }
|
|
305
|
+
: attribute
|
|
306
|
+
),
|
|
307
|
+
children: node.children ?? [],
|
|
308
|
+
name: node.name,
|
|
309
|
+
type: node.type,
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
// `link` covers inline links; `definition` covers reference-style
|
|
315
|
+
// definitions (`[x]: ./install`). Images stay with the image pipeline, which
|
|
316
|
+
// resolves relative embeds from beside the page source.
|
|
317
|
+
return {
|
|
318
|
+
definition: rewrite,
|
|
319
|
+
link: rewrite,
|
|
320
|
+
mdxJsxFlowElement: rewriteHref,
|
|
321
|
+
mdxJsxTextElement: rewriteHref,
|
|
322
|
+
name: "blume-relative-links",
|
|
323
|
+
};
|
|
324
|
+
};
|
package/src/markdown/themes.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* The light/dark Shiki themes Blume highlights code with. Every Shiki surface —
|
|
3
3
|
* fenced code (the generated Astro `shikiConfig.themes`), inline `` `code`{:lang} ``,
|
|
4
4
|
* out-of-pipeline `highlightCode`, and `<Diff>` — resolves to the same pair so a
|
|
5
|
-
* project's `markdown.
|
|
5
|
+
* project's `markdown.code.theme` shifts them all in lockstep. This is the
|
|
6
6
|
* single home for the github fallback used when nothing is configured.
|
|
7
7
|
*/
|
|
8
8
|
|
|
@@ -12,7 +12,7 @@ import type { ThemeRegistrationAny } from "shiki";
|
|
|
12
12
|
export type CodeTheme = string | ThemeRegistrationAny;
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* A light/dark Shiki theme pair (`markdown.
|
|
15
|
+
* A light/dark Shiki theme pair (`markdown.code.theme`). A `type` (not an
|
|
16
16
|
* `interface`) so it keeps the implicit index signature Shiki's `themes`
|
|
17
17
|
* parameter (`Partial<Record<string, …>>`) expects.
|
|
18
18
|
*/
|
|
@@ -22,7 +22,7 @@ export type CodeThemes = {
|
|
|
22
22
|
light: CodeTheme;
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
/** The default pair, used when `markdown.
|
|
25
|
+
/** The default pair, used when `markdown.code.theme` is unset. */
|
|
26
26
|
export const DEFAULT_CODE_THEMES: CodeThemes = {
|
|
27
27
|
dark: "github-dark",
|
|
28
28
|
light: "github-light",
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
|
|
4
|
+
import { join } from "pathe";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* `blume migrate`'s logic, kept out of the command module so it runs (and is
|
|
8
|
+
* covered) in-process. Migration is judgment work — idiomatic navigation,
|
|
9
|
+
* component rewrites, what to drop — so it stays in the `blume-migrate` skill,
|
|
10
|
+
* shipped inside the package; this module only names the source (from the
|
|
11
|
+
* argument, or detected from the repo's own files) and writes the prompt that
|
|
12
|
+
* points a coding agent at the skill and that source's mappings.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** The docs frameworks the skill has a mapping reference for. */
|
|
16
|
+
export const MIGRATE_SOURCES = [
|
|
17
|
+
"mintlify",
|
|
18
|
+
"fumadocs",
|
|
19
|
+
"docusaurus",
|
|
20
|
+
"starlight",
|
|
21
|
+
"nextra",
|
|
22
|
+
] as const;
|
|
23
|
+
|
|
24
|
+
export type MigrateSourceId = (typeof MIGRATE_SOURCES)[number];
|
|
25
|
+
|
|
26
|
+
/** Display names, for messages and the prompt. */
|
|
27
|
+
export const MIGRATE_SOURCE_NAMES: Record<MigrateSourceId, string> = {
|
|
28
|
+
docusaurus: "Docusaurus",
|
|
29
|
+
fumadocs: "Fumadocs",
|
|
30
|
+
mintlify: "Mintlify",
|
|
31
|
+
nextra: "Nextra",
|
|
32
|
+
starlight: "Starlight",
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/** The skill's directory inside the published package. */
|
|
36
|
+
export const MIGRATE_SKILL_DIR = join("skills", "blume-migrate");
|
|
37
|
+
|
|
38
|
+
export const isMigrateSource = (value: string): value is MigrateSourceId =>
|
|
39
|
+
MIGRATE_SOURCES.some((source) => source === value);
|
|
40
|
+
|
|
41
|
+
/** A detected source and the file or dependency that gave it away. */
|
|
42
|
+
export interface DetectedSource {
|
|
43
|
+
evidence: string;
|
|
44
|
+
source: MigrateSourceId;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** The slice of `package.json` detection reads. */
|
|
48
|
+
interface PackageJson {
|
|
49
|
+
dependencies?: Record<string, string>;
|
|
50
|
+
devDependencies?: Record<string, string>;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Every dependency the project's `package.json` names, or none when unreadable. */
|
|
54
|
+
const dependencyNames = async (root: string): Promise<Set<string>> => {
|
|
55
|
+
const path = join(root, "package.json");
|
|
56
|
+
if (!existsSync(path)) {
|
|
57
|
+
return new Set();
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
// SAFETY: package.json is a JSON object; only its dependency maps are read.
|
|
61
|
+
const pkg = JSON.parse(await readFile(path, "utf-8")) as PackageJson;
|
|
62
|
+
return new Set([
|
|
63
|
+
...Object.keys(pkg.dependencies ?? {}),
|
|
64
|
+
...Object.keys(pkg.devDependencies ?? {}),
|
|
65
|
+
]);
|
|
66
|
+
} catch {
|
|
67
|
+
// A malformed package.json is the agent's to deal with; detection just
|
|
68
|
+
// falls back to the other signals.
|
|
69
|
+
return new Set();
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Each source's tell, in the order the skill's workflow checks them: a config
|
|
75
|
+
* file the framework owns, or a dependency only it installs.
|
|
76
|
+
*/
|
|
77
|
+
const SIGNALS: {
|
|
78
|
+
deps?: string[];
|
|
79
|
+
files?: string[];
|
|
80
|
+
source: MigrateSourceId;
|
|
81
|
+
}[] = [
|
|
82
|
+
{ files: ["docs.json", "mint.json"], source: "mintlify" },
|
|
83
|
+
{
|
|
84
|
+
files: [
|
|
85
|
+
"docusaurus.config.ts",
|
|
86
|
+
"docusaurus.config.js",
|
|
87
|
+
"docusaurus.config.mjs",
|
|
88
|
+
"docusaurus.config.cjs",
|
|
89
|
+
],
|
|
90
|
+
source: "docusaurus",
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
deps: ["fumadocs-core", "fumadocs-ui", "fumadocs-mdx"],
|
|
94
|
+
files: ["source.config.ts"],
|
|
95
|
+
source: "fumadocs",
|
|
96
|
+
},
|
|
97
|
+
{ deps: ["nextra"], source: "nextra" },
|
|
98
|
+
{ deps: ["@astrojs/starlight"], source: "starlight" },
|
|
99
|
+
];
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Detect the docs framework a project is built on from its own files, or
|
|
103
|
+
* null when nothing gives it away (the skill still migrates any framework,
|
|
104
|
+
* working from its general model instead of a mapping reference).
|
|
105
|
+
*/
|
|
106
|
+
export const detectMigrateSource = async (
|
|
107
|
+
root: string
|
|
108
|
+
): Promise<DetectedSource | null> => {
|
|
109
|
+
const deps = await dependencyNames(root);
|
|
110
|
+
for (const { deps: tells = [], files = [], source } of SIGNALS) {
|
|
111
|
+
const file = files.find((name) => existsSync(join(root, name)));
|
|
112
|
+
if (file) {
|
|
113
|
+
return { evidence: file, source };
|
|
114
|
+
}
|
|
115
|
+
const dep = tells.find((name) => deps.has(name));
|
|
116
|
+
if (dep) {
|
|
117
|
+
return { evidence: `${dep} in package.json`, source };
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return null;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* The handoff prompt: follow the skill, where its mappings for this source
|
|
125
|
+
* are, and the few rules worth restating — the target version, and that no
|
|
126
|
+
* page or URL is lost.
|
|
127
|
+
*/
|
|
128
|
+
export const migratePrompt = (options: {
|
|
129
|
+
detected: DetectedSource | null;
|
|
130
|
+
skillDir: string;
|
|
131
|
+
source: MigrateSourceId | null;
|
|
132
|
+
version: string;
|
|
133
|
+
}): string => {
|
|
134
|
+
const { detected, skillDir, source, version } = options;
|
|
135
|
+
const evidence =
|
|
136
|
+
detected && detected.source === source
|
|
137
|
+
? ` (detected from ${detected.evidence})`
|
|
138
|
+
: "";
|
|
139
|
+
const sourceLine = source
|
|
140
|
+
? `The source is ${MIGRATE_SOURCE_NAMES[source]}${evidence}. Its exact mappings are in ${join(skillDir, "references", `${source}.md`)}.`
|
|
141
|
+
: `The source framework wasn't detected, so inventory the repo first. If it's ${MIGRATE_SOURCES.map((id) => MIGRATE_SOURCE_NAMES[id]).join(", ")}, read that framework's file in ${join(skillDir, "references")}; otherwise follow the skill's mental model directly.`;
|
|
142
|
+
return `Migrate this documentation project to Blume ${version}.
|
|
143
|
+
|
|
144
|
+
Follow the blume-migrate skill: read ${join(skillDir, "SKILL.md")} first and work through its migration workflow. Wherever the skill says \`<skill>\`, it means ${skillDir}.
|
|
145
|
+
|
|
146
|
+
${sourceLine}
|
|
147
|
+
|
|
148
|
+
Add \`blume@^${version}\` as the docs package's dependency. Keep every page, and add a redirect for any URL that moves. Report everything you drop or approximate, and run the skill's verification steps before you finish.`;
|
|
149
|
+
};
|