blume 2.1.3 → 2.2.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 +1 -1
- package/CHANGELOG.md +134 -0
- package/README.md +4 -4
- package/dist/cli/{chunk-y4msrwm9.js → chunk-080mfch6.js} +15 -15
- package/dist/cli/{chunk-gfc5fqvf.js → chunk-1ch3ct3r.js} +18 -18
- package/dist/cli/{chunk-gfc5fqvf.js.map → chunk-1ch3ct3r.js.map} +1 -1
- package/dist/cli/{chunk-32khwcb6.js → chunk-2ssh60qh.js} +42 -69
- package/dist/cli/{chunk-32khwcb6.js.map → chunk-2ssh60qh.js.map} +9 -10
- package/dist/cli/{chunk-9qzgg6mj.js → chunk-34wap3ed.js} +3 -3
- package/dist/cli/{chunk-k3gr1nm9.js → chunk-40vk8kgf.js} +13 -16
- package/dist/cli/{chunk-k3gr1nm9.js.map → chunk-40vk8kgf.js.map} +3 -3
- package/dist/cli/chunk-487b95qy.js +329 -0
- package/dist/cli/chunk-487b95qy.js.map +13 -0
- package/dist/cli/chunk-4zxh25hc.js +157 -0
- package/dist/cli/chunk-4zxh25hc.js.map +10 -0
- package/dist/cli/chunk-69rjf786.js +146 -0
- package/dist/cli/chunk-69rjf786.js.map +11 -0
- package/dist/cli/{chunk-dqhg54mr.js → chunk-9h8mh2tk.js} +3 -3
- package/dist/cli/{chunk-dqhg54mr.js.map → chunk-9h8mh2tk.js.map} +2 -2
- package/dist/cli/{chunk-bqxaqn5p.js → chunk-9jqmq5hv.js} +8 -8
- package/dist/cli/{chunk-bqxaqn5p.js.map → chunk-9jqmq5hv.js.map} +1 -1
- package/dist/cli/{chunk-dv2z0rzf.js → chunk-aafhwx74.js} +38 -13
- package/dist/cli/{chunk-dv2z0rzf.js.map → chunk-aafhwx74.js.map} +5 -4
- package/dist/cli/{chunk-desvm72z.js → chunk-b680sv30.js} +22 -26
- package/dist/cli/chunk-b680sv30.js.map +13 -0
- package/dist/cli/{chunk-0w6hs479.js → chunk-beb0z983.js} +30 -18
- package/dist/cli/chunk-beb0z983.js.map +10 -0
- package/dist/cli/{chunk-1f882900.js → chunk-c5bjxq8v.js} +2 -2
- package/dist/cli/chunk-e1n41w9m.js +155 -0
- package/dist/cli/chunk-e1n41w9m.js.map +11 -0
- package/dist/cli/{chunk-sc93apfs.js → chunk-etckvbrh.js} +17 -17
- package/dist/cli/{chunk-sc93apfs.js.map → chunk-etckvbrh.js.map} +2 -2
- package/dist/cli/{chunk-bxwhtvw8.js → chunk-f260jdrn.js} +5 -5
- package/dist/cli/{chunk-74wfhv79.js → chunk-fnxgtjeq.js} +1 -1
- package/dist/cli/{chunk-ms9z66nz.js → chunk-gwy55cx3.js} +2 -2
- package/dist/cli/{chunk-ms9z66nz.js.map → chunk-gwy55cx3.js.map} +2 -2
- package/dist/cli/{chunk-dhwtqnnd.js → chunk-gxhcf2hs.js} +2 -2
- package/dist/cli/{chunk-tfycddbt.js → chunk-h0qwdbem.js} +2 -2
- package/dist/cli/{chunk-nbyvgnnm.js → chunk-hktq4j5r.js} +109 -49
- package/dist/cli/chunk-hktq4j5r.js.map +36 -0
- package/dist/cli/{chunk-twy7psdz.js → chunk-hn3g2b89.js} +14 -10
- package/dist/cli/chunk-hn3g2b89.js.map +10 -0
- package/dist/cli/{chunk-j1x92mx9.js → chunk-j4nfgn2j.js} +1 -1
- package/dist/cli/{chunk-dpy8qdjf.js → chunk-k45sq16q.js} +74 -183
- package/dist/cli/chunk-k45sq16q.js.map +18 -0
- package/dist/cli/{chunk-5cmts6dv.js → chunk-kmswjxj9.js} +7 -7
- package/dist/cli/{chunk-5cmts6dv.js.map → chunk-kmswjxj9.js.map} +1 -1
- package/dist/cli/{chunk-36bxs9c7.js → chunk-nqna8dzp.js} +27 -23
- package/dist/cli/chunk-nqna8dzp.js.map +10 -0
- package/dist/cli/{chunk-a57yh0h9.js → chunk-p834rkcn.js} +7 -7
- package/dist/cli/{chunk-a57yh0h9.js.map → chunk-p834rkcn.js.map} +1 -1
- package/dist/cli/{chunk-60hz265r.js → chunk-ppa6mg4d.js} +24 -11
- package/dist/cli/chunk-ppa6mg4d.js.map +10 -0
- package/dist/cli/{chunk-s0bdnc7v.js → chunk-q1wwrxzw.js} +5 -4
- package/dist/cli/chunk-q1wwrxzw.js.map +10 -0
- package/dist/cli/{chunk-ave1wcbr.js → chunk-qcyxkj44.js} +1 -1
- package/dist/cli/{chunk-124fvmzq.js → chunk-r5nm9w0c.js} +11183 -8806
- package/dist/cli/{chunk-124fvmzq.js.map → chunk-r5nm9w0c.js.map} +82 -66
- package/dist/cli/{chunk-ckrcm08h.js → chunk-rtvgmg2j.js} +48 -62
- package/dist/cli/{chunk-ckrcm08h.js.map → chunk-rtvgmg2j.js.map} +4 -5
- package/dist/cli/{chunk-297ajdcv.js → chunk-t2h8pwy1.js} +6 -6
- package/dist/cli/{chunk-297ajdcv.js.map → chunk-t2h8pwy1.js.map} +3 -3
- package/dist/cli/{chunk-gxtg6ed2.js → chunk-x60e15st.js} +21 -21
- package/dist/cli/{chunk-gxtg6ed2.js.map → chunk-x60e15st.js.map} +3 -3
- package/dist/cli/{chunk-58bt3hag.js → chunk-x7bh6d9j.js} +4 -4
- package/dist/cli/{chunk-hvcxng5f.js → chunk-ydqzkhjn.js} +6 -6
- package/dist/cli/{chunk-kdpzw38a.js → chunk-yg8ckc3g.js} +95 -7
- package/dist/cli/chunk-yg8ckc3g.js.map +11 -0
- package/dist/cli/{chunk-0pmb4tr4.js → chunk-zxd5jrgx.js} +1205 -222
- package/dist/cli/chunk-zxd5jrgx.js.map +44 -0
- package/dist/cli/index.js +78 -42
- package/dist/cli/index.js.map +7 -6
- package/dist/types/ai/changelog-components.d.ts +18 -0
- package/dist/types/ai/changelog-markdown.d.ts +12 -0
- package/dist/types/ai/openapi-components.d.ts +7 -7
- package/dist/types/ai/operation-details.d.ts +39 -0
- package/dist/types/ai/relative-links.d.ts +3 -1
- package/dist/types/ai/serializers.d.ts +6 -4
- package/dist/types/analytics/head.d.ts +4 -2
- package/dist/types/analytics/script.d.ts +8 -2
- package/dist/types/components/content/youtube.d.ts +20 -0
- package/dist/types/components/layout/nav-utils.d.ts +8 -0
- package/dist/types/components/openapi/example-panels.d.ts +33 -0
- package/dist/types/components/openapi/helpers.d.ts +53 -11
- package/dist/types/components/openapi/snippets.d.ts +7 -1
- package/dist/types/core/alert-diagnostics.d.ts +10 -0
- package/dist/types/core/builtin-tags.d.ts +16 -0
- package/dist/types/core/changelog-list.d.ts +48 -0
- package/dist/types/core/closest-match.d.ts +6 -0
- package/dist/types/core/code-fence-diagnostics.d.ts +18 -0
- package/dist/types/core/code-fences.d.ts +8 -1
- package/dist/types/core/config-input.d.ts +38 -6
- package/dist/types/core/content-assets.d.ts +16 -18
- package/dist/types/core/data.d.ts +6 -2
- package/dist/types/core/diagnostics.d.ts +14 -0
- package/dist/types/core/directive-diagnostics.d.ts +22 -8
- package/dist/types/core/former-routes.d.ts +14 -0
- package/dist/types/core/github.d.ts +5 -4
- package/dist/types/core/heading-markers.d.ts +65 -2
- package/dist/types/core/hidden-pages.d.ts +3 -0
- package/dist/types/core/includes.d.ts +23 -0
- package/dist/types/core/last-modified.d.ts +18 -6
- package/dist/types/core/links.d.ts +42 -2
- package/dist/types/core/load-module.d.ts +19 -4
- package/dist/types/core/manifest.d.ts +14 -1
- package/dist/types/core/markdown-mirrors.d.ts +22 -0
- package/dist/types/core/mcp-clients.d.ts +47 -0
- package/dist/types/core/mdx-elements.d.ts +32 -0
- package/dist/types/core/mdx-syntax.d.ts +100 -0
- package/dist/types/core/meta-diagnostics.d.ts +7 -0
- package/dist/types/core/meta.d.ts +32 -5
- package/dist/types/core/nav-diagnostics.d.ts +16 -2
- package/dist/types/core/navigation.d.ts +13 -0
- package/dist/types/core/ordering-prefix.d.ts +6 -0
- package/dist/types/core/pinned-ids.d.ts +23 -0
- package/dist/types/core/project-graph.d.ts +9 -1
- package/dist/types/core/redirect-patterns.d.ts +18 -0
- package/dist/types/core/relative-files.d.ts +31 -0
- package/dist/types/core/schema.d.ts +322 -11
- package/dist/types/core/sources/normalize.d.ts +101 -9
- package/dist/types/core/sources/types.d.ts +16 -0
- package/dist/types/core/static-files.d.ts +10 -0
- package/dist/types/core/static-host.d.ts +42 -0
- package/dist/types/core/svg-images.d.ts +26 -0
- package/dist/types/core/syntax-diagnostics.d.ts +14 -0
- package/dist/types/core/types.d.ts +42 -1
- package/dist/types/deploy/generated-files.d.ts +41 -0
- package/dist/types/deploy/redirects.d.ts +21 -7
- package/dist/types/markdown/code-title.d.ts +9 -5
- package/dist/types/markdown/directives.d.ts +8 -0
- package/dist/types/markdown/fence-language.d.ts +51 -0
- package/dist/types/markdown/fence-meta.d.ts +5 -0
- package/dist/types/markdown/github-alerts.d.ts +35 -0
- package/dist/types/openapi/asyncapi.d.ts +6 -5
- package/dist/types/openapi/checks.d.ts +10 -5
- package/dist/types/openapi/model.d.ts +55 -8
- package/dist/types/openapi/parse.d.ts +4 -1
- package/dist/types/ratelimit/index.d.ts +2 -0
- package/dist/types/ratelimit/memory.d.ts +1 -1
- package/dist/types/ratelimit/schema.d.ts +40 -0
- package/dist/types/ratelimit/unkey.d.ts +48 -0
- package/dist/types/sources/filesystem.d.ts +14 -4
- package/dist/types/sources/mdx-remote.d.ts +6 -3
- package/dist/types/sources/registry.d.ts +3 -3
- package/dist/types/theme/color.d.ts +33 -0
- package/dist/types/theme/palette.d.ts +122 -0
- package/docs/01-quickstart.mdx +1 -1
- package/docs/02-deployment.mdx +24 -8
- package/docs/04-migrating.mdx +16 -4
- package/docs/advanced/changelog.mdx +27 -1
- package/docs/advanced/skills.mdx +1 -1
- package/docs/cli/audit.mdx +1 -1
- package/docs/cli/doctor.mdx +2 -2
- package/docs/cli/evals.mdx +1 -1
- package/docs/cli/index.mdx +4 -2
- package/docs/cli/validate.mdx +10 -7
- package/docs/configuration/analytics.mdx +2 -0
- package/docs/configuration/customization.mdx +3 -1
- package/docs/configuration/index.mdx +7 -6
- package/docs/configuration/rate-limiting.mdx +20 -1
- package/docs/configuration/theming.mdx +5 -1
- package/docs/content/components.mdx +26 -6
- package/docs/content/frontmatter.mdx +1 -1
- package/docs/content/i18n.mdx +1 -1
- package/docs/content/includes.mdx +6 -2
- package/docs/content/index.mdx +11 -1
- package/docs/content/islands.mdx +2 -0
- package/docs/content/meta.mdx +9 -3
- package/docs/content/navigation.mdx +14 -6
- package/docs/content/sources/obsidian.mdx +1 -1
- package/docs/content/sources/remote-mdx.mdx +3 -1
- package/docs/content/syntax.mdx +76 -8
- package/docs/content/variables.mdx +3 -1
- package/docs/discoverability/agent-discovery.mdx +1 -1
- package/docs/discoverability/json-api.mdx +1 -1
- package/docs/discoverability/llms-txt.mdx +1 -1
- package/docs/discoverability/markdown.mdx +2 -2
- package/docs/discoverability/mcp.mdx +40 -8
- package/docs/discoverability/open-graph.mdx +1 -1
- package/docs/discoverability/sitemap-and-robots.mdx +1 -1
- package/docs/references/graphql.mdx +2 -0
- package/docs/references/openapi.mdx +45 -7
- package/package.json +4 -4
- package/skills/blume/SKILL.md +2 -2
- package/skills/blume-migrate/SKILL.md +51 -29
- package/skills/blume-migrate/references/docsify.md +262 -0
- package/skills/blume-migrate/references/docus.md +298 -0
- package/skills/blume-migrate/references/docusaurus.md +5 -5
- package/skills/blume-migrate/references/fern.md +327 -0
- package/skills/blume-migrate/references/fumadocs.md +1 -1
- package/skills/blume-migrate/references/gitbook.md +267 -0
- package/skills/blume-migrate/references/github-wiki.md +259 -0
- package/skills/blume-migrate/references/jekyll.md +253 -0
- package/skills/blume-migrate/references/mdbook.md +256 -0
- package/skills/blume-migrate/references/mintlify.md +5 -5
- package/skills/blume-migrate/references/mkdocs.md +236 -0
- package/skills/blume-migrate/references/monorepo.md +20 -8
- package/skills/blume-migrate/references/nextra.md +5 -5
- package/skills/blume-migrate/references/readme.md +257 -0
- package/skills/blume-migrate/references/redocly.md +198 -0
- package/skills/blume-migrate/references/starlight.md +3 -3
- package/skills/blume-migrate/references/vitepress.md +204 -0
- package/skills/blume-migrate/references/vuepress.md +271 -0
- package/skills/blume-migrate/scripts/docsify-codemod.mjs +2387 -0
- package/skills/blume-migrate/scripts/docus-codemod.mjs +2542 -0
- package/skills/blume-migrate/scripts/fern-codemod.mjs +2633 -0
- package/skills/blume-migrate/scripts/github-wiki-codemod.mjs +2808 -0
- package/skills/blume-migrate/scripts/include-excerpts.mjs +649 -0
- package/skills/blume-migrate/scripts/jekyll-codemod.mjs +3649 -0
- package/skills/blume-migrate/scripts/mintlify-codemod.mjs +17 -13
- package/skills/blume-migrate/scripts/mkdocs-codemod.mjs +2526 -0
- package/skills/blume-migrate/scripts/operation-routes.mjs +508 -0
- package/skills/blume-migrate/scripts/pin-heading-ids.mjs +1049 -0
- package/skills/blume-migrate/scripts/readme-codemod.mjs +4139 -0
- package/skills/blume-migrate/scripts/vitepress-codemod.mjs +1511 -0
- package/src/ai/changelog-components.ts +24 -0
- package/src/ai/changelog-markdown.ts +45 -41
- package/src/ai/component-markdown.ts +22 -9
- package/src/ai/llms.ts +36 -5
- package/src/ai/markdown.ts +2 -2
- package/src/ai/openapi-components.ts +25 -9
- package/src/ai/operation-details.ts +208 -0
- package/src/ai/relative-links.ts +48 -8
- package/src/ai/serializers.ts +7 -6
- package/src/ai/site-skill.ts +6 -2
- package/src/analytics/head.ts +11 -5
- package/src/analytics/script.ts +13 -3
- package/src/astro/generate.ts +47 -11
- package/src/astro/index.ts +1 -0
- package/src/astro/integration.ts +27 -1
- package/src/astro/mdx-source-errors.ts +46 -0
- package/src/astro/templates.ts +93 -189
- package/src/audit/checks/redirects.ts +5 -1
- package/src/audit/redirects.ts +36 -19
- package/src/audit/report.ts +22 -9
- package/src/audit/run.ts +12 -28
- package/src/audit/terms.ts +23 -0
- package/src/audit/url.ts +2 -2
- package/src/cli/build-failure.ts +256 -7
- package/src/cli/command-meta.ts +1 -1
- package/src/cli/commands/audit.ts +1 -1
- package/src/cli/commands/build.ts +12 -3
- package/src/cli/commands/check.ts +13 -2
- package/src/cli/commands/dev.ts +1 -1
- package/src/cli/commands/doctor.ts +4 -2
- package/src/cli/commands/init.ts +3 -3
- package/src/cli/commands/preview.ts +17 -1
- package/src/cli/commands/validate.ts +22 -10
- package/src/cli/prepare.ts +1 -1
- package/src/cli/preview-pages.ts +161 -0
- package/src/cli/required-secrets.ts +0 -1
- package/src/cli/unknown-flags.ts +1 -42
- package/src/components/code-copy.ts +51 -0
- package/src/components/code-language.ts +75 -0
- package/src/components/content/AccordionItem.astro +16 -1
- package/src/components/content/Callout.astro +11 -1
- package/src/components/content/Changelog.astro +189 -0
- package/src/components/content/CodeBlock.astro +8 -11
- package/src/components/content/Tabs.astro +16 -2
- package/src/components/content/YouTube.astro +6 -4
- package/src/components/content/code-block.ts +33 -0
- package/src/components/content/content-strings.ts +5 -1
- package/src/components/content/inline-markdown.ts +35 -8
- package/src/components/content/youtube.ts +49 -7
- package/src/components/layout/Analytics.astro +5 -1
- package/src/components/layout/NavTree.astro +8 -3
- package/src/components/layout/PageActions.astro +81 -23
- package/src/components/layout/RootLayout.astro +35 -32
- package/src/components/layout/SiteFooter.astro +31 -8
- package/src/components/layout/nav-utils.ts +14 -0
- package/src/components/layout/search/pagefind.ts +2 -1
- package/src/components/openapi/Operation.astro +4 -0
- package/src/components/openapi/PanelTabs.astro +9 -3
- package/src/components/openapi/RequestBody.astro +42 -8
- package/src/components/openapi/RequestPanel.astro +34 -53
- package/src/components/openapi/example-panels.ts +110 -0
- package/src/components/openapi/helpers.ts +195 -20
- package/src/components/openapi/operation-model.ts +63 -26
- package/src/components/openapi/request.ts +13 -0
- package/src/components/openapi/snippets.ts +14 -2
- package/src/core/alert-diagnostics.ts +89 -0
- package/src/core/builtin-tags.ts +76 -0
- package/src/core/changelog-list.ts +87 -0
- package/src/core/closest-match.ts +41 -0
- package/src/core/code-fence-diagnostics.ts +267 -0
- package/src/core/code-fences.ts +43 -7
- package/src/core/component-diagnostics.ts +65 -12
- package/src/core/config-input.ts +39 -5
- package/src/core/config.ts +46 -1
- package/src/core/content-assets.ts +64 -144
- package/src/core/data.ts +10 -3
- package/src/core/diagnostics.ts +36 -3
- package/src/core/directive-diagnostics.ts +265 -47
- package/src/core/former-routes.ts +46 -0
- package/src/core/git-ignored.ts +53 -0
- package/src/core/github.ts +5 -4
- package/src/core/heading-markers.ts +156 -2
- package/src/core/hidden-pages.ts +64 -0
- package/src/core/includes.ts +181 -41
- package/src/core/last-modified.ts +47 -10
- package/src/core/links.ts +438 -83
- package/src/core/load-module.ts +98 -9
- package/src/core/manifest.ts +12 -9
- package/src/core/markdown-mirrors.ts +52 -0
- package/src/core/mcp-clients.ts +87 -0
- package/src/core/mdx-elements.ts +153 -0
- package/src/core/mdx-syntax.ts +377 -0
- package/src/core/meta-diagnostics.ts +134 -0
- package/src/core/meta.ts +154 -55
- package/src/core/nav-diagnostics.ts +41 -4
- package/src/core/navigation.ts +70 -10
- package/src/core/ordering-prefix.ts +22 -2
- package/src/core/pinned-ids.ts +141 -0
- package/src/core/project-graph.ts +221 -29
- package/src/core/redirect-patterns.ts +41 -0
- package/src/core/relative-files.ts +145 -0
- package/src/core/schema.ts +110 -6
- package/src/core/sources/mdx-remote.ts +75 -14
- package/src/core/sources/normalize.ts +885 -179
- package/src/core/sources/notion.ts +5 -4
- package/src/core/sources/obsidian.ts +2 -5
- package/src/core/sources/types.ts +17 -0
- package/src/core/static-files.ts +40 -0
- package/src/core/static-host.ts +125 -0
- package/src/core/svg-images.ts +98 -0
- package/src/core/syntax-diagnostics.ts +491 -0
- package/src/core/types.ts +43 -1
- package/src/deploy/artifacts.ts +2 -28
- package/src/deploy/generated-files.ts +128 -0
- package/src/deploy/platforms/vercel.ts +25 -1
- package/src/deploy/redirects.ts +43 -16
- package/src/deploy/sitemap.ts +2 -1
- package/src/markdown/base-links.ts +87 -6
- package/src/markdown/code-title.ts +29 -13
- package/src/markdown/content-assets.ts +210 -0
- package/src/markdown/directives.ts +69 -5
- package/src/markdown/fence-language.ts +106 -0
- package/src/markdown/fence-meta.ts +42 -0
- package/src/markdown/github-alerts.ts +172 -0
- package/src/markdown/heading-anchors.ts +265 -56
- package/src/markdown/include.ts +30 -3
- package/src/markdown/index.ts +145 -40
- package/src/markdown/prompt-text.ts +95 -0
- package/src/markdown/relative-links.ts +37 -2
- package/src/markdown/route-snapshot.ts +22 -12
- package/src/markdown/svg-fallback.ts +51 -0
- package/src/markdown/title-heading.ts +134 -0
- package/src/migrate/migrate.ts +127 -2
- package/src/og/card.ts +14 -4
- package/src/openapi/asyncapi.ts +14 -6
- package/src/openapi/checks.ts +160 -15
- package/src/openapi/model.ts +172 -33
- package/src/openapi/parse.ts +13 -4
- package/src/openapi/render-mdx.ts +55 -9
- package/src/openapi/source.ts +87 -6
- package/src/ratelimit/index.ts +2 -0
- package/src/ratelimit/memory.ts +1 -1
- package/src/ratelimit/runtime.ts +81 -0
- package/src/ratelimit/schema.ts +2 -0
- package/src/ratelimit/unkey.ts +61 -0
- package/src/registry/eject.ts +0 -1
- package/src/registry/registry.ts +1 -1
- package/src/search/documents.ts +10 -2
- package/src/sources/filesystem.ts +28 -3
- package/src/sources/mdx-remote.ts +7 -15
- package/src/theme/color.ts +14 -0
- package/src/theme/entry.ts +22 -1
- package/src/theme/palette.ts +74 -1
- package/dist/cli/chunk-0pmb4tr4.js.map +0 -35
- package/dist/cli/chunk-0w6hs479.js.map +0 -10
- package/dist/cli/chunk-150jk7km.js +0 -52
- package/dist/cli/chunk-150jk7km.js.map +0 -10
- package/dist/cli/chunk-36bxs9c7.js.map +0 -10
- package/dist/cli/chunk-53jqw8z0.js +0 -89
- package/dist/cli/chunk-53jqw8z0.js.map +0 -10
- package/dist/cli/chunk-60hz265r.js.map +0 -10
- package/dist/cli/chunk-desvm72z.js.map +0 -14
- package/dist/cli/chunk-dpy8qdjf.js.map +0 -17
- package/dist/cli/chunk-es8h0v3j.js +0 -441
- package/dist/cli/chunk-es8h0v3j.js.map +0 -11
- package/dist/cli/chunk-kdpzw38a.js.map +0 -11
- package/dist/cli/chunk-nbyvgnnm.js.map +0 -36
- package/dist/cli/chunk-s0bdnc7v.js.map +0 -10
- package/dist/cli/chunk-twy7psdz.js.map +0 -10
- package/dist/cli/chunk-ydp3065p.js +0 -64
- package/dist/cli/chunk-ydp3065p.js.map +0 -10
- /package/dist/cli/{chunk-y4msrwm9.js.map → chunk-080mfch6.js.map} +0 -0
- /package/dist/cli/{chunk-9qzgg6mj.js.map → chunk-34wap3ed.js.map} +0 -0
- /package/dist/cli/{chunk-1f882900.js.map → chunk-c5bjxq8v.js.map} +0 -0
- /package/dist/cli/{chunk-bxwhtvw8.js.map → chunk-f260jdrn.js.map} +0 -0
- /package/dist/cli/{chunk-74wfhv79.js.map → chunk-fnxgtjeq.js.map} +0 -0
- /package/dist/cli/{chunk-dhwtqnnd.js.map → chunk-gxhcf2hs.js.map} +0 -0
- /package/dist/cli/{chunk-tfycddbt.js.map → chunk-h0qwdbem.js.map} +0 -0
- /package/dist/cli/{chunk-j1x92mx9.js.map → chunk-j4nfgn2j.js.map} +0 -0
- /package/dist/cli/{chunk-ave1wcbr.js.map → chunk-qcyxkj44.js.map} +0 -0
- /package/dist/cli/{chunk-58bt3hag.js.map → chunk-x7bh6d9j.js.map} +0 -0
- /package/dist/cli/{chunk-hvcxng5f.js.map → chunk-ydqzkhjn.js.map} +0 -0
package/src/audit/run.ts
CHANGED
|
@@ -8,7 +8,6 @@ import type { BlumeProject } from "../core/project-graph.ts";
|
|
|
8
8
|
import type { Diagnostic } from "../core/types.ts";
|
|
9
9
|
import { deployStaticDir } from "../deploy/adapter-output.ts";
|
|
10
10
|
import { applyBaseToAstroRedirects } from "../deploy/redirects.ts";
|
|
11
|
-
import { CHECKS } from "./catalog.ts";
|
|
12
11
|
import type { CheckId } from "./catalog.ts";
|
|
13
12
|
import { assetChecks } from "./checks/assets.ts";
|
|
14
13
|
import { contentChecks } from "./checks/content.ts";
|
|
@@ -32,7 +31,7 @@ import {
|
|
|
32
31
|
import { crawlStaticDir } from "./crawl.ts";
|
|
33
32
|
import { buildGraph } from "./graph.ts";
|
|
34
33
|
import { resolveRedirects } from "./redirects.ts";
|
|
35
|
-
import {
|
|
34
|
+
import { checkSelected } from "./terms.ts";
|
|
36
35
|
import { DEFAULT_THRESHOLDS } from "./types.ts";
|
|
37
36
|
import type {
|
|
38
37
|
AuditContext,
|
|
@@ -84,6 +83,10 @@ export interface AuditResult {
|
|
|
84
83
|
origin: string | null;
|
|
85
84
|
/** Which tiers actually ran. A skipped tier is reported, never hidden. */
|
|
86
85
|
tiers: Record<AuditTier, boolean>;
|
|
86
|
+
/** The `--only` terms the findings were filtered to, if any. */
|
|
87
|
+
only?: string[];
|
|
88
|
+
/** The `--skip` terms the findings were filtered by, if any. */
|
|
89
|
+
skip?: string[];
|
|
87
90
|
}
|
|
88
91
|
|
|
89
92
|
/** Thrown when there's no build to audit. */
|
|
@@ -123,18 +126,6 @@ const readSources = async (
|
|
|
123
126
|
return new Map(entries.filter((entry) => entry !== null));
|
|
124
127
|
};
|
|
125
128
|
|
|
126
|
-
/** Does a check id or its category match one of the user's `--only`/`--skip` terms? */
|
|
127
|
-
const matches = (id: CheckId, terms: string[]): boolean => {
|
|
128
|
-
const meta = CHECKS.find((check) => check.id === id);
|
|
129
|
-
const short = shortId(id);
|
|
130
|
-
return terms.some((raw) => {
|
|
131
|
-
const term = raw.trim().toLowerCase();
|
|
132
|
-
return (
|
|
133
|
-
term === short || term === id.toLowerCase() || term === meta?.category
|
|
134
|
-
);
|
|
135
|
-
});
|
|
136
|
-
};
|
|
137
|
-
|
|
138
129
|
/** Audit a built site. */
|
|
139
130
|
export const runAudit = async (options: AuditOptions): Promise<AuditResult> => {
|
|
140
131
|
const { project } = options;
|
|
@@ -203,25 +194,18 @@ export const runAudit = async (options: AuditOptions): Promise<AuditResult> => {
|
|
|
203
194
|
)
|
|
204
195
|
);
|
|
205
196
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
matches(d.code as CheckId, options.only ?? [])
|
|
212
|
-
);
|
|
213
|
-
}
|
|
214
|
-
if (options.skip?.length) {
|
|
215
|
-
// SAFETY: same invariant — every audit diagnostic code is a catalog `CheckId`.
|
|
216
|
-
diagnostics = diagnostics.filter(
|
|
217
|
-
(d) => !matches(d.code as CheckId, options.skip ?? [])
|
|
218
|
-
);
|
|
219
|
-
}
|
|
197
|
+
// SAFETY: audit diagnostics are created through `finding()`, whose codes
|
|
198
|
+
// all come from the check catalog's `CheckId` set.
|
|
199
|
+
const diagnostics = results
|
|
200
|
+
.flat()
|
|
201
|
+
.filter((d) => checkSelected(d.code as CheckId, options));
|
|
220
202
|
|
|
221
203
|
return {
|
|
222
204
|
diagnostics,
|
|
205
|
+
only: options.only,
|
|
223
206
|
origin,
|
|
224
207
|
pages: crawl.pages.length,
|
|
208
|
+
skip: options.skip,
|
|
225
209
|
staticDir,
|
|
226
210
|
tiers,
|
|
227
211
|
};
|
package/src/audit/terms.ts
CHANGED
|
@@ -5,6 +5,29 @@ import type { CheckId } from "./catalog.ts";
|
|
|
5
5
|
export const shortId = (id: CheckId): string =>
|
|
6
6
|
id.replace("BLUME_AUDIT_", "").toLowerCase();
|
|
7
7
|
|
|
8
|
+
/** Does a check id or its category match one of the user's `--only`/`--skip` terms? */
|
|
9
|
+
const matchesTerms = (id: CheckId, terms: readonly string[]): boolean => {
|
|
10
|
+
const meta = CHECKS.find((check) => check.id === id);
|
|
11
|
+
const short = shortId(id);
|
|
12
|
+
return terms.some((raw) => {
|
|
13
|
+
const term = raw.trim().toLowerCase();
|
|
14
|
+
return (
|
|
15
|
+
term === short || term === id.toLowerCase() || term === meta?.category
|
|
16
|
+
);
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Whether `--only` and `--skip` leave a check in: it matches an `--only`
|
|
22
|
+
* term, when any are given, and no `--skip` term.
|
|
23
|
+
*/
|
|
24
|
+
export const checkSelected = (
|
|
25
|
+
id: CheckId,
|
|
26
|
+
filter: { only?: readonly string[]; skip?: readonly string[] }
|
|
27
|
+
): boolean =>
|
|
28
|
+
(!filter.only?.length || matchesTerms(id, filter.only)) &&
|
|
29
|
+
!matchesTerms(id, filter.skip ?? []);
|
|
30
|
+
|
|
8
31
|
/**
|
|
9
32
|
* Every term `--only`/`--skip` accept, as the audit's filter compares them:
|
|
10
33
|
* each check's short id and each category. The full `BLUME_AUDIT_…` id is
|
package/src/audit/url.ts
CHANGED
|
@@ -158,8 +158,8 @@ export const resolveHref = (
|
|
|
158
158
|
// A relative href resolves the way a browser resolves it from the page's
|
|
159
159
|
// canonical URL. `URL` needs an origin to do that, so borrow a placeholder
|
|
160
160
|
// one and keep only the path. The canonical URL is slashless — the generated
|
|
161
|
-
// config sets `trailingSlash: "never"`, Vercel
|
|
162
|
-
// `/docs/api
|
|
161
|
+
// config sets `trailingSlash: "never"`, and Vercel and the dev server
|
|
162
|
+
// redirect `/docs/api/` onto `/docs/api` — so `./auth` there
|
|
163
163
|
// means `/docs/auth`, exactly where a reader's click lands. Content links
|
|
164
164
|
// never hit this: the Markdown pipeline rewrites them root-relative (see
|
|
165
165
|
// `resolveRelativeHref`); what's left is hand-written HTML, which a browser
|
package/src/cli/build-failure.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
|
|
3
|
+
import { basename, dirname, isAbsolute, join, relative, resolve } from "pathe";
|
|
4
|
+
import ts from "typescript";
|
|
1
5
|
import { z } from "zod";
|
|
2
6
|
|
|
7
|
+
import { locateMdxFailure } from "../core/mdx-syntax.ts";
|
|
8
|
+
import type { MdxFailure, MdxFailureSite } from "../core/mdx-syntax.ts";
|
|
9
|
+
import type { BlumeProject } from "../core/project-graph.ts";
|
|
3
10
|
import type { Diagnostic } from "../core/types.ts";
|
|
4
11
|
|
|
5
12
|
/**
|
|
@@ -39,22 +46,231 @@ const blumeErrorSchema = z.looseObject({
|
|
|
39
46
|
}),
|
|
40
47
|
});
|
|
41
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Finds where in an `.mdx` page's files a failure Astro reported with no line
|
|
51
|
+
* happened (see `locateMdxFailure`).
|
|
52
|
+
*/
|
|
53
|
+
export type MdxFailureLocator = (
|
|
54
|
+
file: string,
|
|
55
|
+
failure: MdxFailure
|
|
56
|
+
) => Promise<MdxFailureSite | null>;
|
|
57
|
+
|
|
58
|
+
/** What the report reads besides the error. */
|
|
59
|
+
export interface BuildFailureContext {
|
|
60
|
+
locate?: MdxFailureLocator;
|
|
61
|
+
/** The project root, where the build reads `tsconfig.json`. */
|
|
62
|
+
root?: string;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// The message for a name nothing defines, in V8 (Node) and JavaScriptCore (Bun).
|
|
66
|
+
const UNDEFINED_NAME = [
|
|
67
|
+
/^(?<name>[\w$]+) is not defined$/u,
|
|
68
|
+
/^Can't find variable: (?<name>[\w$]+)$/u,
|
|
69
|
+
];
|
|
70
|
+
// A compiler message that opens with where it failed.
|
|
71
|
+
const POSITIONED = /^\d+:\d+: /u;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* A `{…}` expression in an `.mdx` page that reads a name nothing defines: the
|
|
75
|
+
* page compiles, then throws while it renders. Placed at the expression when
|
|
76
|
+
* the page (or a partial it includes) shows where.
|
|
77
|
+
*/
|
|
78
|
+
const undefinedNameDiagnostic = (
|
|
79
|
+
name: string,
|
|
80
|
+
file: string,
|
|
81
|
+
site: MdxFailureSite | null
|
|
82
|
+
): Diagnostic => {
|
|
83
|
+
const escape =
|
|
84
|
+
"show the braces as text: escape each opening brace (`\\{`) or put it in inline code";
|
|
85
|
+
// `{{name}}` is a Blume variable the site doesn't define.
|
|
86
|
+
const variable = site?.expression === `{{${name}}}`;
|
|
87
|
+
return {
|
|
88
|
+
code: "BLUME_MDX_UNDEFINED_NAME",
|
|
89
|
+
column: site?.column,
|
|
90
|
+
file: site?.file ?? file,
|
|
91
|
+
line: site?.line,
|
|
92
|
+
message: site?.expression
|
|
93
|
+
? `\`${site.expression}\` reads \`${name}\`, which isn't defined, so the page fails to render. In .mdx, \`{…}\` is a JavaScript expression.`
|
|
94
|
+
: `\`${name}\` isn't defined, so the page fails to render. In .mdx, \`{…}\` is a JavaScript expression, and one reads it.`,
|
|
95
|
+
severity: "error",
|
|
96
|
+
suggestion: variable
|
|
97
|
+
? `Define \`${name}\` under \`variables\` in blume.config.ts, or ${escape}.`
|
|
98
|
+
: `To ${escape}. For a value every page shares, define a variable in blume.config.ts and write \`{{name}}\`.`,
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// Vite's message for an `extends` or `references` entry it can't resolve. It
|
|
103
|
+
// names an `extends` package as written, and a path resolved.
|
|
104
|
+
const TSCONFIG_NOT_FOUND = /Tsconfig not found (?<target>\S+?)\.?$/mu;
|
|
105
|
+
|
|
106
|
+
const tsconfigLinksSchema = z.object({
|
|
107
|
+
extends: z.union([z.string(), z.array(z.string())]).optional(),
|
|
108
|
+
references: z.array(z.object({ path: z.string() })).optional(),
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
/** An entry in a tsconfig's `extends` or `references`, as written. */
|
|
112
|
+
interface TsconfigLink {
|
|
113
|
+
key: "extends" | "references";
|
|
114
|
+
written: string;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* The `extends` or `references` entry in the tsconfig at `path` that names
|
|
119
|
+
* `target`: written as is, or resolved from the tsconfig's folder (a
|
|
120
|
+
* reference can name a folder, which means its `tsconfig.json`).
|
|
121
|
+
*/
|
|
122
|
+
const linkTo = (path: string, target: string): TsconfigLink | undefined => {
|
|
123
|
+
const parsed = tsconfigLinksSchema.safeParse(
|
|
124
|
+
ts.readConfigFile(path, ts.sys.readFile).config
|
|
125
|
+
);
|
|
126
|
+
if (!parsed.success) {
|
|
127
|
+
return undefined;
|
|
128
|
+
}
|
|
129
|
+
const names = (written: string): boolean => {
|
|
130
|
+
const resolved = resolve(dirname(path), written);
|
|
131
|
+
return (
|
|
132
|
+
written === target ||
|
|
133
|
+
resolved === target ||
|
|
134
|
+
join(resolved, "tsconfig.json") === target
|
|
135
|
+
);
|
|
136
|
+
};
|
|
137
|
+
const extended = [parsed.data.extends ?? []].flat().find(names);
|
|
138
|
+
if (extended !== undefined) {
|
|
139
|
+
return { key: "extends", written: extended };
|
|
140
|
+
}
|
|
141
|
+
const referenced = (parsed.data.references ?? [])
|
|
142
|
+
.map((reference) => reference.path)
|
|
143
|
+
.find(names);
|
|
144
|
+
return referenced === undefined
|
|
145
|
+
? undefined
|
|
146
|
+
: { key: "references", written: referenced };
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
/** How to fix a tsconfig entry that doesn't resolve. */
|
|
150
|
+
const tsconfigFix = ({ key, written }: TsconfigLink, name: string): string => {
|
|
151
|
+
if (key === "references") {
|
|
152
|
+
return `Create \`${written}\` (a framework's generated tsconfig appears once its prepare or build step runs), or remove it from \`references\` in ${name}.`;
|
|
153
|
+
}
|
|
154
|
+
if (written.startsWith(".") || isAbsolute(written)) {
|
|
155
|
+
return `Restore \`${written}\`, or remove it from \`extends\` in ${name}.`;
|
|
156
|
+
}
|
|
157
|
+
const packageName = written
|
|
158
|
+
.split("/")
|
|
159
|
+
.slice(0, written.startsWith("@") ? 2 : 1)
|
|
160
|
+
.join("/");
|
|
161
|
+
return `Install the package that provides it (\`${packageName}\`), or remove it from \`extends\` in ${name}.`;
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* An `extends` or `references` entry in the project's `tsconfig.json` that
|
|
166
|
+
* doesn't resolve: Vite reads that file while it builds the site, so the
|
|
167
|
+
* build fails in `astro sync` before any page compiles. Placed at the entry's
|
|
168
|
+
* line when the project's own tsconfig names the target.
|
|
169
|
+
*/
|
|
170
|
+
const tsconfigExtendsDiagnostic = (
|
|
171
|
+
target: string,
|
|
172
|
+
root: string | undefined
|
|
173
|
+
): Diagnostic => {
|
|
174
|
+
const found = root
|
|
175
|
+
? ["tsconfig.json", "jsconfig.json"]
|
|
176
|
+
.map((name) => join(root, name))
|
|
177
|
+
.filter((path) => existsSync(path))
|
|
178
|
+
.map((path) => ({ link: linkTo(path, target), path }))
|
|
179
|
+
.find(({ link }) => link !== undefined)
|
|
180
|
+
: undefined;
|
|
181
|
+
const file = found?.path;
|
|
182
|
+
const { key, written } = found?.link ?? { key: "extends", written: target };
|
|
183
|
+
const line = file
|
|
184
|
+
? readFileSync(file, "utf-8")
|
|
185
|
+
.split("\n")
|
|
186
|
+
.findIndex((text) => text.includes(JSON.stringify(written))) + 1
|
|
187
|
+
: 0;
|
|
188
|
+
const name = file ? basename(file) : "tsconfig.json";
|
|
189
|
+
return {
|
|
190
|
+
code: "BLUME_TSCONFIG_EXTENDS",
|
|
191
|
+
file,
|
|
192
|
+
line: line > 0 ? line : undefined,
|
|
193
|
+
message: `${file ? name : "A tsconfig.json in the project"} ${key} \`${written}\`, which can't be found. The build reads the project's ${name} to resolve imports, so it stops here.`,
|
|
194
|
+
severity: "error",
|
|
195
|
+
suggestion: tsconfigFix({ key, written }, name),
|
|
196
|
+
};
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
/** The `extends` target an unresolvable tsconfig names, if `error` is that. */
|
|
200
|
+
const missingTsconfig = (error: Error): string | undefined =>
|
|
201
|
+
(
|
|
202
|
+
TSCONFIG_NOT_FOUND.exec(error.message) ??
|
|
203
|
+
// `astro sync` wraps the resolver's error in its own.
|
|
204
|
+
(error.cause instanceof Error
|
|
205
|
+
? TSCONFIG_NOT_FOUND.exec(error.cause.message)
|
|
206
|
+
: null)
|
|
207
|
+
)?.groups?.target;
|
|
208
|
+
|
|
209
|
+
/** The name a render error says nothing defines, if it says that. */
|
|
210
|
+
const undefinedName = (error: Error): string | undefined =>
|
|
211
|
+
error.name === "ReferenceError"
|
|
212
|
+
? UNDEFINED_NAME.map((pattern) => pattern.exec(error.message)).find(Boolean)
|
|
213
|
+
?.groups?.name
|
|
214
|
+
: undefined;
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Where in an `.mdx` page's files a failure the compiler didn't place
|
|
218
|
+
* happened: a render error the page threw, or a compile error in a partial it
|
|
219
|
+
* includes, which the compiler pins on the page with no `line:column:` in its
|
|
220
|
+
* message. (Bun stamps a `line` of its own on every error, so `loc` can't
|
|
221
|
+
* tell.)
|
|
222
|
+
*/
|
|
223
|
+
const locateFailure = async (
|
|
224
|
+
error: Error,
|
|
225
|
+
page: string,
|
|
226
|
+
name: string | undefined,
|
|
227
|
+
locate: MdxFailureLocator | undefined
|
|
228
|
+
): Promise<MdxFailureSite | null> => {
|
|
229
|
+
if (!locate) {
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
if (name) {
|
|
233
|
+
return await locate(page, { kind: "undefined-name", name });
|
|
234
|
+
}
|
|
235
|
+
return error.name === "MDXError" && !POSITIONED.test(error.message)
|
|
236
|
+
? await locate(page, { kind: "syntax" })
|
|
237
|
+
: null;
|
|
238
|
+
};
|
|
239
|
+
|
|
42
240
|
/** One failure as a diagnostic at the file (and position) it names. */
|
|
43
|
-
const failureDiagnostic = (
|
|
241
|
+
const failureDiagnostic = async (
|
|
242
|
+
error: Error,
|
|
243
|
+
context: BuildFailureContext
|
|
244
|
+
): Promise<Diagnostic> => {
|
|
44
245
|
const raised = blumeErrorSchema.safeParse(error);
|
|
45
246
|
if (raised.success) {
|
|
46
247
|
return raised.data.diagnostic;
|
|
47
248
|
}
|
|
249
|
+
const tsconfig = missingTsconfig(error);
|
|
250
|
+
if (tsconfig) {
|
|
251
|
+
return tsconfigExtendsDiagnostic(tsconfig, context.root);
|
|
252
|
+
}
|
|
48
253
|
const parsed = buildErrorSchema.safeParse(error);
|
|
49
254
|
const { id, loc } = parsed.success ? parsed.data : {};
|
|
255
|
+
const file = loc?.file ?? id;
|
|
256
|
+
const name = undefinedName(error);
|
|
257
|
+
const site = file?.endsWith(".mdx")
|
|
258
|
+
? await locateFailure(error, file, name, context.locate)
|
|
259
|
+
: null;
|
|
260
|
+
if (file?.endsWith(".mdx") && name) {
|
|
261
|
+
return undefinedNameDiagnostic(name, file, site);
|
|
262
|
+
}
|
|
263
|
+
if (site?.diagnostic) {
|
|
264
|
+
return site.diagnostic;
|
|
265
|
+
}
|
|
50
266
|
// A named error (`MDXError`, `CompilerError`) says which step failed.
|
|
51
|
-
const
|
|
267
|
+
const label = error.name === "Error" ? "" : `${error.name}: `;
|
|
52
268
|
return {
|
|
53
269
|
code: "BLUME_BUILD_FAILED",
|
|
54
270
|
column: loc?.column,
|
|
55
|
-
file
|
|
271
|
+
file,
|
|
56
272
|
line: loc?.line,
|
|
57
|
-
message: `${
|
|
273
|
+
message: `${label}${error.message}`,
|
|
58
274
|
severity: "error",
|
|
59
275
|
};
|
|
60
276
|
};
|
|
@@ -66,8 +282,41 @@ const failureDiagnostic = (error: Error): Diagnostic => {
|
|
|
66
282
|
* is a problem in the site, reported at its file, rather than an internal
|
|
67
283
|
* error blaming Blume.
|
|
68
284
|
*/
|
|
69
|
-
export const astroBuildDiagnostics = (
|
|
70
|
-
|
|
285
|
+
export const astroBuildDiagnostics = async (
|
|
286
|
+
rejection: Error,
|
|
287
|
+
context: BuildFailureContext = {}
|
|
288
|
+
): Promise<Diagnostic[]> => {
|
|
289
|
+
const parsed = buildErrorSchema.safeParse(rejection);
|
|
71
290
|
const failures = parsed.success ? (parsed.data.errors ?? []) : [];
|
|
72
|
-
return
|
|
291
|
+
return await Promise.all(
|
|
292
|
+
(failures.length > 0 ? failures : [rejection]).map(
|
|
293
|
+
async (failure) => await failureDiagnostic(failure, context)
|
|
294
|
+
)
|
|
295
|
+
);
|
|
73
296
|
};
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* The locator a build uses: the failing page's source, read with the includes
|
|
300
|
+
* and variables the scan resolved for it.
|
|
301
|
+
*/
|
|
302
|
+
export const buildFailureLocator =
|
|
303
|
+
(
|
|
304
|
+
project: Pick<BlumeProject, "config" | "context" | "graph" | "sources">
|
|
305
|
+
): MdxFailureLocator =>
|
|
306
|
+
(file, failure) => {
|
|
307
|
+
const page = project.graph.pages.find(
|
|
308
|
+
(candidate) => candidate.sourcePath === file
|
|
309
|
+
);
|
|
310
|
+
const source = project.sources.find(
|
|
311
|
+
(candidate) => candidate.name === page?.source.name
|
|
312
|
+
);
|
|
313
|
+
return locateMdxFailure(
|
|
314
|
+
{
|
|
315
|
+
contentRoot: source?.staged ? undefined : source?.contentRoot,
|
|
316
|
+
name: relative(project.context.root, file),
|
|
317
|
+
sourcePath: file,
|
|
318
|
+
variables: project.config.variables,
|
|
319
|
+
},
|
|
320
|
+
failure
|
|
321
|
+
);
|
|
322
|
+
};
|
package/src/cli/command-meta.ts
CHANGED
|
@@ -55,7 +55,7 @@ export const commandMeta = {
|
|
|
55
55
|
},
|
|
56
56
|
migrate: {
|
|
57
57
|
description:
|
|
58
|
-
"Migrate a docs site from Mintlify,
|
|
58
|
+
"Migrate a docs site from Mintlify, Docusaurus, GitBook, MkDocs, ReadMe, or another framework with a coding agent.",
|
|
59
59
|
name: "migrate",
|
|
60
60
|
},
|
|
61
61
|
preview: {
|
|
@@ -12,6 +12,7 @@ import { NoBuildError, runAudit } from "../../audit/run.ts";
|
|
|
12
12
|
import type { AuditResult } from "../../audit/run.ts";
|
|
13
13
|
import { checkTerms, unknownCheckTerms } from "../../audit/terms.ts";
|
|
14
14
|
import { isHttpUrl } from "../../audit/url.ts";
|
|
15
|
+
import { closestMatch } from "../../core/closest-match.ts";
|
|
15
16
|
import { BlumeError } from "../../core/diagnostics.ts";
|
|
16
17
|
import { scanProject } from "../../core/project-graph.ts";
|
|
17
18
|
import type { DiagnosticSeverity } from "../../core/types.ts";
|
|
@@ -19,7 +20,6 @@ import { parseIgnoreFlag } from "../args.ts";
|
|
|
19
20
|
import { commandMeta } from "../command-meta.ts";
|
|
20
21
|
import { reportInternalError } from "../internal-error.ts";
|
|
21
22
|
import { flushStdout, logger, reportDiagnostics } from "../log.ts";
|
|
22
|
-
import { closestMatch } from "../unknown-flags.ts";
|
|
23
23
|
|
|
24
24
|
const SEVERITIES: DiagnosticSeverity[] = ["error", "warning", "info"];
|
|
25
25
|
|
|
@@ -22,7 +22,10 @@ import {
|
|
|
22
22
|
removedBuildFlags,
|
|
23
23
|
removedBuildFlagsAdvice,
|
|
24
24
|
} from "../../upgrade/upgrade.ts";
|
|
25
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
astroBuildDiagnostics,
|
|
27
|
+
buildFailureLocator,
|
|
28
|
+
} from "../build-failure.ts";
|
|
26
29
|
import { commandMeta } from "../command-meta.ts";
|
|
27
30
|
import { refuseIfDevRunning } from "../dev-lock.ts";
|
|
28
31
|
import { refuseIfEjected } from "../eject-scripts.ts";
|
|
@@ -248,7 +251,7 @@ const reportBuild = async (
|
|
|
248
251
|
// count next to the success banner so it can't scroll away unseen.
|
|
249
252
|
if (project.droppedPages > 0) {
|
|
250
253
|
logger.warn(
|
|
251
|
-
`${project.droppedPages} page(s) failed
|
|
254
|
+
`${project.droppedPages} page(s) failed validation and are missing from this build.`
|
|
252
255
|
);
|
|
253
256
|
}
|
|
254
257
|
logger.success(`Built to ${distDir}`);
|
|
@@ -348,7 +351,13 @@ export const buildCommand = defineCommand({
|
|
|
348
351
|
if (error instanceof BlumeError || !(error instanceof Error)) {
|
|
349
352
|
throw error;
|
|
350
353
|
}
|
|
351
|
-
reportDiagnostics(
|
|
354
|
+
reportDiagnostics(
|
|
355
|
+
await astroBuildDiagnostics(error, {
|
|
356
|
+
locate: buildFailureLocator(project),
|
|
357
|
+
root,
|
|
358
|
+
}),
|
|
359
|
+
root
|
|
360
|
+
);
|
|
352
361
|
process.exit(1);
|
|
353
362
|
}
|
|
354
363
|
|
|
@@ -6,10 +6,11 @@ import { defineCommand } from "citty";
|
|
|
6
6
|
import { join } from "pathe";
|
|
7
7
|
|
|
8
8
|
import { ensureGitignore } from "../../core/gitignore.ts";
|
|
9
|
+
import { astroBuildDiagnostics } from "../build-failure.ts";
|
|
9
10
|
import { commandMeta } from "../command-meta.ts";
|
|
10
11
|
import { refuseIfDevRunning } from "../dev-lock.ts";
|
|
11
12
|
import { refuseIfEjected } from "../eject-scripts.ts";
|
|
12
|
-
import { logger } from "../log.ts";
|
|
13
|
+
import { logger, reportDiagnostics } from "../log.ts";
|
|
13
14
|
import { prepareProject } from "../prepare.ts";
|
|
14
15
|
|
|
15
16
|
export const checkCommand = defineCommand({
|
|
@@ -57,7 +58,17 @@ export const checkCommand = defineCommand({
|
|
|
57
58
|
|
|
58
59
|
// Generate Astro's content/collection and font types into `.blume/.astro`
|
|
59
60
|
// so `astro:*` virtual modules resolve during the check.
|
|
60
|
-
|
|
61
|
+
try {
|
|
62
|
+
await sync({ logLevel: "warn", root: outDir });
|
|
63
|
+
} catch (error) {
|
|
64
|
+
// A sync that rejects on the site (a tsconfig `extends` that doesn't
|
|
65
|
+
// resolve, a page Astro can't load) is reported as `blume build` does.
|
|
66
|
+
if (!(error instanceof Error)) {
|
|
67
|
+
throw error;
|
|
68
|
+
}
|
|
69
|
+
reportDiagnostics(await astroBuildDiagnostics(error, { root }), root);
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
61
72
|
|
|
62
73
|
// The project-root tsconfig is what covers the authored `pages/` and config;
|
|
63
74
|
// without it astro check only sees the generated `.blume` project. Falls back
|
package/src/cli/commands/dev.ts
CHANGED
|
@@ -152,7 +152,7 @@ export const devCommand = defineCommand({
|
|
|
152
152
|
if (error instanceof BlumeError || !(error instanceof Error)) {
|
|
153
153
|
throw error;
|
|
154
154
|
}
|
|
155
|
-
reportDiagnostics(astroBuildDiagnostics(error), root);
|
|
155
|
+
reportDiagnostics(await astroBuildDiagnostics(error, { root }), root);
|
|
156
156
|
process.exit(1);
|
|
157
157
|
}
|
|
158
158
|
|
|
@@ -22,6 +22,7 @@ import type { ResolvedConfig } from "../../core/schema.ts";
|
|
|
22
22
|
import { serverFeatures } from "../../core/server-features.ts";
|
|
23
23
|
import type { Diagnostic } from "../../core/types.ts";
|
|
24
24
|
import { unregisteredSnapshotDiagnostics } from "../../core/version-cut.ts";
|
|
25
|
+
import { servedFiles } from "../../deploy/generated-files.ts";
|
|
25
26
|
import { commandMeta } from "../command-meta.ts";
|
|
26
27
|
import { loadEnvFiles } from "../env.ts";
|
|
27
28
|
import { reportInternalError } from "../internal-error.ts";
|
|
@@ -33,7 +34,7 @@ import {
|
|
|
33
34
|
} from "../log.ts";
|
|
34
35
|
import { checkRequiredSecrets } from "../required-secrets.ts";
|
|
35
36
|
|
|
36
|
-
const FALLBACK_NODE_RANGE = ">=22.
|
|
37
|
+
const FALLBACK_NODE_RANGE = ">=22.19.0";
|
|
37
38
|
|
|
38
39
|
/**
|
|
39
40
|
* Plan `components.ts` the way `blume dev`/`build` do, reporting each override
|
|
@@ -142,7 +143,8 @@ export const doctorCommand = defineCommand({
|
|
|
142
143
|
...unregisteredSnapshotDiagnostics(project),
|
|
143
144
|
...validateNavTargets(
|
|
144
145
|
project.graph.navigation,
|
|
145
|
-
navTargetRoutes(project, userPages)
|
|
146
|
+
navTargetRoutes(project, userPages),
|
|
147
|
+
servedFiles(project)
|
|
146
148
|
)
|
|
147
149
|
);
|
|
148
150
|
|
package/src/cli/commands/init.ts
CHANGED
|
@@ -75,9 +75,9 @@ const installScaffold = async (
|
|
|
75
75
|
/**
|
|
76
76
|
* Eject the freshly scaffolded project, or print the install-then-eject path.
|
|
77
77
|
* Eject jiti-loads the scaffolded blume.config.ts, whose `import { defineConfig }
|
|
78
|
-
* from "blume"`
|
|
79
|
-
*
|
|
80
|
-
*
|
|
78
|
+
* from "blume"` resolves to the running Blume package even before an install
|
|
79
|
+
* (see `blumeModuleAliases`). When eject still fails after a skipped install,
|
|
80
|
+
* the fallback below names the install as the likely fix.
|
|
81
81
|
*/
|
|
82
82
|
const ejectScaffold = async (
|
|
83
83
|
root: string,
|
|
@@ -4,15 +4,19 @@ import { preview } from "astro";
|
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
5
|
import { join } from "pathe";
|
|
6
6
|
|
|
7
|
+
import { normalizeBasePath } from "../../core/base-path.ts";
|
|
7
8
|
import { loadConfig } from "../../core/config.ts";
|
|
8
9
|
import { resolveProjectContext } from "../../core/project.ts";
|
|
10
|
+
import { publicFolder } from "../../core/static-host.ts";
|
|
9
11
|
import { deployOutputDir } from "../../deploy/adapter-output.ts";
|
|
10
12
|
import { deployPlatform } from "../../deploy/platforms/index.ts";
|
|
13
|
+
import { distDir } from "../../deploy/platforms/paths.ts";
|
|
11
14
|
import { parsePort } from "../args.ts";
|
|
12
15
|
import { commandMeta } from "../command-meta.ts";
|
|
13
16
|
import { refuseIfEjected } from "../eject-scripts.ts";
|
|
14
17
|
import { normalizeHost } from "../host-args.ts";
|
|
15
18
|
import { logger } from "../log.ts";
|
|
19
|
+
import { previewRedirects, servePreview } from "../preview-pages.ts";
|
|
16
20
|
|
|
17
21
|
export const previewCommand = defineCommand({
|
|
18
22
|
args: {
|
|
@@ -48,7 +52,7 @@ export const previewCommand = defineCommand({
|
|
|
48
52
|
process.exit(1);
|
|
49
53
|
}
|
|
50
54
|
|
|
51
|
-
await preview({
|
|
55
|
+
const server = await preview({
|
|
52
56
|
logLevel: "info",
|
|
53
57
|
root: context.outDir,
|
|
54
58
|
server: {
|
|
@@ -58,5 +62,17 @@ export const previewCommand = defineCommand({
|
|
|
58
62
|
port: parsePort(args.port),
|
|
59
63
|
},
|
|
60
64
|
});
|
|
65
|
+
// A static build is served by Vite, which knows nothing of the host's
|
|
66
|
+
// redirect rules or trailing-slash handling, and whose HTML fallback
|
|
67
|
+
// would answer a page with the redirect page of a redirect from its
|
|
68
|
+
// `.html` URL.
|
|
69
|
+
if (deployment.options.output === "static") {
|
|
70
|
+
servePreview(server, {
|
|
71
|
+
base: normalizeBasePath(deployment.options.base),
|
|
72
|
+
distDir: distDir(context),
|
|
73
|
+
isPublicFolder: publicFolder(join(context.root, "public")),
|
|
74
|
+
redirects: previewRedirects(config, context.outDir),
|
|
75
|
+
});
|
|
76
|
+
}
|
|
61
77
|
},
|
|
62
78
|
});
|