blume 2.0.2 → 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 +113 -0
- package/README.md +1 -1
- package/dist/cli/{chunk-6k4ftwze.js → chunk-0gz36akr.js} +18 -2
- package/dist/cli/{chunk-6k4ftwze.js.map → chunk-0gz36akr.js.map} +3 -3
- package/dist/cli/{chunk-zp79m0ts.js → chunk-1n228xqb.js} +2 -2
- package/dist/cli/{chunk-ddndchfr.js → chunk-2f3ndkpw.js} +57 -29
- package/dist/cli/chunk-2f3ndkpw.js.map +14 -0
- package/dist/cli/{chunk-fsmrqk8a.js → chunk-2f7n4qzt.js} +8 -2
- package/dist/cli/{chunk-fsmrqk8a.js.map → chunk-2f7n4qzt.js.map} +3 -3
- package/dist/cli/{chunk-ppzjqwx2.js → chunk-2n4ps1b3.js} +17 -18
- package/dist/cli/{chunk-ppzjqwx2.js.map → chunk-2n4ps1b3.js.map} +3 -3
- package/dist/cli/{chunk-5r8g91qn.js → chunk-43zcf4gz.js} +398 -159
- package/dist/cli/chunk-43zcf4gz.js.map +36 -0
- package/dist/cli/chunk-4ejxbzee.js +39 -0
- package/dist/cli/chunk-4ejxbzee.js.map +10 -0
- package/dist/cli/{chunk-hr8ne106.js → chunk-4h8z9vv5.js} +296 -77
- package/dist/cli/chunk-4h8z9vv5.js.map +16 -0
- package/dist/cli/{chunk-k7pj68a8.js → chunk-5cg2rzgf.js} +18 -16
- package/dist/cli/{chunk-k7pj68a8.js.map → chunk-5cg2rzgf.js.map} +2 -2
- package/dist/cli/{chunk-h2ez8dzb.js → chunk-5ffywsmb.js} +4 -4
- package/dist/cli/{chunk-g698a744.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-3yce002v.js → chunk-713mngdq.js} +15 -8
- package/dist/cli/chunk-713mngdq.js.map +14 -0
- package/dist/cli/{chunk-91ws1n6j.js → chunk-9geymqns.js} +17 -15
- package/dist/cli/{chunk-91ws1n6j.js.map → chunk-9geymqns.js.map} +2 -2
- package/dist/cli/{chunk-6dtt0zfn.js → chunk-9xr4dgee.js} +27 -18
- package/dist/cli/chunk-9xr4dgee.js.map +10 -0
- package/dist/cli/{chunk-sqw4ekg1.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-wdrt2k2v.js → chunk-cmtcnh9f.js} +90 -26
- package/dist/cli/chunk-cmtcnh9f.js.map +10 -0
- package/dist/cli/chunk-cy5bm0j0.js +104 -0
- package/dist/cli/chunk-cy5bm0j0.js.map +11 -0
- package/dist/cli/{chunk-7mbqtmgb.js → chunk-e7vvk5ya.js} +21 -12
- package/dist/cli/chunk-e7vvk5ya.js.map +10 -0
- package/dist/cli/{chunk-qkb5a8sa.js → chunk-g2z9x01v.js} +6 -98
- package/dist/cli/chunk-g2z9x01v.js.map +10 -0
- package/dist/cli/{chunk-273ygyr4.js → chunk-ga0pf4aj.js} +7 -7
- package/dist/cli/{chunk-273ygyr4.js.map → chunk-ga0pf4aj.js.map} +3 -3
- package/dist/cli/{chunk-h7k3nq3v.js → chunk-gp84za0h.js} +2 -2
- package/dist/cli/{chunk-hqp2ajnh.js → chunk-h2a48yhd.js} +195 -73
- package/dist/cli/chunk-h2a48yhd.js.map +36 -0
- package/dist/cli/{chunk-pbg5a4s3.js → chunk-jnwj5kjj.js} +71 -47
- package/dist/cli/chunk-jnwj5kjj.js.map +19 -0
- package/dist/cli/chunk-kwrg63tm.js +31 -0
- package/dist/cli/chunk-kwrg63tm.js.map +10 -0
- package/dist/cli/{chunk-8g8ytmgx.js → chunk-nd1821sk.js} +21 -19
- package/dist/cli/{chunk-8g8ytmgx.js.map → chunk-nd1821sk.js.map} +2 -2
- package/dist/cli/{chunk-w4bxdvsa.js → chunk-ntv4qrt7.js} +17 -15
- package/dist/cli/{chunk-w4bxdvsa.js.map → chunk-ntv4qrt7.js.map} +2 -2
- package/dist/cli/{chunk-bfwp9vp6.js → chunk-p804f3pe.js} +7 -7
- package/dist/cli/{chunk-4e9b9ra6.js → chunk-py62fewh.js} +6 -6
- package/dist/cli/{chunk-4e9b9ra6.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-j85scx15.js → chunk-rekqz4qg.js} +142 -46
- package/dist/cli/chunk-rekqz4qg.js.map +10 -0
- package/dist/cli/{chunk-00gs3wqs.js → chunk-ta27feev.js} +1 -1
- package/dist/cli/{chunk-v6ya5kcb.js → chunk-xkz5xbtv.js} +4031 -1132
- package/dist/cli/chunk-xkz5xbtv.js.map +213 -0
- package/dist/cli/{chunk-bbnwccaz.js → chunk-y4ykbark.js} +2 -2
- package/dist/cli/{chunk-n1yg3tj3.js → chunk-y5h4r2y0.js} +6 -6
- package/dist/cli/{chunk-n1yg3tj3.js.map → chunk-y5h4r2y0.js.map} +3 -3
- package/dist/cli/{chunk-nfcyttvj.js → chunk-yj17vs39.js} +9 -9
- package/dist/cli/{chunk-nfcyttvj.js.map → chunk-yj17vs39.js.map} +1 -1
- package/dist/cli/{chunk-7vtckvaw.js → chunk-yxmk4pec.js} +16 -14
- package/dist/cli/{chunk-7vtckvaw.js.map → chunk-yxmk4pec.js.map} +2 -2
- package/dist/cli/{chunk-gs7r695n.js → chunk-zccbjcj0.js} +22 -8
- package/dist/cli/{chunk-gs7r695n.js.map → chunk-zccbjcj0.js.map} +3 -3
- package/dist/cli/{chunk-xh43dwgw.js → chunk-zf748avv.js} +415 -225
- package/dist/cli/chunk-zf748avv.js.map +37 -0
- package/dist/cli/{chunk-d1v5rhy0.js → chunk-zhvd6adm.js} +16 -14
- package/dist/cli/{chunk-d1v5rhy0.js.map → chunk-zhvd6adm.js.map} +2 -2
- package/dist/cli/index.js +28 -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/link-headers.d.ts +8 -1
- package/dist/types/ai/openapi-components.d.ts +5 -2
- package/dist/types/ai/relative-links.d.ts +9 -7
- package/dist/types/ai/site-skill.d.ts +26 -0
- package/dist/types/ai/skills.d.ts +20 -1
- package/dist/types/ai/tar.d.ts +1 -3
- package/dist/types/analytics/index.d.ts +2 -0
- package/dist/types/analytics/one-dollar-stats.d.ts +48 -0
- package/dist/types/analytics/schema.d.ts +14 -0
- package/dist/types/astro/integration.d.ts +11 -2
- 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/base-path.d.ts +21 -7
- package/dist/types/core/config-input.d.ts +196 -27
- package/dist/types/core/data.d.ts +49 -4
- package/dist/types/core/directive-diagnostics.d.ts +12 -0
- package/dist/types/core/footer.d.ts +8 -0
- package/dist/types/core/heading-markers.d.ts +5 -7
- package/dist/types/core/i18n-ui.d.ts +86 -0
- package/dist/types/core/i18n.d.ts +2 -0
- package/dist/types/core/includes.d.ts +8 -2
- package/dist/types/core/last-modified.d.ts +10 -0
- package/dist/types/core/localizable.d.ts +7 -0
- package/dist/types/core/meta.d.ts +8 -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 +558 -56
- package/dist/types/core/sources/lower.d.ts +29 -16
- package/dist/types/core/sources/normalize.d.ts +13 -1
- package/dist/types/core/sources/read.d.ts +5 -0
- package/dist/types/core/sources/watch.d.ts +12 -5
- package/dist/types/core/standard-schema.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/artifacts.d.ts +6 -4
- package/dist/types/deploy/headers.d.ts +5 -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/types.d.ts +8 -0
- package/dist/types/deploy/platforms/vercel.d.ts +6 -0
- package/dist/types/deploy/redirects.d.ts +61 -22
- package/dist/types/deploy/vercel-negotiation.d.ts +9 -0
- package/dist/types/markdown/code-title.d.ts +17 -0
- package/dist/types/markdown/directives.d.ts +62 -0
- package/dist/types/markdown/features.d.ts +24 -2
- package/dist/types/markdown/mdast.d.ts +63 -0
- 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/asyncapi.d.ts +4 -2
- 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 +44 -6
- package/docs/03-upgrading.mdx +4 -4
- package/docs/04-migrating.mdx +1 -1
- package/docs/08-faq.mdx +1 -1
- package/docs/advanced/changelog.mdx +2 -2
- package/docs/advanced/custom-pages.mdx +3 -3
- package/docs/advanced/skills.mdx +14 -0
- package/docs/cli/audit.mdx +38 -2
- package/docs/cli/evals.mdx +3 -3
- package/docs/cli/index.mdx +1 -0
- package/docs/cli/translate.mdx +3 -3
- package/docs/cli/version.mdx +1 -1
- package/docs/configuration/analytics.mdx +22 -1
- package/docs/configuration/assistant.mdx +188 -36
- package/docs/configuration/consent.mdx +100 -0
- package/docs/configuration/customization.mdx +6 -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 +30 -2
- package/docs/configuration/theming.mdx +3 -1
- package/docs/content/components.mdx +107 -1
- package/docs/content/frontmatter.mdx +77 -1
- package/docs/content/i18n.mdx +40 -3
- package/docs/content/includes.mdx +16 -0
- package/docs/content/index.mdx +4 -2
- package/docs/content/islands.mdx +1 -1
- package/docs/content/meta.mdx +4 -1
- 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 +81 -2
- package/docs/content/variables.mdx +41 -0
- package/docs/content/versioning.mdx +1 -1
- package/docs/discoverability/agent-discovery.mdx +30 -3
- package/docs/discoverability/index.mdx +3 -2
- package/docs/discoverability/llms-txt.mdx +1 -1
- package/docs/discoverability/markdown.mdx +2 -2
- package/docs/discoverability/metadata.mdx +17 -0
- package/docs/discoverability/open-graph.mdx +5 -3
- package/docs/discoverability/rss.mdx +1 -1
- package/docs/references/api-pages.mdx +74 -0
- package/docs/references/asyncapi.mdx +2 -2
- package/docs/references/graphql.mdx +3 -3
- package/docs/references/meta.ts +1 -1
- package/docs/references/openapi.mdx +106 -5
- 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/fumadocs.md +1 -1
- package/skills/blume-migrate/references/mintlify.md +37 -19
- package/skills/blume-migrate/references/nextra.md +3 -3
- package/skills/blume-migrate/references/starlight.md +2 -1
- package/skills/blume-migrate/scripts/mintlify-codemod.mjs +67 -16
- package/skills/blume-write-skill/SKILL.md +82 -0
- package/src/ai/agent-readability.ts +4 -3
- package/src/ai/agent-surface.ts +9 -7
- package/src/ai/ai-catalog.ts +12 -5
- package/src/ai/api/handlers.ts +2 -2
- package/src/ai/api/spec.ts +2 -2
- package/src/ai/api-catalog.ts +6 -2
- 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/changelog-markdown.ts +2 -2
- 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/link-headers.ts +14 -5
- package/src/ai/llms.ts +24 -9
- package/src/ai/markdown.ts +2 -1
- package/src/ai/mcp/data.ts +6 -0
- package/src/ai/mcp/discovery.ts +2 -2
- package/src/ai/mcp/query.ts +2 -2
- package/src/ai/mcp/server.ts +2 -2
- package/src/ai/openapi-components.ts +31 -9
- package/src/ai/relative-links.ts +42 -26
- package/src/ai/serializers.ts +2 -1
- package/src/ai/site-skill.ts +274 -0
- package/src/ai/skills.ts +49 -3
- package/src/ai/tar.ts +139 -12
- package/src/ai/write-skill.ts +97 -0
- package/src/analytics/head.ts +4 -0
- package/src/analytics/index.ts +5 -0
- package/src/analytics/one-dollar-stats.ts +86 -0
- package/src/analytics/schema.ts +2 -0
- package/src/astro/generate.ts +133 -19
- package/src/astro/include-hmr.ts +31 -12
- package/src/astro/include-refresh.ts +19 -8
- package/src/astro/index.ts +1 -0
- package/src/astro/integration.ts +143 -14
- package/src/astro/module-types.ts +6 -0
- package/src/astro/runtime-modules.ts +28 -13
- package/src/astro/templates.ts +364 -67
- 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 +13 -13
- package/src/audit/checks/sitemap.ts +2 -3
- package/src/audit/graph.ts +3 -1
- package/src/audit/redirects.ts +46 -15
- package/src/audit/run.ts +14 -9
- package/src/audit/snapshot.ts +5 -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/args.ts +32 -0
- package/src/cli/command-meta.ts +5 -0
- package/src/cli/commands/audit.ts +4 -1
- package/src/cli/commands/doctor.ts +25 -17
- package/src/cli/commands/eval.ts +19 -11
- package/src/cli/commands/skill.ts +96 -0
- package/src/cli/commands/translate.ts +9 -12
- package/src/cli/commands/validate.ts +3 -1
- package/src/cli/dev-lock.ts +157 -37
- package/src/cli/index.ts +5 -0
- package/src/cli/report-format.ts +11 -6
- package/src/cli/required-secrets.ts +71 -29
- package/src/components/BlumePage.astro +2 -0
- package/src/components/colors.ts +19 -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/Badge.astro +5 -3
- package/src/components/content/Color.astro +1 -0
- package/src/components/content/Component.astro +2 -2
- 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/Tab.astro +0 -1
- package/src/components/content/Tabs.astro +4 -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/badge-color.ts +5 -2
- package/src/components/content/base-href.ts +13 -36
- 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 +125 -18
- package/src/components/islands/base-path.ts +47 -10
- package/src/components/islands/code-question.ts +62 -0
- package/src/components/islands/hooks.ts +145 -40
- package/src/components/islands/support-link.ts +68 -0
- package/src/components/islands/webmcp.ts +4 -2
- package/src/components/layout/Analytics.astro +11 -2
- package/src/components/layout/Banner.astro +14 -10
- package/src/components/layout/Breadcrumbs.astro +11 -4
- 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/DiscoveryLinks.astro +9 -5
- package/src/components/layout/DrawerSwitchers.astro +51 -0
- package/src/components/layout/Empty.astro +2 -2
- package/src/components/layout/Header.astro +124 -82
- package/src/components/layout/LanguageSwitcher.astro +50 -17
- package/src/components/layout/NarrationPlayer.astro +1085 -0
- package/src/components/layout/NavSelector.astro +35 -9
- package/src/components/layout/NavTabMenu.astro +3 -3
- package/src/components/layout/NavTree.astro +16 -6
- package/src/components/layout/PageActions.astro +4 -3
- package/src/components/layout/PageFeedback.astro +54 -49
- package/src/components/layout/PageLayout.astro +78 -9
- package/src/components/layout/Pagination.astro +3 -3
- package/src/components/layout/ReferenceLayout.astro +17 -6
- package/src/components/layout/RelatedPages.astro +42 -0
- package/src/components/layout/RootLayout.astro +313 -50
- package/src/components/layout/Search.astro +64 -30
- package/src/components/layout/SiteFooter.astro +124 -0
- package/src/components/layout/SiteMetatags.astro +16 -0
- package/src/components/layout/VersionBanner.astro +2 -2
- package/src/components/layout/analytics-client.ts +12 -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/layout/toc-active.ts +41 -0
- package/src/components/layout/toc-element.ts +8 -14
- package/src/components/openapi/ApiTagOperations.astro +2 -2
- package/src/components/openapi/AsyncApiOperation.astro +7 -4
- package/src/components/openapi/GraphqlChip.astro +2 -2
- package/src/components/openapi/Operation.astro +163 -13
- package/src/components/openapi/Playground.astro +4 -4
- package/src/components/openapi/RequestBody.astro +6 -4
- package/src/components/openapi/RequestPanel.astro +63 -8
- package/src/components/openapi/Responses.astro +6 -4
- package/src/components/openapi/SchemaTable.astro +7 -0
- package/src/components/openapi/async-snippets.ts +4 -4
- package/src/components/openapi/async.ts +38 -6
- package/src/components/openapi/code-samples.ts +97 -0
- package/src/components/openapi/helpers.ts +19 -9
- package/src/components/openapi/message-composer.ts +6 -1
- package/src/components/openapi/message.ts +17 -2
- package/src/components/openapi/operation-model.ts +81 -11
- package/src/components/openapi/panel.ts +4 -2
- package/src/components/openapi/param-style.ts +181 -0
- package/src/components/openapi/playground-client.ts +73 -16
- package/src/components/openapi/request.ts +190 -26
- package/src/components/openapi/schema-tree.ts +30 -24
- package/src/components/openapi/security.ts +6 -3
- package/src/components/openapi/snippets.ts +953 -13
- package/src/components/openapi/ws-client.ts +18 -2
- 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/base-path.ts +62 -16
- package/src/core/builtin-tags.ts +5 -0
- package/src/core/client-address.ts +19 -0
- package/src/core/config-input.ts +203 -27
- package/src/core/data.ts +44 -4
- package/src/core/diagnostics.ts +5 -2
- package/src/core/directive-diagnostics.ts +99 -0
- package/src/core/footer.ts +26 -0
- package/src/core/frontmatter.ts +21 -18
- package/src/core/graph.ts +39 -36
- package/src/core/heading-markers.ts +5 -18
- package/src/core/i18n-ui.ts +82 -2
- package/src/core/i18n.ts +31 -3
- package/src/core/includes.ts +20 -3
- package/src/core/last-modified.ts +25 -3
- package/src/core/links.ts +16 -2
- package/src/core/locale-links.ts +5 -1
- package/src/core/localizable.ts +26 -0
- package/src/core/meta.ts +33 -19
- package/src/core/navigation.ts +71 -20
- package/src/core/page-modes.ts +56 -0
- package/src/core/project-graph.ts +138 -10
- package/src/core/redirect-patterns.ts +491 -0
- package/src/core/related.ts +131 -0
- package/src/core/schema.ts +342 -68
- package/src/core/sources/contentful-rich-text.ts +27 -20
- package/src/core/sources/filesystem.ts +20 -2
- package/src/core/sources/github-releases.ts +25 -6
- package/src/core/sources/lexical.ts +23 -18
- package/src/core/sources/lower.ts +201 -34
- package/src/core/sources/mdx-remote.ts +51 -16
- package/src/core/sources/normalize.ts +327 -91
- package/src/core/sources/notion.ts +52 -25
- package/src/core/sources/obsidian.ts +23 -6
- package/src/core/sources/portable-text.ts +38 -21
- package/src/core/sources/read.ts +8 -3
- package/src/core/sources/strapi-blocks.ts +20 -16
- package/src/core/sources/watch.ts +20 -7
- package/src/core/standard-schema.ts +10 -6
- 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/core/version-cut.ts +52 -15
- package/src/deploy/artifacts.ts +104 -14
- package/src/deploy/cloudflare-negotiation.ts +39 -17
- package/src/deploy/headers.ts +10 -5
- package/src/deploy/node-headers.ts +64 -10
- package/src/deploy/platforms/cloudflare.ts +44 -3
- package/src/deploy/platforms/netlify.ts +34 -1
- package/src/deploy/platforms/node.ts +1 -0
- package/src/deploy/platforms/static.ts +1 -0
- package/src/deploy/platforms/types.ts +8 -0
- package/src/deploy/platforms/vercel.ts +38 -2
- package/src/deploy/redirects.ts +139 -36
- package/src/deploy/robots.ts +2 -2
- package/src/deploy/rss.ts +4 -3
- package/src/deploy/sitemap.ts +7 -5
- package/src/deploy/vercel-negotiation.ts +36 -0
- package/src/markdown/api-rail.ts +259 -0
- package/src/markdown/base-links.ts +34 -36
- package/src/markdown/code-title.ts +35 -9
- package/src/markdown/directives.ts +242 -36
- package/src/markdown/features.ts +20 -2
- package/src/markdown/fence-meta.ts +2 -0
- package/src/markdown/include.ts +11 -1
- package/src/markdown/index.ts +35 -11
- package/src/markdown/math.ts +4 -4
- package/src/markdown/mdast.ts +5 -2
- package/src/markdown/relative-links.ts +12 -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 +136 -11
- package/src/og/derive.ts +41 -31
- package/src/og/index.ts +1 -0
- package/src/openapi/asyncapi.ts +4 -2
- package/src/openapi/model.ts +77 -36
- package/src/openapi/overlay.ts +256 -0
- package/src/openapi/parse.ts +55 -2
- package/src/openapi/proxy.ts +63 -10
- package/src/openapi/references.ts +21 -5
- package/src/openapi/render-mdx.ts +46 -3
- 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 +201 -28
- package/src/registry/registry.ts +7 -0
- package/src/search/adapters/version-scope.ts +30 -0
- package/src/search/documents.ts +93 -28
- package/src/search/orama-index.ts +28 -3
- package/src/search/pagefind-ranking.ts +39 -0
- package/src/search/popular.ts +2 -1
- 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/jsonld.ts +7 -3
- 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/meta.ts +68 -24
- package/src/translate/prompts.ts +1 -0
- package/src/translate/run.ts +3 -3
- package/src/translate/validate.ts +12 -3
- package/src/translate/work-list.ts +56 -17
- package/src/upgrade/upgrade.ts +4 -171
- package/dist/cli/chunk-3yce002v.js.map +0 -14
- package/dist/cli/chunk-5r8g91qn.js.map +0 -34
- package/dist/cli/chunk-6dtt0zfn.js.map +0 -10
- package/dist/cli/chunk-7mbqtmgb.js.map +0 -10
- package/dist/cli/chunk-ddndchfr.js.map +0 -14
- package/dist/cli/chunk-esh98wmb.js +0 -23
- package/dist/cli/chunk-esh98wmb.js.map +0 -10
- package/dist/cli/chunk-hqp2ajnh.js.map +0 -35
- package/dist/cli/chunk-hr8ne106.js.map +0 -13
- package/dist/cli/chunk-j85scx15.js.map +0 -10
- package/dist/cli/chunk-mqc662a6.js +0 -75
- package/dist/cli/chunk-mqc662a6.js.map +0 -11
- package/dist/cli/chunk-pbg5a4s3.js.map +0 -19
- package/dist/cli/chunk-qkb5a8sa.js.map +0 -10
- package/dist/cli/chunk-v6ya5kcb.js.map +0 -189
- package/dist/cli/chunk-wdrt2k2v.js.map +0 -10
- package/dist/cli/chunk-xh43dwgw.js.map +0 -36
- package/docs/content/sources.mdx +0 -338
- /package/dist/cli/{chunk-zp79m0ts.js.map → chunk-1n228xqb.js.map} +0 -0
- /package/dist/cli/{chunk-h2ez8dzb.js.map → chunk-5ffywsmb.js.map} +0 -0
- /package/dist/cli/{chunk-g698a744.js.map → chunk-5wj2qwn2.js.map} +0 -0
- /package/dist/cli/{chunk-sqw4ekg1.js.map → chunk-amrb6hgh.js.map} +0 -0
- /package/dist/cli/{chunk-h7k3nq3v.js.map → chunk-gp84za0h.js.map} +0 -0
- /package/dist/cli/{chunk-bfwp9vp6.js.map → chunk-p804f3pe.js.map} +0 -0
- /package/dist/cli/{chunk-00gs3wqs.js.map → chunk-ta27feev.js.map} +0 -0
- /package/dist/cli/{chunk-bbnwccaz.js.map → chunk-y4ykbark.js.map} +0 -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
|
+
};
|
|
@@ -335,12 +335,17 @@ const isRecord = (value: SpecValue): value is Record<string, SpecValue> =>
|
|
|
335
335
|
|
|
336
336
|
/**
|
|
337
337
|
* The example a parameter or media type declares: its `example`, else the
|
|
338
|
-
* first
|
|
339
|
-
*
|
|
340
|
-
*
|
|
341
|
-
*
|
|
338
|
+
* first `value` in its `examples` map — inline, or behind a `$ref` to
|
|
339
|
+
* `#/components/examples`, resolved against `components`. Scalar's upgrade
|
|
340
|
+
* moves every OpenAPI 3.0 and Swagger 2.0 `example` into
|
|
341
|
+
* `examples.default.value`, and 3.1 authors write that map directly, so
|
|
342
|
+
* reading `example` alone would drop them all. `undefined` when nothing is
|
|
343
|
+
* declared.
|
|
342
344
|
*/
|
|
343
|
-
export const declaredExample = (
|
|
345
|
+
export const declaredExample = (
|
|
346
|
+
carrier: ExampleCarrier,
|
|
347
|
+
components?: ComponentsLike
|
|
348
|
+
): SpecValue => {
|
|
344
349
|
if (carrier.example !== undefined) {
|
|
345
350
|
return carrier.example;
|
|
346
351
|
}
|
|
@@ -349,8 +354,11 @@ export const declaredExample = (carrier: ExampleCarrier): SpecValue => {
|
|
|
349
354
|
return undefined;
|
|
350
355
|
}
|
|
351
356
|
for (const entry of Object.values(examples)) {
|
|
352
|
-
|
|
353
|
-
|
|
357
|
+
const example = isRecord(entry)
|
|
358
|
+
? resolveComponentRef(entry, components, "examples")
|
|
359
|
+
: undefined;
|
|
360
|
+
if (example?.value !== undefined) {
|
|
361
|
+
return example.value;
|
|
354
362
|
}
|
|
355
363
|
}
|
|
356
364
|
return undefined;
|
|
@@ -363,9 +371,11 @@ export const declaredExample = (carrier: ExampleCarrier): SpecValue => {
|
|
|
363
371
|
*/
|
|
364
372
|
export const responseExample = (
|
|
365
373
|
media: ExampleCarrier & { schema?: SchemaLike },
|
|
366
|
-
schemas: Record<string, SchemaLike
|
|
374
|
+
schemas: Record<string, SchemaLike>,
|
|
375
|
+
components?: ComponentsLike
|
|
367
376
|
): SpecValue =>
|
|
368
|
-
declaredExample(media) ??
|
|
377
|
+
declaredExample(media, components) ??
|
|
378
|
+
exampleValue(media.schema, schemas, "response");
|
|
369
379
|
|
|
370
380
|
/** Pretty-print a JSON value for an example/code block. */
|
|
371
381
|
export const toJson = <T>(value: T): string => JSON.stringify(value, null, 2);
|
|
@@ -171,7 +171,12 @@ export const initComposer = (root: HTMLElement): void => {
|
|
|
171
171
|
return;
|
|
172
172
|
}
|
|
173
173
|
if (state === "error") {
|
|
174
|
-
|
|
174
|
+
// A detail is the browser refusing the URL before dialing; a failed
|
|
175
|
+
// handshake carries none.
|
|
176
|
+
setStatus(
|
|
177
|
+
detail ? `Couldn't connect: ${detail}` : ERROR_MESSAGE,
|
|
178
|
+
ERROR_TEXT
|
|
179
|
+
);
|
|
175
180
|
return;
|
|
176
181
|
}
|
|
177
182
|
setStatus(
|
|
@@ -87,6 +87,17 @@ export const defaultMessageValues = (model: MessageModel): MessageValues => ({
|
|
|
87
87
|
|
|
88
88
|
const PARAM_TEMPLATE = /\{(?<name>[^{}]+)\}/gu;
|
|
89
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Protocols whose channel address is a URL path, where a parameter value must
|
|
92
|
+
* be percent-encoded. Everywhere else — a Kafka or MQTT topic, an AMQP routing
|
|
93
|
+
* key — the address is a name the value goes into as written: `sensor 1`,
|
|
94
|
+
* not `sensor%201`.
|
|
95
|
+
*/
|
|
96
|
+
const URL_PROTOCOLS = { http: true, https: true, ws: true } satisfies Record<
|
|
97
|
+
string,
|
|
98
|
+
true
|
|
99
|
+
>;
|
|
100
|
+
|
|
90
101
|
/**
|
|
91
102
|
* A free-text base URL lowered onto the server shape the snippet builders and
|
|
92
103
|
* the connect URL read. A full URL contributes its scheme, host, and path.
|
|
@@ -114,7 +125,8 @@ const customServer = (url: string): AsyncApiServerObject => {
|
|
|
114
125
|
/**
|
|
115
126
|
* THE one message builder: the composer's samples, its copy buttons, and the
|
|
116
127
|
* live WebSocket frame all consume its output. Parameter values are
|
|
117
|
-
* URL-encoded into the address
|
|
128
|
+
* URL-encoded into the address when the protocol addresses channels by URL
|
|
129
|
+
* (see {@link URL_PROTOCOLS}); a parameter left blank keeps its `{name}`
|
|
118
130
|
* template so the sample still reads as a template rather than a broken
|
|
119
131
|
* address. Payload text that doesn't parse yields no payload — the editor is
|
|
120
132
|
* showing the reader a validation error at that moment, and neither a sample
|
|
@@ -126,6 +138,9 @@ export const buildMessage = (
|
|
|
126
138
|
): MessageSample => {
|
|
127
139
|
const custom = values.customUrl.trim();
|
|
128
140
|
const picked = model.servers[values.server] ?? model.servers[0];
|
|
141
|
+
const encode = Object.hasOwn(URL_PROTOCOLS, model.protocol ?? "")
|
|
142
|
+
? encodeURIComponent
|
|
143
|
+
: (value: string) => value;
|
|
129
144
|
let payload: unknown;
|
|
130
145
|
try {
|
|
131
146
|
// SAFETY: JSON.parse returns `any`; widening it to `unknown` claims
|
|
@@ -138,7 +153,7 @@ export const buildMessage = (
|
|
|
138
153
|
action: model.action,
|
|
139
154
|
address: model.address.replaceAll(PARAM_TEMPLATE, (template, name) => {
|
|
140
155
|
const value = values.params[String(name)] ?? "";
|
|
141
|
-
return value === "" ? template :
|
|
156
|
+
return value === "" ? template : encode(value);
|
|
142
157
|
}),
|
|
143
158
|
payload,
|
|
144
159
|
server: custom === "" ? picked?.server : customServer(custom),
|
|
@@ -6,14 +6,21 @@ import {
|
|
|
6
6
|
resolveSchema,
|
|
7
7
|
toJson,
|
|
8
8
|
} from "./helpers.ts";
|
|
9
|
-
import type {
|
|
9
|
+
import type {
|
|
10
|
+
ComponentsLike,
|
|
11
|
+
ParameterLike,
|
|
12
|
+
SchemaLike,
|
|
13
|
+
SpecValue,
|
|
14
|
+
} from "./helpers.ts";
|
|
10
15
|
import {
|
|
11
16
|
declaredTypes,
|
|
12
17
|
inputValue,
|
|
13
18
|
scalarType,
|
|
14
19
|
validationSchema,
|
|
15
20
|
} from "./playground-schema.ts";
|
|
21
|
+
import { bodyEncoding } from "./request.ts";
|
|
16
22
|
import type {
|
|
23
|
+
ParamSerialization,
|
|
17
24
|
PlaygroundAuthInput,
|
|
18
25
|
PlaygroundBody,
|
|
19
26
|
PlaygroundBodyField,
|
|
@@ -34,6 +41,7 @@ interface MediaTypeLike {
|
|
|
34
41
|
schema?: SchemaLike;
|
|
35
42
|
example?: SpecValue;
|
|
36
43
|
examples?: SpecValue;
|
|
44
|
+
encoding?: SpecValue;
|
|
37
45
|
}
|
|
38
46
|
|
|
39
47
|
/** A server entry: its URL template and the variables that fill it. */
|
|
@@ -70,6 +78,45 @@ const isExampleObject = (
|
|
|
70
78
|
): value is Record<string, SpecValue> =>
|
|
71
79
|
typeof value === "object" && value !== null && !Array.isArray(value);
|
|
72
80
|
|
|
81
|
+
const isString = (value: SpecValue): value is string =>
|
|
82
|
+
typeof value === "string";
|
|
83
|
+
|
|
84
|
+
const isBoolean = (value: SpecValue): value is boolean =>
|
|
85
|
+
typeof value === "boolean";
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* The `style`/`explode` a parameter or form-body encoding declares, kept only
|
|
89
|
+
* when declared so the embedded model stays small; the request builder
|
|
90
|
+
* applies the OpenAPI defaults for the rest.
|
|
91
|
+
*/
|
|
92
|
+
const serialization = (node: Record<string, SpecValue>): ParamSerialization => {
|
|
93
|
+
const rule: ParamSerialization = {};
|
|
94
|
+
if (isString(node.style)) {
|
|
95
|
+
rule.style = node.style;
|
|
96
|
+
}
|
|
97
|
+
if (isBoolean(node.explode)) {
|
|
98
|
+
rule.explode = node.explode;
|
|
99
|
+
}
|
|
100
|
+
return rule;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
/** A form body's declared per-field `encoding`, when it names any style. */
|
|
104
|
+
const formEncoding = (
|
|
105
|
+
encoding: SpecValue
|
|
106
|
+
): PlaygroundBody["encoding"] | undefined => {
|
|
107
|
+
if (!isExampleObject(encoding)) {
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
110
|
+
const fields: NonNullable<PlaygroundBody["encoding"]> = {};
|
|
111
|
+
for (const [name, entry] of Object.entries(encoding)) {
|
|
112
|
+
const rule = isExampleObject(entry) ? serialization(entry) : {};
|
|
113
|
+
if (Object.keys(rule).length > 0) {
|
|
114
|
+
fields[name] = rule;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return Object.keys(fields).length > 0 ? fields : undefined;
|
|
118
|
+
};
|
|
119
|
+
|
|
73
120
|
/**
|
|
74
121
|
* Playground inputs for the operation's parameters. Cookie params are skipped
|
|
75
122
|
* (not supported in v1 — browsers won't let a page set arbitrary cookies).
|
|
@@ -80,7 +127,8 @@ const isExampleObject = (
|
|
|
80
127
|
*/
|
|
81
128
|
const modelParams = (
|
|
82
129
|
parameters: ParameterLike[],
|
|
83
|
-
schemas: Record<string, SchemaLike
|
|
130
|
+
schemas: Record<string, SchemaLike>,
|
|
131
|
+
components: ComponentsLike | undefined
|
|
84
132
|
): PlaygroundParam[] => {
|
|
85
133
|
const params: PlaygroundParam[] = [];
|
|
86
134
|
for (const param of parameters) {
|
|
@@ -102,9 +150,11 @@ const modelParams = (
|
|
|
102
150
|
type: scalarType(param.schema, schemas),
|
|
103
151
|
value: required
|
|
104
152
|
? inputValue(
|
|
105
|
-
declaredExample(param) ??
|
|
153
|
+
declaredExample(param, components) ??
|
|
154
|
+
exampleValue(param.schema, schemas)
|
|
106
155
|
)
|
|
107
156
|
: "",
|
|
157
|
+
...serialization(param),
|
|
108
158
|
});
|
|
109
159
|
}
|
|
110
160
|
return params;
|
|
@@ -165,10 +215,16 @@ const bodyFields = (
|
|
|
165
215
|
return fields;
|
|
166
216
|
};
|
|
167
217
|
|
|
168
|
-
/**
|
|
218
|
+
/**
|
|
219
|
+
* The playground's body editor state, when the operation takes a request body.
|
|
220
|
+
* JSON, form-urlencoded, and multipart bodies are edited as JSON (typed fields
|
|
221
|
+
* when flat) and serialized for their media type on send; any other media
|
|
222
|
+
* type is raw text, prefilled with a string example as written.
|
|
223
|
+
*/
|
|
169
224
|
const modelBody = (
|
|
170
225
|
requestBody: { content?: Record<string, MediaTypeLike> } | undefined,
|
|
171
|
-
schemas: Record<string, SchemaLike
|
|
226
|
+
schemas: Record<string, SchemaLike>,
|
|
227
|
+
components: ComponentsLike | undefined
|
|
172
228
|
): PlaygroundBody | undefined => {
|
|
173
229
|
const media = jsonContentType(requestBody?.content);
|
|
174
230
|
if (!media) {
|
|
@@ -176,13 +232,25 @@ const modelBody = (
|
|
|
176
232
|
}
|
|
177
233
|
const [contentType, mediaType] = media;
|
|
178
234
|
const exampleData =
|
|
179
|
-
declaredExample(mediaType) ??
|
|
180
|
-
|
|
235
|
+
declaredExample(mediaType, components) ??
|
|
236
|
+
exampleValue(mediaType.schema, schemas);
|
|
237
|
+
const encoding = bodyEncoding(contentType);
|
|
238
|
+
const raw = encoding === "raw";
|
|
239
|
+
const body: PlaygroundBody = {
|
|
181
240
|
contentType,
|
|
182
|
-
example:
|
|
183
|
-
|
|
241
|
+
example:
|
|
242
|
+
raw && isString(exampleData) ? exampleData : (toJson(exampleData) ?? ""),
|
|
243
|
+
fields: raw
|
|
244
|
+
? undefined
|
|
245
|
+
: bodyFields(mediaType.schema, schemas, exampleData),
|
|
184
246
|
schema: validationSchema(mediaType.schema, schemas),
|
|
185
247
|
};
|
|
248
|
+
const fieldEncoding =
|
|
249
|
+
encoding === "form" ? formEncoding(mediaType.encoding) : undefined;
|
|
250
|
+
if (fieldEncoding) {
|
|
251
|
+
body.encoding = fieldEncoding;
|
|
252
|
+
}
|
|
253
|
+
return body;
|
|
186
254
|
};
|
|
187
255
|
|
|
188
256
|
const AUTHORIZATION_HEADER = { in: "header", name: "Authorization" } as const;
|
|
@@ -272,6 +340,8 @@ export const operationModel = (args: {
|
|
|
272
340
|
/** The operation's effective servers (`effectiveServers` output). */
|
|
273
341
|
servers: ServerLike[];
|
|
274
342
|
schemas: Record<string, SchemaLike>;
|
|
343
|
+
/** The document's `components`, which `$ref`'d examples resolve against. */
|
|
344
|
+
components?: ComponentsLike;
|
|
275
345
|
security: OperationSecurity;
|
|
276
346
|
}): PlaygroundModel => ({
|
|
277
347
|
// First alternative only — the spec's preferred way to authorize, matching
|
|
@@ -281,9 +351,9 @@ export const operationModel = (args: {
|
|
|
281
351
|
return input ? [input] : [];
|
|
282
352
|
}),
|
|
283
353
|
authOptional: args.security.optional,
|
|
284
|
-
body: modelBody(args.requestBody, args.schemas),
|
|
354
|
+
body: modelBody(args.requestBody, args.schemas, args.components),
|
|
285
355
|
method: args.method.toUpperCase(),
|
|
286
|
-
params: modelParams(args.parameters, args.schemas),
|
|
356
|
+
params: modelParams(args.parameters, args.schemas, args.components),
|
|
287
357
|
path: args.path,
|
|
288
358
|
// Variables resolve to their defaults: the samples and Send need a real URL.
|
|
289
359
|
servers: args.servers.map((server) =>
|
|
@@ -40,10 +40,12 @@ class BlumePanelTabs extends HTMLElement {
|
|
|
40
40
|
// wrap, Home and End jump to the ends, and focus follows selection.
|
|
41
41
|
tab.addEventListener("keydown", (event) => {
|
|
42
42
|
const last = tabs.length - 1;
|
|
43
|
+
// The strip runs right to left under dir="rtl", so the arrows swap.
|
|
44
|
+
const rtl = getComputedStyle(this).direction === "rtl";
|
|
43
45
|
let next: number | undefined;
|
|
44
|
-
if (event.key === "ArrowRight") {
|
|
46
|
+
if (event.key === (rtl ? "ArrowLeft" : "ArrowRight")) {
|
|
45
47
|
next = index === last ? 0 : index + 1;
|
|
46
|
-
} else if (event.key === "ArrowLeft") {
|
|
48
|
+
} else if (event.key === (rtl ? "ArrowRight" : "ArrowLeft")) {
|
|
47
49
|
next = index === 0 ? last : index - 1;
|
|
48
50
|
} else if (event.key === "Home") {
|
|
49
51
|
next = 0;
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAPI 3 parameter serialization — `style` and `explode` — for the
|
|
3
|
+
* playground's one request builder (`request.ts`). An array or object value
|
|
4
|
+
* has a different wire shape per style: `tags: ["dog", "cat"]` is
|
|
5
|
+
* `tags=dog&tags=cat` in a query (form, exploded), `dog,cat` in a path
|
|
6
|
+
* (simple), and `filter: { color: "red" }` is `filter[color]=red` as a
|
|
7
|
+
* deepObject. Ships in the client bundle with `request.ts`, so it stays
|
|
8
|
+
* dependency-free.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/** Parsed JSON: everything `JSON.parse` can produce. */
|
|
12
|
+
export type JsonValue =
|
|
13
|
+
| string
|
|
14
|
+
| number
|
|
15
|
+
| boolean
|
|
16
|
+
| null
|
|
17
|
+
| JsonValue[]
|
|
18
|
+
| { [key: string]: JsonValue };
|
|
19
|
+
|
|
20
|
+
/** A value lowered for serialization: a scalar, a list's items, or an object's entries. */
|
|
21
|
+
export type StyledValue =
|
|
22
|
+
| { kind: "scalar"; text: string }
|
|
23
|
+
| { kind: "list"; items: string[] }
|
|
24
|
+
| { kind: "object"; entries: [string, string][] };
|
|
25
|
+
|
|
26
|
+
// `typeof` checks live in named predicates (the form the oxlint anti-slop
|
|
27
|
+
// config sanctions).
|
|
28
|
+
const isString = (value: JsonValue): value is string =>
|
|
29
|
+
typeof value === "string";
|
|
30
|
+
|
|
31
|
+
/** Whether a parsed value is a plain JSON object. */
|
|
32
|
+
export const isJsonObject = (
|
|
33
|
+
value: JsonValue
|
|
34
|
+
): value is { [key: string]: JsonValue } =>
|
|
35
|
+
typeof value === "object" && value !== null && !Array.isArray(value);
|
|
36
|
+
|
|
37
|
+
/** One member as wire text: a string verbatim, anything else as its JSON. */
|
|
38
|
+
export const memberText = (value: JsonValue): string =>
|
|
39
|
+
isString(value) ? value : JSON.stringify(value);
|
|
40
|
+
|
|
41
|
+
/** A parsed value, lowered: arrays to items, objects to entries, the rest to text. */
|
|
42
|
+
export const styledValue = (value: JsonValue): StyledValue => {
|
|
43
|
+
if (Array.isArray(value)) {
|
|
44
|
+
return { items: value.map(memberText), kind: "list" };
|
|
45
|
+
}
|
|
46
|
+
if (isJsonObject(value)) {
|
|
47
|
+
return {
|
|
48
|
+
entries: Object.entries(value).map(([key, member]) => [
|
|
49
|
+
key,
|
|
50
|
+
memberText(member),
|
|
51
|
+
]),
|
|
52
|
+
kind: "object",
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
return { kind: "scalar", text: memberText(value) };
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* A playground input's text as a styled value. Only an array- or object-typed
|
|
60
|
+
* parameter reads its text as JSON — its prefill is the example's JSON
|
|
61
|
+
* (`["dog","cat"]`) — and only when the text parses to that shape; anything
|
|
62
|
+
* else is sent as the one scalar it reads as.
|
|
63
|
+
*/
|
|
64
|
+
export const parseStyledValue = (text: string, type: string): StyledValue => {
|
|
65
|
+
if (type === "array" || type === "object") {
|
|
66
|
+
let parsed: JsonValue;
|
|
67
|
+
try {
|
|
68
|
+
parsed = JSON.parse(text);
|
|
69
|
+
} catch {
|
|
70
|
+
return { kind: "scalar", text };
|
|
71
|
+
}
|
|
72
|
+
if (type === "array" ? Array.isArray(parsed) : isJsonObject(parsed)) {
|
|
73
|
+
return styledValue(parsed);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return { kind: "scalar", text };
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
/** The OpenAPI 3 default style: `form` in a query or cookie, `simple` elsewhere. */
|
|
80
|
+
export const defaultStyle = (location: string): string =>
|
|
81
|
+
location === "query" || location === "cookie" ? "form" : "simple";
|
|
82
|
+
|
|
83
|
+
/** `explode` when the spec leaves it out: true for `form`, false for the rest. */
|
|
84
|
+
export const defaultExplode = (style: string): boolean => style === "form";
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* A list or object joined into one value: exploded object entries as
|
|
88
|
+
* `key=value` separated by `separator`, exploded items by `separator`, and
|
|
89
|
+
* the unexploded forms comma-separated (`a,b`, `key,value,key2,value2`).
|
|
90
|
+
*/
|
|
91
|
+
const joined = (
|
|
92
|
+
value: StyledValue,
|
|
93
|
+
explode: boolean,
|
|
94
|
+
encode: (text: string) => string,
|
|
95
|
+
separator: string
|
|
96
|
+
): string => {
|
|
97
|
+
if (value.kind === "scalar") {
|
|
98
|
+
return encode(value.text);
|
|
99
|
+
}
|
|
100
|
+
if (value.kind === "list") {
|
|
101
|
+
return value.items.map(encode).join(explode ? separator : ",");
|
|
102
|
+
}
|
|
103
|
+
return explode
|
|
104
|
+
? value.entries
|
|
105
|
+
.map(([key, member]) => `${encode(key)}=${encode(member)}`)
|
|
106
|
+
.join(separator)
|
|
107
|
+
: value.entries.flat().map(encode).join(",");
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* A query parameter, or an `application/x-www-form-urlencoded` body field, as
|
|
112
|
+
* its percent-encoded `name=value` pairs in order. Exploded lists repeat the
|
|
113
|
+
* name (`tags=dog&tags=cat`) and exploded objects spread their entries
|
|
114
|
+
* (`color=red&size=L`) whatever the style; unexploded ones join with the
|
|
115
|
+
* style's delimiter — `,` for form, `%20` for spaceDelimited, `|` for
|
|
116
|
+
* pipeDelimited. deepObject nests entries under the name (`filter[color]=red`).
|
|
117
|
+
*/
|
|
118
|
+
export const queryPairs = (
|
|
119
|
+
name: string,
|
|
120
|
+
value: StyledValue,
|
|
121
|
+
style: string,
|
|
122
|
+
explode: boolean
|
|
123
|
+
): string[] => {
|
|
124
|
+
const key = encodeURIComponent(name);
|
|
125
|
+
if (value.kind === "object" && style === "deepObject") {
|
|
126
|
+
return value.entries.map(
|
|
127
|
+
([entry, member]) =>
|
|
128
|
+
`${key}[${encodeURIComponent(entry)}]=${encodeURIComponent(member)}`
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
if (value.kind === "list" && explode) {
|
|
132
|
+
return value.items.map((item) => `${key}=${encodeURIComponent(item)}`);
|
|
133
|
+
}
|
|
134
|
+
if (value.kind === "object" && explode) {
|
|
135
|
+
return value.entries.map(
|
|
136
|
+
([entry, member]) =>
|
|
137
|
+
`${encodeURIComponent(entry)}=${encodeURIComponent(member)}`
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
let delimiter = ",";
|
|
141
|
+
if (style === "spaceDelimited") {
|
|
142
|
+
delimiter = "%20";
|
|
143
|
+
} else if (style === "pipeDelimited") {
|
|
144
|
+
delimiter = "|";
|
|
145
|
+
}
|
|
146
|
+
const text =
|
|
147
|
+
value.kind === "scalar"
|
|
148
|
+
? encodeURIComponent(value.text)
|
|
149
|
+
: (value.kind === "list" ? value.items : value.entries.flat())
|
|
150
|
+
.map(encodeURIComponent)
|
|
151
|
+
.join(delimiter);
|
|
152
|
+
return [`${key}=${text}`];
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* A path or header parameter's value: `simple` (`dog,cat`), or one of the
|
|
157
|
+
* path-only `label` (`.dog.cat`) and `matrix` (`;tags=dog;tags=cat`) styles.
|
|
158
|
+
* `encode` percent-encodes a path segment; a header passes values through.
|
|
159
|
+
*/
|
|
160
|
+
export const templateValue = (
|
|
161
|
+
name: string,
|
|
162
|
+
value: StyledValue,
|
|
163
|
+
style: string,
|
|
164
|
+
explode: boolean,
|
|
165
|
+
encode: (text: string) => string
|
|
166
|
+
): string => {
|
|
167
|
+
if (style === "label") {
|
|
168
|
+
return `.${joined(value, explode, encode, ".")}`;
|
|
169
|
+
}
|
|
170
|
+
if (style !== "matrix") {
|
|
171
|
+
return joined(value, explode, encode, ",");
|
|
172
|
+
}
|
|
173
|
+
const key = encode(name);
|
|
174
|
+
if (value.kind === "list" && explode) {
|
|
175
|
+
return value.items.map((item) => `;${key}=${encode(item)}`).join("");
|
|
176
|
+
}
|
|
177
|
+
if (value.kind === "object" && explode) {
|
|
178
|
+
return `;${joined(value, true, encode, ";")}`;
|
|
179
|
+
}
|
|
180
|
+
return `;${key}=${joined(value, false, encode, ",")}`;
|
|
181
|
+
};
|