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
|
@@ -9,14 +9,63 @@ interface PagefindResult {
|
|
|
9
9
|
}>;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
/** One Pagefind instance: a page language's index, plus any merged into it. */
|
|
13
|
+
interface PagefindInstance {
|
|
14
|
+
mergeIndex: (
|
|
15
|
+
url: string,
|
|
16
|
+
options: { baseUrl: string; language: string }
|
|
17
|
+
) => Promise<void>;
|
|
13
18
|
search: (query: string) => Promise<{ results: PagefindResult[] }>;
|
|
14
19
|
}
|
|
15
20
|
|
|
21
|
+
interface PagefindModule {
|
|
22
|
+
createInstance: (options: {
|
|
23
|
+
basePath: string;
|
|
24
|
+
baseUrl: string;
|
|
25
|
+
}) => PagefindInstance;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** `pagefind-entry.json`: the bundle's index for each language. */
|
|
29
|
+
interface PagefindEntry {
|
|
30
|
+
languages: Record<string, { page_count: number }>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Pagefind names each page after its built file (`quickstart/index.html`), so
|
|
34
|
+
// its URLs end in a slash. Blume serves pages without one (`trailingSlash:
|
|
35
|
+
// "never"`): hosts redirect the slashed URL, and `blume preview` 404s it.
|
|
36
|
+
const TRAILING_SLASH = /(?<=.)\/(?=[#?]|$)/u;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The language whose index Pagefind loads for a page, picked the way its
|
|
40
|
+
* `findIndex` does: the page's own, else its base language (`pt` for
|
|
41
|
+
* `pt-br`), else the language with the most pages (a locale with no
|
|
42
|
+
* translated pages has no index of its own).
|
|
43
|
+
*/
|
|
44
|
+
const loadedLanguage = (
|
|
45
|
+
languages: PagefindEntry["languages"],
|
|
46
|
+
language: string
|
|
47
|
+
): string | undefined => {
|
|
48
|
+
const [base = language] = language.split("-");
|
|
49
|
+
if (languages[language]) {
|
|
50
|
+
return language;
|
|
51
|
+
}
|
|
52
|
+
if (languages[base]) {
|
|
53
|
+
return base;
|
|
54
|
+
}
|
|
55
|
+
return Object.entries(languages).toSorted(
|
|
56
|
+
([, a], [, b]) => b.page_count - a.page_count
|
|
57
|
+
)[0]?.[0];
|
|
58
|
+
};
|
|
59
|
+
|
|
16
60
|
/**
|
|
17
61
|
* Pagefind: load the index emitted into the built site and query it. The bundle
|
|
18
62
|
* lives in the output (not `node_modules`), so it is imported at runtime by URL
|
|
19
63
|
* — which is why this only works in the production build, not `dev`.
|
|
64
|
+
*
|
|
65
|
+
* Pagefind keeps an index per language and searches the one for the page's
|
|
66
|
+
* `<html lang>`, which Blume sets to the locale the dialog scopes to. A
|
|
67
|
+
* search scoped to a locale is that index alone; a search across every
|
|
68
|
+
* language (no `locale`) merges every other language's index into it.
|
|
20
69
|
*/
|
|
21
70
|
export const createSearch = async (opts: {
|
|
22
71
|
url: string;
|
|
@@ -24,25 +73,85 @@ export const createSearch = async (opts: {
|
|
|
24
73
|
// The pagefind bundle lives in the built site (not node_modules) and is
|
|
25
74
|
// resolved at runtime by URL — it can't be a static, code-splittable path.
|
|
26
75
|
// SAFETY: the URL points at the `pagefind.js` module our own build emitted,
|
|
27
|
-
// whose export contract (`
|
|
76
|
+
// whose export contract (`createInstance()`) is fixed by pagefind.
|
|
28
77
|
// oxlint-disable-next-line react-doctor/no-dynamic-import-path
|
|
29
78
|
const pagefind = (await import(
|
|
30
79
|
/* @vite-ignore */
|
|
31
80
|
opts.url
|
|
32
81
|
)) as PagefindModule;
|
|
82
|
+
// The bundle's folder, which holds the entry file and every language's index.
|
|
83
|
+
const bundle = new URL("./", new URL(opts.url, document.baseURI));
|
|
84
|
+
// `baseUrl` "/" keeps result URLs base-less routes, like every other
|
|
85
|
+
// provider's: by default Pagefind prefixes the folder the bundle is served
|
|
86
|
+
// under, and the dialog adds the deployment base itself.
|
|
87
|
+
const create = (): PagefindInstance =>
|
|
88
|
+
pagefind.createInstance({ basePath: bundle.pathname, baseUrl: "/" });
|
|
89
|
+
|
|
90
|
+
// Every language's index: the page's own, and every other one merged in.
|
|
91
|
+
const everyLanguage = async (language: string): Promise<PagefindInstance> => {
|
|
92
|
+
const instance = create();
|
|
93
|
+
const response = await fetch(new URL("pagefind-entry.json", bundle));
|
|
94
|
+
// SAFETY: the entry file is the one Pagefind wrote into this bundle.
|
|
95
|
+
const { languages } = (await response.json()) as PagefindEntry;
|
|
96
|
+
const own = loadedLanguage(languages, language);
|
|
97
|
+
// Pagefind skips a merge whose path its own `basePath` starts with, as
|
|
98
|
+
// the same index twice, so the bundle is merged by its full URL.
|
|
99
|
+
await Promise.all(
|
|
100
|
+
Object.keys(languages)
|
|
101
|
+
.filter((code) => code !== own)
|
|
102
|
+
.map((code) =>
|
|
103
|
+
instance.mergeIndex(bundle.href, { baseUrl: "/", language: code })
|
|
104
|
+
)
|
|
105
|
+
);
|
|
106
|
+
return instance;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
// Pagefind reads the page's language once, when an instance is created. A
|
|
110
|
+
// client-side language switch changes the page's language without a
|
|
111
|
+
// reload, so each language gets its own instance, created on its first
|
|
112
|
+
// search: after the switch, search moves to the new page's index. The
|
|
113
|
+
// every-language instance is one for the whole page load.
|
|
114
|
+
const instances = new Map<string, Promise<PagefindInstance>>();
|
|
115
|
+
const cached = (
|
|
116
|
+
key: string,
|
|
117
|
+
load: () => Promise<PagefindInstance>
|
|
118
|
+
): Promise<PagefindInstance> => {
|
|
119
|
+
const existing = instances.get(key);
|
|
120
|
+
if (existing) {
|
|
121
|
+
return existing;
|
|
122
|
+
}
|
|
123
|
+
const loading = (async () => {
|
|
124
|
+
try {
|
|
125
|
+
return await load();
|
|
126
|
+
} catch (error) {
|
|
127
|
+
// A failed load (the entry file's fetch, say) is forgotten, so the
|
|
128
|
+
// next search retries it.
|
|
129
|
+
instances.delete(key);
|
|
130
|
+
throw error;
|
|
131
|
+
}
|
|
132
|
+
})();
|
|
133
|
+
instances.set(key, loading);
|
|
134
|
+
return loading;
|
|
135
|
+
};
|
|
136
|
+
|
|
33
137
|
// Pagefind builds its own marked-up excerpt; we keep its `<mark>` highlights
|
|
34
138
|
// (dropping any other markup — the excerpt is rendered via innerHTML) and
|
|
35
139
|
// only highlight the title ourselves. It carries no section/breadcrumb data,
|
|
36
140
|
// so pills stay hidden and the preview pane falls back to the excerpt.
|
|
37
|
-
return async (query) => {
|
|
38
|
-
|
|
141
|
+
return async (query, options) => {
|
|
142
|
+
// Lowercased like Pagefind's own reading, which names the entry's indexes.
|
|
143
|
+
const language = document.documentElement.lang.toLowerCase() || "unknown";
|
|
144
|
+
const instance = await (options?.locale
|
|
145
|
+
? cached(language, () => Promise.resolve(create()))
|
|
146
|
+
: cached("*", () => everyLanguage(language)));
|
|
147
|
+
const response = await instance.search(query);
|
|
39
148
|
const docs = await Promise.all(
|
|
40
149
|
response.results.slice(0, SEARCH_LIMIT).map((result) => result.data())
|
|
41
150
|
);
|
|
42
151
|
const hits = docs.map((doc) => ({
|
|
43
152
|
excerpt: sanitizeExcerpt(doc.excerpt),
|
|
44
153
|
title: highlight(doc.meta?.title ?? doc.url, query),
|
|
45
|
-
url: doc.url,
|
|
154
|
+
url: doc.url.replace(TRAILING_SLASH, ""),
|
|
46
155
|
}));
|
|
47
156
|
return { hits, sections: [] };
|
|
48
157
|
};
|
|
@@ -43,6 +43,18 @@ export type SearchFn = (
|
|
|
43
43
|
}
|
|
44
44
|
) => Promise<SearchResult>;
|
|
45
45
|
|
|
46
|
+
/** What a caller tells `createSearch` (`blume:search-client`) about its queries. */
|
|
47
|
+
export interface SearchClientOptions {
|
|
48
|
+
/**
|
|
49
|
+
* The queries come from a reader typing, as in the search dialog, so each
|
|
50
|
+
* one supersedes the last. The server-proxied client (Mixedbread), whose
|
|
51
|
+
* endpoint is rate-limited, then waits for a pause in typing before it
|
|
52
|
+
* sends a query and aborts the one a newer query supersedes. Other
|
|
53
|
+
* providers ignore it.
|
|
54
|
+
*/
|
|
55
|
+
typing?: boolean;
|
|
56
|
+
}
|
|
57
|
+
|
|
46
58
|
/** A document in the client-loaded `blume-search.json` index. */
|
|
47
59
|
export interface IndexedDocument {
|
|
48
60
|
route: string;
|
|
@@ -53,8 +65,28 @@ export interface IndexedDocument {
|
|
|
53
65
|
section?: string;
|
|
54
66
|
locale?: string;
|
|
55
67
|
version?: string;
|
|
68
|
+
/** The page's relevance multiplier (`search.boost`). */
|
|
69
|
+
boost?: number;
|
|
70
|
+
/** Extra terms the page is found by (`search.keywords`). */
|
|
71
|
+
keywords?: string[];
|
|
56
72
|
}
|
|
57
73
|
|
|
74
|
+
/** Something ranked with a relevance score, and the page it belongs to. */
|
|
75
|
+
export interface ScoredMatch<Match> {
|
|
76
|
+
boost?: number;
|
|
77
|
+
match: Match;
|
|
78
|
+
score: number;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Re-rank matches by score times their page's `search.boost`. The sort is
|
|
83
|
+
* stable, so equal scores keep the provider's order.
|
|
84
|
+
*/
|
|
85
|
+
export const byBoost = <Match>(scored: ScoredMatch<Match>[]): Match[] =>
|
|
86
|
+
scored
|
|
87
|
+
.toSorted((a, b) => b.score * (b.boost ?? 1) - a.score * (a.boost ?? 1))
|
|
88
|
+
.map(({ match }) => match);
|
|
89
|
+
|
|
58
90
|
/** Max results surfaced in the dialog. */
|
|
59
91
|
export const SEARCH_LIMIT = 12;
|
|
60
92
|
|
|
@@ -17,10 +17,19 @@ interface TypesenseRecord extends Record<string, unknown> {
|
|
|
17
17
|
* key. Documents are imported at build time by the sync step. Every adapter
|
|
18
18
|
* option Blume doesn't read (`connectionTimeoutSeconds`, `numRetries`, …) is
|
|
19
19
|
* the site's own client option and goes to the `Client` untouched; the named
|
|
20
|
-
* connection options still decide `apiKey` and `nodes`.
|
|
20
|
+
* connection options still decide `apiKey` and `nodes`. `locale` is the
|
|
21
|
+
* sync's: Typesense tokenizes a query for the fields it searches.
|
|
21
22
|
*/
|
|
22
23
|
export const createSearch = (opts: TypesenseOptions): SearchFn => {
|
|
23
|
-
const {
|
|
24
|
+
const {
|
|
25
|
+
apiKey,
|
|
26
|
+
collection,
|
|
27
|
+
host,
|
|
28
|
+
locale: _locale,
|
|
29
|
+
port,
|
|
30
|
+
protocol,
|
|
31
|
+
...clientOptions
|
|
32
|
+
} = opts;
|
|
24
33
|
const client = new Client({
|
|
25
34
|
...clientOptions,
|
|
26
35
|
apiKey,
|
|
@@ -34,7 +43,14 @@ export const createSearch = (opts: TypesenseOptions): SearchFn => {
|
|
|
34
43
|
{
|
|
35
44
|
per_page: SEARCH_LIMIT,
|
|
36
45
|
q: query,
|
|
37
|
-
query_by: "title,description,content",
|
|
46
|
+
query_by: "title,keywords,description,content",
|
|
47
|
+
// Relevance first, then each page's `search.boost` among pages that
|
|
48
|
+
// match equally well: a boost settles a tie without floating a page
|
|
49
|
+
// over a better match. Bucketing the relevance instead
|
|
50
|
+
// (`_text_match(buckets: 10)`) ranks by boost alone inside each
|
|
51
|
+
// bucket, so at equal boosts a bucket falls back to indexing order
|
|
52
|
+
// and the best match can land behind weaker ones.
|
|
53
|
+
sort_by: "_text_match:desc,boost:desc",
|
|
38
54
|
// The sync marks `locale` and `version` as facets so hosted results
|
|
39
55
|
// scope to the active language and the viewed docs version (the
|
|
40
56
|
// current docs upload as "current").
|
|
@@ -7,11 +7,12 @@ import { asyncApiOperationObject } from "../../openapi/asyncapi.ts";
|
|
|
7
7
|
import { operationOf, specOf } from "../../openapi/model.ts";
|
|
8
8
|
import { highlightCode } from "../../markdown/index.ts";
|
|
9
9
|
import {
|
|
10
|
-
|
|
10
|
+
asyncApiSecurity,
|
|
11
11
|
bindingGroups,
|
|
12
12
|
channelParameters,
|
|
13
|
-
|
|
13
|
+
kafkaTopic,
|
|
14
14
|
messageLabel,
|
|
15
|
+
namedChannelServers,
|
|
15
16
|
operationMessages,
|
|
16
17
|
payloadSchema,
|
|
17
18
|
protocolOf,
|
|
@@ -33,7 +34,6 @@ import PanelTabs from "./PanelTabs.astro";
|
|
|
33
34
|
import ParametersTable from "./ParametersTable.astro";
|
|
34
35
|
import SchemaTable from "./SchemaTable.astro";
|
|
35
36
|
import type { SecuritySchemeLike } from "./security.ts";
|
|
36
|
-
import { resolveAsyncApiSecurity } from "./security.ts";
|
|
37
37
|
import OperationPanel from "./OperationPanel.astro";
|
|
38
38
|
|
|
39
39
|
/**
|
|
@@ -61,9 +61,11 @@ const schemas = (document.components?.schemas ?? {}) as Record<
|
|
|
61
61
|
string,
|
|
62
62
|
SchemaLike
|
|
63
63
|
>;
|
|
64
|
-
const
|
|
65
|
-
const
|
|
66
|
-
|
|
64
|
+
const namedServers = namedChannelServers(channel, document);
|
|
65
|
+
const servers = namedServers.map(({ server }) => server);
|
|
66
|
+
const security = asyncApiSecurity(
|
|
67
|
+
operation,
|
|
68
|
+
namedServers,
|
|
67
69
|
document.components?.securitySchemes as
|
|
68
70
|
| Record<string, SecuritySchemeLike>
|
|
69
71
|
| undefined
|
|
@@ -96,10 +98,15 @@ const messagePanels = await Promise.all(
|
|
|
96
98
|
|
|
97
99
|
// One derived model feeds the static default sample, the composer form, and
|
|
98
100
|
// (client-side) the live samples + WebSocket frame — they can never drift.
|
|
101
|
+
// A Kafka channel binding's `topic` names the real topic when the address
|
|
102
|
+
// doesn't, so the samples use it.
|
|
103
|
+
const topic =
|
|
104
|
+
protocol === "kafka" ? kafkaTopic(channel, document.components) : undefined;
|
|
99
105
|
const model = ref
|
|
100
106
|
? messageModel({
|
|
101
107
|
action: ref.method === "send" ? "send" : "receive",
|
|
102
|
-
address: ref.path,
|
|
108
|
+
address: topic ?? ref.path,
|
|
109
|
+
components: document.components,
|
|
103
110
|
messages,
|
|
104
111
|
parameters,
|
|
105
112
|
protocol,
|
|
@@ -28,6 +28,13 @@ const { security } = Astro.props;
|
|
|
28
28
|
Optional — this operation also accepts unauthenticated requests.
|
|
29
29
|
</p>
|
|
30
30
|
)}
|
|
31
|
+
{security.unauthenticatedServers &&
|
|
32
|
+
security.unauthenticatedServers.length > 0 && (
|
|
33
|
+
<p class="mb-2 text-muted-foreground text-sm">
|
|
34
|
+
No authorization needed on{" "}
|
|
35
|
+
{security.unauthenticatedServers.join(", ")}.
|
|
36
|
+
</p>
|
|
37
|
+
)}
|
|
31
38
|
{security.alternatives.map((alternative, index) => (
|
|
32
39
|
<>
|
|
33
40
|
{index > 0 && (
|
|
@@ -47,6 +54,9 @@ const { security } = Astro.props;
|
|
|
47
54
|
<span class="text-muted-foreground text-xs">
|
|
48
55
|
{schemeLabel(resolved)}
|
|
49
56
|
{carrier ? ` · ${carrier.in}` : ""}
|
|
57
|
+
{resolved.servers
|
|
58
|
+
? ` · on ${resolved.servers.join(", ")}`
|
|
59
|
+
: ""}
|
|
50
60
|
</span>
|
|
51
61
|
{!security.optional && (
|
|
52
62
|
<span class="font-medium text-[0.625rem] text-red-600 uppercase tracking-wide dark:text-red-400">
|
|
@@ -19,10 +19,12 @@ import {
|
|
|
19
19
|
exampleVariables,
|
|
20
20
|
graphqlPlaygroundModel,
|
|
21
21
|
graphqlRoutes,
|
|
22
|
+
graphqlSecurity,
|
|
22
23
|
} from "./graphql-helpers.ts";
|
|
23
24
|
import { buildRequest, defaultValues } from "./request.ts";
|
|
24
25
|
import { languageSamplePanels } from "./sample-panels.ts";
|
|
25
26
|
import { sampleLanguages } from "./snippets.ts";
|
|
27
|
+
import Authorization from "./Authorization.astro";
|
|
26
28
|
import Description from "./Description.astro";
|
|
27
29
|
import GraphqlChip from "./GraphqlChip.astro";
|
|
28
30
|
import GraphqlFieldsTable from "./GraphqlFieldsTable.astro";
|
|
@@ -107,6 +109,7 @@ const responsePanels =
|
|
|
107
109
|
: [];
|
|
108
110
|
|
|
109
111
|
const returnRoute = field ? routes.get(field.type.name) : undefined;
|
|
112
|
+
const security = spec ? graphqlSecurity(spec) : undefined;
|
|
110
113
|
---
|
|
111
114
|
|
|
112
115
|
{
|
|
@@ -134,6 +137,7 @@ const returnRoute = field ? routes.get(field.type.name) : undefined;
|
|
|
134
137
|
Deprecated: <span set:text={field.deprecationReason} />
|
|
135
138
|
</p>
|
|
136
139
|
)}
|
|
140
|
+
{security && <Authorization security={security} />}
|
|
137
141
|
<GraphqlFieldsTable
|
|
138
142
|
routes={routes}
|
|
139
143
|
rows={field.args}
|
|
@@ -169,6 +173,7 @@ const returnRoute = field ? routes.get(field.type.name) : undefined;
|
|
|
169
173
|
model={model}
|
|
170
174
|
operation={id}
|
|
171
175
|
proxy={spec.playground.proxy}
|
|
176
|
+
proxyConfig="graphql"
|
|
172
177
|
slug={spec.slug}
|
|
173
178
|
/>
|
|
174
179
|
)}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
import specs from "blume:openapi";
|
|
3
|
-
import { operationOf, specOf } from "../../openapi/model.ts";
|
|
3
|
+
import { HTTP_METHODS, operationOf, specOf } from "../../openapi/model.ts";
|
|
4
4
|
import {
|
|
5
5
|
mergeParameters,
|
|
6
6
|
type ParameterLike,
|
|
@@ -21,10 +21,13 @@ import {
|
|
|
21
21
|
type SecuritySchemeLike,
|
|
22
22
|
} from "./security.ts";
|
|
23
23
|
import { DEPRECATED_LABEL_CLASS } from "../colors.ts";
|
|
24
|
+
import { customCodeSamples } from "./code-samples.ts";
|
|
25
|
+
import type { CodeSamplesCarrier } from "./code-samples.ts";
|
|
24
26
|
import { sampleLanguages } from "./snippets.ts";
|
|
25
27
|
import AsyncApiOperation from "./AsyncApiOperation.astro";
|
|
26
28
|
import GraphqlOperation from "./GraphqlOperation.astro";
|
|
27
29
|
import Authorization from "./Authorization.astro";
|
|
30
|
+
import Description from "./Description.astro";
|
|
28
31
|
import MethodBadge from "./MethodBadge.astro";
|
|
29
32
|
import ParametersTable from "./ParametersTable.astro";
|
|
30
33
|
import Playground from "./Playground.astro";
|
|
@@ -57,7 +60,18 @@ interface ResponseLike {
|
|
|
57
60
|
content?: Record<string, MediaTypeLike>;
|
|
58
61
|
}
|
|
59
62
|
|
|
60
|
-
|
|
63
|
+
/**
|
|
64
|
+
* One callback: a map of runtime URL expressions
|
|
65
|
+
* (`{$request.body#/callbackUrl}`) to the path item the API will call there,
|
|
66
|
+
* or a `$ref` to one under `components.callbacks`.
|
|
67
|
+
*/
|
|
68
|
+
type CallbackLike = { $ref?: string } & Record<
|
|
69
|
+
string,
|
|
70
|
+
Record<string, unknown> | string | undefined
|
|
71
|
+
>;
|
|
72
|
+
|
|
73
|
+
interface FullOperation extends CodeSamplesCarrier {
|
|
74
|
+
callbacks?: Record<string, CallbackLike>;
|
|
61
75
|
summary?: string;
|
|
62
76
|
description?: string;
|
|
63
77
|
deprecated?: boolean;
|
|
@@ -77,15 +91,17 @@ const ref = spec ? operationOf(spec, id) : undefined;
|
|
|
77
91
|
const isAsyncApi = spec?.kind === "asyncapi";
|
|
78
92
|
const isGraphql = spec?.kind === "graphql";
|
|
79
93
|
|
|
94
|
+
type PathItemLike = Record<string, unknown> & {
|
|
95
|
+
parameters?: ParameterLike[];
|
|
96
|
+
servers?: ServerLike[];
|
|
97
|
+
};
|
|
98
|
+
|
|
80
99
|
const doc = (spec?.document ?? {}) as {
|
|
81
|
-
paths?: Record<
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
parameters?: ParameterLike[];
|
|
85
|
-
servers?: ServerLike[];
|
|
86
|
-
}
|
|
87
|
-
>;
|
|
100
|
+
paths?: Record<string, PathItemLike>;
|
|
101
|
+
// OpenAPI 3.1 webhooks: requests the API sends, keyed by name.
|
|
102
|
+
webhooks?: Record<string, PathItemLike>;
|
|
88
103
|
components?: {
|
|
104
|
+
callbacks?: Record<string, CallbackLike>;
|
|
89
105
|
schemas?: Record<string, SchemaLike>;
|
|
90
106
|
parameters?: Record<string, ParameterLike>;
|
|
91
107
|
requestBodies?: Record<string, RequestBodyLike>;
|
|
@@ -95,7 +111,12 @@ const doc = (spec?.document ?? {}) as {
|
|
|
95
111
|
security?: SecurityRequirementLike[];
|
|
96
112
|
servers?: ServerLike[];
|
|
97
113
|
};
|
|
98
|
-
const
|
|
114
|
+
const isWebhook = ref?.webhook === true;
|
|
115
|
+
const pathItem = ref
|
|
116
|
+
? isWebhook
|
|
117
|
+
? doc.webhooks?.[ref.path]
|
|
118
|
+
: doc.paths?.[ref.path]
|
|
119
|
+
: undefined;
|
|
99
120
|
const operation = (
|
|
100
121
|
pathItem && ref ? pathItem[ref.method] : undefined
|
|
101
122
|
) as FullOperation | undefined;
|
|
@@ -110,6 +131,10 @@ const params = mergeParameters(
|
|
|
110
131
|
const requestBody = operation?.requestBody
|
|
111
132
|
? resolveComponentRef(operation.requestBody, components, "requestBodies")
|
|
112
133
|
: undefined;
|
|
134
|
+
// A request body table leaves out `readOnly` fields. A webhook's or
|
|
135
|
+
// callback's body is a request the API sends, so it reads like a response
|
|
136
|
+
// (and like its payload example): `readOnly` fields in, `writeOnly` out.
|
|
137
|
+
const bodyDirection = isWebhook ? "response" : "request";
|
|
113
138
|
const responses = Object.fromEntries(
|
|
114
139
|
Object.entries(operation?.responses ?? {}).map(([status, response]) => [
|
|
115
140
|
status,
|
|
@@ -118,14 +143,16 @@ const responses = Object.fromEntries(
|
|
|
118
143
|
);
|
|
119
144
|
|
|
120
145
|
const security = resolveSecurity(
|
|
121
|
-
effectiveSecurity(operation?.security, doc.security),
|
|
146
|
+
effectiveSecurity(operation?.security, doc.security, isWebhook),
|
|
122
147
|
doc.components?.securitySchemes
|
|
123
148
|
);
|
|
124
149
|
|
|
125
150
|
// One derived model feeds the static default sample, the playground form,
|
|
126
|
-
// and (client-side) the live samples + fetch — they can never drift apart.
|
|
151
|
+
// and (client-side) the live samples + fetch — they can never drift apart. A
|
|
152
|
+
// webhook has none: the API sends it, so there is nothing for a reader to
|
|
153
|
+
// call, and its rail shows the payload instead.
|
|
127
154
|
const model =
|
|
128
|
-
ref && operation
|
|
155
|
+
ref && operation && !isWebhook
|
|
129
156
|
? operationModel({
|
|
130
157
|
components,
|
|
131
158
|
method: ref.method,
|
|
@@ -145,6 +172,70 @@ const model =
|
|
|
145
172
|
: null;
|
|
146
173
|
const sample = model ? buildRequest(model, defaultValues(model)) : null;
|
|
147
174
|
const languages = sampleLanguages(spec?.codeSamples ?? []);
|
|
175
|
+
// The spec's own `x-codeSamples`, shown ahead of the generated ones.
|
|
176
|
+
const customSamples = operation ? customCodeSamples(operation) : [];
|
|
177
|
+
|
|
178
|
+
/** One request the API makes back to the reader, flattened for rendering. */
|
|
179
|
+
interface CallbackEntry {
|
|
180
|
+
expression: string;
|
|
181
|
+
key: string;
|
|
182
|
+
method: string;
|
|
183
|
+
name: string;
|
|
184
|
+
operation: FullOperation;
|
|
185
|
+
/** The callback path item's own parameters, which each method inherits. */
|
|
186
|
+
pathParameters?: ParameterLike[];
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Callbacks: for each named callback (resolved through
|
|
190
|
+
// `components.callbacks`), each URL expression, each method it declares.
|
|
191
|
+
const callbacks: CallbackEntry[] = Object.entries(
|
|
192
|
+
operation?.callbacks ?? {}
|
|
193
|
+
).flatMap(([name, raw]) => {
|
|
194
|
+
const callback = resolveComponentRef(raw, components, "callbacks");
|
|
195
|
+
return Object.entries(callback).flatMap(([expression, item]) => {
|
|
196
|
+
if (expression === "$ref" || typeof item !== "object" || item === null) {
|
|
197
|
+
return [];
|
|
198
|
+
}
|
|
199
|
+
return HTTP_METHODS.flatMap((method) => {
|
|
200
|
+
const entry = item[method];
|
|
201
|
+
return typeof entry === "object" && entry !== null
|
|
202
|
+
? [
|
|
203
|
+
{
|
|
204
|
+
expression,
|
|
205
|
+
key: `${name}-${expression}-${method}`,
|
|
206
|
+
method,
|
|
207
|
+
name,
|
|
208
|
+
// SAFETY: a path item's method entry is an operation object; the
|
|
209
|
+
// object check above guards a spec that put a scalar there.
|
|
210
|
+
operation: entry as FullOperation,
|
|
211
|
+
// SAFETY: the object check above passed, and a path item's
|
|
212
|
+
// `parameters` is a parameter list, which `mergeParameters`
|
|
213
|
+
// reads the way it reads an operation's.
|
|
214
|
+
pathParameters: (item as PathItemLike).parameters,
|
|
215
|
+
},
|
|
216
|
+
]
|
|
217
|
+
: [];
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
/** A callback's parameters, request body, and responses, `$ref`s resolved. */
|
|
223
|
+
const callbackParts = (entry: CallbackEntry) => ({
|
|
224
|
+
parameters: mergeParameters(
|
|
225
|
+
entry.pathParameters,
|
|
226
|
+
entry.operation.parameters,
|
|
227
|
+
components
|
|
228
|
+
),
|
|
229
|
+
requestBody: entry.operation.requestBody
|
|
230
|
+
? resolveComponentRef(entry.operation.requestBody, components, "requestBodies")
|
|
231
|
+
: undefined,
|
|
232
|
+
responses: Object.fromEntries(
|
|
233
|
+
Object.entries(entry.operation.responses ?? {}).map(([status, response]) => [
|
|
234
|
+
status,
|
|
235
|
+
resolveComponentRef(response, components, "responses"),
|
|
236
|
+
])
|
|
237
|
+
),
|
|
238
|
+
});
|
|
148
239
|
---
|
|
149
240
|
{
|
|
150
241
|
isAsyncApi ? (
|
|
@@ -160,6 +251,11 @@ const languages = sampleLanguages(spec?.codeSamples ?? []);
|
|
|
160
251
|
<code class="break-all font-mono text-foreground text-sm">
|
|
161
252
|
{ref.path}
|
|
162
253
|
</code>
|
|
254
|
+
{isWebhook && (
|
|
255
|
+
<span class="rounded-md border border-border px-1.5 py-0.5 font-medium text-[0.625rem] text-muted-foreground uppercase tracking-wide">
|
|
256
|
+
Webhook
|
|
257
|
+
</span>
|
|
258
|
+
)}
|
|
163
259
|
{operation.deprecated && (
|
|
164
260
|
<span class={DEPRECATED_LABEL_CLASS}>
|
|
165
261
|
deprecated
|
|
@@ -172,6 +268,7 @@ const languages = sampleLanguages(spec?.codeSamples ?? []);
|
|
|
172
268
|
<ParametersTable parameters={params} schemas={schemas} />
|
|
173
269
|
{requestBody && (
|
|
174
270
|
<RequestBody
|
|
271
|
+
direction={bodyDirection}
|
|
175
272
|
expandAll={spec.expandSchemas}
|
|
176
273
|
requestBody={requestBody}
|
|
177
274
|
schemas={schemas}
|
|
@@ -184,7 +281,79 @@ const languages = sampleLanguages(spec?.codeSamples ?? []);
|
|
|
184
281
|
schemas={schemas}
|
|
185
282
|
/>
|
|
186
283
|
)}
|
|
284
|
+
{callbacks.length > 0 && (
|
|
285
|
+
<section class="mt-10">
|
|
286
|
+
<div
|
|
287
|
+
aria-level="2"
|
|
288
|
+
class="mb-3 font-semibold text-foreground text-lg"
|
|
289
|
+
role="heading"
|
|
290
|
+
>
|
|
291
|
+
Callbacks
|
|
292
|
+
</div>
|
|
293
|
+
<div class="flex flex-col gap-6">
|
|
294
|
+
{callbacks.map((entry) => {
|
|
295
|
+
const parts = callbackParts(entry);
|
|
296
|
+
return (
|
|
297
|
+
<div class="rounded-blume border border-border p-4">
|
|
298
|
+
<div
|
|
299
|
+
aria-level="3"
|
|
300
|
+
class="font-semibold text-foreground"
|
|
301
|
+
role="heading"
|
|
302
|
+
>
|
|
303
|
+
{entry.operation.summary || entry.name}
|
|
304
|
+
</div>
|
|
305
|
+
<div class="mt-2 flex flex-wrap items-center gap-2">
|
|
306
|
+
<MethodBadge method={entry.method} />
|
|
307
|
+
<code class="break-all font-mono text-muted-foreground text-xs">
|
|
308
|
+
{entry.expression}
|
|
309
|
+
</code>
|
|
310
|
+
</div>
|
|
311
|
+
{entry.operation.description && (
|
|
312
|
+
<Description
|
|
313
|
+
class="mt-2 text-muted-foreground text-sm"
|
|
314
|
+
text={entry.operation.description}
|
|
315
|
+
/>
|
|
316
|
+
)}
|
|
317
|
+
<ParametersTable
|
|
318
|
+
level={4}
|
|
319
|
+
parameters={parts.parameters}
|
|
320
|
+
schemas={schemas}
|
|
321
|
+
/>
|
|
322
|
+
{parts.requestBody && (
|
|
323
|
+
<RequestBody
|
|
324
|
+
direction="response"
|
|
325
|
+
expandAll={spec.expandSchemas}
|
|
326
|
+
level={4}
|
|
327
|
+
requestBody={parts.requestBody}
|
|
328
|
+
schemas={schemas}
|
|
329
|
+
/>
|
|
330
|
+
)}
|
|
331
|
+
{entry.operation.responses && (
|
|
332
|
+
<Responses
|
|
333
|
+
expandAll={spec.expandSchemas}
|
|
334
|
+
level={4}
|
|
335
|
+
responses={parts.responses}
|
|
336
|
+
schemas={schemas}
|
|
337
|
+
/>
|
|
338
|
+
)}
|
|
339
|
+
</div>
|
|
340
|
+
);
|
|
341
|
+
})}
|
|
342
|
+
</div>
|
|
343
|
+
</section>
|
|
344
|
+
)}
|
|
187
345
|
</div>
|
|
346
|
+
{isWebhook && (requestBody?.content || operation.responses) && (
|
|
347
|
+
<OperationPanel>
|
|
348
|
+
<RequestPanel
|
|
349
|
+
components={components}
|
|
350
|
+
customSamples={customSamples}
|
|
351
|
+
payload={requestBody?.content}
|
|
352
|
+
responses={responses}
|
|
353
|
+
schemas={schemas}
|
|
354
|
+
/>
|
|
355
|
+
</OperationPanel>
|
|
356
|
+
)}
|
|
188
357
|
{sample && model && (
|
|
189
358
|
<OperationPanel>
|
|
190
359
|
{spec.playground.enabled && (
|
|
@@ -192,11 +361,13 @@ const languages = sampleLanguages(spec?.codeSamples ?? []);
|
|
|
192
361
|
model={model}
|
|
193
362
|
operation={id}
|
|
194
363
|
proxy={spec.playground.proxy}
|
|
364
|
+
proxyConfig="openapi"
|
|
195
365
|
slug={spec.slug}
|
|
196
366
|
/>
|
|
197
367
|
)}
|
|
198
368
|
<RequestPanel
|
|
199
369
|
components={components}
|
|
370
|
+
customSamples={customSamples}
|
|
200
371
|
languages={languages}
|
|
201
372
|
responses={responses}
|
|
202
373
|
sample={sample}
|