blume 2.0.3 → 2.1.0
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 +48 -0
- package/README.md +1 -1
- package/dist/cli/{chunk-1d7ve1dm.js → chunk-0gz36akr.js} +18 -2
- package/dist/cli/{chunk-1d7ve1dm.js.map → chunk-0gz36akr.js.map} +3 -3
- package/dist/cli/{chunk-2eytanqx.js → chunk-1n228xqb.js} +2 -2
- package/dist/cli/{chunk-yfyb25rh.js → chunk-2f3ndkpw.js} +24 -8
- package/dist/cli/chunk-2f3ndkpw.js.map +14 -0
- package/dist/cli/{chunk-r20tn01b.js → chunk-2f7n4qzt.js} +8 -2
- package/dist/cli/{chunk-r20tn01b.js.map → chunk-2f7n4qzt.js.map} +3 -3
- package/dist/cli/{chunk-35d4wj9f.js → chunk-2n4ps1b3.js} +7 -7
- package/dist/cli/{chunk-j85vccga.js → chunk-43zcf4gz.js} +97 -57
- package/dist/cli/{chunk-j85vccga.js.map → chunk-43zcf4gz.js.map} +6 -6
- package/dist/cli/{chunk-e04dxsz1.js → chunk-4ejxbzee.js} +1 -1
- package/dist/cli/{chunk-5m5nmvyq.js → chunk-4h8z9vv5.js} +233 -39
- package/dist/cli/chunk-4h8z9vv5.js.map +16 -0
- package/dist/cli/{chunk-5f86nr5m.js → chunk-5cg2rzgf.js} +18 -16
- package/dist/cli/{chunk-5f86nr5m.js.map → chunk-5cg2rzgf.js.map} +2 -2
- package/dist/cli/{chunk-tzmab476.js → chunk-5ffywsmb.js} +4 -4
- package/dist/cli/{chunk-2z928egk.js → chunk-5wj2qwn2.js} +5 -5
- package/dist/cli/chunk-6bm0xpgd.js +18 -0
- package/dist/cli/chunk-6bm0xpgd.js.map +10 -0
- package/dist/cli/{chunk-vg9r4eb9.js → chunk-713mngdq.js} +12 -5
- package/dist/cli/{chunk-vg9r4eb9.js.map → chunk-713mngdq.js.map} +3 -3
- package/dist/cli/{chunk-5xvm6tfj.js → chunk-9geymqns.js} +17 -15
- package/dist/cli/{chunk-5xvm6tfj.js.map → chunk-9geymqns.js.map} +2 -2
- package/dist/cli/{chunk-q58y5e6a.js → chunk-9xr4dgee.js} +26 -17
- package/dist/cli/chunk-9xr4dgee.js.map +10 -0
- package/dist/cli/{chunk-b07cmahc.js → chunk-amrb6hgh.js} +2 -2
- package/dist/cli/chunk-cm89scdv.js +443 -0
- package/dist/cli/chunk-cm89scdv.js.map +11 -0
- package/dist/cli/{chunk-akbpwfxc.js → chunk-cmtcnh9f.js} +2 -2
- package/dist/cli/chunk-cy5bm0j0.js +104 -0
- package/dist/cli/chunk-cy5bm0j0.js.map +11 -0
- package/dist/cli/{chunk-crgn1q09.js → chunk-e7vvk5ya.js} +4 -4
- package/dist/cli/{chunk-pehfxfta.js → chunk-g2z9x01v.js} +6 -98
- package/dist/cli/chunk-g2z9x01v.js.map +10 -0
- package/dist/cli/{chunk-tkacnehg.js → chunk-gp84za0h.js} +2 -2
- package/dist/cli/{chunk-wrr3j9w9.js → chunk-h2a48yhd.js} +186 -63
- package/dist/cli/chunk-h2a48yhd.js.map +36 -0
- package/dist/cli/{chunk-hm3vjy5s.js → chunk-jnwj5kjj.js} +14 -9
- package/dist/cli/{chunk-hm3vjy5s.js.map → chunk-jnwj5kjj.js.map} +4 -4
- package/dist/cli/chunk-kwrg63tm.js +31 -0
- package/dist/cli/chunk-kwrg63tm.js.map +10 -0
- package/dist/cli/{chunk-2hsdwb9n.js → chunk-nd1821sk.js} +18 -16
- package/dist/cli/{chunk-2hsdwb9n.js.map → chunk-nd1821sk.js.map} +2 -2
- package/dist/cli/{chunk-6dsbexzp.js → chunk-ntv4qrt7.js} +17 -15
- package/dist/cli/{chunk-6dsbexzp.js.map → chunk-ntv4qrt7.js.map} +2 -2
- package/dist/cli/{chunk-r9rcc4w7.js → chunk-p804f3pe.js} +7 -7
- package/dist/cli/{chunk-ey84smr6.js → chunk-py62fewh.js} +6 -6
- package/dist/cli/{chunk-ey84smr6.js.map → chunk-py62fewh.js.map} +1 -1
- package/dist/cli/chunk-q3wxxq39.js +126 -0
- package/dist/cli/chunk-q3wxxq39.js.map +11 -0
- package/dist/cli/{chunk-9t7a85s3.js → chunk-rekqz4qg.js} +23 -13
- package/dist/cli/chunk-rekqz4qg.js.map +10 -0
- package/dist/cli/{chunk-8ktnccpt.js → chunk-ta27feev.js} +1 -1
- package/dist/cli/{chunk-pv29h0wf.js → chunk-xkz5xbtv.js} +3476 -822
- package/dist/cli/chunk-xkz5xbtv.js.map +213 -0
- package/dist/cli/{chunk-a58773jm.js → chunk-y4ykbark.js} +2 -2
- package/dist/cli/{chunk-p3v96n38.js → chunk-y5h4r2y0.js} +4 -4
- package/dist/cli/{chunk-acanzt5p.js → chunk-yj17vs39.js} +6 -6
- package/dist/cli/{chunk-p73c0m7w.js → chunk-yxmk4pec.js} +16 -14
- package/dist/cli/{chunk-p73c0m7w.js.map → chunk-yxmk4pec.js.map} +2 -2
- 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/{chunk-c8chx29p.js → chunk-zf748avv.js} +384 -207
- package/dist/cli/chunk-zf748avv.js.map +37 -0
- package/dist/cli/{chunk-g4hq16wv.js → chunk-zhvd6adm.js} +16 -14
- package/dist/cli/{chunk-g4hq16wv.js.map → chunk-zhvd6adm.js.map} +2 -2
- package/dist/cli/index.js +26 -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 +22 -0
- package/dist/types/ai/ask.d.ts +271 -58
- package/dist/types/ai/index.d.ts +2 -2
- 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 +8 -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/components/content/api-field.d.ts +59 -0
- package/dist/types/components/content/api-page.d.ts +95 -0
- package/dist/types/components/layout/nav-utils.d.ts +26 -0
- package/dist/types/components/openapi/helpers.d.ts +137 -0
- package/dist/types/components/openapi/security.d.ts +85 -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/config-input.d.ts +187 -20
- package/dist/types/core/data.d.ts +49 -4
- package/dist/types/core/footer.d.ts +8 -0
- package/dist/types/core/i18n-ui.d.ts +86 -0
- package/dist/types/core/includes.d.ts +8 -2
- package/dist/types/core/localizable.d.ts +7 -0
- package/dist/types/core/page-modes.d.ts +29 -0
- package/dist/types/core/redirect-patterns.d.ts +144 -0
- package/dist/types/core/related.d.ts +40 -0
- package/dist/types/core/schema.d.ts +551 -56
- package/dist/types/core/sources/read.d.ts +5 -0
- package/dist/types/core/types.d.ts +1 -1
- package/dist/types/core/variables.d.ts +42 -0
- package/dist/types/deploy/node-headers.d.ts +13 -2
- package/dist/types/deploy/platforms/cloudflare.d.ts +5 -0
- package/dist/types/deploy/platforms/netlify.d.ts +7 -0
- package/dist/types/deploy/platforms/vercel.d.ts +6 -0
- package/dist/types/deploy/redirects.d.ts +39 -11
- package/dist/types/deploy/vercel-negotiation.d.ts +9 -0
- 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/model.d.ts +12 -6
- package/dist/types/openapi/overlay.d.ts +54 -0
- package/dist/types/openapi/parse.d.ts +13 -0
- package/dist/types/openapi/references.d.ts +14 -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 +111 -0
- package/dist/types/ratelimit/upstash.d.ts +21 -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 +13 -10
- package/dist/types/reference/openapi.d.ts +33 -12
- package/dist/types/reference/options.d.ts +45 -5
- package/dist/types/reference/scalar.d.ts +13 -0
- package/dist/types/reference/schema.d.ts +60 -36
- package/dist/types/search/documents.d.ts +12 -1
- package/dist/types/search/orama-index.d.ts +4 -0
- package/dist/types/seo/metatags.d.ts +20 -0
- package/docs/02-deployment.mdx +41 -5
- package/docs/03-upgrading.mdx +4 -4
- package/docs/04-migrating.mdx +1 -1
- package/docs/advanced/changelog.mdx +2 -2
- package/docs/advanced/skills.mdx +14 -0
- package/docs/cli/audit.mdx +21 -1
- package/docs/cli/index.mdx +1 -0
- package/docs/configuration/analytics.mdx +3 -1
- package/docs/configuration/assistant.mdx +188 -36
- package/docs/configuration/consent.mdx +100 -0
- package/docs/configuration/customization.mdx +4 -4
- package/docs/configuration/index.mdx +63 -5
- package/docs/configuration/meta.ts +3 -0
- package/docs/configuration/narration.mdx +119 -0
- package/docs/configuration/rate-limiting.mdx +69 -0
- package/docs/configuration/search.mdx +29 -1
- package/docs/configuration/theming.mdx +3 -1
- package/docs/content/components.mdx +106 -0
- package/docs/content/frontmatter.mdx +76 -0
- package/docs/content/i18n.mdx +38 -3
- 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 +28 -6
- package/docs/content/sources/contentful.mdx +32 -0
- package/docs/content/sources/custom.mdx +39 -0
- package/docs/content/sources/github-releases.mdx +31 -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 +30 -0
- package/docs/content/sources/remote-mdx.mdx +40 -0
- package/docs/content/sources/sanity.mdx +29 -0
- package/docs/content/sources/strapi.mdx +31 -0
- package/docs/content/syntax.mdx +67 -2
- package/docs/content/variables.mdx +41 -0
- package/docs/discoverability/agent-discovery.mdx +29 -2
- package/docs/discoverability/index.mdx +1 -1
- package/docs/discoverability/llms-txt.mdx +1 -1
- package/docs/discoverability/metadata.mdx +17 -0
- package/docs/references/api-pages.mdx +74 -0
- package/docs/references/asyncapi.mdx +1 -1
- package/docs/references/graphql.mdx +2 -2
- package/docs/references/meta.ts +1 -1
- package/docs/references/openapi.mdx +102 -3
- package/docs/references/scalar.mdx +3 -1
- package/package.json +36 -1
- package/skills/blume/SKILL.md +3 -0
- package/skills/blume-migrate/SKILL.md +5 -5
- package/skills/blume-migrate/references/docusaurus.md +3 -3
- package/skills/blume-migrate/references/mintlify.md +37 -19
- package/skills/blume-migrate/references/nextra.md +2 -2
- package/skills/blume-migrate/references/starlight.md +2 -1
- 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 +73 -20
- package/src/ai/ask-data.ts +6 -0
- package/src/ai/ask-tools.ts +142 -0
- package/src/ai/ask.ts +354 -76
- package/src/ai/component-markdown.ts +75 -0
- package/src/ai/cors.ts +2 -0
- 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/openapi-components.ts +9 -3
- 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 +132 -18
- package/src/astro/index.ts +1 -0
- package/src/astro/integration.ts +35 -0
- package/src/astro/module-types.ts +6 -0
- package/src/astro/templates.ts +283 -30
- package/src/astro/variables.ts +31 -0
- package/src/audit/catalog.ts +19 -0
- 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 +5 -12
- package/src/audit/checks/sitemap.ts +2 -3
- package/src/audit/redirects.ts +46 -15
- package/src/audit/run.ts +2 -0
- package/src/audit/types.ts +2 -1
- package/src/blume-modules.d.ts +7 -0
- 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/command-meta.ts +5 -0
- package/src/cli/commands/doctor.ts +22 -16
- package/src/cli/commands/skill.ts +96 -0
- package/src/cli/index.ts +5 -0
- package/src/cli/required-secrets.ts +71 -29
- 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 +62 -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 +100 -0
- package/src/components/content/api-page.ts +224 -0
- 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 +110 -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/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 +308 -45
- package/src/components/layout/Search.astro +31 -17
- package/src/components/layout/SiteFooter.astro +124 -0
- package/src/components/layout/SiteMetatags.astro +16 -0
- 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/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/analytics.ts +98 -0
- package/src/components/layout/search/flexsearch.ts +17 -5
- package/src/components/layout/search/orama-cloud.ts +26 -14
- package/src/components/layout/search/types.ts +20 -0
- package/src/components/layout/search/typesense.ts +5 -1
- package/src/components/openapi/Operation.astro +161 -13
- package/src/components/openapi/RequestBody.astro +6 -4
- package/src/components/openapi/RequestPanel.astro +59 -7
- package/src/components/openapi/Responses.astro +6 -4
- package/src/components/openapi/async-snippets.ts +4 -4
- package/src/components/openapi/code-samples.ts +97 -0
- package/src/components/openapi/security.ts +6 -3
- package/src/components/openapi/snippets.ts +869 -8
- 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/client-address.ts +19 -0
- package/src/core/config-input.ts +194 -20
- package/src/core/data.ts +44 -4
- package/src/core/diagnostics.ts +3 -2
- package/src/core/footer.ts +26 -0
- package/src/core/graph.ts +39 -36
- package/src/core/i18n-ui.ts +82 -2
- package/src/core/includes.ts +20 -3
- package/src/core/links.ts +16 -2
- 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/project-graph.ts +111 -5
- package/src/core/redirect-patterns.ts +491 -0
- package/src/core/related.ts +131 -0
- package/src/core/schema.ts +318 -64
- package/src/core/sources/normalize.ts +2 -1
- package/src/core/sources/read.ts +8 -3
- package/src/core/types.ts +1 -1
- package/src/core/ui-packs/ar.ts +43 -0
- package/src/core/ui-packs/bg.ts +45 -0
- package/src/core/ui-packs/bn.ts +43 -0
- package/src/core/ui-packs/ca.ts +46 -0
- package/src/core/ui-packs/cs.ts +44 -0
- package/src/core/ui-packs/da.ts +45 -0
- package/src/core/ui-packs/de.ts +46 -0
- package/src/core/ui-packs/el.ts +45 -0
- package/src/core/ui-packs/es.ts +46 -0
- package/src/core/ui-packs/fa.ts +45 -0
- package/src/core/ui-packs/fi.ts +45 -0
- package/src/core/ui-packs/fr.ts +46 -0
- package/src/core/ui-packs/he.ts +43 -0
- package/src/core/ui-packs/hi.ts +44 -0
- package/src/core/ui-packs/hr.ts +45 -0
- package/src/core/ui-packs/hu.ts +44 -0
- package/src/core/ui-packs/id.ts +45 -0
- package/src/core/ui-packs/it.ts +45 -0
- package/src/core/ui-packs/ja.ts +45 -0
- package/src/core/ui-packs/ko.ts +44 -0
- package/src/core/ui-packs/nl.ts +46 -0
- package/src/core/ui-packs/no.ts +44 -0
- package/src/core/ui-packs/pl.ts +45 -0
- package/src/core/ui-packs/pt-br.ts +46 -0
- package/src/core/ui-packs/pt.ts +45 -0
- package/src/core/ui-packs/ro.ts +45 -0
- package/src/core/ui-packs/ru.ts +45 -0
- package/src/core/ui-packs/sk.ts +44 -0
- package/src/core/ui-packs/sr.ts +45 -0
- package/src/core/ui-packs/sv.ts +44 -0
- package/src/core/ui-packs/th.ts +43 -0
- package/src/core/ui-packs/tr.ts +45 -0
- package/src/core/ui-packs/uk.ts +45 -0
- package/src/core/ui-packs/vi.ts +45 -0
- package/src/core/ui-packs/zh-tw.ts +43 -0
- package/src/core/ui-packs/zh.ts +43 -0
- package/src/core/variables.ts +103 -0
- package/src/deploy/artifacts.ts +77 -8
- 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 +32 -0
- package/src/deploy/platforms/netlify.ts +33 -1
- package/src/deploy/platforms/vercel.ts +37 -2
- package/src/deploy/redirects.ts +91 -24
- package/src/deploy/vercel-negotiation.ts +36 -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/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/model.ts +57 -24
- package/src/openapi/overlay.ts +256 -0
- package/src/openapi/parse.ts +55 -2
- package/src/openapi/references.ts +21 -5
- package/src/openapi/render-mdx.ts +5 -1
- package/src/openapi/scalar.ts +40 -6
- package/src/openapi/source.ts +1 -1
- 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 +229 -0
- package/src/ratelimit/schema.ts +28 -0
- package/src/ratelimit/upstash.ts +30 -0
- package/src/ratelimit/wrangler.ts +70 -0
- package/src/reference/asyncapi.ts +2 -2
- package/src/reference/graphql.ts +5 -2
- package/src/reference/openapi.ts +21 -7
- package/src/reference/options.ts +51 -7
- package/src/reference/scalar.ts +33 -8
- package/src/registry/eject.ts +20 -4
- package/src/registry/registry.ts +7 -0
- package/src/search/documents.ts +26 -2
- package/src/search/orama-index.ts +28 -3
- package/src/search/pagefind-ranking.ts +39 -0
- package/src/search/sync/algolia.ts +15 -4
- package/src/search/sync/orama-cloud.ts +3 -0
- package/src/search/sync/typesense.ts +5 -0
- package/src/seo/metatags.ts +67 -0
- package/src/theme/chrome-icons.ts +1 -0
- package/src/theme/color.ts +500 -0
- package/src/theme/entry.ts +56 -3
- package/src/theme/palette.ts +121 -45
- package/src/translate/prompts.ts +1 -0
- package/src/translate/validate.ts +8 -2
- package/src/upgrade/upgrade.ts +4 -171
- 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-9t7a85s3.js.map +0 -10
- package/dist/cli/chunk-c8chx29p.js.map +0 -36
- 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-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-2eytanqx.js.map → chunk-1n228xqb.js.map} +0 -0
- /package/dist/cli/{chunk-35d4wj9f.js.map → chunk-2n4ps1b3.js.map} +0 -0
- /package/dist/cli/{chunk-e04dxsz1.js.map → chunk-4ejxbzee.js.map} +0 -0
- /package/dist/cli/{chunk-tzmab476.js.map → chunk-5ffywsmb.js.map} +0 -0
- /package/dist/cli/{chunk-2z928egk.js.map → chunk-5wj2qwn2.js.map} +0 -0
- /package/dist/cli/{chunk-b07cmahc.js.map → chunk-amrb6hgh.js.map} +0 -0
- /package/dist/cli/{chunk-akbpwfxc.js.map → chunk-cmtcnh9f.js.map} +0 -0
- /package/dist/cli/{chunk-crgn1q09.js.map → chunk-e7vvk5ya.js.map} +0 -0
- /package/dist/cli/{chunk-tkacnehg.js.map → chunk-gp84za0h.js.map} +0 -0
- /package/dist/cli/{chunk-r9rcc4w7.js.map → chunk-p804f3pe.js.map} +0 -0
- /package/dist/cli/{chunk-8ktnccpt.js.map → chunk-ta27feev.js.map} +0 -0
- /package/dist/cli/{chunk-a58773jm.js.map → chunk-y4ykbark.js.map} +0 -0
- /package/dist/cli/{chunk-p3v96n38.js.map → chunk-y5h4r2y0.js.map} +0 -0
- /package/dist/cli/{chunk-acanzt5p.js.map → chunk-yj17vs39.js.map} +0 -0
|
@@ -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;
|
|
@@ -118,14 +139,16 @@ const responses = Object.fromEntries(
|
|
|
118
139
|
);
|
|
119
140
|
|
|
120
141
|
const security = resolveSecurity(
|
|
121
|
-
effectiveSecurity(operation?.security, doc.security),
|
|
142
|
+
effectiveSecurity(operation?.security, doc.security, isWebhook),
|
|
122
143
|
doc.components?.securitySchemes
|
|
123
144
|
);
|
|
124
145
|
|
|
125
146
|
// One derived model feeds the static default sample, the playground form,
|
|
126
|
-
// and (client-side) the live samples + fetch — they can never drift apart.
|
|
147
|
+
// and (client-side) the live samples + fetch — they can never drift apart. A
|
|
148
|
+
// webhook has none: the API sends it, so there is nothing for a reader to
|
|
149
|
+
// call, and its rail shows the payload instead.
|
|
127
150
|
const model =
|
|
128
|
-
ref && operation
|
|
151
|
+
ref && operation && !isWebhook
|
|
129
152
|
? operationModel({
|
|
130
153
|
components,
|
|
131
154
|
method: ref.method,
|
|
@@ -145,6 +168,59 @@ const model =
|
|
|
145
168
|
: null;
|
|
146
169
|
const sample = model ? buildRequest(model, defaultValues(model)) : null;
|
|
147
170
|
const languages = sampleLanguages(spec?.codeSamples ?? []);
|
|
171
|
+
// The spec's own `x-codeSamples`, shown ahead of the generated ones.
|
|
172
|
+
const customSamples = operation ? customCodeSamples(operation) : [];
|
|
173
|
+
|
|
174
|
+
/** One request the API makes back to the reader, flattened for rendering. */
|
|
175
|
+
interface CallbackEntry {
|
|
176
|
+
expression: string;
|
|
177
|
+
key: string;
|
|
178
|
+
method: string;
|
|
179
|
+
name: string;
|
|
180
|
+
operation: FullOperation;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Callbacks: for each named callback (resolved through
|
|
184
|
+
// `components.callbacks`), each URL expression, each method it declares.
|
|
185
|
+
const callbacks: CallbackEntry[] = Object.entries(
|
|
186
|
+
operation?.callbacks ?? {}
|
|
187
|
+
).flatMap(([name, raw]) => {
|
|
188
|
+
const callback = resolveComponentRef(raw, components, "callbacks");
|
|
189
|
+
return Object.entries(callback).flatMap(([expression, item]) => {
|
|
190
|
+
if (expression === "$ref" || typeof item !== "object" || item === null) {
|
|
191
|
+
return [];
|
|
192
|
+
}
|
|
193
|
+
return HTTP_METHODS.flatMap((method) => {
|
|
194
|
+
const entry = item[method];
|
|
195
|
+
return typeof entry === "object" && entry !== null
|
|
196
|
+
? [
|
|
197
|
+
{
|
|
198
|
+
expression,
|
|
199
|
+
key: `${name}-${expression}-${method}`,
|
|
200
|
+
method,
|
|
201
|
+
name,
|
|
202
|
+
// SAFETY: a path item's method entry is an operation object; the
|
|
203
|
+
// object check above guards a spec that put a scalar there.
|
|
204
|
+
operation: entry as FullOperation,
|
|
205
|
+
},
|
|
206
|
+
]
|
|
207
|
+
: [];
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
/** A callback's request body and responses, `$ref`s resolved. */
|
|
213
|
+
const callbackParts = (entry: CallbackEntry) => ({
|
|
214
|
+
requestBody: entry.operation.requestBody
|
|
215
|
+
? resolveComponentRef(entry.operation.requestBody, components, "requestBodies")
|
|
216
|
+
: undefined,
|
|
217
|
+
responses: Object.fromEntries(
|
|
218
|
+
Object.entries(entry.operation.responses ?? {}).map(([status, response]) => [
|
|
219
|
+
status,
|
|
220
|
+
resolveComponentRef(response, components, "responses"),
|
|
221
|
+
])
|
|
222
|
+
),
|
|
223
|
+
});
|
|
148
224
|
---
|
|
149
225
|
{
|
|
150
226
|
isAsyncApi ? (
|
|
@@ -160,6 +236,11 @@ const languages = sampleLanguages(spec?.codeSamples ?? []);
|
|
|
160
236
|
<code class="break-all font-mono text-foreground text-sm">
|
|
161
237
|
{ref.path}
|
|
162
238
|
</code>
|
|
239
|
+
{isWebhook && (
|
|
240
|
+
<span class="rounded-md border border-border px-1.5 py-0.5 font-medium text-[0.625rem] text-muted-foreground uppercase tracking-wide">
|
|
241
|
+
Webhook
|
|
242
|
+
</span>
|
|
243
|
+
)}
|
|
163
244
|
{operation.deprecated && (
|
|
164
245
|
<span class={DEPRECATED_LABEL_CLASS}>
|
|
165
246
|
deprecated
|
|
@@ -184,7 +265,73 @@ const languages = sampleLanguages(spec?.codeSamples ?? []);
|
|
|
184
265
|
schemas={schemas}
|
|
185
266
|
/>
|
|
186
267
|
)}
|
|
268
|
+
{callbacks.length > 0 && (
|
|
269
|
+
<section class="mt-10">
|
|
270
|
+
<div
|
|
271
|
+
aria-level="2"
|
|
272
|
+
class="mb-3 font-semibold text-foreground text-lg"
|
|
273
|
+
role="heading"
|
|
274
|
+
>
|
|
275
|
+
Callbacks
|
|
276
|
+
</div>
|
|
277
|
+
<div class="flex flex-col gap-6">
|
|
278
|
+
{callbacks.map((entry) => {
|
|
279
|
+
const parts = callbackParts(entry);
|
|
280
|
+
return (
|
|
281
|
+
<div class="rounded-blume border border-border p-4">
|
|
282
|
+
<div
|
|
283
|
+
aria-level="3"
|
|
284
|
+
class="font-semibold text-foreground"
|
|
285
|
+
role="heading"
|
|
286
|
+
>
|
|
287
|
+
{entry.operation.summary || entry.name}
|
|
288
|
+
</div>
|
|
289
|
+
<div class="mt-2 flex flex-wrap items-center gap-2">
|
|
290
|
+
<MethodBadge method={entry.method} />
|
|
291
|
+
<code class="break-all font-mono text-muted-foreground text-xs">
|
|
292
|
+
{entry.expression}
|
|
293
|
+
</code>
|
|
294
|
+
</div>
|
|
295
|
+
{entry.operation.description && (
|
|
296
|
+
<Description
|
|
297
|
+
class="mt-2 text-muted-foreground text-sm"
|
|
298
|
+
text={entry.operation.description}
|
|
299
|
+
/>
|
|
300
|
+
)}
|
|
301
|
+
{parts.requestBody && (
|
|
302
|
+
<RequestBody
|
|
303
|
+
expandAll={spec.expandSchemas}
|
|
304
|
+
level={4}
|
|
305
|
+
requestBody={parts.requestBody}
|
|
306
|
+
schemas={schemas}
|
|
307
|
+
/>
|
|
308
|
+
)}
|
|
309
|
+
{entry.operation.responses && (
|
|
310
|
+
<Responses
|
|
311
|
+
expandAll={spec.expandSchemas}
|
|
312
|
+
level={4}
|
|
313
|
+
responses={parts.responses}
|
|
314
|
+
schemas={schemas}
|
|
315
|
+
/>
|
|
316
|
+
)}
|
|
317
|
+
</div>
|
|
318
|
+
);
|
|
319
|
+
})}
|
|
320
|
+
</div>
|
|
321
|
+
</section>
|
|
322
|
+
)}
|
|
187
323
|
</div>
|
|
324
|
+
{isWebhook && (requestBody?.content || operation.responses) && (
|
|
325
|
+
<OperationPanel>
|
|
326
|
+
<RequestPanel
|
|
327
|
+
components={components}
|
|
328
|
+
customSamples={customSamples}
|
|
329
|
+
payload={requestBody?.content}
|
|
330
|
+
responses={responses}
|
|
331
|
+
schemas={schemas}
|
|
332
|
+
/>
|
|
333
|
+
</OperationPanel>
|
|
334
|
+
)}
|
|
188
335
|
{sample && model && (
|
|
189
336
|
<OperationPanel>
|
|
190
337
|
{spec.playground.enabled && (
|
|
@@ -197,6 +344,7 @@ const languages = sampleLanguages(spec?.codeSamples ?? []);
|
|
|
197
344
|
)}
|
|
198
345
|
<RequestPanel
|
|
199
346
|
components={components}
|
|
347
|
+
customSamples={customSamples}
|
|
200
348
|
languages={languages}
|
|
201
349
|
responses={responses}
|
|
202
350
|
sample={sample}
|
|
@@ -17,9 +17,11 @@ interface Props {
|
|
|
17
17
|
requestBody: RequestBodyLike;
|
|
18
18
|
schemas: Record<string, SchemaLike>;
|
|
19
19
|
expandAll?: boolean;
|
|
20
|
+
/** The heading's level: 2 on an operation, deeper inside a callback. */
|
|
21
|
+
level?: number;
|
|
20
22
|
}
|
|
21
23
|
|
|
22
|
-
const { requestBody, schemas, expandAll = false } = Astro.props;
|
|
24
|
+
const { requestBody, schemas, expandAll = false, level = 2 } = Astro.props;
|
|
23
25
|
|
|
24
26
|
const entries = Object.entries(requestBody.content ?? {});
|
|
25
27
|
const chosen = entries.find(([type]) => type.includes("json")) ?? entries[0];
|
|
@@ -27,11 +29,11 @@ const contentType = chosen?.[0] ?? "application/json";
|
|
|
27
29
|
const schema = chosen?.[1]?.schema ?? {};
|
|
28
30
|
---
|
|
29
31
|
|
|
30
|
-
<section class="mt-8">
|
|
32
|
+
<section class:list={[level > 2 ? "mt-5" : "mt-8"]}>
|
|
31
33
|
<div class="mb-2 flex flex-wrap items-center gap-2">
|
|
32
34
|
<div
|
|
33
|
-
aria-level=
|
|
34
|
-
class="font-semibold text-foreground text-lg"
|
|
35
|
+
aria-level={level}
|
|
36
|
+
class:list={["font-semibold text-foreground", level > 2 ? "text-sm" : "text-lg"]}
|
|
35
37
|
role="heading"
|
|
36
38
|
>
|
|
37
39
|
Request body
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
type SpecValue,
|
|
10
10
|
toJson,
|
|
11
11
|
} from "./helpers.ts";
|
|
12
|
+
import type { CustomCodeSample } from "./code-samples.ts";
|
|
12
13
|
import { languageSamplePanels } from "./sample-panels.ts";
|
|
13
14
|
import PanelTabs from "./PanelTabs.astro";
|
|
14
15
|
import type { RequestSample, SampleLanguage } from "./snippets.ts";
|
|
@@ -27,19 +28,69 @@ interface ResponseLike {
|
|
|
27
28
|
interface Props {
|
|
28
29
|
/** The document's `components`, which `$ref`'d examples resolve against. */
|
|
29
30
|
components?: ComponentsLike;
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
/** The spec's hand-written `x-codeSamples`, shown first and never re-rendered live. */
|
|
32
|
+
customSamples?: CustomCodeSample[];
|
|
33
|
+
/**
|
|
34
|
+
* A webhook's body: the rail shows it as a "Payload" example per media
|
|
35
|
+
* type in place of client code, since the API sends the request.
|
|
36
|
+
*/
|
|
37
|
+
payload?: Record<string, MediaTypeLike>;
|
|
38
|
+
sample?: RequestSample;
|
|
39
|
+
languages?: SampleLanguage[];
|
|
32
40
|
responses: Record<string, ResponseLike>;
|
|
33
41
|
schemas: Record<string, SchemaLike>;
|
|
34
42
|
}
|
|
35
43
|
|
|
36
|
-
const {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
44
|
+
const {
|
|
45
|
+
components,
|
|
46
|
+
customSamples = [],
|
|
47
|
+
payload,
|
|
40
48
|
sample,
|
|
41
|
-
|
|
49
|
+
languages = [],
|
|
50
|
+
responses,
|
|
51
|
+
schemas,
|
|
52
|
+
} = Astro.props;
|
|
53
|
+
|
|
54
|
+
/** A media type's example, highlighted, or null when it has none. */
|
|
55
|
+
const highlightExample = async (media: MediaTypeLike, type: string) => {
|
|
56
|
+
const example = responseExample(media, schemas, components);
|
|
57
|
+
if (example === undefined || example === null) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
const json = type.includes("json");
|
|
61
|
+
return highlightCode(
|
|
62
|
+
json || typeof example !== "string" ? toJson(example) : example,
|
|
63
|
+
json ? "json" : "text",
|
|
64
|
+
{ icons: false, themes: data.config.codeThemes }
|
|
65
|
+
);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// Hand-written samples carry no `lang` key, so the playground leaves them
|
|
69
|
+
// as written when it re-renders the generated ones from the form.
|
|
70
|
+
const customPanels = await Promise.all(
|
|
71
|
+
customSamples.map(async (custom) => ({
|
|
72
|
+
html: await highlightCode(custom.source, custom.lang, {
|
|
73
|
+
icons: false,
|
|
74
|
+
themes: data.config.codeThemes,
|
|
75
|
+
}),
|
|
76
|
+
key: custom.key,
|
|
77
|
+
label: custom.label,
|
|
78
|
+
}))
|
|
79
|
+
);
|
|
80
|
+
const payloadPanels = await Promise.all(
|
|
81
|
+
Object.entries(payload ?? {}).map(async ([type, media]) => ({
|
|
82
|
+
html: await highlightExample(media, type),
|
|
83
|
+
key: type,
|
|
84
|
+
label: type,
|
|
85
|
+
text: "No example payload.",
|
|
86
|
+
}))
|
|
42
87
|
);
|
|
88
|
+
const requestPanels = [
|
|
89
|
+
...customPanels,
|
|
90
|
+
...(sample
|
|
91
|
+
? await languageSamplePanels(languages, sample, data.config.codeThemes)
|
|
92
|
+
: []),
|
|
93
|
+
];
|
|
43
94
|
|
|
44
95
|
const responsePanels = await Promise.all(
|
|
45
96
|
Object.entries(responses).map(async ([status, response]) => {
|
|
@@ -66,6 +117,7 @@ const responsePanels = await Promise.all(
|
|
|
66
117
|
---
|
|
67
118
|
|
|
68
119
|
<div class="not-prose flex flex-col gap-6">
|
|
120
|
+
<PanelTabs copy heading="Payload" mono panels={payloadPanels} />
|
|
69
121
|
<PanelTabs copy heading="Request" panels={requestPanels} />
|
|
70
122
|
<PanelTabs heading="Response" mono panels={responsePanels} />
|
|
71
123
|
</div>
|
|
@@ -17,19 +17,21 @@ interface Props {
|
|
|
17
17
|
responses: Record<string, ResponseLike>;
|
|
18
18
|
schemas: Record<string, SchemaLike>;
|
|
19
19
|
expandAll?: boolean;
|
|
20
|
+
/** The heading's level: 2 on an operation, deeper inside a callback. */
|
|
21
|
+
level?: number;
|
|
20
22
|
}
|
|
21
23
|
|
|
22
|
-
const { responses, schemas, expandAll = false } = Astro.props;
|
|
24
|
+
const { responses, schemas, expandAll = false, level = 2 } = Astro.props;
|
|
23
25
|
|
|
24
26
|
const items = Object.entries(responses);
|
|
25
27
|
---
|
|
26
28
|
|
|
27
29
|
{
|
|
28
30
|
items.length > 0 && (
|
|
29
|
-
<section class="mt-8">
|
|
31
|
+
<section class:list={[level > 2 ? "mt-5" : "mt-8"]}>
|
|
30
32
|
<div
|
|
31
|
-
aria-level=
|
|
32
|
-
class="mb-3 font-semibold text-foreground text-lg"
|
|
33
|
+
aria-level={level}
|
|
34
|
+
class:list={["mb-3 font-semibold text-foreground", level > 2 ? "text-sm" : "text-lg"]}
|
|
33
35
|
role="heading"
|
|
34
36
|
>
|
|
35
37
|
Responses
|
|
@@ -157,15 +157,15 @@ const ALIASES = new Map<string, ToolId>([
|
|
|
157
157
|
/**
|
|
158
158
|
* The sample tools to render for an operation. The protocol picks the
|
|
159
159
|
* candidate set; a non-empty `codeSamples` config filters and orders it
|
|
160
|
-
* (unknown ids are dropped, aliases accepted).
|
|
161
|
-
* one, or a filter that matches nothing yields no samples.
|
|
160
|
+
* (unknown ids are dropped, aliases accepted). `false`, no protocol, an
|
|
161
|
+
* unsupported one, or a filter that matches nothing yields no samples.
|
|
162
162
|
*/
|
|
163
163
|
export const asyncSampleLanguages = (
|
|
164
|
-
ids: string[],
|
|
164
|
+
ids: string[] | false,
|
|
165
165
|
protocol?: string
|
|
166
166
|
): AsyncSampleLanguage[] => {
|
|
167
167
|
const candidates = PROTOCOL_TOOLS.get(protocol ?? "") ?? [];
|
|
168
|
-
if (candidates.length === 0) {
|
|
168
|
+
if (ids === false || candidates.length === 0) {
|
|
169
169
|
return [];
|
|
170
170
|
}
|
|
171
171
|
if (ids.length === 0) {
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { sampleLanguageInfo } from "./snippets.ts";
|
|
2
|
+
import type { SampleLanguageInfo } from "./snippets.ts";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Hand-written code samples from a spec: the `x-codeSamples` extension on an
|
|
6
|
+
* operation (Redocly's, which Mintlify, Speakeasy, and Stainless write too),
|
|
7
|
+
* or its older spelling `x-code-samples`. Each entry names a `lang`, holds
|
|
8
|
+
* the `source`, and may carry a `label`. They render as their own tabs ahead
|
|
9
|
+
* of the generated samples and, being fixed text, the playground leaves them
|
|
10
|
+
* as written.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** One hand-written sample, ready to render as a tab. */
|
|
14
|
+
export interface CustomCodeSample {
|
|
15
|
+
/** A stable, unique tab key. */
|
|
16
|
+
key: string;
|
|
17
|
+
/** The tab label: the entry's own, else the language's name. */
|
|
18
|
+
label: string;
|
|
19
|
+
/** The Shiki language to highlight `source` with. */
|
|
20
|
+
lang: string;
|
|
21
|
+
source: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** The two places an operation keeps them. */
|
|
25
|
+
export interface CodeSamplesCarrier {
|
|
26
|
+
"x-code-samples"?: unknown;
|
|
27
|
+
"x-codeSamples"?: unknown;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface RawSample {
|
|
31
|
+
label?: string;
|
|
32
|
+
lang: string;
|
|
33
|
+
source: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const isRawSample = (value: unknown): value is RawSample =>
|
|
37
|
+
typeof value === "object" &&
|
|
38
|
+
value !== null &&
|
|
39
|
+
"lang" in value &&
|
|
40
|
+
typeof value.lang === "string" &&
|
|
41
|
+
"source" in value &&
|
|
42
|
+
typeof value.source === "string" &&
|
|
43
|
+
(!("label" in value) || typeof value.label === "string");
|
|
44
|
+
|
|
45
|
+
// Shell tools in an `x-codeSamples` entry are usually an SDK's CLI, not curl,
|
|
46
|
+
// so they're named for the shell rather than "cURL".
|
|
47
|
+
const SHELL_LANGS = new Set(["bash", "sh", "shell", "zsh"]);
|
|
48
|
+
|
|
49
|
+
/** The display name and highlighter for a sample's `lang`. */
|
|
50
|
+
const describe = (lang: string): SampleLanguageInfo => {
|
|
51
|
+
const lower = lang.toLowerCase();
|
|
52
|
+
if (SHELL_LANGS.has(lower)) {
|
|
53
|
+
return { label: "Shell", lang: "bash" };
|
|
54
|
+
}
|
|
55
|
+
// A language Blume doesn't generate keeps its own name, and Shiki tries
|
|
56
|
+
// it as written (it knows most languages by their common names).
|
|
57
|
+
return sampleLanguageInfo(lower) ?? { label: lang, lang: lower };
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The operation's hand-written samples, with a unique tab label each. A label
|
|
62
|
+
* two samples share gains its language (`List plants · JavaScript`), and one
|
|
63
|
+
* that still repeats gains a number. Malformed entries are skipped.
|
|
64
|
+
*/
|
|
65
|
+
export const customCodeSamples = (
|
|
66
|
+
operation: CodeSamplesCarrier
|
|
67
|
+
): CustomCodeSample[] => {
|
|
68
|
+
const raw = operation["x-codeSamples"] ?? operation["x-code-samples"];
|
|
69
|
+
if (!Array.isArray(raw)) {
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
72
|
+
const entries = raw.filter(isRawSample).map((entry) => {
|
|
73
|
+
const language = describe(entry.lang);
|
|
74
|
+
return {
|
|
75
|
+
base: entry.label?.trim() || language.label,
|
|
76
|
+
language,
|
|
77
|
+
source: entry.source.replace(/\n$/u, ""),
|
|
78
|
+
};
|
|
79
|
+
});
|
|
80
|
+
const counts = new Map<string, number>();
|
|
81
|
+
for (const { base } of entries) {
|
|
82
|
+
counts.set(base, (counts.get(base) ?? 0) + 1);
|
|
83
|
+
}
|
|
84
|
+
const used = new Set<string>();
|
|
85
|
+
return entries.map(({ base, language, source }, index) => {
|
|
86
|
+
const first =
|
|
87
|
+
(counts.get(base) ?? 0) > 1 && base !== language.label
|
|
88
|
+
? `${base} · ${language.label}`
|
|
89
|
+
: base;
|
|
90
|
+
let label = first;
|
|
91
|
+
for (let n = 2; used.has(label); n += 1) {
|
|
92
|
+
label = `${first} (${n})`;
|
|
93
|
+
}
|
|
94
|
+
used.add(label);
|
|
95
|
+
return { key: `x-${index}`, label, lang: language.lang, source };
|
|
96
|
+
});
|
|
97
|
+
};
|
|
@@ -45,12 +45,15 @@ export interface OperationSecurity {
|
|
|
45
45
|
/**
|
|
46
46
|
* The requirement list an operation actually enforces: its own `security` when
|
|
47
47
|
* declared — the OpenAPI override rule, where `[]` removes the default and
|
|
48
|
-
* makes the operation public — else the document's root `security`.
|
|
48
|
+
* makes the operation public — else the document's root `security`. A webhook
|
|
49
|
+
* takes only its own: the API sends it, so the root requirements, which guard
|
|
50
|
+
* calls to the API, say nothing about what the receiving endpoint checks.
|
|
49
51
|
*/
|
|
50
52
|
export const effectiveSecurity = (
|
|
51
53
|
operation?: SecurityRequirementLike[],
|
|
52
|
-
document?: SecurityRequirementLike[]
|
|
53
|
-
|
|
54
|
+
document?: SecurityRequirementLike[],
|
|
55
|
+
webhook = false
|
|
56
|
+
): SecurityRequirementLike[] => operation ?? (webhook ? [] : document) ?? [];
|
|
54
57
|
|
|
55
58
|
/**
|
|
56
59
|
* Resolve requirement names against `components.securitySchemes`. A name with
|