blume 2.1.0 → 2.1.2
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/CHANGELOG.md +110 -0
- package/dist/cli/{chunk-ga0pf4aj.js → chunk-0n9xkp3d.js} +12 -3
- package/dist/cli/{chunk-ga0pf4aj.js.map → chunk-0n9xkp3d.js.map} +3 -3
- package/dist/cli/{chunk-43zcf4gz.js → chunk-0pmb4tr4.js} +541 -368
- package/dist/cli/chunk-0pmb4tr4.js.map +35 -0
- package/dist/cli/{chunk-9geymqns.js → chunk-0w6hs479.js} +15 -15
- package/dist/cli/{chunk-xkz5xbtv.js → chunk-124fvmzq.js} +2802 -1422
- package/dist/cli/chunk-124fvmzq.js.map +220 -0
- package/dist/cli/chunk-150jk7km.js +52 -0
- package/dist/cli/chunk-150jk7km.js.map +10 -0
- package/dist/cli/{chunk-y4ykbark.js → chunk-1f882900.js} +2 -2
- package/dist/cli/{chunk-5ffywsmb.js → chunk-297ajdcv.js} +8 -6
- package/dist/cli/{chunk-5ffywsmb.js.map → chunk-297ajdcv.js.map} +3 -3
- package/dist/cli/{chunk-h2a48yhd.js → chunk-32khwcb6.js} +120 -16
- package/dist/cli/{chunk-h2a48yhd.js.map → chunk-32khwcb6.js.map} +10 -10
- package/dist/cli/{chunk-5cg2rzgf.js → chunk-36bxs9c7.js} +20 -49
- package/dist/cli/{chunk-5cg2rzgf.js.map → chunk-36bxs9c7.js.map} +4 -5
- package/dist/cli/{chunk-py62fewh.js → chunk-53jqw8z0.js} +3 -3
- package/dist/cli/{chunk-5wj2qwn2.js → chunk-58bt3hag.js} +4 -4
- package/dist/cli/{chunk-e7vvk5ya.js → chunk-5cmts6dv.js} +3 -3
- package/dist/cli/{chunk-y5h4r2y0.js → chunk-60hz265r.js} +15 -5
- package/dist/cli/chunk-60hz265r.js.map +10 -0
- package/dist/cli/chunk-74wfhv79.js +65 -0
- package/dist/cli/chunk-74wfhv79.js.map +10 -0
- package/dist/cli/{chunk-g2z9x01v.js → chunk-9qzgg6mj.js} +3 -3
- package/dist/cli/{chunk-q3wxxq39.js → chunk-a57yh0h9.js} +5 -5
- package/dist/cli/{chunk-713mngdq.js → chunk-ave1wcbr.js} +76 -10
- package/dist/cli/chunk-ave1wcbr.js.map +14 -0
- package/dist/cli/{chunk-2n4ps1b3.js → chunk-bqxaqn5p.js} +40 -22
- package/dist/cli/chunk-bqxaqn5p.js.map +15 -0
- package/dist/cli/{chunk-jnwj5kjj.js → chunk-bxwhtvw8.js} +20 -7
- package/dist/cli/{chunk-jnwj5kjj.js.map → chunk-bxwhtvw8.js.map} +3 -3
- package/dist/cli/chunk-ckrcm08h.js +324 -0
- package/dist/cli/chunk-ckrcm08h.js.map +14 -0
- package/dist/cli/{chunk-2f3ndkpw.js → chunk-desvm72z.js} +3 -3
- package/dist/cli/{chunk-gp84za0h.js → chunk-dhwtqnnd.js} +2 -2
- package/dist/cli/{chunk-4h8z9vv5.js → chunk-dpy8qdjf.js} +93 -47
- package/dist/cli/chunk-dpy8qdjf.js.map +17 -0
- package/dist/cli/{chunk-2f7n4qzt.js → chunk-dqhg54mr.js} +1 -1
- package/dist/cli/{chunk-0gz36akr.js → chunk-dv2z0rzf.js} +21 -5
- package/dist/cli/chunk-dv2z0rzf.js.map +12 -0
- package/dist/cli/{chunk-cm89scdv.js → chunk-es8h0v3j.js} +9 -11
- package/dist/cli/{chunk-cm89scdv.js.map → chunk-es8h0v3j.js.map} +3 -3
- package/dist/cli/{chunk-zhvd6adm.js → chunk-gfc5fqvf.js} +14 -14
- package/dist/cli/{chunk-nd1821sk.js → chunk-gxtg6ed2.js} +33 -19
- package/dist/cli/chunk-gxtg6ed2.js.map +10 -0
- package/dist/cli/{chunk-p804f3pe.js → chunk-hvcxng5f.js} +6 -6
- package/dist/cli/{chunk-ta27feev.js → chunk-j1x92mx9.js} +21 -2
- package/dist/cli/chunk-j1x92mx9.js.map +10 -0
- package/dist/cli/{chunk-rekqz4qg.js → chunk-k3gr1nm9.js} +19 -16
- package/dist/cli/chunk-k3gr1nm9.js.map +10 -0
- package/dist/cli/{chunk-1n228xqb.js → chunk-kdpzw38a.js} +2 -2
- package/dist/cli/{chunk-cy5bm0j0.js → chunk-ms9z66nz.js} +2 -2
- package/dist/cli/{chunk-cy5bm0j0.js.map → chunk-ms9z66nz.js.map} +2 -2
- package/dist/cli/{chunk-zf748avv.js → chunk-nbyvgnnm.js} +193 -286
- package/dist/cli/chunk-nbyvgnnm.js.map +36 -0
- package/dist/cli/{chunk-6bm0xpgd.js → chunk-s0bdnc7v.js} +2 -2
- package/dist/cli/{chunk-yxmk4pec.js → chunk-sc93apfs.js} +17 -16
- package/dist/cli/{chunk-yxmk4pec.js.map → chunk-sc93apfs.js.map} +3 -3
- package/dist/cli/{chunk-cmtcnh9f.js → chunk-tfycddbt.js} +2 -2
- package/dist/cli/{chunk-9xr4dgee.js → chunk-twy7psdz.js} +29 -16
- package/dist/cli/chunk-twy7psdz.js.map +10 -0
- package/dist/cli/{chunk-ntv4qrt7.js → chunk-y4msrwm9.js} +15 -15
- package/dist/cli/{chunk-yj17vs39.js → chunk-ydp3065p.js} +5 -5
- package/dist/cli/index.js +24 -19
- package/dist/cli/index.js.map +3 -3
- package/dist/types/ai/ask-context.d.ts +6 -2
- package/dist/types/ai/ask.d.ts +24 -5
- package/dist/types/ai/component-markdown.d.ts +2 -0
- package/dist/types/ai/openapi-components.d.ts +4 -1
- package/dist/types/analytics/clics.d.ts +37 -0
- package/dist/types/analytics/index.d.ts +2 -0
- package/dist/types/analytics/schema.d.ts +18 -0
- package/dist/types/astro/integration.d.ts +11 -4
- package/dist/types/astro/markdown-negotiation.d.ts +3 -0
- package/dist/types/astro/pages.d.ts +10 -0
- package/dist/types/cli/init/scaffold.d.ts +1 -1
- package/dist/types/components/content/api-field.d.ts +4 -1
- package/dist/types/components/content/api-page.d.ts +6 -1
- package/dist/types/components/openapi/code-samples.d.ts +29 -0
- package/dist/types/components/openapi/helpers.d.ts +22 -1
- package/dist/types/components/openapi/security.d.ts +10 -0
- package/dist/types/components/openapi/snippets.d.ts +60 -0
- package/dist/types/core/changelog-index.d.ts +8 -0
- package/dist/types/core/config-input.d.ts +37 -6
- package/dist/types/core/data.d.ts +4 -0
- package/dist/types/core/i18n-ui.d.ts +2 -0
- package/dist/types/core/links.d.ts +8 -0
- package/dist/types/core/powered-by.d.ts +12 -0
- package/dist/types/core/probe.d.ts +2 -0
- package/dist/types/core/project-graph.d.ts +6 -0
- package/dist/types/core/redirect-patterns.d.ts +11 -3
- package/dist/types/core/schema.d.ts +228 -3
- package/dist/types/core/sources/cache.d.ts +3 -0
- package/dist/types/core/sources/contentful-rich-text.d.ts +11 -2
- package/dist/types/core/sources/contentful.d.ts +17 -1
- package/dist/types/core/sources/lexical.d.ts +5 -0
- package/dist/types/core/sources/lower.d.ts +10 -2
- package/dist/types/core/sources/normalize.d.ts +20 -1
- package/dist/types/core/sources/notion.d.ts +8 -0
- package/dist/types/core/sources/remote.d.ts +37 -10
- package/dist/types/core/sources/sanity.d.ts +1 -1
- package/dist/types/core/types.d.ts +17 -0
- package/dist/types/deploy/adapter-output.d.ts +2 -1
- package/dist/types/deploy/adapters/cloudflare.d.ts +7 -5
- package/dist/types/deploy/adapters/node.d.ts +58 -23
- package/dist/types/deploy/adapters/registry.d.ts +10 -0
- package/dist/types/deploy/adapters/types.d.ts +3 -2
- package/dist/types/deploy/cloudflare-negotiation.d.ts +5 -2
- package/dist/types/deploy/node-headers.d.ts +12 -4
- package/dist/types/deploy/platforms/cloudflare.d.ts +10 -7
- package/dist/types/deploy/platforms/node.d.ts +3 -1
- package/dist/types/deploy/platforms/types.d.ts +18 -7
- package/dist/types/deploy/platforms/vercel.d.ts +21 -2
- package/dist/types/deploy/redirects.d.ts +17 -1
- package/dist/types/deploy/sitemap.d.ts +2 -1
- package/dist/types/deploy/vercel-negotiation.d.ts +44 -21
- package/dist/types/narration/build.d.ts +34 -12
- package/dist/types/narration/provider.d.ts +96 -8
- package/dist/types/openapi/checks.d.ts +27 -0
- package/dist/types/openapi/graphql.d.ts +6 -0
- package/dist/types/openapi/model.d.ts +15 -4
- package/dist/types/openapi/parse.d.ts +3 -0
- package/dist/types/openapi/references.d.ts +16 -0
- package/dist/types/openapi/sentence.d.ts +11 -1
- package/dist/types/ratelimit/index.d.ts +1 -1
- package/dist/types/ratelimit/schema.d.ts +8 -0
- package/dist/types/ratelimit/upstash.d.ts +39 -14
- package/dist/types/reference/graphql.d.ts +76 -1
- package/dist/types/reference/index.d.ts +1 -1
- package/dist/types/reference/openapi.d.ts +2 -2
- package/dist/types/reference/options.d.ts +37 -1
- package/dist/types/reference/schema.d.ts +84 -0
- package/dist/types/search/adapters/registry.d.ts +3 -0
- package/dist/types/search/adapters/typesense.d.ts +14 -4
- package/dist/types/search/build.d.ts +3 -1
- package/dist/types/search/orama-index.d.ts +9 -9
- package/dist/types/search/sync/algolia.d.ts +5 -2
- package/dist/types/search/sync/index.d.ts +3 -1
- package/dist/types/search/sync/typesense.d.ts +11 -7
- package/dist/types/seo/jsonld.d.ts +11 -6
- package/dist/types/sources/contentful.d.ts +16 -0
- package/dist/types/sources/github-releases.d.ts +8 -1
- package/dist/types/sources/notion.d.ts +8 -0
- package/dist/types/sources/payload.d.ts +2 -0
- package/dist/types/sources/registry.d.ts +63 -0
- package/dist/types/sources/shared.d.ts +3 -0
- package/dist/types/sources/strapi.d.ts +2 -0
- package/docs/01-quickstart.mdx +4 -2
- package/docs/02-deployment.mdx +59 -13
- package/docs/03-upgrading.mdx +2 -1
- package/docs/04-migrating.mdx +9 -9
- package/docs/08-faq.mdx +12 -12
- package/docs/advanced/changelog.mdx +30 -2
- package/docs/advanced/custom-pages.mdx +1 -1
- package/docs/advanced/skills.mdx +1 -1
- package/docs/cli/audit.mdx +30 -7
- package/docs/cli/doctor.mdx +6 -2
- package/docs/cli/evals.mdx +4 -4
- package/docs/cli/translate.mdx +1 -0
- package/docs/cli/validate.mdx +4 -3
- package/docs/configuration/analytics.mdx +19 -1
- package/docs/configuration/assistant.mdx +6 -2
- package/docs/configuration/customization.mdx +4 -2
- package/docs/configuration/export.mdx +5 -3
- package/docs/configuration/index.mdx +4 -2
- package/docs/configuration/narration.mdx +43 -6
- package/docs/configuration/rate-limiting.mdx +23 -2
- package/docs/configuration/search.mdx +37 -14
- package/docs/content/components.mdx +2 -2
- package/docs/content/frontmatter.mdx +5 -3
- package/docs/content/i18n.mdx +2 -2
- package/docs/content/includes.mdx +1 -1
- package/docs/content/navigation.mdx +8 -6
- package/docs/content/sources/contentful.mdx +9 -4
- package/docs/content/sources/custom.mdx +7 -3
- package/docs/content/sources/github-releases.mdx +12 -2
- package/docs/content/sources/index.mdx +3 -3
- package/docs/content/sources/notion.mdx +17 -2
- package/docs/content/sources/obsidian.mdx +3 -1
- package/docs/content/sources/payload.mdx +5 -2
- package/docs/content/sources/remote-mdx.mdx +6 -0
- package/docs/content/sources/sanity.mdx +4 -2
- package/docs/content/sources/strapi.mdx +5 -2
- package/docs/content/syntax.mdx +2 -2
- package/docs/discoverability/agent-discovery.mdx +1 -1
- package/docs/discoverability/index.mdx +1 -1
- package/docs/discoverability/json-api.mdx +2 -0
- package/docs/discoverability/llms-txt.mdx +1 -1
- package/docs/discoverability/markdown.mdx +3 -1
- package/docs/discoverability/mcp.mdx +6 -0
- package/docs/discoverability/sitemap-and-robots.mdx +1 -1
- package/docs/discoverability/structured-data.mdx +8 -6
- package/docs/references/api-pages.mdx +1 -1
- package/docs/references/asyncapi.mdx +5 -1
- package/docs/references/graphql.mdx +15 -1
- package/docs/references/openapi.mdx +64 -8
- package/package.json +9 -9
- package/skills/blume/SKILL.md +1 -1
- package/skills/blume-migrate/SKILL.md +2 -2
- package/skills/blume-migrate/assets/{oxfmt@0.67.0.patch → oxfmt@0.71.0.patch} +7 -7
- package/skills/blume-migrate/references/docusaurus.md +4 -4
- package/skills/blume-migrate/references/fumadocs.md +17 -13
- package/skills/blume-migrate/references/monorepo.md +5 -5
- package/skills/blume-migrate/references/nextra.md +8 -5
- package/skills/blume-migrate/references/starlight.md +9 -7
- package/src/ai/ask-context.ts +33 -3
- package/src/ai/ask-limits.ts +13 -0
- package/src/ai/ask.ts +24 -6
- package/src/ai/changelog-markdown.ts +11 -6
- package/src/ai/component-markdown.ts +1 -1
- package/src/ai/cors.ts +12 -3
- package/src/ai/mcp/query.ts +14 -6
- package/src/ai/openapi-components.ts +28 -4
- package/src/ai/relative-links.ts +4 -38
- package/src/analytics/clics.ts +58 -0
- package/src/analytics/head.ts +5 -0
- package/src/analytics/index.ts +2 -0
- package/src/analytics/schema.ts +2 -0
- package/src/astro/generate.ts +91 -56
- package/src/astro/integration.ts +72 -22
- package/src/astro/markdown-negotiation.ts +3 -0
- package/src/astro/module-types.ts +3 -1
- package/src/astro/pages.ts +23 -0
- package/src/astro/render-deps.ts +10 -5
- package/src/astro/runtime-deps.ts +23 -2
- package/src/astro/templates.ts +129 -81
- package/src/audit/catalog.ts +19 -3
- package/src/audit/checks/links.ts +14 -1
- package/src/audit/checks/network.ts +110 -6
- package/src/audit/checks/redirects.ts +6 -4
- package/src/audit/checks/robots.ts +58 -2
- package/src/audit/run.ts +3 -0
- package/src/audit/types.ts +2 -0
- package/src/audit/url.ts +14 -5
- package/src/blume-modules.d.ts +5 -1
- package/src/cli/args.ts +51 -0
- package/src/cli/build-failure.ts +23 -0
- package/src/cli/commands/audit.ts +10 -1
- package/src/cli/commands/dev.ts +18 -2
- package/src/cli/commands/doctor.ts +45 -12
- package/src/cli/commands/eval.ts +36 -4
- package/src/cli/commands/init.ts +6 -4
- package/src/cli/commands/validate.ts +10 -1
- package/src/cli/init/scaffold.ts +9 -6
- package/src/cli/prepare.ts +6 -3
- package/src/cli/required-secrets.ts +3 -2
- package/src/components/content/ApiPlayground.astro +6 -2
- package/src/components/content/api-field.ts +4 -1
- package/src/components/content/api-page.ts +31 -7
- package/src/components/content/mermaid-element.ts +15 -1
- package/src/components/content/view-switcher.ts +7 -4
- package/src/components/islands/hooks.ts +27 -1
- package/src/components/layout/NavTree.astro +49 -5
- package/src/components/layout/NavTreeScript.astro +18 -0
- package/src/components/layout/PageActions.astro +139 -24
- package/src/components/layout/PageLayout.astro +13 -3
- package/src/components/layout/RootLayout.astro +27 -14
- package/src/components/layout/Search.astro +17 -3
- package/src/components/layout/TableOfContents.astro +24 -17
- package/src/components/layout/analytics-client.ts +8 -8
- package/src/components/layout/head-scripts.ts +6 -1
- package/src/components/layout/search/algolia.ts +10 -1
- package/src/components/layout/search/analytics.ts +42 -14
- package/src/components/layout/search/endpoint.ts +48 -5
- package/src/components/layout/search/pagefind.ts +114 -5
- package/src/components/layout/search/types.ts +12 -0
- package/src/components/layout/search/typesense.ts +18 -6
- package/src/components/openapi/AsyncApiOperation.astro +14 -7
- package/src/components/openapi/Authorization.astro +10 -0
- package/src/components/openapi/GraphqlOperation.astro +5 -0
- package/src/components/openapi/Operation.astro +24 -1
- package/src/components/openapi/ParametersTable.astro +8 -4
- package/src/components/openapi/Playground.astro +7 -1
- package/src/components/openapi/RequestBody.astro +19 -2
- package/src/components/openapi/Responses.astro +1 -0
- package/src/components/openapi/SchemaTable.astro +15 -3
- package/src/components/openapi/async-snippets.ts +61 -5
- package/src/components/openapi/async.ts +123 -29
- package/src/components/openapi/graphql-helpers.ts +35 -12
- package/src/components/openapi/helpers.ts +36 -2
- package/src/components/openapi/message-model.ts +54 -11
- package/src/components/openapi/message.ts +14 -4
- package/src/components/openapi/operation-model.ts +16 -7
- package/src/components/openapi/playground-client.ts +77 -58
- package/src/components/openapi/playground-schema.ts +1 -1
- package/src/components/openapi/schema-tree.ts +44 -14
- package/src/components/openapi/security.ts +10 -0
- package/src/components/openapi/snippets.ts +5 -3
- package/src/components/openapi/validate-json.ts +4 -3
- package/src/components/powered-by-middleware.ts +33 -0
- package/src/core/changelog-index.ts +31 -1
- package/src/core/component-diagnostics.ts +53 -0
- package/src/core/component-overrides.ts +32 -0
- package/src/core/config-input.ts +42 -6
- package/src/core/data.ts +2 -0
- package/src/core/diagnostics.ts +5 -0
- package/src/core/i18n-ui.ts +2 -0
- package/src/core/includes.ts +1 -1
- package/src/core/links.ts +47 -17
- package/src/core/powered-by.ts +12 -0
- package/src/core/probe.ts +26 -6
- package/src/core/project-graph.ts +59 -18
- package/src/core/redirect-patterns.ts +36 -7
- package/src/core/schema.ts +26 -6
- package/src/core/sources/cache.ts +6 -0
- package/src/core/sources/contentful-rich-text.ts +29 -6
- package/src/core/sources/contentful.ts +135 -25
- package/src/core/sources/filesystem.ts +26 -4
- package/src/core/sources/github-releases.ts +12 -1
- package/src/core/sources/lexical.ts +15 -10
- package/src/core/sources/lower.ts +19 -3
- package/src/core/sources/mdx-remote.ts +62 -10
- package/src/core/sources/normalize.ts +227 -41
- package/src/core/sources/notion.ts +34 -10
- package/src/core/sources/obsidian.ts +16 -3
- package/src/core/sources/payload.ts +38 -15
- package/src/core/sources/remote.ts +72 -15
- package/src/core/sources/resolve.ts +11 -1
- package/src/core/sources/sanity.ts +43 -25
- package/src/core/sources/strapi.ts +2 -2
- package/src/core/types.ts +18 -0
- package/src/core/ui-packs/ar.ts +1 -0
- package/src/core/ui-packs/bg.ts +1 -0
- package/src/core/ui-packs/bn.ts +1 -0
- package/src/core/ui-packs/ca.ts +1 -0
- package/src/core/ui-packs/cs.ts +1 -0
- package/src/core/ui-packs/da.ts +1 -0
- package/src/core/ui-packs/de.ts +1 -0
- package/src/core/ui-packs/el.ts +1 -0
- package/src/core/ui-packs/es.ts +1 -0
- package/src/core/ui-packs/fa.ts +1 -0
- package/src/core/ui-packs/fi.ts +1 -0
- package/src/core/ui-packs/fr.ts +1 -0
- package/src/core/ui-packs/he.ts +1 -0
- package/src/core/ui-packs/hi.ts +1 -0
- package/src/core/ui-packs/hr.ts +1 -0
- package/src/core/ui-packs/hu.ts +1 -0
- package/src/core/ui-packs/id.ts +1 -0
- package/src/core/ui-packs/it.ts +1 -0
- package/src/core/ui-packs/ja.ts +1 -0
- package/src/core/ui-packs/ko.ts +1 -0
- package/src/core/ui-packs/nl.ts +1 -0
- package/src/core/ui-packs/no.ts +1 -0
- package/src/core/ui-packs/pl.ts +1 -0
- package/src/core/ui-packs/pt-br.ts +1 -0
- package/src/core/ui-packs/pt.ts +1 -0
- package/src/core/ui-packs/ro.ts +1 -0
- package/src/core/ui-packs/ru.ts +1 -0
- package/src/core/ui-packs/sk.ts +1 -0
- package/src/core/ui-packs/sr.ts +1 -0
- package/src/core/ui-packs/sv.ts +1 -0
- package/src/core/ui-packs/th.ts +1 -0
- package/src/core/ui-packs/tr.ts +1 -0
- package/src/core/ui-packs/uk.ts +1 -0
- package/src/core/ui-packs/vi.ts +1 -0
- package/src/core/ui-packs/zh-tw.ts +1 -0
- package/src/core/ui-packs/zh.ts +1 -0
- package/src/deploy/adapter-output.ts +7 -2
- package/src/deploy/adapters/cloudflare.ts +7 -5
- package/src/deploy/adapters/node.ts +47 -9
- package/src/deploy/adapters/types.ts +7 -3
- package/src/deploy/artifacts.ts +2 -1
- package/src/deploy/cloudflare-negotiation.ts +36 -7
- package/src/deploy/headers.ts +15 -1
- package/src/deploy/node-headers.ts +32 -20
- package/src/deploy/platforms/cloudflare.ts +14 -9
- package/src/deploy/platforms/netlify.ts +2 -1
- package/src/deploy/platforms/node.ts +12 -2
- package/src/deploy/platforms/types.ts +21 -7
- package/src/deploy/platforms/vercel.ts +115 -17
- package/src/deploy/redirects.ts +66 -6
- package/src/deploy/rss.ts +3 -1
- package/src/deploy/sitemap.ts +39 -5
- package/src/deploy/vercel-negotiation.ts +325 -103
- package/src/eval/agents.ts +18 -1
- package/src/eval/prompts.ts +6 -3
- package/src/eval/report.ts +34 -13
- package/src/eval/run.ts +5 -0
- package/src/markdown/base-links.ts +15 -14
- package/src/markdown/package-commands.ts +9 -8
- package/src/markdown/relative-links.ts +3 -2
- package/src/narration/build.ts +218 -40
- package/src/narration/provider.ts +89 -9
- package/src/openapi/checks.ts +273 -0
- package/src/openapi/graphql-build.ts +21 -0
- package/src/openapi/graphql.ts +11 -0
- package/src/openapi/model.ts +15 -3
- package/src/openapi/parse.ts +127 -2
- package/src/openapi/references.ts +43 -3
- package/src/openapi/render-mdx.ts +68 -8
- package/src/openapi/sentence.ts +29 -2
- package/src/openapi/source.ts +39 -14
- package/src/ratelimit/index.ts +1 -1
- package/src/ratelimit/runtime.ts +37 -19
- package/src/ratelimit/upstash.ts +40 -10
- package/src/reference/graphql.ts +15 -1
- package/src/reference/index.ts +1 -0
- package/src/reference/openapi.ts +2 -2
- package/src/reference/options.ts +29 -1
- package/src/registry/eject.ts +8 -2
- package/src/search/adapters/locale-scope.ts +30 -0
- package/src/search/adapters/typesense.ts +14 -4
- package/src/search/build.ts +21 -3
- package/src/search/orama-index.ts +163 -31
- package/src/search/source-pages.ts +29 -0
- package/src/search/sync/algolia.ts +99 -9
- package/src/search/sync/index.ts +52 -13
- package/src/search/sync/typesense.ts +72 -27
- package/src/seo/jsonld.ts +38 -20
- package/src/sources/contentful.ts +12 -0
- package/src/sources/github-releases.ts +7 -1
- package/src/sources/notion.ts +7 -0
- package/src/sources/shared.ts +3 -0
- package/src/theme/color.ts +9 -10
- package/src/theme/entry.ts +43 -6
- package/src/translate/validate.ts +23 -1
- package/dist/cli/chunk-0gz36akr.js.map +0 -12
- package/dist/cli/chunk-2n4ps1b3.js.map +0 -15
- package/dist/cli/chunk-43zcf4gz.js.map +0 -36
- package/dist/cli/chunk-4ejxbzee.js +0 -39
- package/dist/cli/chunk-4ejxbzee.js.map +0 -10
- package/dist/cli/chunk-4h8z9vv5.js.map +0 -16
- package/dist/cli/chunk-713mngdq.js.map +0 -14
- package/dist/cli/chunk-9xr4dgee.js.map +0 -10
- package/dist/cli/chunk-amrb6hgh.js +0 -145
- package/dist/cli/chunk-amrb6hgh.js.map +0 -11
- package/dist/cli/chunk-nd1821sk.js.map +0 -10
- package/dist/cli/chunk-rekqz4qg.js.map +0 -10
- package/dist/cli/chunk-ta27feev.js.map +0 -10
- package/dist/cli/chunk-xkz5xbtv.js.map +0 -213
- package/dist/cli/chunk-y5h4r2y0.js.map +0 -10
- package/dist/cli/chunk-zf748avv.js.map +0 -37
- /package/dist/cli/{chunk-9geymqns.js.map → chunk-0w6hs479.js.map} +0 -0
- /package/dist/cli/{chunk-y4ykbark.js.map → chunk-1f882900.js.map} +0 -0
- /package/dist/cli/{chunk-py62fewh.js.map → chunk-53jqw8z0.js.map} +0 -0
- /package/dist/cli/{chunk-5wj2qwn2.js.map → chunk-58bt3hag.js.map} +0 -0
- /package/dist/cli/{chunk-e7vvk5ya.js.map → chunk-5cmts6dv.js.map} +0 -0
- /package/dist/cli/{chunk-g2z9x01v.js.map → chunk-9qzgg6mj.js.map} +0 -0
- /package/dist/cli/{chunk-q3wxxq39.js.map → chunk-a57yh0h9.js.map} +0 -0
- /package/dist/cli/{chunk-2f3ndkpw.js.map → chunk-desvm72z.js.map} +0 -0
- /package/dist/cli/{chunk-gp84za0h.js.map → chunk-dhwtqnnd.js.map} +0 -0
- /package/dist/cli/{chunk-2f7n4qzt.js.map → chunk-dqhg54mr.js.map} +0 -0
- /package/dist/cli/{chunk-zhvd6adm.js.map → chunk-gfc5fqvf.js.map} +0 -0
- /package/dist/cli/{chunk-p804f3pe.js.map → chunk-hvcxng5f.js.map} +0 -0
- /package/dist/cli/{chunk-1n228xqb.js.map → chunk-kdpzw38a.js.map} +0 -0
- /package/dist/cli/{chunk-6bm0xpgd.js.map → chunk-s0bdnc7v.js.map} +0 -0
- /package/dist/cli/{chunk-cmtcnh9f.js.map → chunk-tfycddbt.js.map} +0 -0
- /package/dist/cli/{chunk-ntv4qrt7.js.map → chunk-y4msrwm9.js.map} +0 -0
- /package/dist/cli/{chunk-yj17vs39.js.map → chunk-ydp3065p.js.map} +0 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/cli/build-failure.ts
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
var buildErrorSchema = z.looseObject({
|
|
6
|
+
errors: z.array(z.instanceof(Error)).optional(),
|
|
7
|
+
id: z.string().optional(),
|
|
8
|
+
loc: z.looseObject({
|
|
9
|
+
column: z.number().optional(),
|
|
10
|
+
file: z.string().optional(),
|
|
11
|
+
line: z.number().optional()
|
|
12
|
+
}).optional()
|
|
13
|
+
});
|
|
14
|
+
var blumeErrorSchema = z.looseObject({
|
|
15
|
+
diagnostic: z.object({
|
|
16
|
+
code: z.string(),
|
|
17
|
+
column: z.number().optional(),
|
|
18
|
+
docsUrl: z.string().optional(),
|
|
19
|
+
file: z.string().optional(),
|
|
20
|
+
line: z.number().optional(),
|
|
21
|
+
message: z.string(),
|
|
22
|
+
severity: z.enum(["error", "info", "warning"]),
|
|
23
|
+
suggestion: z.string().optional()
|
|
24
|
+
})
|
|
25
|
+
});
|
|
26
|
+
var failureDiagnostic = (error) => {
|
|
27
|
+
const raised = blumeErrorSchema.safeParse(error);
|
|
28
|
+
if (raised.success) {
|
|
29
|
+
return raised.data.diagnostic;
|
|
30
|
+
}
|
|
31
|
+
const parsed = buildErrorSchema.safeParse(error);
|
|
32
|
+
const { id, loc } = parsed.success ? parsed.data : {};
|
|
33
|
+
const name = error.name === "Error" ? "" : `${error.name}: `;
|
|
34
|
+
return {
|
|
35
|
+
code: "BLUME_BUILD_FAILED",
|
|
36
|
+
column: loc?.column,
|
|
37
|
+
file: loc?.file ?? id,
|
|
38
|
+
line: loc?.line,
|
|
39
|
+
message: `${name}${error.message}`,
|
|
40
|
+
severity: "error"
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
var astroBuildDiagnostics = (error) => {
|
|
44
|
+
const parsed = buildErrorSchema.safeParse(error);
|
|
45
|
+
const failures = parsed.success ? parsed.data.errors ?? [] : [];
|
|
46
|
+
return (failures.length > 0 ? failures : [error]).map(failureDiagnostic);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export { astroBuildDiagnostics };
|
|
50
|
+
|
|
51
|
+
//# debugId=1B83F4391B57E32464756E2164756E21
|
|
52
|
+
//# sourceMappingURL=chunk-150jk7km.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/cli/build-failure.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import { z } from \"zod\";\n\nimport type { Diagnostic } from \"../core/types.ts\";\n\n/**\n * The fields of an `astro build` rejection the report reads. Rolldown bundles\n * every plugin failure (an MDX compile error, say) into one error whose\n * `errors` holds each; a failure carries `loc` where the compiler pinned it,\n * or only `id`, the module that failed.\n */\nconst buildErrorSchema = z.looseObject({\n errors: z.array(z.instanceof(Error)).optional(),\n id: z.string().optional(),\n loc: z\n .looseObject({\n column: z.number().optional(),\n file: z.string().optional(),\n line: z.number().optional(),\n })\n .optional(),\n});\n\n/**\n * The diagnostic a `BlumeError` thrown inside the build carries, such as a\n * failed hosted search sync in `astro:build:done`. The hook runs Blume's\n * source rather than the CLI bundle, so its error is another copy of the class\n * that the command's `instanceof BlumeError` doesn't recognize.\n */\nconst blumeErrorSchema = z.looseObject({\n diagnostic: z.object({\n code: z.string(),\n column: z.number().optional(),\n docsUrl: z.string().optional(),\n file: z.string().optional(),\n line: z.number().optional(),\n message: z.string(),\n severity: z.enum([\"error\", \"info\", \"warning\"]),\n suggestion: z.string().optional(),\n }),\n});\n\n/** One failure as a diagnostic at the file (and position) it names. */\nconst failureDiagnostic = (error: Error): Diagnostic => {\n const raised = blumeErrorSchema.safeParse(error);\n if (raised.success) {\n return raised.data.diagnostic;\n }\n const parsed = buildErrorSchema.safeParse(error);\n const { id, loc } = parsed.success ? parsed.data : {};\n // A named error (`MDXError`, `CompilerError`) says which step failed.\n const name = error.name === \"Error\" ? \"\" : `${error.name}: `;\n return {\n code: \"BLUME_BUILD_FAILED\",\n column: loc?.column,\n file: loc?.file ?? id,\n line: loc?.line,\n message: `${name}${error.message}`,\n severity: \"error\",\n };\n};\n\n/**\n * What `astro build` rejected with, as build diagnostics: one per failure\n * Rolldown collected, else the error itself. A page Blume's own checks pass\n * can still fail Astro's compile (MDX that doesn't parse) or render, and that\n * is a problem in the site, reported at its file, rather than an internal\n * error blaming Blume.\n */\nexport const astroBuildDiagnostics = (error: Error): Diagnostic[] => {\n const parsed = buildErrorSchema.safeParse(error);\n const failures = parsed.success ? (parsed.data.errors ?? []) : [];\n return (failures.length > 0 ? failures : [error]).map(failureDiagnostic);\n};\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";;;AAAA;AAUA,IAAM,mBAAmB,EAAE,YAAY;AAAA,EACrC,QAAQ,EAAE,MAAM,EAAE,WAAW,KAAK,CAAC,EAAE,SAAS;AAAA,EAC9C,IAAI,EAAE,OAAO,EAAE,SAAS;AAAA,EACxB,KAAK,EACF,YAAY;AAAA,IACX,QAAQ,EAAE,OAAO,EAAE,SAAS;AAAA,IAC5B,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,IAC1B,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,EAC5B,CAAC,EACA,SAAS;AACd,CAAC;AAQD,IAAM,mBAAmB,EAAE,YAAY;AAAA,EACrC,YAAY,EAAE,OAAO;AAAA,IACnB,MAAM,EAAE,OAAO;AAAA,IACf,QAAQ,EAAE,OAAO,EAAE,SAAS;AAAA,IAC5B,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,IAC7B,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,IAC1B,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,IAC1B,SAAS,EAAE,OAAO;AAAA,IAClB,UAAU,EAAE,KAAK,CAAC,SAAS,QAAQ,SAAS,CAAC;AAAA,IAC7C,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,EAClC,CAAC;AACH,CAAC;AAGD,IAAM,oBAAoB,CAAC,UAA6B;AAAA,EACtD,MAAM,SAAS,iBAAiB,UAAU,KAAK;AAAA,EAC/C,IAAI,OAAO,SAAS;AAAA,IAClB,OAAO,OAAO,KAAK;AAAA,EACrB;AAAA,EACA,MAAM,SAAS,iBAAiB,UAAU,KAAK;AAAA,EAC/C,QAAQ,IAAI,QAAQ,OAAO,UAAU,OAAO,OAAO,CAAC;AAAA,EAEpD,MAAM,OAAO,MAAM,SAAS,UAAU,KAAK,GAAG,MAAM;AAAA,EACpD,OAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ,KAAK;AAAA,IACb,MAAM,KAAK,QAAQ;AAAA,IACnB,MAAM,KAAK;AAAA,IACX,SAAS,GAAG,OAAO,MAAM;AAAA,IACzB,UAAU;AAAA,EACZ;AAAA;AAUK,IAAM,wBAAwB,CAAC,UAA+B;AAAA,EACnE,MAAM,SAAS,iBAAiB,UAAU,KAAK;AAAA,EAC/C,MAAM,WAAW,OAAO,UAAW,OAAO,KAAK,UAAU,CAAC,IAAK,CAAC;AAAA,EAChE,QAAQ,SAAS,SAAS,IAAI,WAAW,CAAC,KAAK,GAAG,IAAI,iBAAiB;AAAA;",
|
|
8
|
+
"debugId": "1B83F4391B57E32464756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
packageSrc,
|
|
8
8
|
registry,
|
|
9
9
|
findItem
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-dqhg54mr.js";
|
|
11
11
|
|
|
12
12
|
// src/cli/commands/add.ts
|
|
13
13
|
import { existsSync } from "node:fs";
|
|
@@ -96,4 +96,4 @@ export {
|
|
|
96
96
|
};
|
|
97
97
|
|
|
98
98
|
//# debugId=B640E77C94BA0A0364756E2164756E21
|
|
99
|
-
//# sourceMappingURL=chunk-
|
|
99
|
+
//# sourceMappingURL=chunk-1f882900.js.map
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
packageDirFrom,
|
|
4
4
|
generateRuntime
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-nbyvgnnm.js";
|
|
6
6
|
import {
|
|
7
7
|
loadEnvFiles,
|
|
8
8
|
reportInternalError,
|
|
@@ -13,11 +13,11 @@ import {
|
|
|
13
13
|
} from "./index.js";
|
|
14
14
|
import {
|
|
15
15
|
scanProject
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-0pmb4tr4.js";
|
|
17
17
|
import {
|
|
18
18
|
serverFeatures,
|
|
19
19
|
checkRequiredSecrets
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-ms9z66nz.js";
|
|
21
21
|
|
|
22
22
|
// src/cli/yarn-pnp.ts
|
|
23
23
|
import { existsSync } from "node:fs";
|
|
@@ -59,6 +59,9 @@ var prepareProject = async (options) => {
|
|
|
59
59
|
let project;
|
|
60
60
|
try {
|
|
61
61
|
project = await scanProject(options.root, {
|
|
62
|
+
beforeSources: (config) => {
|
|
63
|
+
reportDiagnostics(checkRequiredSecrets(config), options.root);
|
|
64
|
+
},
|
|
62
65
|
devServerUrl: options.devServerUrl,
|
|
63
66
|
mode: options.mode,
|
|
64
67
|
overrides: options.overrides,
|
|
@@ -112,11 +115,10 @@ var prepareProject = async (options) => {
|
|
|
112
115
|
for (const warning of warnings) {
|
|
113
116
|
logger.warn(warning);
|
|
114
117
|
}
|
|
115
|
-
reportDiagnostics(checkRequiredSecrets(project.config), options.root);
|
|
116
118
|
return project;
|
|
117
119
|
};
|
|
118
120
|
|
|
119
121
|
export { prepareProject };
|
|
120
122
|
|
|
121
|
-
//# debugId=
|
|
122
|
-
//# sourceMappingURL=chunk-
|
|
123
|
+
//# debugId=306EB25EAF65994264756E2164756E21
|
|
124
|
+
//# sourceMappingURL=chunk-297ajdcv.js.map
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
"sources": ["../src/cli/yarn-pnp.ts", "../src/cli/prepare.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"import { existsSync } from \"node:fs\";\n\nimport { dirname, join } from \"pathe\";\n\nimport { packageDirFrom } from \"../astro/render-deps.ts\";\nimport type { Diagnostic } from \"../core/types.ts\";\n\n/** Whether `root` or one of its ancestors holds a Yarn Plug'n'Play manifest. */\nconst hasPnpManifest = (root: string): boolean => {\n let dir = root;\n while (true) {\n if (existsSync(join(dir, \".pnp.cjs\")) || existsSync(join(dir, \".pnp.js\"))) {\n return true;\n }\n const parent = dirname(dir);\n if (parent === dir) {\n return false;\n }\n dir = parent;\n }\n};\n\n/**\n * The diagnostic for a project installed with Yarn Plug'n'Play, or null.\n *\n * Plug'n'Play installs no `node_modules`, and the Astro project Blume\n * generates in `.blume/` imports Astro and Blume's dependencies by name, which\n * only a `node_modules` tree resolves — so under PnP the build dies loading\n * `astro/config`, a failure that reads like a bug in Blume. Caught up front\n * instead: when the command runs under the PnP runtime (`process.versions.pnp`,\n * set by `yarn run`), or when a `.pnp.cjs` manifest sits in the project with no\n * `node_modules` copy of Blume beside it.\n */\nexport const yarnPnpDiagnostic = (\n root: string,\n pnpVersion: string | undefined = process.versions.pnp\n): Diagnostic | null => {\n const underPnp =\n pnpVersion !== undefined ||\n (hasPnpManifest(root) && packageDirFrom(\"blume\", root) === null);\n if (!underPnp) {\n return null;\n }\n return {\n code: \"BLUME_YARN_PNP\",\n message:\n \"Yarn Plug'n'Play isn't supported: the Astro project Blume generates in `.blume/` resolves Astro and Blume's dependencies from a `node_modules` folder, which Plug'n'Play doesn't create.\",\n severity: \"error\",\n suggestion:\n \"Add `nodeLinker: node-modules` to `.yarnrc.yml`, run `yarn install`, then run this command again.\",\n };\n};\n",
|
|
6
|
-
"import { generateRuntime } from \"../astro/generate.ts\";\nimport { BlumeError, hasErrors } from \"../core/diagnostics.ts\";\nimport { scanProject } from \"../core/project-graph.ts\";\nimport type {\n BlumeProject,\n BuildMode,\n ConfigOverrides,\n} from \"../core/project-graph.ts\";\nimport { serverFeatures } from \"../core/server-features.ts\";\nimport { loadEnvFiles } from \"./env.ts\";\nimport { reportInternalError } from \"./internal-error.ts\";\nimport { logger, reportDiagnostics } from \"./log.ts\";\nimport { checkRequiredSecrets } from \"./required-secrets.ts\";\nimport { yarnPnpDiagnostic } from \"./yarn-pnp.ts\";\n\nexport interface PrepareOptions {\n root: string;\n mode?: BuildMode;\n strict?: boolean;\n /**\n * Whether the command is strict only on request (`blume check --strict`),\n * which changes how the abort message says to continue. Defaults to true in\n * dev mode (`blume dev`, `blume sync`) and false otherwise, where strict is\n * the default a user turns off with `--no-strict` (`blume build`).\n */\n strictOptIn?: boolean;\n /** Local dev server URL, used as the `deployment.site` fallback (dev only). */\n devServerUrl?: string;\n /** Render drafts and fetch unpublished CMS content. */\n preview?: boolean;\n /** Force remote sources to re-fetch instead of serving the cached snapshot. */\n refresh?: boolean;\n /** CLI config overrides (e.g. `--output`, `--content-dir`). */\n overrides?: ConfigOverrides;\n /** Relocate the generated runtime (e.g. `.blume-verify` for `--isolated`). */\n runtimeDir?: string;\n}\n\n/**\n * Scan the project, surface diagnostics, and (re)generate the `.blume` runtime.\n * In strict mode, any error aborts. Returns the resolved project.\n */\nexport const prepareProject = async (\n options: PrepareOptions\n): Promise<BlumeProject> => {\n // Under Yarn Plug'n'Play the generated runtime can't resolve anything; say\n // so before scanning, instead of failing inside Astro's config load.\n const pnp = yarnPnpDiagnostic(options.root);\n if (pnp) {\n reportDiagnostics([pnp], options.root);\n process.exit(1);\n }\n\n // Load `.env` files from the project root before the scan: remote sources\n // read their tokens from `process.env` during `scanProject`, and\n // `loadEnvFiles` never overrides variables that are already set.\n loadEnvFiles(options.root);\n\n let project: BlumeProject;\n try {\n project = await scanProject(options.root, {\n devServerUrl: options.devServerUrl,\n mode: options.mode,\n overrides: options.overrides,\n preview: options.preview,\n refresh: options.refresh,\n runtimeDir: options.runtimeDir,\n });\n } catch (error) {\n if (error instanceof BlumeError) {\n reportDiagnostics([error.diagnostic], options.root);\n } else {\n reportInternalError(error);\n }\n process.exit(1);\n }\n\n // Hard gate: server-only features cannot ship in a static build.\n if (\n options.mode === \"build\" &&\n project.config.deployment.options.output === \"static\"\n ) {\n const features = serverFeatures(project.config);\n if (features.length > 0) {\n // A host adapter already names the target, so only its\n // `output: \"static\"` stands in the way; otherwise name one.\n const { kind } = project.config.deployment;\n reportDiagnostics(\n [\n {\n code: \"BLUME_SERVER_FEATURE_REQUIRED\",\n message: `${features.join(\", \")} ${features.length === 1 ? \"requires\" : \"require\"} server output, but this is a static build.`,\n severity: \"error\",\n suggestion:\n kind === \"static\"\n ? 'Set deployment to a host adapter from \"blume/deploy\" in blume.config.ts, e.g. `deployment: vercel()`.'\n : `Drop \\`output: \"static\"\\` from \\`deployment: ${kind}()\\` in blume.config.ts to build for the server.`,\n },\n ],\n options.root\n );\n process.exit(1);\n }\n }\n\n const hadErrors = reportDiagnostics(project.diagnostics, options.root);\n const dropped =\n project.droppedPages > 0\n ? `${project.droppedPages} page(s) failed frontmatter validation and were dropped from the site. `\n : \"\";\n const optIn = options.strictOptIn ?? options.mode === \"dev\";\n if (hadErrors && options.strict) {\n logger.error(\n `Aborting due to errors. ${dropped}Fix the diagnostics above, or ${optIn ? \"drop --strict\" : \"pass --no-strict\"} to continue despite them.`\n );\n process.exit(1);\n }\n if (hasErrors(project.diagnostics) && !options.strict) {\n logger.warn(\n `Continuing despite errors. ${dropped}${optIn ? \"Pass --strict\" : \"Drop --no-strict\"} to fail instead.`\n );\n }\n\n let warnings: string[];\n try {\n ({ warnings } = await generateRuntime(project));\n } catch (error) {\n // A config error the generator raised (an unplannable `components.ts`\n // override, a missing font file) is the user's to fix, not an internal\n // failure: report the diagnostic and stop, like a scan-time error.\n if (error instanceof BlumeError) {\n reportDiagnostics([error.diagnostic], options.root);\n process.exit(1);\n }\n throw error;\n }\n for (const warning of warnings) {\n logger.warn(warning);\n }\n\n
|
|
6
|
+
"import { generateRuntime } from \"../astro/generate.ts\";\nimport { BlumeError, hasErrors } from \"../core/diagnostics.ts\";\nimport { scanProject } from \"../core/project-graph.ts\";\nimport type {\n BlumeProject,\n BuildMode,\n ConfigOverrides,\n} from \"../core/project-graph.ts\";\nimport { serverFeatures } from \"../core/server-features.ts\";\nimport { loadEnvFiles } from \"./env.ts\";\nimport { reportInternalError } from \"./internal-error.ts\";\nimport { logger, reportDiagnostics } from \"./log.ts\";\nimport { checkRequiredSecrets } from \"./required-secrets.ts\";\nimport { yarnPnpDiagnostic } from \"./yarn-pnp.ts\";\n\nexport interface PrepareOptions {\n root: string;\n mode?: BuildMode;\n strict?: boolean;\n /**\n * Whether the command is strict only on request (`blume check --strict`),\n * which changes how the abort message says to continue. Defaults to true in\n * dev mode (`blume dev`, `blume sync`) and false otherwise, where strict is\n * the default a user turns off with `--no-strict` (`blume build`).\n */\n strictOptIn?: boolean;\n /** Local dev server URL, used as the `deployment.site` fallback (dev only). */\n devServerUrl?: string;\n /** Render drafts and fetch unpublished CMS content. */\n preview?: boolean;\n /** Force remote sources to re-fetch instead of serving the cached snapshot. */\n refresh?: boolean;\n /** CLI config overrides (e.g. `--output`, `--content-dir`). */\n overrides?: ConfigOverrides;\n /** Relocate the generated runtime (e.g. `.blume-verify` for `--isolated`). */\n runtimeDir?: string;\n}\n\n/**\n * Scan the project, surface diagnostics, and (re)generate the `.blume` runtime.\n * In strict mode, any error aborts. Returns the resolved project.\n */\nexport const prepareProject = async (\n options: PrepareOptions\n): Promise<BlumeProject> => {\n // Under Yarn Plug'n'Play the generated runtime can't resolve anything; say\n // so before scanning, instead of failing inside Astro's config load.\n const pnp = yarnPnpDiagnostic(options.root);\n if (pnp) {\n reportDiagnostics([pnp], options.root);\n process.exit(1);\n }\n\n // Load `.env` files from the project root before the scan: remote sources\n // read their tokens from `process.env` during `scanProject`, and\n // `loadEnvFiles` never overrides variables that are already set.\n loadEnvFiles(options.root);\n\n let project: BlumeProject;\n try {\n project = await scanProject(options.root, {\n // Fail-fast on missing secrets: warn now, not at the first request, and\n // before the sources fetch, so a source that can't authenticate on a\n // fresh build still gets its variable named.\n beforeSources: (config) => {\n reportDiagnostics(checkRequiredSecrets(config), options.root);\n },\n devServerUrl: options.devServerUrl,\n mode: options.mode,\n overrides: options.overrides,\n preview: options.preview,\n refresh: options.refresh,\n runtimeDir: options.runtimeDir,\n });\n } catch (error) {\n if (error instanceof BlumeError) {\n reportDiagnostics([error.diagnostic], options.root);\n } else {\n reportInternalError(error);\n }\n process.exit(1);\n }\n\n // Hard gate: server-only features cannot ship in a static build.\n if (\n options.mode === \"build\" &&\n project.config.deployment.options.output === \"static\"\n ) {\n const features = serverFeatures(project.config);\n if (features.length > 0) {\n // A host adapter already names the target, so only its\n // `output: \"static\"` stands in the way; otherwise name one.\n const { kind } = project.config.deployment;\n reportDiagnostics(\n [\n {\n code: \"BLUME_SERVER_FEATURE_REQUIRED\",\n message: `${features.join(\", \")} ${features.length === 1 ? \"requires\" : \"require\"} server output, but this is a static build.`,\n severity: \"error\",\n suggestion:\n kind === \"static\"\n ? 'Set deployment to a host adapter from \"blume/deploy\" in blume.config.ts, e.g. `deployment: vercel()`.'\n : `Drop \\`output: \"static\"\\` from \\`deployment: ${kind}()\\` in blume.config.ts to build for the server.`,\n },\n ],\n options.root\n );\n process.exit(1);\n }\n }\n\n const hadErrors = reportDiagnostics(project.diagnostics, options.root);\n const dropped =\n project.droppedPages > 0\n ? `${project.droppedPages} page(s) failed frontmatter validation and were dropped from the site. `\n : \"\";\n const optIn = options.strictOptIn ?? options.mode === \"dev\";\n if (hadErrors && options.strict) {\n logger.error(\n `Aborting due to errors. ${dropped}Fix the diagnostics above, or ${optIn ? \"drop --strict\" : \"pass --no-strict\"} to continue despite them.`\n );\n process.exit(1);\n }\n if (hasErrors(project.diagnostics) && !options.strict) {\n logger.warn(\n `Continuing despite errors. ${dropped}${optIn ? \"Pass --strict\" : \"Drop --no-strict\"} to fail instead.`\n );\n }\n\n let warnings: string[];\n try {\n ({ warnings } = await generateRuntime(project));\n } catch (error) {\n // A config error the generator raised (an unplannable `components.ts`\n // override, a missing font file) is the user's to fix, not an internal\n // failure: report the diagnostic and stop, like a scan-time error.\n if (error instanceof BlumeError) {\n reportDiagnostics([error.diagnostic], options.root);\n process.exit(1);\n }\n throw error;\n }\n for (const warning of warnings) {\n logger.warn(warning);\n }\n\n return project;\n};\n"
|
|
7
7
|
],
|
|
8
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;AAAA;AAEA;AAMA,IAAM,iBAAiB,CAAC,SAA0B;AAAA,EAChD,IAAI,MAAM;AAAA,EACV,OAAO,MAAM;AAAA,IACX,IAAI,WAAW,KAAK,KAAK,UAAU,CAAC,KAAK,WAAW,KAAK,KAAK,SAAS,CAAC,GAAG;AAAA,MACzE,OAAO;AAAA,IACT;AAAA,IACA,MAAM,SAAS,QAAQ,GAAG;AAAA,IAC1B,IAAI,WAAW,KAAK;AAAA,MAClB,OAAO;AAAA,IACT;AAAA,IACA,MAAM;AAAA,EACR;AAAA;AAcK,IAAM,oBAAoB,CAC/B,MACA,aAAiC,QAAQ,SAAS,QAC5B;AAAA,EACtB,MAAM,WACJ,eAAe,aACd,eAAe,IAAI,KAAK,eAAe,SAAS,IAAI,MAAM;AAAA,EAC7D,IAAI,CAAC,UAAU;AAAA,IACb,OAAO;AAAA,EACT;AAAA,EACA,OAAO;AAAA,IACL,MAAM;AAAA,IACN,SACE;AAAA,IACF,UAAU;AAAA,IACV,YACE;AAAA,EACJ;AAAA;;;ACRK,IAAM,iBAAiB,OAC5B,YAC0B;AAAA,EAG1B,MAAM,MAAM,kBAAkB,QAAQ,IAAI;AAAA,EAC1C,IAAI,KAAK;AAAA,IACP,kBAAkB,CAAC,GAAG,GAAG,QAAQ,IAAI;AAAA,IACrC,QAAQ,KAAK,CAAC;AAAA,EAChB;AAAA,EAKA,aAAa,QAAQ,IAAI;AAAA,EAEzB,IAAI;AAAA,EACJ,IAAI;AAAA,IACF,UAAU,MAAM,YAAY,QAAQ,MAAM;AAAA,
|
|
9
|
-
"debugId": "
|
|
8
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;AAAA;AAEA;AAMA,IAAM,iBAAiB,CAAC,SAA0B;AAAA,EAChD,IAAI,MAAM;AAAA,EACV,OAAO,MAAM;AAAA,IACX,IAAI,WAAW,KAAK,KAAK,UAAU,CAAC,KAAK,WAAW,KAAK,KAAK,SAAS,CAAC,GAAG;AAAA,MACzE,OAAO;AAAA,IACT;AAAA,IACA,MAAM,SAAS,QAAQ,GAAG;AAAA,IAC1B,IAAI,WAAW,KAAK;AAAA,MAClB,OAAO;AAAA,IACT;AAAA,IACA,MAAM;AAAA,EACR;AAAA;AAcK,IAAM,oBAAoB,CAC/B,MACA,aAAiC,QAAQ,SAAS,QAC5B;AAAA,EACtB,MAAM,WACJ,eAAe,aACd,eAAe,IAAI,KAAK,eAAe,SAAS,IAAI,MAAM;AAAA,EAC7D,IAAI,CAAC,UAAU;AAAA,IACb,OAAO;AAAA,EACT;AAAA,EACA,OAAO;AAAA,IACL,MAAM;AAAA,IACN,SACE;AAAA,IACF,UAAU;AAAA,IACV,YACE;AAAA,EACJ;AAAA;;;ACRK,IAAM,iBAAiB,OAC5B,YAC0B;AAAA,EAG1B,MAAM,MAAM,kBAAkB,QAAQ,IAAI;AAAA,EAC1C,IAAI,KAAK;AAAA,IACP,kBAAkB,CAAC,GAAG,GAAG,QAAQ,IAAI;AAAA,IACrC,QAAQ,KAAK,CAAC;AAAA,EAChB;AAAA,EAKA,aAAa,QAAQ,IAAI;AAAA,EAEzB,IAAI;AAAA,EACJ,IAAI;AAAA,IACF,UAAU,MAAM,YAAY,QAAQ,MAAM;AAAA,MAIxC,eAAe,CAAC,WAAW;AAAA,QACzB,kBAAkB,qBAAqB,MAAM,GAAG,QAAQ,IAAI;AAAA;AAAA,MAE9D,cAAc,QAAQ;AAAA,MACtB,MAAM,QAAQ;AAAA,MACd,WAAW,QAAQ;AAAA,MACnB,SAAS,QAAQ;AAAA,MACjB,SAAS,QAAQ;AAAA,MACjB,YAAY,QAAQ;AAAA,IACtB,CAAC;AAAA,IACD,OAAO,OAAO;AAAA,IACd,IAAI,iBAAiB,YAAY;AAAA,MAC/B,kBAAkB,CAAC,MAAM,UAAU,GAAG,QAAQ,IAAI;AAAA,IACpD,EAAO;AAAA,MACL,oBAAoB,KAAK;AAAA;AAAA,IAE3B,QAAQ,KAAK,CAAC;AAAA;AAAA,EAIhB,IACE,QAAQ,SAAS,WACjB,QAAQ,OAAO,WAAW,QAAQ,WAAW,UAC7C;AAAA,IACA,MAAM,WAAW,eAAe,QAAQ,MAAM;AAAA,IAC9C,IAAI,SAAS,SAAS,GAAG;AAAA,MAGvB,QAAQ,SAAS,QAAQ,OAAO;AAAA,MAChC,kBACE;AAAA,QACE;AAAA,UACE,MAAM;AAAA,UACN,SAAS,GAAG,SAAS,KAAK,IAAI,KAAK,SAAS,WAAW,IAAI,aAAa;AAAA,UACxE,UAAU;AAAA,UACV,YACE,SAAS,WACL,0GACA,gDAAgD;AAAA,QACxD;AAAA,MACF,GACA,QAAQ,IACV;AAAA,MACA,QAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AAAA,EAEA,MAAM,YAAY,kBAAkB,QAAQ,aAAa,QAAQ,IAAI;AAAA,EACrE,MAAM,UACJ,QAAQ,eAAe,IACnB,GAAG,QAAQ,wFACX;AAAA,EACN,MAAM,QAAQ,QAAQ,eAAe,QAAQ,SAAS;AAAA,EACtD,IAAI,aAAa,QAAQ,QAAQ;AAAA,IAC/B,OAAO,MACL,2BAA2B,wCAAwC,QAAQ,kBAAkB,8CAC/F;AAAA,IACA,QAAQ,KAAK,CAAC;AAAA,EAChB;AAAA,EACA,IAAI,UAAU,QAAQ,WAAW,KAAK,CAAC,QAAQ,QAAQ;AAAA,IACrD,OAAO,KACL,8BAA8B,UAAU,QAAQ,kBAAkB,qCACpE;AAAA,EACF;AAAA,EAEA,IAAI;AAAA,EACJ,IAAI;AAAA,KACD,EAAE,SAAS,IAAI,MAAM,gBAAgB,OAAO;AAAA,IAC7C,OAAO,OAAO;AAAA,IAId,IAAI,iBAAiB,YAAY;AAAA,MAC/B,kBAAkB,CAAC,MAAM,UAAU,GAAG,QAAQ,IAAI;AAAA,MAClD,QAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,IACA,MAAM;AAAA;AAAA,EAER,WAAW,WAAW,UAAU;AAAA,IAC9B,OAAO,KAAK,OAAO;AAAA,EACrB;AAAA,EAEA,OAAO;AAAA;",
|
|
9
|
+
"debugId": "306EB25EAF65994264756E2164756E21",
|
|
10
10
|
"names": []
|
|
11
11
|
}
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
writeAgentReport,
|
|
20
20
|
fixPrompt,
|
|
21
21
|
launchInstalledAgent
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-dv2z0rzf.js";
|
|
23
23
|
import {
|
|
24
24
|
routeSetFor,
|
|
25
25
|
frontmatter_default,
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
probeAll,
|
|
30
30
|
applyBaseToAstroRedirects,
|
|
31
31
|
deployPlatform
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-124fvmzq.js";
|
|
33
33
|
import {
|
|
34
34
|
normalizeBasePath,
|
|
35
35
|
normalizePath,
|
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
import {
|
|
39
39
|
deployStaticDir,
|
|
40
40
|
examplesRouteBase
|
|
41
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-dpy8qdjf.js";
|
|
42
42
|
import {
|
|
43
43
|
parseColor,
|
|
44
44
|
composite,
|
|
@@ -48,10 +48,13 @@ import {
|
|
|
48
48
|
labelOn,
|
|
49
49
|
resolveAccent,
|
|
50
50
|
resolveAction
|
|
51
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-es8h0v3j.js";
|
|
52
52
|
import {
|
|
53
53
|
scanProject
|
|
54
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-0pmb4tr4.js";
|
|
55
|
+
import {
|
|
56
|
+
parseIgnoreFlag
|
|
57
|
+
} from "./chunk-74wfhv79.js";
|
|
55
58
|
|
|
56
59
|
// src/cli/commands/audit.ts
|
|
57
60
|
import { defineCommand } from "citty";
|
|
@@ -128,7 +131,11 @@ var resolveHref = (pageUrl, href, origin, deployBase = "") => {
|
|
|
128
131
|
if (origin && parsed.origin === origin) {
|
|
129
132
|
const served = decodePath(parsed.pathname);
|
|
130
133
|
if (!underBase(deployBase, served)) {
|
|
131
|
-
return {
|
|
134
|
+
return {
|
|
135
|
+
absolute: true,
|
|
136
|
+
kind: "outside-base",
|
|
137
|
+
path: normalizePath(served)
|
|
138
|
+
};
|
|
132
139
|
}
|
|
133
140
|
return {
|
|
134
141
|
hash: parsed.hash.slice(1),
|
|
@@ -147,7 +154,11 @@ var resolveHref = (pageUrl, href, origin, deployBase = "") => {
|
|
|
147
154
|
}
|
|
148
155
|
const served = decodePath(resolved.pathname);
|
|
149
156
|
if (target.startsWith("/") && !underBase(deployBase, served)) {
|
|
150
|
-
return {
|
|
157
|
+
return {
|
|
158
|
+
absolute: false,
|
|
159
|
+
kind: "outside-base",
|
|
160
|
+
path: normalizePath(served)
|
|
161
|
+
};
|
|
151
162
|
}
|
|
152
163
|
return {
|
|
153
164
|
hash: resolved.hash.slice(1),
|
|
@@ -965,6 +976,9 @@ var linkChecks = {
|
|
|
965
976
|
return;
|
|
966
977
|
}
|
|
967
978
|
if (resolved.kind === "outside-base") {
|
|
979
|
+
if (resolved.absolute) {
|
|
980
|
+
return;
|
|
981
|
+
}
|
|
968
982
|
if (link.content) {
|
|
969
983
|
found.push(finding("BLUME_AUDIT_LINK_TO_BROKEN", pageSite(context, page), `Link to ${link.href} is missing deployment.base (${deployBase}), so the deployed site does not serve it.`));
|
|
970
984
|
} else if (!brokenChrome.has(resolved.path)) {
|
|
@@ -1018,7 +1032,10 @@ var linkChecks = {
|
|
|
1018
1032
|
}
|
|
1019
1033
|
const homeUrl = normalizeBasePath(context.project.config.basePath) || "/";
|
|
1020
1034
|
for (const page of orphanPages(context.pages, context.graph, homeUrl)) {
|
|
1021
|
-
|
|
1035
|
+
const fromNavigation = [
|
|
1036
|
+
...context.graph.chromeIn.get(page.url) ?? []
|
|
1037
|
+
].some((from) => from !== page.url);
|
|
1038
|
+
found.push(finding("BLUME_AUDIT_ORPHAN_PAGE", pageSite(context, page), fromNavigation ? "No other page's body links here — it is reachable only from the sidebar." : "No page links here, from its body or from navigation, so readers and crawlers can't reach it."));
|
|
1022
1039
|
}
|
|
1023
1040
|
return found;
|
|
1024
1041
|
},
|
|
@@ -1134,6 +1151,33 @@ var servedPageChecks = (context, page, result, origin) => {
|
|
|
1134
1151
|
}
|
|
1135
1152
|
return found;
|
|
1136
1153
|
};
|
|
1154
|
+
var liveRedirects = (context) => context.redirects.filter((redirect) => (redirect.outcome === "ok" || redirect.outcome === "chain") && !context.byUrl.has(normalizePath(redirect.from)));
|
|
1155
|
+
var liveRedirectCheck = (context, redirect, result, deployBase) => {
|
|
1156
|
+
const from = normalizePath(redirect.from);
|
|
1157
|
+
const site = {
|
|
1158
|
+
file: context.project.context.configFile ?? undefined,
|
|
1159
|
+
url: from
|
|
1160
|
+
};
|
|
1161
|
+
const landed = result.redirected && result.finalUrl ? normalizePath(stripBasePath(deployBase, decodePath(new URL(result.finalUrl).pathname))) : from;
|
|
1162
|
+
if (landed === from) {
|
|
1163
|
+
let answer = `could not be reached (${result.error ?? "no response"})`;
|
|
1164
|
+
if (result.timedOut) {
|
|
1165
|
+
answer = "did not respond in time";
|
|
1166
|
+
} else if (result.status !== undefined) {
|
|
1167
|
+
answer = `answered it with HTTP ${result.status} instead`;
|
|
1168
|
+
}
|
|
1169
|
+
const found = finding("BLUME_AUDIT_REDIRECT_NOT_SERVED", site, `${from} should redirect to ${redirect.to}, but the live site ${answer}.`);
|
|
1170
|
+
return result.ok ? { ...found, severity: "warning" } : found;
|
|
1171
|
+
}
|
|
1172
|
+
const destination = redirect.chain.at(-1) ?? from;
|
|
1173
|
+
if (/^https?:\/\//iu.test(destination) || landed === destination) {
|
|
1174
|
+
return null;
|
|
1175
|
+
}
|
|
1176
|
+
return {
|
|
1177
|
+
...finding("BLUME_AUDIT_REDIRECT_NOT_SERVED", site, `${from} redirects to ${landed} on the live site, not to ${destination}.`),
|
|
1178
|
+
severity: "warning"
|
|
1179
|
+
};
|
|
1180
|
+
};
|
|
1137
1181
|
var networkChecks = {
|
|
1138
1182
|
category: "network",
|
|
1139
1183
|
async run(context) {
|
|
@@ -1146,7 +1190,16 @@ var networkChecks = {
|
|
|
1146
1190
|
const targets = context.pages.map((page) => liveUrl(origin, page, deployBase));
|
|
1147
1191
|
const robotsUrl = new URL(`${deployBase}/robots.txt`, origin).toString();
|
|
1148
1192
|
const sitemapUrl = new URL(`${deployBase}/sitemap.xml`, origin).toString();
|
|
1149
|
-
const
|
|
1193
|
+
const redirects = liveRedirects(context).map((redirect) => [
|
|
1194
|
+
redirect,
|
|
1195
|
+
new URL(`${deployBase}${redirect.from}`, origin).toString()
|
|
1196
|
+
]);
|
|
1197
|
+
const results = await probeAll([
|
|
1198
|
+
...targets,
|
|
1199
|
+
robotsUrl,
|
|
1200
|
+
sitemapUrl,
|
|
1201
|
+
...redirects.map(([, url]) => url)
|
|
1202
|
+
]);
|
|
1150
1203
|
for (const page of context.pages) {
|
|
1151
1204
|
const result = results.get(liveUrl(origin, page, deployBase));
|
|
1152
1205
|
if (!result) {
|
|
@@ -1159,6 +1212,13 @@ var networkChecks = {
|
|
|
1159
1212
|
}
|
|
1160
1213
|
found.push(...servedPageChecks(context, page, result, origin));
|
|
1161
1214
|
}
|
|
1215
|
+
for (const [redirect, url] of redirects) {
|
|
1216
|
+
const result = results.get(url);
|
|
1217
|
+
const wrong = liveRedirectCheck(context, redirect, result, deployBase);
|
|
1218
|
+
if (wrong) {
|
|
1219
|
+
found.push(wrong);
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1162
1222
|
const robots = results.get(robotsUrl);
|
|
1163
1223
|
if (context.project.config.seo.robots && robots && !robots.ok) {
|
|
1164
1224
|
found.push(finding("BLUME_AUDIT_ROBOTS_NOT_ACCESSIBLE", { url: "/robots.txt" }, `robots.txt is not reachable at ${robotsUrl}.`));
|
|
@@ -1180,7 +1240,7 @@ var externalChecks = {
|
|
|
1180
1240
|
for (const page of context.pages) {
|
|
1181
1241
|
for (const link of page.links) {
|
|
1182
1242
|
const resolved = resolveHref(page.url, link.href, origin, deployBase);
|
|
1183
|
-
if (resolved.kind !== "external") {
|
|
1243
|
+
if (resolved.kind !== "external" || context.ignore(resolved.url)) {
|
|
1184
1244
|
continue;
|
|
1185
1245
|
}
|
|
1186
1246
|
const pages = linkers.get(resolved.url);
|
|
@@ -1307,7 +1367,7 @@ var redirectChecks = {
|
|
|
1307
1367
|
for (const redirect of context.redirects) {
|
|
1308
1368
|
const from = normalizePath(redirect.from);
|
|
1309
1369
|
if (context.byUrl.has(from)) {
|
|
1310
|
-
found.push(finding("BLUME_AUDIT_REDIRECT_SOURCE_IS_PAGE", { ...site, url: from }, `A redirect is configured from ${from}, but ${from} is also a real page — the
|
|
1370
|
+
found.push(finding("BLUME_AUDIT_REDIRECT_SOURCE_IS_PAGE", { ...site, url: from }, `A redirect is configured from ${from}, but ${from} is also a real page — readers get one or the other, depending on the host.`));
|
|
1311
1371
|
continue;
|
|
1312
1372
|
}
|
|
1313
1373
|
if (redirect.outcome === "loop") {
|
|
@@ -1333,6 +1393,18 @@ var redirectChecks = {
|
|
|
1333
1393
|
// src/audit/checks/robots.ts
|
|
1334
1394
|
import robotsParser from "robots-parser";
|
|
1335
1395
|
var MATCH_ORIGIN = "https://robots-audit.invalid";
|
|
1396
|
+
var USER_AGENT_LINE = /^\s*user-agent\s*:\s*(?<agent>[^#]*)/iu;
|
|
1397
|
+
var namedAgents = (raw) => {
|
|
1398
|
+
const agents = new Map;
|
|
1399
|
+
for (const line of raw.split(/\r?\n/u)) {
|
|
1400
|
+
const agent = USER_AGENT_LINE.exec(line)?.groups?.agent?.trim() ?? "";
|
|
1401
|
+
const key = agent.toLowerCase().split("/")[0]?.trim() ?? "";
|
|
1402
|
+
if (key && key !== "*" && !agents.has(key)) {
|
|
1403
|
+
agents.set(key, agent);
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
return [...agents.values()];
|
|
1407
|
+
};
|
|
1336
1408
|
var robotsChecks = {
|
|
1337
1409
|
category: "robots",
|
|
1338
1410
|
run(context) {
|
|
@@ -1352,6 +1424,12 @@ var robotsChecks = {
|
|
|
1352
1424
|
}
|
|
1353
1425
|
const parser = robotsParser(`${MATCH_ORIGIN}/robots.txt`, robots.raw);
|
|
1354
1426
|
const lines = robots.raw.split(/\r?\n/u);
|
|
1427
|
+
const ruleAt = (url, agent) => {
|
|
1428
|
+
const line = parser.getMatchingLineNumber(url, agent);
|
|
1429
|
+
return { line, rule: line > 0 ? lines[line - 1]?.trim() : undefined };
|
|
1430
|
+
};
|
|
1431
|
+
const agents = namedAgents(robots.raw);
|
|
1432
|
+
const blockedFor = new Map;
|
|
1355
1433
|
for (const loc of context.sitemap?.urls ?? []) {
|
|
1356
1434
|
let pathname;
|
|
1357
1435
|
try {
|
|
@@ -1362,10 +1440,28 @@ var robotsChecks = {
|
|
|
1362
1440
|
const path = normalizePath(pathname);
|
|
1363
1441
|
const url = `${MATCH_ORIGIN}${pathname}`;
|
|
1364
1442
|
if (parser.isDisallowed(url, "*")) {
|
|
1365
|
-
const
|
|
1366
|
-
const rule = line > 0 ? lines[line - 1]?.trim() : undefined;
|
|
1443
|
+
const { rule } = ruleAt(url, "*");
|
|
1367
1444
|
found.push(finding("BLUME_AUDIT_ROBOTS_DISALLOWS_INDEXABLE", { file: robots.file, url: path }, `robots.txt "${rule ?? "Disallow"}" blocks ${path}, which sitemap.xml advertises.`));
|
|
1445
|
+
continue;
|
|
1368
1446
|
}
|
|
1447
|
+
for (const agent of agents) {
|
|
1448
|
+
if (!parser.isDisallowed(url, agent)) {
|
|
1449
|
+
continue;
|
|
1450
|
+
}
|
|
1451
|
+
const blocked = blockedFor.get(agent);
|
|
1452
|
+
if (blocked) {
|
|
1453
|
+
blocked.push(url);
|
|
1454
|
+
} else {
|
|
1455
|
+
blockedFor.set(agent, [url]);
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
for (const [agent, urls] of blockedFor) {
|
|
1460
|
+
const [first = ""] = urls;
|
|
1461
|
+
const { line, rule } = ruleAt(first, agent);
|
|
1462
|
+
const path = normalizePath(new URL(first).pathname);
|
|
1463
|
+
const more = urls.length > 1 ? ` and ${urls.length - 1} more` : "";
|
|
1464
|
+
found.push(finding("BLUME_AUDIT_ROBOTS_BLOCKS_CRAWLER", { file: robots.file, line, url: "/robots.txt" }, `robots.txt "${rule ?? "Disallow"}" blocks ${agent} from ${path}${more}, which sitemap.xml advertises.`));
|
|
1369
1465
|
}
|
|
1370
1466
|
return found;
|
|
1371
1467
|
},
|
|
@@ -2038,6 +2134,7 @@ var runAudit = async (options) => {
|
|
|
2038
2134
|
byUrl,
|
|
2039
2135
|
files: crawl.files,
|
|
2040
2136
|
graph: buildGraph(crawl.pages, siteOrigin(project.config.deployment.options.site), normalizeBasePath(project.config.deployment.options.base)),
|
|
2137
|
+
ignore: options.ignore ?? (() => false),
|
|
2041
2138
|
llms: crawl.llms,
|
|
2042
2139
|
origin,
|
|
2043
2140
|
pages: crawl.pages,
|
|
@@ -2119,6 +2216,11 @@ var auditCommand = defineCommand({
|
|
|
2119
2216
|
description: "Exit non-zero at this severity or above: error | warning | info. Defaults to error.",
|
|
2120
2217
|
type: "string"
|
|
2121
2218
|
},
|
|
2219
|
+
ignore: {
|
|
2220
|
+
description: 'With --external, skip outbound links whose URL matches this glob (e.g. "https://example.com/**"). Repeat it for more; internal links are always checked.',
|
|
2221
|
+
type: "string",
|
|
2222
|
+
valueHint: "glob"
|
|
2223
|
+
},
|
|
2122
2224
|
json: {
|
|
2123
2225
|
description: "Emit the report as JSON on stdout (for CI/editors).",
|
|
2124
2226
|
type: "boolean"
|
|
@@ -2149,7 +2251,7 @@ var auditCommand = defineCommand({
|
|
|
2149
2251
|
}
|
|
2150
2252
|
},
|
|
2151
2253
|
meta: commandMeta.audit,
|
|
2152
|
-
async run({ args }) {
|
|
2254
|
+
async run({ args, rawArgs }) {
|
|
2153
2255
|
if (args["list-checks"]) {
|
|
2154
2256
|
process.stdout.write(formatCatalog());
|
|
2155
2257
|
return;
|
|
@@ -2178,11 +2280,13 @@ var auditCommand = defineCommand({
|
|
|
2178
2280
|
const only = splitTerms(args.only);
|
|
2179
2281
|
const skip = splitTerms(args.skip);
|
|
2180
2282
|
rejectUnknownTerms([...only, ...skip]);
|
|
2283
|
+
const ignore = parseIgnoreFlag(rawArgs);
|
|
2181
2284
|
let result;
|
|
2182
2285
|
try {
|
|
2183
2286
|
const project = await scanProject(root, { mode: "build" });
|
|
2184
2287
|
result = await runAudit({
|
|
2185
2288
|
external: args.external,
|
|
2289
|
+
ignore,
|
|
2186
2290
|
only,
|
|
2187
2291
|
origin: args.url,
|
|
2188
2292
|
project,
|
|
@@ -2236,5 +2340,5 @@ export {
|
|
|
2236
2340
|
shouldFail
|
|
2237
2341
|
};
|
|
2238
2342
|
|
|
2239
|
-
//# debugId=
|
|
2240
|
-
//# sourceMappingURL=chunk-
|
|
2343
|
+
//# debugId=E0347EF127A1E50964756E2164756E21
|
|
2344
|
+
//# sourceMappingURL=chunk-32khwcb6.js.map
|