blume 2.0.3 → 2.1.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 -0
- package/CHANGELOG.md +142 -0
- package/README.md +1 -1
- package/dist/cli/{chunk-5f86nr5m.js → chunk-073rdvgb.js} +21 -48
- package/dist/cli/{chunk-5f86nr5m.js.map → chunk-073rdvgb.js.map} +4 -5
- 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-150jk7km.js +52 -0
- package/dist/cli/chunk-150jk7km.js.map +10 -0
- package/dist/cli/{chunk-9t7a85s3.js → chunk-313vnn40.js} +30 -19
- package/dist/cli/chunk-313vnn40.js.map +10 -0
- package/dist/cli/{chunk-tkacnehg.js → chunk-3v3ffbrj.js} +2 -2
- package/dist/cli/{chunk-q58y5e6a.js → chunk-3x6x3pph.js} +46 -24
- package/dist/cli/chunk-3x6x3pph.js.map +10 -0
- package/dist/cli/{chunk-1d7ve1dm.js → chunk-42t4jxdx.js} +37 -5
- package/dist/cli/chunk-42t4jxdx.js.map +12 -0
- package/dist/cli/{chunk-8ktnccpt.js → chunk-54ztw1nj.js} +21 -2
- package/dist/cli/chunk-54ztw1nj.js.map +10 -0
- package/dist/cli/{chunk-hm3vjy5s.js → chunk-5vjtgs6e.js} +28 -10
- package/dist/cli/{chunk-hm3vjy5s.js.map → chunk-5vjtgs6e.js.map} +4 -4
- package/dist/cli/chunk-66w9j7p6.js +322 -0
- package/dist/cli/chunk-66w9j7p6.js.map +14 -0
- package/dist/cli/{chunk-2hsdwb9n.js → chunk-7ppf1rva.js} +34 -18
- package/dist/cli/chunk-7ppf1rva.js.map +10 -0
- package/dist/cli/{chunk-r9rcc4w7.js → chunk-8y2kmjv8.js} +7 -7
- package/dist/cli/{chunk-r20tn01b.js → chunk-c1y538kd.js} +8 -2
- package/dist/cli/{chunk-r20tn01b.js.map → chunk-c1y538kd.js.map} +3 -3
- package/dist/cli/{chunk-2eytanqx.js → chunk-c887fj0s.js} +2 -2
- package/dist/cli/{chunk-p3v96n38.js → chunk-cfyg47zg.js} +16 -6
- package/dist/cli/chunk-cfyg47zg.js.map +10 -0
- package/dist/cli/chunk-cm89scdv.js +443 -0
- package/dist/cli/chunk-cm89scdv.js.map +11 -0
- package/dist/cli/{chunk-akbpwfxc.js → chunk-dzwehpy7.js} +2 -2
- package/dist/cli/{chunk-wrr3j9w9.js → chunk-e6atmn4h.js} +299 -72
- package/dist/cli/chunk-e6atmn4h.js.map +36 -0
- package/dist/cli/{chunk-tzmab476.js → chunk-e8xw9qkh.js} +8 -6
- package/dist/cli/{chunk-tzmab476.js.map → chunk-e8xw9qkh.js.map} +3 -3
- package/dist/cli/{chunk-6dsbexzp.js → chunk-e9q7a2ak.js} +17 -15
- package/dist/cli/{chunk-6dsbexzp.js.map → chunk-e9q7a2ak.js.map} +2 -2
- package/dist/cli/{chunk-pv29h0wf.js → chunk-ehweg4fr.js} +5155 -1249
- package/dist/cli/chunk-ehweg4fr.js.map +218 -0
- package/dist/cli/{chunk-c8chx29p.js → chunk-ep6nd0rn.js} +390 -318
- package/dist/cli/chunk-ep6nd0rn.js.map +36 -0
- package/dist/cli/{chunk-p73c0m7w.js → chunk-fdrkhpjy.js} +18 -15
- package/dist/cli/{chunk-p73c0m7w.js.map → chunk-fdrkhpjy.js.map} +3 -3
- package/dist/cli/{chunk-2z928egk.js → chunk-ft9vfys6.js} +5 -5
- package/dist/cli/{chunk-5m5nmvyq.js → chunk-gb420vvz.js} +316 -79
- package/dist/cli/chunk-gb420vvz.js.map +17 -0
- package/dist/cli/{chunk-vg9r4eb9.js → chunk-hebn0tpx.js} +86 -13
- package/dist/cli/chunk-hebn0tpx.js.map +14 -0
- package/dist/cli/{chunk-35d4wj9f.js → chunk-htrwgabr.js} +41 -23
- package/dist/cli/chunk-htrwgabr.js.map +15 -0
- package/dist/cli/{chunk-g4hq16wv.js → chunk-hx3xqnk9.js} +16 -14
- package/dist/cli/{chunk-g4hq16wv.js.map → chunk-hx3xqnk9.js.map} +2 -2
- package/dist/cli/chunk-j134vrp2.js +65 -0
- package/dist/cli/chunk-j134vrp2.js.map +10 -0
- package/dist/cli/{chunk-a58773jm.js → chunk-kma9f6sf.js} +2 -2
- package/dist/cli/chunk-kwrg63tm.js +31 -0
- package/dist/cli/chunk-kwrg63tm.js.map +10 -0
- package/dist/cli/{chunk-ey84smr6.js → chunk-mrcccgnh.js} +6 -6
- package/dist/cli/{chunk-ey84smr6.js.map → chunk-mrcccgnh.js.map} +1 -1
- package/dist/cli/{chunk-yfyb25rh.js → chunk-n0v7m8ry.js} +24 -8
- package/dist/cli/chunk-n0v7m8ry.js.map +14 -0
- package/dist/cli/{chunk-j85vccga.js → chunk-ncj7w596.js} +576 -367
- package/dist/cli/chunk-ncj7w596.js.map +35 -0
- package/dist/cli/{chunk-5xvm6tfj.js → chunk-nq1d20w2.js} +17 -15
- package/dist/cli/{chunk-5xvm6tfj.js.map → chunk-nq1d20w2.js.map} +2 -2
- package/dist/cli/{chunk-pehfxfta.js → chunk-nrns10mj.js} +6 -98
- package/dist/cli/chunk-nrns10mj.js.map +10 -0
- package/dist/cli/{chunk-crgn1q09.js → chunk-sds923fa.js} +4 -4
- package/dist/cli/chunk-t2m5j4pr.js +104 -0
- package/dist/cli/chunk-t2m5j4pr.js.map +11 -0
- package/dist/cli/{chunk-acanzt5p.js → chunk-tdqhyxfz.js} +6 -6
- package/dist/cli/chunk-tphac74f.js +126 -0
- package/dist/cli/chunk-tphac74f.js.map +11 -0
- package/dist/cli/chunk-w1r4vase.js +18 -0
- package/dist/cli/chunk-w1r4vase.js.map +10 -0
- package/dist/cli/{chunk-3em5wd2y.js → chunk-zccbjcj0.js} +4 -3
- package/dist/cli/{chunk-3em5wd2y.js.map → chunk-zccbjcj0.js.map} +2 -2
- package/dist/cli/index.js +31 -20
- package/dist/cli/index.js.map +5 -5
- package/dist/types/ai/agent-surface.d.ts +8 -7
- package/dist/types/ai/ai-catalog.d.ts +7 -0
- package/dist/types/ai/ask-context.d.ts +26 -0
- package/dist/types/ai/ask.d.ts +271 -58
- package/dist/types/ai/component-markdown.d.ts +2 -0
- package/dist/types/ai/index.d.ts +2 -2
- package/dist/types/ai/openapi-components.d.ts +4 -1
- package/dist/types/ai/site-skill.d.ts +26 -0
- package/dist/types/ai/skills.d.ts +16 -0
- package/dist/types/astro/integration.d.ts +9 -0
- package/dist/types/astro/markdown-negotiation.d.ts +3 -0
- package/dist/types/astro/pages.d.ts +10 -0
- package/dist/types/captcha/hcaptcha.d.ts +27 -0
- package/dist/types/captcha/index.d.ts +28 -0
- package/dist/types/captcha/schema.d.ts +29 -0
- package/dist/types/captcha/turnstile.d.ts +28 -0
- package/dist/types/cli/init/scaffold.d.ts +1 -1
- package/dist/types/components/content/api-field.d.ts +62 -0
- package/dist/types/components/content/api-page.d.ts +100 -0
- package/dist/types/components/layout/nav-utils.d.ts +26 -0
- package/dist/types/components/openapi/code-samples.d.ts +29 -0
- package/dist/types/components/openapi/helpers.d.ts +158 -0
- package/dist/types/components/openapi/security.d.ts +95 -0
- package/dist/types/components/openapi/snippets.d.ts +60 -0
- package/dist/types/consent/ethyca.d.ts +48 -0
- package/dist/types/consent/index.d.ts +37 -0
- package/dist/types/consent/native.d.ts +28 -0
- package/dist/types/consent/osano.d.ts +42 -0
- package/dist/types/consent/schema.d.ts +110 -0
- package/dist/types/core/changelog-index.d.ts +8 -0
- package/dist/types/core/config-input.d.ts +217 -23
- package/dist/types/core/data.d.ts +53 -4
- package/dist/types/core/footer.d.ts +8 -0
- package/dist/types/core/i18n-ui.d.ts +88 -0
- package/dist/types/core/includes.d.ts +8 -2
- package/dist/types/core/links.d.ts +8 -0
- package/dist/types/core/localizable.d.ts +7 -0
- package/dist/types/core/page-modes.d.ts +29 -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 +152 -0
- package/dist/types/core/related.d.ts +40 -0
- package/dist/types/core/schema.d.ts +670 -56
- 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/normalize.d.ts +20 -1
- package/dist/types/core/sources/read.d.ts +5 -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 +18 -1
- package/dist/types/core/variables.d.ts +42 -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/node-headers.d.ts +13 -2
- package/dist/types/deploy/platforms/cloudflare.d.ts +15 -7
- package/dist/types/deploy/platforms/netlify.d.ts +7 -0
- 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 +26 -1
- package/dist/types/deploy/redirects.d.ts +55 -11
- package/dist/types/deploy/sitemap.d.ts +2 -1
- package/dist/types/deploy/vercel-negotiation.d.ts +51 -21
- package/dist/types/markdown/code-title.d.ts +17 -0
- package/dist/types/markdown/features.d.ts +3 -2
- package/dist/types/narration/build.d.ts +70 -0
- package/dist/types/narration/provider.d.ts +26 -0
- package/dist/types/narration/script.d.ts +154 -0
- 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 +27 -10
- package/dist/types/openapi/overlay.d.ts +54 -0
- package/dist/types/openapi/parse.d.ts +16 -0
- package/dist/types/openapi/references.d.ts +30 -4
- package/dist/types/ratelimit/cloudflare.d.ts +39 -0
- package/dist/types/ratelimit/index.d.ts +27 -0
- package/dist/types/ratelimit/memory.d.ts +36 -0
- package/dist/types/ratelimit/schema.d.ts +119 -0
- package/dist/types/ratelimit/upstash.d.ts +46 -0
- package/dist/types/ratelimit/wrangler.d.ts +23 -0
- package/dist/types/reference/asyncapi.d.ts +10 -10
- package/dist/types/reference/graphql.d.ts +89 -11
- package/dist/types/reference/index.d.ts +1 -1
- package/dist/types/reference/openapi.d.ts +33 -12
- package/dist/types/reference/options.d.ts +82 -6
- package/dist/types/reference/scalar.d.ts +13 -0
- package/dist/types/reference/schema.d.ts +144 -36
- 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/documents.d.ts +12 -1
- package/dist/types/search/orama-index.d.ts +13 -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/metatags.d.ts +20 -0
- package/dist/types/sources/contentful.d.ts +16 -0
- package/dist/types/sources/github-releases.d.ts +8 -1
- package/dist/types/sources/payload.d.ts +2 -0
- package/dist/types/sources/registry.d.ts +54 -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 +71 -17
- package/docs/03-upgrading.mdx +4 -4
- package/docs/04-migrating.mdx +1 -1
- package/docs/advanced/changelog.mdx +13 -2
- package/docs/advanced/skills.mdx +15 -1
- package/docs/cli/audit.mdx +51 -8
- package/docs/cli/doctor.mdx +5 -1
- package/docs/cli/evals.mdx +4 -4
- package/docs/cli/index.mdx +1 -0
- package/docs/cli/translate.mdx +1 -0
- package/docs/cli/validate.mdx +4 -3
- package/docs/configuration/analytics.mdx +3 -1
- package/docs/configuration/assistant.mdx +194 -38
- package/docs/configuration/consent.mdx +100 -0
- package/docs/configuration/customization.mdx +8 -6
- package/docs/configuration/export.mdx +5 -3
- package/docs/configuration/index.mdx +64 -5
- package/docs/configuration/meta.ts +3 -0
- package/docs/configuration/narration.mdx +119 -0
- package/docs/configuration/rate-limiting.mdx +90 -0
- package/docs/configuration/search.mdx +63 -12
- package/docs/configuration/theming.mdx +3 -1
- package/docs/content/components.mdx +108 -2
- package/docs/content/frontmatter.mdx +80 -2
- package/docs/content/i18n.mdx +39 -4
- package/docs/content/includes.mdx +16 -0
- package/docs/content/meta.mdx +1 -0
- package/docs/content/meta.ts +1 -0
- package/docs/content/navigation.mdx +32 -10
- package/docs/content/sources/contentful.mdx +35 -0
- package/docs/content/sources/custom.mdx +43 -0
- package/docs/content/sources/github-releases.mdx +39 -0
- package/docs/content/sources/index.mdx +91 -0
- package/docs/content/sources/meta.ts +16 -0
- package/docs/content/sources/notion.mdx +32 -0
- package/docs/content/sources/obsidian.mdx +37 -0
- package/docs/content/sources/payload.mdx +31 -0
- package/docs/content/sources/remote-mdx.mdx +44 -0
- package/docs/content/sources/sanity.mdx +29 -0
- package/docs/content/sources/strapi.mdx +32 -0
- package/docs/content/syntax.mdx +69 -4
- package/docs/content/variables.mdx +41 -0
- package/docs/discoverability/agent-discovery.mdx +29 -2
- package/docs/discoverability/index.mdx +2 -2
- package/docs/discoverability/json-api.mdx +2 -0
- package/docs/discoverability/llms-txt.mdx +2 -2
- package/docs/discoverability/markdown.mdx +3 -1
- package/docs/discoverability/mcp.mdx +4 -0
- package/docs/discoverability/metadata.mdx +17 -0
- package/docs/discoverability/sitemap-and-robots.mdx +1 -1
- package/docs/references/api-pages.mdx +74 -0
- package/docs/references/asyncapi.mdx +4 -2
- package/docs/references/graphql.mdx +14 -2
- package/docs/references/meta.ts +1 -1
- package/docs/references/openapi.mdx +148 -7
- package/docs/references/scalar.mdx +3 -1
- package/package.json +43 -8
- package/skills/blume/SKILL.md +3 -0
- package/skills/blume-migrate/SKILL.md +6 -6
- package/skills/blume-migrate/references/docusaurus.md +7 -7
- package/skills/blume-migrate/references/fumadocs.md +17 -13
- package/skills/blume-migrate/references/mintlify.md +37 -19
- package/skills/blume-migrate/references/nextra.md +10 -7
- package/skills/blume-migrate/references/starlight.md +11 -8
- package/skills/blume-migrate/scripts/mintlify-codemod.mjs +60 -14
- package/skills/blume-write-skill/SKILL.md +82 -0
- package/src/ai/agent-readability.ts +2 -1
- package/src/ai/agent-surface.ts +9 -7
- package/src/ai/ai-catalog.ts +6 -3
- package/src/ai/ask-context.ts +103 -20
- package/src/ai/ask-data.ts +6 -0
- package/src/ai/ask-limits.ts +13 -0
- package/src/ai/ask-tools.ts +142 -0
- package/src/ai/ask.ts +354 -76
- package/src/ai/changelog-markdown.ts +11 -6
- package/src/ai/component-markdown.ts +76 -1
- package/src/ai/cors.ts +14 -3
- package/src/ai/index.ts +12 -0
- package/src/ai/llms.ts +6 -2
- package/src/ai/markdown.ts +2 -1
- package/src/ai/mcp/data.ts +6 -0
- package/src/ai/mcp/query.ts +14 -6
- package/src/ai/openapi-components.ts +36 -6
- package/src/ai/relative-links.ts +4 -38
- package/src/ai/site-skill.ts +274 -0
- package/src/ai/skills.ts +35 -2
- package/src/ai/write-skill.ts +97 -0
- package/src/astro/generate.ts +210 -66
- package/src/astro/index.ts +1 -0
- package/src/astro/integration.ts +42 -4
- package/src/astro/markdown-negotiation.ts +3 -0
- package/src/astro/module-types.ts +9 -1
- package/src/astro/pages.ts +23 -0
- package/src/astro/templates.ts +406 -108
- package/src/astro/variables.ts +31 -0
- package/src/audit/catalog.ts +38 -3
- package/src/audit/checks/contrast.ts +183 -0
- package/src/audit/checks/i18n.ts +2 -3
- package/src/audit/checks/indexability.ts +2 -3
- package/src/audit/checks/links.ts +19 -13
- 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/checks/sitemap.ts +2 -3
- package/src/audit/redirects.ts +46 -15
- package/src/audit/run.ts +5 -0
- package/src/audit/types.ts +4 -1
- package/src/audit/url.ts +14 -5
- package/src/blume-modules.d.ts +12 -1
- package/src/captcha/client.ts +152 -0
- package/src/captcha/hcaptcha.ts +36 -0
- package/src/captcha/index.ts +28 -0
- package/src/captcha/schema.ts +32 -0
- package/src/captcha/turnstile.ts +38 -0
- package/src/captcha/verify.ts +71 -0
- package/src/cli/args.ts +51 -0
- package/src/cli/build-failure.ts +23 -0
- package/src/cli/command-meta.ts +5 -0
- package/src/cli/commands/audit.ts +10 -1
- package/src/cli/commands/dev.ts +18 -2
- package/src/cli/commands/doctor.ts +67 -28
- package/src/cli/commands/eval.ts +36 -4
- package/src/cli/commands/init.ts +6 -4
- package/src/cli/commands/skill.ts +96 -0
- package/src/cli/commands/validate.ts +10 -1
- package/src/cli/index.ts +5 -0
- package/src/cli/init/scaffold.ts +3 -3
- package/src/cli/prepare.ts +6 -3
- package/src/cli/required-secrets.ts +72 -30
- package/src/components/BlumePage.astro +2 -0
- package/src/components/content/ApiEndpoint.astro +18 -0
- package/src/components/content/ApiField.astro +79 -0
- package/src/components/content/ApiPlayground.astro +66 -0
- package/src/components/content/ApiRail.astro +19 -0
- package/src/components/content/Color.astro +1 -0
- package/src/components/content/FileTree.astro +1 -0
- package/src/components/content/GithubInfo.astro +1 -0
- package/src/components/content/Panel.astro +1 -0
- package/src/components/content/ParamField.astro +25 -0
- package/src/components/content/RequestExample.astro +17 -0
- package/src/components/content/ResponseExample.astro +17 -0
- package/src/components/content/ResponseField.astro +32 -0
- package/src/components/content/Step.astro +1 -0
- package/src/components/content/Tile.astro +1 -0
- package/src/components/content/Tooltip.astro +1 -0
- package/src/components/content/Tree.astro +1 -0
- package/src/components/content/TypeTable.astro +4 -1
- package/src/components/content/View.astro +21 -0
- package/src/components/content/ViewSwitcher.astro +168 -0
- package/src/components/content/api-field.ts +103 -0
- package/src/components/content/api-page.ts +248 -0
- package/src/components/content/mermaid-element.ts +15 -1
- package/src/components/content/view-switcher.ts +71 -0
- package/src/components/index.ts +2 -0
- package/src/components/islands/Assistant.astro +10 -1
- package/src/components/islands/assistant.tsx +104 -14
- package/src/components/islands/code-question.ts +62 -0
- package/src/components/islands/hooks.ts +136 -21
- package/src/components/islands/support-link.ts +68 -0
- package/src/components/layout/Analytics.astro +11 -2
- package/src/components/layout/Banner.astro +14 -10
- package/src/components/layout/Breadcrumbs.astro +6 -2
- package/src/components/layout/ConsentBanner.astro +62 -0
- package/src/components/layout/ConsentHead.astro +38 -0
- package/src/components/layout/Directory.astro +94 -0
- package/src/components/layout/DrawerSwitchers.astro +51 -0
- package/src/components/layout/Empty.astro +2 -2
- package/src/components/layout/Header.astro +122 -80
- package/src/components/layout/LanguageSwitcher.astro +48 -15
- package/src/components/layout/NarrationPlayer.astro +1085 -0
- package/src/components/layout/NavSelector.astro +33 -7
- package/src/components/layout/PageActions.astro +139 -24
- package/src/components/layout/PageFeedback.astro +54 -49
- package/src/components/layout/PageLayout.astro +71 -3
- package/src/components/layout/ReferenceLayout.astro +17 -6
- package/src/components/layout/RelatedPages.astro +42 -0
- package/src/components/layout/RootLayout.astro +318 -47
- package/src/components/layout/Search.astro +47 -19
- package/src/components/layout/SiteFooter.astro +124 -0
- package/src/components/layout/SiteMetatags.astro +16 -0
- package/src/components/layout/TableOfContents.astro +24 -17
- package/src/components/layout/consent/native.ts +79 -0
- package/src/components/layout/consent/types.ts +37 -0
- package/src/components/layout/footer-links.ts +53 -0
- package/src/components/layout/footer-socials.ts +87 -0
- package/src/components/layout/head-scripts.ts +6 -1
- package/src/components/layout/locale-redirect.ts +107 -0
- package/src/components/layout/nav-utils.ts +83 -0
- package/src/components/layout/page-feedback.ts +96 -0
- package/src/components/layout/search/algolia.ts +10 -1
- package/src/components/layout/search/analytics.ts +126 -0
- package/src/components/layout/search/endpoint.ts +48 -5
- package/src/components/layout/search/flexsearch.ts +17 -5
- package/src/components/layout/search/orama-cloud.ts +26 -14
- package/src/components/layout/search/pagefind.ts +114 -5
- package/src/components/layout/search/types.ts +32 -0
- package/src/components/layout/search/typesense.ts +19 -3
- 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 +184 -13
- package/src/components/openapi/ParametersTable.astro +8 -4
- package/src/components/openapi/Playground.astro +7 -1
- package/src/components/openapi/RequestBody.astro +24 -5
- package/src/components/openapi/RequestPanel.astro +59 -7
- package/src/components/openapi/Responses.astro +7 -4
- package/src/components/openapi/SchemaTable.astro +15 -3
- package/src/components/openapi/async-snippets.ts +65 -9
- package/src/components/openapi/async.ts +123 -29
- package/src/components/openapi/code-samples.ts +97 -0
- 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 +24 -5
- package/src/components/openapi/playground-schema.ts +1 -1
- package/src/components/openapi/schema-tree.ts +44 -14
- package/src/components/openapi/security.ts +16 -3
- package/src/components/openapi/snippets.ts +873 -10
- package/src/components/openapi/validate-json.ts +4 -3
- package/src/components/props.ts +6 -0
- package/src/consent/client.ts +95 -0
- package/src/consent/clients.ts +19 -0
- package/src/consent/ethyca.ts +71 -0
- package/src/consent/head.ts +24 -0
- package/src/consent/index.ts +37 -0
- package/src/consent/init.ts +29 -0
- package/src/consent/native.ts +36 -0
- package/src/consent/osano.ts +59 -0
- package/src/consent/schema.ts +30 -0
- package/src/core/builtin-tags.ts +5 -0
- package/src/core/changelog-index.ts +31 -1
- package/src/core/client-address.ts +19 -0
- package/src/core/component-diagnostics.ts +53 -0
- package/src/core/component-overrides.ts +32 -0
- package/src/core/config-input.ts +225 -23
- package/src/core/data.ts +46 -4
- package/src/core/diagnostics.ts +8 -2
- package/src/core/footer.ts +26 -0
- package/src/core/graph.ts +39 -36
- package/src/core/i18n-ui.ts +84 -2
- package/src/core/includes.ts +21 -4
- package/src/core/links.ts +63 -19
- package/src/core/localizable.ts +26 -0
- package/src/core/navigation.ts +43 -12
- package/src/core/page-modes.ts +56 -0
- package/src/core/probe.ts +26 -6
- package/src/core/project-graph.ts +163 -16
- package/src/core/redirect-patterns.ts +520 -0
- package/src/core/related.ts +131 -0
- package/src/core/schema.ts +339 -66
- 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/mdx-remote.ts +62 -10
- package/src/core/sources/normalize.ts +228 -41
- package/src/core/sources/notion.ts +7 -1
- package/src/core/sources/obsidian.ts +16 -3
- package/src/core/sources/payload.ts +38 -15
- package/src/core/sources/read.ts +8 -3
- 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 +19 -1
- package/src/core/ui-packs/ar.ts +44 -0
- package/src/core/ui-packs/bg.ts +46 -0
- package/src/core/ui-packs/bn.ts +44 -0
- package/src/core/ui-packs/ca.ts +47 -0
- package/src/core/ui-packs/cs.ts +45 -0
- package/src/core/ui-packs/da.ts +46 -0
- package/src/core/ui-packs/de.ts +47 -0
- package/src/core/ui-packs/el.ts +46 -0
- package/src/core/ui-packs/es.ts +47 -0
- package/src/core/ui-packs/fa.ts +46 -0
- package/src/core/ui-packs/fi.ts +46 -0
- package/src/core/ui-packs/fr.ts +47 -0
- package/src/core/ui-packs/he.ts +44 -0
- package/src/core/ui-packs/hi.ts +45 -0
- package/src/core/ui-packs/hr.ts +46 -0
- package/src/core/ui-packs/hu.ts +45 -0
- package/src/core/ui-packs/id.ts +46 -0
- package/src/core/ui-packs/it.ts +46 -0
- package/src/core/ui-packs/ja.ts +46 -0
- package/src/core/ui-packs/ko.ts +45 -0
- package/src/core/ui-packs/nl.ts +47 -0
- package/src/core/ui-packs/no.ts +45 -0
- package/src/core/ui-packs/pl.ts +46 -0
- package/src/core/ui-packs/pt-br.ts +47 -0
- package/src/core/ui-packs/pt.ts +46 -0
- package/src/core/ui-packs/ro.ts +46 -0
- package/src/core/ui-packs/ru.ts +46 -0
- package/src/core/ui-packs/sk.ts +45 -0
- package/src/core/ui-packs/sr.ts +46 -0
- package/src/core/ui-packs/sv.ts +45 -0
- package/src/core/ui-packs/th.ts +44 -0
- package/src/core/ui-packs/tr.ts +46 -0
- package/src/core/ui-packs/uk.ts +46 -0
- package/src/core/ui-packs/vi.ts +46 -0
- package/src/core/ui-packs/zh-tw.ts +44 -0
- package/src/core/ui-packs/zh.ts +44 -0
- package/src/core/variables.ts +103 -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 +79 -9
- package/src/deploy/cloudflare-negotiation.ts +35 -5
- package/src/deploy/headers.ts +2 -1
- package/src/deploy/node-headers.ts +63 -9
- package/src/deploy/platforms/cloudflare.ts +45 -9
- package/src/deploy/platforms/netlify.ts +35 -2
- package/src/deploy/platforms/node.ts +12 -2
- package/src/deploy/platforms/types.ts +21 -7
- package/src/deploy/platforms/vercel.ts +149 -17
- package/src/deploy/redirects.ts +151 -24
- package/src/deploy/rss.ts +3 -1
- package/src/deploy/sitemap.ts +39 -5
- package/src/deploy/vercel-negotiation.ts +326 -102
- 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/api-rail.ts +259 -0
- package/src/markdown/code-title.ts +35 -9
- package/src/markdown/features.ts +3 -2
- package/src/markdown/fence-meta.ts +2 -0
- package/src/markdown/include.ts +11 -1
- package/src/markdown/index.ts +28 -5
- package/src/markdown/math.ts +4 -4
- package/src/markdown/relative-links.ts +3 -2
- package/src/markdown/variables.ts +56 -0
- package/src/markdown/views.ts +82 -0
- package/src/narration/build.ts +412 -0
- package/src/narration/player.ts +249 -0
- package/src/narration/provider.ts +29 -0
- package/src/narration/script.ts +592 -0
- package/src/og/card.ts +7 -6
- 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 +72 -27
- package/src/openapi/overlay.ts +256 -0
- package/src/openapi/parse.ts +182 -4
- package/src/openapi/references.ts +64 -8
- package/src/openapi/render-mdx.ts +5 -1
- package/src/openapi/scalar.ts +40 -6
- package/src/openapi/source.ts +40 -15
- package/src/ratelimit/cloudflare.ts +54 -0
- package/src/ratelimit/index.ts +30 -0
- package/src/ratelimit/memory.ts +45 -0
- package/src/ratelimit/runtime.ts +247 -0
- package/src/ratelimit/schema.ts +28 -0
- package/src/ratelimit/upstash.ts +60 -0
- package/src/ratelimit/wrangler.ts +70 -0
- package/src/reference/asyncapi.ts +2 -2
- package/src/reference/graphql.ts +20 -3
- package/src/reference/index.ts +1 -0
- package/src/reference/openapi.ts +21 -7
- package/src/reference/options.ts +80 -8
- package/src/reference/scalar.ts +33 -8
- package/src/registry/eject.ts +23 -5
- package/src/registry/registry.ts +7 -0
- 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/documents.ts +26 -2
- package/src/search/orama-index.ts +191 -34
- package/src/search/pagefind-ranking.ts +39 -0
- package/src/search/source-pages.ts +29 -0
- package/src/search/sync/algolia.ts +111 -10
- package/src/search/sync/index.ts +52 -13
- package/src/search/sync/orama-cloud.ts +3 -0
- package/src/search/sync/typesense.ts +76 -26
- package/src/seo/metatags.ts +67 -0
- package/src/sources/contentful.ts +12 -0
- package/src/sources/github-releases.ts +7 -1
- package/src/sources/shared.ts +3 -0
- package/src/theme/chrome-icons.ts +1 -0
- package/src/theme/color.ts +500 -0
- package/src/theme/entry.ts +85 -6
- package/src/theme/palette.ts +121 -45
- package/src/translate/prompts.ts +1 -0
- package/src/translate/validate.ts +31 -3
- package/src/upgrade/upgrade.ts +4 -171
- package/dist/cli/chunk-1d7ve1dm.js.map +0 -12
- package/dist/cli/chunk-2hsdwb9n.js.map +0 -10
- package/dist/cli/chunk-35d4wj9f.js.map +0 -15
- package/dist/cli/chunk-364znk6q.js +0 -75
- package/dist/cli/chunk-364znk6q.js.map +0 -11
- package/dist/cli/chunk-5m5nmvyq.js.map +0 -13
- package/dist/cli/chunk-8ktnccpt.js.map +0 -10
- package/dist/cli/chunk-9t7a85s3.js.map +0 -10
- package/dist/cli/chunk-b07cmahc.js +0 -145
- package/dist/cli/chunk-b07cmahc.js.map +0 -11
- package/dist/cli/chunk-c8chx29p.js.map +0 -36
- package/dist/cli/chunk-e04dxsz1.js +0 -39
- package/dist/cli/chunk-e04dxsz1.js.map +0 -10
- package/dist/cli/chunk-j85vccga.js.map +0 -36
- package/dist/cli/chunk-p3v96n38.js.map +0 -10
- package/dist/cli/chunk-pehfxfta.js.map +0 -10
- package/dist/cli/chunk-pv29h0wf.js.map +0 -190
- package/dist/cli/chunk-q58y5e6a.js.map +0 -10
- package/dist/cli/chunk-vg9r4eb9.js.map +0 -14
- package/dist/cli/chunk-wrr3j9w9.js.map +0 -35
- package/dist/cli/chunk-yfyb25rh.js.map +0 -14
- package/docs/content/sources.mdx +0 -334
- /package/dist/cli/{chunk-tkacnehg.js.map → chunk-3v3ffbrj.js.map} +0 -0
- /package/dist/cli/{chunk-r9rcc4w7.js.map → chunk-8y2kmjv8.js.map} +0 -0
- /package/dist/cli/{chunk-2eytanqx.js.map → chunk-c887fj0s.js.map} +0 -0
- /package/dist/cli/{chunk-akbpwfxc.js.map → chunk-dzwehpy7.js.map} +0 -0
- /package/dist/cli/{chunk-2z928egk.js.map → chunk-ft9vfys6.js.map} +0 -0
- /package/dist/cli/{chunk-a58773jm.js.map → chunk-kma9f6sf.js.map} +0 -0
- /package/dist/cli/{chunk-crgn1q09.js.map → chunk-sds923fa.js.map} +0 -0
- /package/dist/cli/{chunk-acanzt5p.js.map → chunk-tdqhyxfz.js.map} +0 -0
|
@@ -19,27 +19,42 @@ import {
|
|
|
19
19
|
writeAgentReport,
|
|
20
20
|
fixPrompt,
|
|
21
21
|
launchInstalledAgent
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-42t4jxdx.js";
|
|
23
23
|
import {
|
|
24
24
|
routeSetFor,
|
|
25
25
|
frontmatter_default,
|
|
26
|
+
isPatternPath,
|
|
27
|
+
patternDestination,
|
|
26
28
|
gradeExternal,
|
|
27
29
|
probeAll,
|
|
28
30
|
applyBaseToAstroRedirects,
|
|
29
31
|
deployPlatform
|
|
30
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-ehweg4fr.js";
|
|
31
33
|
import {
|
|
32
34
|
normalizeBasePath,
|
|
33
35
|
normalizePath,
|
|
34
36
|
stripBasePath
|
|
35
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-zccbjcj0.js";
|
|
36
38
|
import {
|
|
37
39
|
deployStaticDir,
|
|
38
40
|
examplesRouteBase
|
|
39
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-gb420vvz.js";
|
|
42
|
+
import {
|
|
43
|
+
parseColor,
|
|
44
|
+
composite,
|
|
45
|
+
contrastRatio,
|
|
46
|
+
MIN_TEXT_CONTRAST,
|
|
47
|
+
themeInk,
|
|
48
|
+
labelOn,
|
|
49
|
+
resolveAccent,
|
|
50
|
+
resolveAction
|
|
51
|
+
} from "./chunk-cm89scdv.js";
|
|
40
52
|
import {
|
|
41
53
|
scanProject
|
|
42
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-ncj7w596.js";
|
|
55
|
+
import {
|
|
56
|
+
parseIgnoreFlag
|
|
57
|
+
} from "./chunk-j134vrp2.js";
|
|
43
58
|
|
|
44
59
|
// src/cli/commands/audit.ts
|
|
45
60
|
import { defineCommand } from "citty";
|
|
@@ -116,7 +131,11 @@ var resolveHref = (pageUrl, href, origin, deployBase = "") => {
|
|
|
116
131
|
if (origin && parsed.origin === origin) {
|
|
117
132
|
const served = decodePath(parsed.pathname);
|
|
118
133
|
if (!underBase(deployBase, served)) {
|
|
119
|
-
return {
|
|
134
|
+
return {
|
|
135
|
+
absolute: true,
|
|
136
|
+
kind: "outside-base",
|
|
137
|
+
path: normalizePath(served)
|
|
138
|
+
};
|
|
120
139
|
}
|
|
121
140
|
return {
|
|
122
141
|
hash: parsed.hash.slice(1),
|
|
@@ -135,7 +154,11 @@ var resolveHref = (pageUrl, href, origin, deployBase = "") => {
|
|
|
135
154
|
}
|
|
136
155
|
const served = decodePath(resolved.pathname);
|
|
137
156
|
if (target.startsWith("/") && !underBase(deployBase, served)) {
|
|
138
|
-
return {
|
|
157
|
+
return {
|
|
158
|
+
absolute: false,
|
|
159
|
+
kind: "outside-base",
|
|
160
|
+
path: normalizePath(served)
|
|
161
|
+
};
|
|
139
162
|
}
|
|
140
163
|
return {
|
|
141
164
|
hash: resolved.hash.slice(1),
|
|
@@ -337,6 +360,105 @@ var contentChecks = {
|
|
|
337
360
|
tier: "static"
|
|
338
361
|
};
|
|
339
362
|
|
|
363
|
+
// src/audit/checks/contrast.ts
|
|
364
|
+
var MODES = ["light", "dark"];
|
|
365
|
+
var fillPair = (key, fill, page, mode) => ({
|
|
366
|
+
fix: `Neither white nor dark text reaches ${MIN_TEXT_CONTRAST}:1 on this shade. Move \`${key}\`'s ${mode} shade lighter or darker.`,
|
|
367
|
+
key,
|
|
368
|
+
label: key === "theme.action" ? "The call-to-action label" : "Button labels on the accent",
|
|
369
|
+
surface: composite(fill, page),
|
|
370
|
+
text: parseColor(labelOn(fill, mode)) ?? fill
|
|
371
|
+
});
|
|
372
|
+
var accentPairs = (fill, page, mode) => [
|
|
373
|
+
{
|
|
374
|
+
fix: `${mode === "light" ? "Darken" : "Lighten"} \`theme.accent\`'s ${mode} shade (\`theme.accent: { light, dark }\`).`,
|
|
375
|
+
key: "theme.accent",
|
|
376
|
+
label: "Accent text on the page",
|
|
377
|
+
surface: page,
|
|
378
|
+
text: fill
|
|
379
|
+
},
|
|
380
|
+
fillPair("theme.accent", fill, page, mode)
|
|
381
|
+
];
|
|
382
|
+
var backgroundPairs = (page, mode) => {
|
|
383
|
+
const fix = `Pick a \`theme.background\` ${mode} color further from the text color.`;
|
|
384
|
+
return [
|
|
385
|
+
{
|
|
386
|
+
fix,
|
|
387
|
+
key: "theme.background",
|
|
388
|
+
label: "Body text on the page",
|
|
389
|
+
surface: page,
|
|
390
|
+
text: themeInk(mode, "foreground")
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
fix,
|
|
394
|
+
key: "theme.background",
|
|
395
|
+
label: "Secondary text on the page",
|
|
396
|
+
surface: page,
|
|
397
|
+
text: themeInk(mode, "mutedForeground")
|
|
398
|
+
}
|
|
399
|
+
];
|
|
400
|
+
};
|
|
401
|
+
var modeColors = (theme, mode) => {
|
|
402
|
+
const unread = [];
|
|
403
|
+
const read = (color) => {
|
|
404
|
+
const parsed = parseColor(color.value);
|
|
405
|
+
if (!parsed) {
|
|
406
|
+
unread.push(color);
|
|
407
|
+
}
|
|
408
|
+
return parsed;
|
|
409
|
+
};
|
|
410
|
+
const custom = theme.background?.[mode];
|
|
411
|
+
const customPage = custom === undefined ? null : read({ key: "theme.background", value: custom });
|
|
412
|
+
if (custom !== undefined && !customPage) {
|
|
413
|
+
return { pairs: [], unread };
|
|
414
|
+
}
|
|
415
|
+
const page = customPage ?? themeInk(mode, "background");
|
|
416
|
+
const pairs = customPage ? backgroundPairs(customPage, mode) : [];
|
|
417
|
+
const accent = read({
|
|
418
|
+
key: "theme.accent",
|
|
419
|
+
value: resolveAccent(theme)[mode]
|
|
420
|
+
});
|
|
421
|
+
if (accent) {
|
|
422
|
+
pairs.push(...accentPairs(accent, page, mode));
|
|
423
|
+
}
|
|
424
|
+
const action = resolveAction(theme);
|
|
425
|
+
const actionFill = action && read({ key: "theme.action", value: action[mode] });
|
|
426
|
+
if (actionFill) {
|
|
427
|
+
pairs.push(fillPair("theme.action", actionFill, page, mode));
|
|
428
|
+
}
|
|
429
|
+
return { pairs, unread };
|
|
430
|
+
};
|
|
431
|
+
var contrastChecks = {
|
|
432
|
+
category: "accessibility",
|
|
433
|
+
run(context) {
|
|
434
|
+
const { theme } = context.project.config;
|
|
435
|
+
const site = {
|
|
436
|
+
file: context.project.context.configFile ?? undefined,
|
|
437
|
+
url: "/"
|
|
438
|
+
};
|
|
439
|
+
const found = [];
|
|
440
|
+
const reported = new Set;
|
|
441
|
+
for (const mode of MODES) {
|
|
442
|
+
const { pairs, unread } = modeColors(theme, mode);
|
|
443
|
+
for (const color of unread) {
|
|
444
|
+
const id = `${color.key}:${color.value}`;
|
|
445
|
+
if (!reported.has(id)) {
|
|
446
|
+
reported.add(id);
|
|
447
|
+
found.push(finding("BLUME_AUDIT_THEME_COLOR_UNCHECKED", site, `\`${color.key}\` is "${color.value}", which the audit can't read as a color, so its contrast went unchecked.`));
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
for (const pair of pairs) {
|
|
451
|
+
const ratio = contrastRatio(pair.text, pair.surface);
|
|
452
|
+
if (ratio < MIN_TEXT_CONTRAST) {
|
|
453
|
+
found.push(finding("BLUME_AUDIT_THEME_CONTRAST_LOW", site, `${pair.label} in ${mode} mode is ${ratio.toFixed(2)}:1, under the ${MIN_TEXT_CONTRAST}:1 WCAG AA asks of body text (\`${pair.key}\`).`, pair.fix));
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
return found;
|
|
458
|
+
},
|
|
459
|
+
tier: "static"
|
|
460
|
+
};
|
|
461
|
+
|
|
340
462
|
// src/audit/checks/dns-aid.ts
|
|
341
463
|
var RR_SVCB = 64;
|
|
342
464
|
var RR_HTTPS = 65;
|
|
@@ -495,6 +617,68 @@ var duplicateChecks = {
|
|
|
495
617
|
tier: "static"
|
|
496
618
|
};
|
|
497
619
|
|
|
620
|
+
// src/audit/redirects.ts
|
|
621
|
+
var pathOnly = (value) => {
|
|
622
|
+
const cut = value.search(/[?#]/u);
|
|
623
|
+
return cut === -1 ? value : value.slice(0, cut);
|
|
624
|
+
};
|
|
625
|
+
var resolveRedirects = (redirects, served) => {
|
|
626
|
+
const byFrom = new Map;
|
|
627
|
+
for (const redirect of redirects) {
|
|
628
|
+
byFrom.set(normalizePath(redirect.from), redirect);
|
|
629
|
+
}
|
|
630
|
+
const hopFrom = (path) => byFrom.get(path)?.to ?? patternDestination(redirects, path);
|
|
631
|
+
return redirects.map((redirect) => {
|
|
632
|
+
const from = normalizePath(redirect.from);
|
|
633
|
+
if (isPatternPath(redirect.from)) {
|
|
634
|
+
return { ...redirect, chain: [from], outcome: "pattern" };
|
|
635
|
+
}
|
|
636
|
+
const chain = [from];
|
|
637
|
+
const seen = new Set([from]);
|
|
638
|
+
let current = redirect.to;
|
|
639
|
+
for (;; ) {
|
|
640
|
+
if (/^https?:\/\//iu.test(current)) {
|
|
641
|
+
chain.push(current);
|
|
642
|
+
break;
|
|
643
|
+
}
|
|
644
|
+
const next = normalizePath(pathOnly(current));
|
|
645
|
+
if (seen.has(next)) {
|
|
646
|
+
chain.push(next);
|
|
647
|
+
return {
|
|
648
|
+
...redirect,
|
|
649
|
+
chain,
|
|
650
|
+
outcome: "loop"
|
|
651
|
+
};
|
|
652
|
+
}
|
|
653
|
+
chain.push(next);
|
|
654
|
+
seen.add(next);
|
|
655
|
+
const hop = hopFrom(next);
|
|
656
|
+
if (hop === undefined) {
|
|
657
|
+
break;
|
|
658
|
+
}
|
|
659
|
+
current = hop;
|
|
660
|
+
}
|
|
661
|
+
const destination = chain.at(-1) ?? from;
|
|
662
|
+
const external = /^https?:\/\//iu.test(destination);
|
|
663
|
+
if (!(external || served(destination))) {
|
|
664
|
+
return { ...redirect, chain, outcome: "broken" };
|
|
665
|
+
}
|
|
666
|
+
return {
|
|
667
|
+
...redirect,
|
|
668
|
+
chain,
|
|
669
|
+
outcome: chain.length > 2 ? "chain" : "ok"
|
|
670
|
+
};
|
|
671
|
+
});
|
|
672
|
+
};
|
|
673
|
+
var redirectAt = (redirects, path) => {
|
|
674
|
+
const exact = redirects.find((entry) => normalizePath(entry.from) === path);
|
|
675
|
+
if (exact) {
|
|
676
|
+
return exact;
|
|
677
|
+
}
|
|
678
|
+
const to = patternDestination(redirects, path);
|
|
679
|
+
return to === undefined ? undefined : { to };
|
|
680
|
+
};
|
|
681
|
+
|
|
498
682
|
// src/audit/checks/indexability.ts
|
|
499
683
|
var parseCanonical = (canonical) => {
|
|
500
684
|
try {
|
|
@@ -538,7 +722,7 @@ var canonicalChecks = (context, page) => {
|
|
|
538
722
|
if (target === normalizePath(page.url)) {
|
|
539
723
|
return found;
|
|
540
724
|
}
|
|
541
|
-
const redirect = context.redirects
|
|
725
|
+
const redirect = redirectAt(context.redirects, target);
|
|
542
726
|
if (redirect) {
|
|
543
727
|
found.push(finding("BLUME_AUDIT_CANONICAL_BAD_TARGET", pageSite(context, page, ["seo", "canonical"]), `Canonical points at ${target}, which is a redirect to ${redirect.to}.`));
|
|
544
728
|
} else if (context.byUrl.has(target)) {
|
|
@@ -643,7 +827,7 @@ var hreflangChecks = (context, page) => {
|
|
|
643
827
|
continue;
|
|
644
828
|
}
|
|
645
829
|
const target = context.byUrl.get(path);
|
|
646
|
-
const redirect = context.redirects
|
|
830
|
+
const redirect = redirectAt(context.redirects, path);
|
|
647
831
|
if (redirect) {
|
|
648
832
|
found.push(finding("BLUME_AUDIT_HREFLANG_BAD_TARGET", pageSite(context, page), `hreflang="${alternate.lang}" points at ${path}, which redirects to ${redirect.to}.`));
|
|
649
833
|
} else if (!target) {
|
|
@@ -758,7 +942,6 @@ var anchorResolves = (target, fragment) => {
|
|
|
758
942
|
return target.ids.has(fragment);
|
|
759
943
|
}
|
|
760
944
|
};
|
|
761
|
-
var redirectFrom = (context, path) => context.redirects.find((entry) => normalizePath(entry.from) === path);
|
|
762
945
|
var linkChecks = {
|
|
763
946
|
category: "links",
|
|
764
947
|
run(context) {
|
|
@@ -793,6 +976,9 @@ var linkChecks = {
|
|
|
793
976
|
return;
|
|
794
977
|
}
|
|
795
978
|
if (resolved.kind === "outside-base") {
|
|
979
|
+
if (resolved.absolute) {
|
|
980
|
+
return;
|
|
981
|
+
}
|
|
796
982
|
if (link.content) {
|
|
797
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.`));
|
|
798
984
|
} else if (!brokenChrome.has(resolved.path)) {
|
|
@@ -811,7 +997,7 @@ var linkChecks = {
|
|
|
811
997
|
found.push(finding("BLUME_AUDIT_INTERNAL_LINK_NOFOLLOW", pageSite(context, page), `Internal link to ${resolved.path} is rel="nofollow".`));
|
|
812
998
|
}
|
|
813
999
|
const { path } = resolved;
|
|
814
|
-
const redirect =
|
|
1000
|
+
const redirect = redirectAt(context.redirects, path);
|
|
815
1001
|
if (redirect) {
|
|
816
1002
|
if (link.content) {
|
|
817
1003
|
found.push(finding("BLUME_AUDIT_LINK_TO_REDIRECT", pageSite(context, page), `Link to ${path} goes through a redirect to ${redirect.to}.`));
|
|
@@ -838,7 +1024,7 @@ var linkChecks = {
|
|
|
838
1024
|
found.push(finding("BLUME_AUDIT_LINK_TO_BROKEN", { url: page.url }, `Navigation links to ${path}, which the build does not serve.`, "Fix the entry in your navigation config or meta file."));
|
|
839
1025
|
}
|
|
840
1026
|
for (const [path, page] of redirectedChrome) {
|
|
841
|
-
const redirect =
|
|
1027
|
+
const redirect = redirectAt(context.redirects, path);
|
|
842
1028
|
found.push(finding("BLUME_AUDIT_LINK_TO_REDIRECT", { url: page.url }, `Navigation links to ${path}, which redirects to ${redirect?.to}.`, "Point the navigation entry straight at the destination."));
|
|
843
1029
|
}
|
|
844
1030
|
for (const [key, page] of brokenChromeAnchors) {
|
|
@@ -846,7 +1032,10 @@ var linkChecks = {
|
|
|
846
1032
|
}
|
|
847
1033
|
const homeUrl = normalizeBasePath(context.project.config.basePath) || "/";
|
|
848
1034
|
for (const page of orphanPages(context.pages, context.graph, homeUrl)) {
|
|
849
|
-
|
|
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."));
|
|
850
1039
|
}
|
|
851
1040
|
return found;
|
|
852
1041
|
},
|
|
@@ -962,6 +1151,33 @@ var servedPageChecks = (context, page, result, origin) => {
|
|
|
962
1151
|
}
|
|
963
1152
|
return found;
|
|
964
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
|
+
};
|
|
965
1181
|
var networkChecks = {
|
|
966
1182
|
category: "network",
|
|
967
1183
|
async run(context) {
|
|
@@ -974,7 +1190,16 @@ var networkChecks = {
|
|
|
974
1190
|
const targets = context.pages.map((page) => liveUrl(origin, page, deployBase));
|
|
975
1191
|
const robotsUrl = new URL(`${deployBase}/robots.txt`, origin).toString();
|
|
976
1192
|
const sitemapUrl = new URL(`${deployBase}/sitemap.xml`, origin).toString();
|
|
977
|
-
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
|
+
]);
|
|
978
1203
|
for (const page of context.pages) {
|
|
979
1204
|
const result = results.get(liveUrl(origin, page, deployBase));
|
|
980
1205
|
if (!result) {
|
|
@@ -987,6 +1212,13 @@ var networkChecks = {
|
|
|
987
1212
|
}
|
|
988
1213
|
found.push(...servedPageChecks(context, page, result, origin));
|
|
989
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
|
+
}
|
|
990
1222
|
const robots = results.get(robotsUrl);
|
|
991
1223
|
if (context.project.config.seo.robots && robots && !robots.ok) {
|
|
992
1224
|
found.push(finding("BLUME_AUDIT_ROBOTS_NOT_ACCESSIBLE", { url: "/robots.txt" }, `robots.txt is not reachable at ${robotsUrl}.`));
|
|
@@ -1008,7 +1240,7 @@ var externalChecks = {
|
|
|
1008
1240
|
for (const page of context.pages) {
|
|
1009
1241
|
for (const link of page.links) {
|
|
1010
1242
|
const resolved = resolveHref(page.url, link.href, origin, deployBase);
|
|
1011
|
-
if (resolved.kind !== "external") {
|
|
1243
|
+
if (resolved.kind !== "external" || context.ignore(resolved.url)) {
|
|
1012
1244
|
continue;
|
|
1013
1245
|
}
|
|
1014
1246
|
const pages = linkers.get(resolved.url);
|
|
@@ -1135,7 +1367,7 @@ var redirectChecks = {
|
|
|
1135
1367
|
for (const redirect of context.redirects) {
|
|
1136
1368
|
const from = normalizePath(redirect.from);
|
|
1137
1369
|
if (context.byUrl.has(from)) {
|
|
1138
|
-
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.`));
|
|
1139
1371
|
continue;
|
|
1140
1372
|
}
|
|
1141
1373
|
if (redirect.outcome === "loop") {
|
|
@@ -1161,6 +1393,18 @@ var redirectChecks = {
|
|
|
1161
1393
|
// src/audit/checks/robots.ts
|
|
1162
1394
|
import robotsParser from "robots-parser";
|
|
1163
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
|
+
};
|
|
1164
1408
|
var robotsChecks = {
|
|
1165
1409
|
category: "robots",
|
|
1166
1410
|
run(context) {
|
|
@@ -1180,6 +1424,12 @@ var robotsChecks = {
|
|
|
1180
1424
|
}
|
|
1181
1425
|
const parser = robotsParser(`${MATCH_ORIGIN}/robots.txt`, robots.raw);
|
|
1182
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;
|
|
1183
1433
|
for (const loc of context.sitemap?.urls ?? []) {
|
|
1184
1434
|
let pathname;
|
|
1185
1435
|
try {
|
|
@@ -1190,11 +1440,29 @@ var robotsChecks = {
|
|
|
1190
1440
|
const path = normalizePath(pathname);
|
|
1191
1441
|
const url = `${MATCH_ORIGIN}${pathname}`;
|
|
1192
1442
|
if (parser.isDisallowed(url, "*")) {
|
|
1193
|
-
const
|
|
1194
|
-
const rule = line > 0 ? lines[line - 1]?.trim() : undefined;
|
|
1443
|
+
const { rule } = ruleAt(url, "*");
|
|
1195
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;
|
|
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
|
+
}
|
|
1196
1457
|
}
|
|
1197
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.`));
|
|
1465
|
+
}
|
|
1198
1466
|
return found;
|
|
1199
1467
|
},
|
|
1200
1468
|
tier: "static"
|
|
@@ -1238,7 +1506,7 @@ var checkListedUrl = (context, loc, origin, file, deployBase) => {
|
|
|
1238
1506
|
const path = normalizePath(stripBasePath(deployBase, decodePath(parsed.pathname)));
|
|
1239
1507
|
const page = context.byUrl.get(path);
|
|
1240
1508
|
if (!page) {
|
|
1241
|
-
const redirect = context.redirects
|
|
1509
|
+
const redirect = redirectAt(context.redirects, path);
|
|
1242
1510
|
return [
|
|
1243
1511
|
finding("BLUME_AUDIT_SITEMAP_BAD_URL", { file, url: loc }, redirect ? `sitemap.xml lists ${path}, which redirects to ${redirect.to}.` : `sitemap.xml lists ${path}, which the build does not serve.`)
|
|
1244
1512
|
];
|
|
@@ -1779,56 +2047,6 @@ var crawlStaticDir = async (options) => {
|
|
|
1779
2047
|
};
|
|
1780
2048
|
};
|
|
1781
2049
|
|
|
1782
|
-
// src/audit/redirects.ts
|
|
1783
|
-
var pathOnly = (value) => {
|
|
1784
|
-
const cut = value.search(/[?#]/u);
|
|
1785
|
-
return cut === -1 ? value : value.slice(0, cut);
|
|
1786
|
-
};
|
|
1787
|
-
var resolveRedirects = (redirects, served) => {
|
|
1788
|
-
const byFrom = new Map;
|
|
1789
|
-
for (const redirect of redirects) {
|
|
1790
|
-
byFrom.set(normalizePath(redirect.from), redirect);
|
|
1791
|
-
}
|
|
1792
|
-
return redirects.map((redirect) => {
|
|
1793
|
-
const from = normalizePath(redirect.from);
|
|
1794
|
-
const chain = [from];
|
|
1795
|
-
const seen = new Set([from]);
|
|
1796
|
-
let current = redirect.to;
|
|
1797
|
-
for (;; ) {
|
|
1798
|
-
if (/^https?:\/\//iu.test(current)) {
|
|
1799
|
-
chain.push(current);
|
|
1800
|
-
break;
|
|
1801
|
-
}
|
|
1802
|
-
const next = normalizePath(pathOnly(current));
|
|
1803
|
-
if (seen.has(next)) {
|
|
1804
|
-
chain.push(next);
|
|
1805
|
-
return {
|
|
1806
|
-
...redirect,
|
|
1807
|
-
chain,
|
|
1808
|
-
outcome: "loop"
|
|
1809
|
-
};
|
|
1810
|
-
}
|
|
1811
|
-
chain.push(next);
|
|
1812
|
-
seen.add(next);
|
|
1813
|
-
const hop = byFrom.get(next);
|
|
1814
|
-
if (!hop) {
|
|
1815
|
-
break;
|
|
1816
|
-
}
|
|
1817
|
-
current = hop.to;
|
|
1818
|
-
}
|
|
1819
|
-
const destination = chain.at(-1) ?? from;
|
|
1820
|
-
const external = /^https?:\/\//iu.test(destination);
|
|
1821
|
-
if (!(external || served(destination))) {
|
|
1822
|
-
return { ...redirect, chain, outcome: "broken" };
|
|
1823
|
-
}
|
|
1824
|
-
return {
|
|
1825
|
-
...redirect,
|
|
1826
|
-
chain,
|
|
1827
|
-
outcome: chain.length > 2 ? "chain" : "ok"
|
|
1828
|
-
};
|
|
1829
|
-
});
|
|
1830
|
-
};
|
|
1831
|
-
|
|
1832
2050
|
// src/audit/terms.ts
|
|
1833
2051
|
var shortId = (id) => id.replace("BLUME_AUDIT_", "").toLowerCase();
|
|
1834
2052
|
var checkTerms = () => [
|
|
@@ -1856,6 +2074,7 @@ var MODULES = [
|
|
|
1856
2074
|
ogImageChecks,
|
|
1857
2075
|
i18nChecks,
|
|
1858
2076
|
assetChecks,
|
|
2077
|
+
contrastChecks,
|
|
1859
2078
|
sitemapChecks,
|
|
1860
2079
|
robotsChecks,
|
|
1861
2080
|
llmsChecks,
|
|
@@ -1915,6 +2134,7 @@ var runAudit = async (options) => {
|
|
|
1915
2134
|
byUrl,
|
|
1916
2135
|
files: crawl.files,
|
|
1917
2136
|
graph: buildGraph(crawl.pages, siteOrigin(project.config.deployment.options.site), normalizeBasePath(project.config.deployment.options.base)),
|
|
2137
|
+
ignore: options.ignore ?? (() => false),
|
|
1918
2138
|
llms: crawl.llms,
|
|
1919
2139
|
origin,
|
|
1920
2140
|
pages: crawl.pages,
|
|
@@ -1996,6 +2216,11 @@ var auditCommand = defineCommand({
|
|
|
1996
2216
|
description: "Exit non-zero at this severity or above: error | warning | info. Defaults to error.",
|
|
1997
2217
|
type: "string"
|
|
1998
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
|
+
},
|
|
1999
2224
|
json: {
|
|
2000
2225
|
description: "Emit the report as JSON on stdout (for CI/editors).",
|
|
2001
2226
|
type: "boolean"
|
|
@@ -2026,7 +2251,7 @@ var auditCommand = defineCommand({
|
|
|
2026
2251
|
}
|
|
2027
2252
|
},
|
|
2028
2253
|
meta: commandMeta.audit,
|
|
2029
|
-
async run({ args }) {
|
|
2254
|
+
async run({ args, rawArgs }) {
|
|
2030
2255
|
if (args["list-checks"]) {
|
|
2031
2256
|
process.stdout.write(formatCatalog());
|
|
2032
2257
|
return;
|
|
@@ -2055,11 +2280,13 @@ var auditCommand = defineCommand({
|
|
|
2055
2280
|
const only = splitTerms(args.only);
|
|
2056
2281
|
const skip = splitTerms(args.skip);
|
|
2057
2282
|
rejectUnknownTerms([...only, ...skip]);
|
|
2283
|
+
const ignore = parseIgnoreFlag(rawArgs);
|
|
2058
2284
|
let result;
|
|
2059
2285
|
try {
|
|
2060
2286
|
const project = await scanProject(root, { mode: "build" });
|
|
2061
2287
|
result = await runAudit({
|
|
2062
2288
|
external: args.external,
|
|
2289
|
+
ignore,
|
|
2063
2290
|
only,
|
|
2064
2291
|
origin: args.url,
|
|
2065
2292
|
project,
|
|
@@ -2113,5 +2340,5 @@ export {
|
|
|
2113
2340
|
shouldFail
|
|
2114
2341
|
};
|
|
2115
2342
|
|
|
2116
|
-
//# debugId=
|
|
2117
|
-
//# sourceMappingURL=chunk-
|
|
2343
|
+
//# debugId=E0347EF127A1E50964756E2164756E21
|
|
2344
|
+
//# sourceMappingURL=chunk-e6atmn4h.js.map
|