blume 2.1.3 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -1
- package/CHANGELOG.md +134 -0
- package/README.md +4 -4
- package/dist/cli/{chunk-y4msrwm9.js → chunk-080mfch6.js} +15 -15
- package/dist/cli/{chunk-gfc5fqvf.js → chunk-1ch3ct3r.js} +18 -18
- package/dist/cli/{chunk-gfc5fqvf.js.map → chunk-1ch3ct3r.js.map} +1 -1
- package/dist/cli/{chunk-32khwcb6.js → chunk-2ssh60qh.js} +42 -69
- package/dist/cli/{chunk-32khwcb6.js.map → chunk-2ssh60qh.js.map} +9 -10
- package/dist/cli/{chunk-9qzgg6mj.js → chunk-34wap3ed.js} +3 -3
- package/dist/cli/{chunk-k3gr1nm9.js → chunk-40vk8kgf.js} +13 -16
- package/dist/cli/{chunk-k3gr1nm9.js.map → chunk-40vk8kgf.js.map} +3 -3
- package/dist/cli/chunk-487b95qy.js +329 -0
- package/dist/cli/chunk-487b95qy.js.map +13 -0
- package/dist/cli/chunk-4zxh25hc.js +157 -0
- package/dist/cli/chunk-4zxh25hc.js.map +10 -0
- package/dist/cli/chunk-69rjf786.js +146 -0
- package/dist/cli/chunk-69rjf786.js.map +11 -0
- package/dist/cli/{chunk-dqhg54mr.js → chunk-9h8mh2tk.js} +3 -3
- package/dist/cli/{chunk-dqhg54mr.js.map → chunk-9h8mh2tk.js.map} +2 -2
- package/dist/cli/{chunk-bqxaqn5p.js → chunk-9jqmq5hv.js} +8 -8
- package/dist/cli/{chunk-bqxaqn5p.js.map → chunk-9jqmq5hv.js.map} +1 -1
- package/dist/cli/{chunk-dv2z0rzf.js → chunk-aafhwx74.js} +38 -13
- package/dist/cli/{chunk-dv2z0rzf.js.map → chunk-aafhwx74.js.map} +5 -4
- package/dist/cli/{chunk-desvm72z.js → chunk-b680sv30.js} +22 -26
- package/dist/cli/chunk-b680sv30.js.map +13 -0
- package/dist/cli/{chunk-0w6hs479.js → chunk-beb0z983.js} +30 -18
- package/dist/cli/chunk-beb0z983.js.map +10 -0
- package/dist/cli/{chunk-1f882900.js → chunk-c5bjxq8v.js} +2 -2
- package/dist/cli/chunk-e1n41w9m.js +155 -0
- package/dist/cli/chunk-e1n41w9m.js.map +11 -0
- package/dist/cli/{chunk-sc93apfs.js → chunk-etckvbrh.js} +17 -17
- package/dist/cli/{chunk-sc93apfs.js.map → chunk-etckvbrh.js.map} +2 -2
- package/dist/cli/{chunk-bxwhtvw8.js → chunk-f260jdrn.js} +5 -5
- package/dist/cli/{chunk-74wfhv79.js → chunk-fnxgtjeq.js} +1 -1
- package/dist/cli/{chunk-ms9z66nz.js → chunk-gwy55cx3.js} +2 -2
- package/dist/cli/{chunk-ms9z66nz.js.map → chunk-gwy55cx3.js.map} +2 -2
- package/dist/cli/{chunk-dhwtqnnd.js → chunk-gxhcf2hs.js} +2 -2
- package/dist/cli/{chunk-tfycddbt.js → chunk-h0qwdbem.js} +2 -2
- package/dist/cli/{chunk-nbyvgnnm.js → chunk-hktq4j5r.js} +109 -49
- package/dist/cli/chunk-hktq4j5r.js.map +36 -0
- package/dist/cli/{chunk-twy7psdz.js → chunk-hn3g2b89.js} +14 -10
- package/dist/cli/chunk-hn3g2b89.js.map +10 -0
- package/dist/cli/{chunk-j1x92mx9.js → chunk-j4nfgn2j.js} +1 -1
- package/dist/cli/{chunk-dpy8qdjf.js → chunk-k45sq16q.js} +74 -183
- package/dist/cli/chunk-k45sq16q.js.map +18 -0
- package/dist/cli/{chunk-5cmts6dv.js → chunk-kmswjxj9.js} +7 -7
- package/dist/cli/{chunk-5cmts6dv.js.map → chunk-kmswjxj9.js.map} +1 -1
- package/dist/cli/{chunk-36bxs9c7.js → chunk-nqna8dzp.js} +27 -23
- package/dist/cli/chunk-nqna8dzp.js.map +10 -0
- package/dist/cli/{chunk-a57yh0h9.js → chunk-p834rkcn.js} +7 -7
- package/dist/cli/{chunk-a57yh0h9.js.map → chunk-p834rkcn.js.map} +1 -1
- package/dist/cli/{chunk-60hz265r.js → chunk-ppa6mg4d.js} +24 -11
- package/dist/cli/chunk-ppa6mg4d.js.map +10 -0
- package/dist/cli/{chunk-s0bdnc7v.js → chunk-q1wwrxzw.js} +5 -4
- package/dist/cli/chunk-q1wwrxzw.js.map +10 -0
- package/dist/cli/{chunk-ave1wcbr.js → chunk-qcyxkj44.js} +1 -1
- package/dist/cli/{chunk-124fvmzq.js → chunk-r5nm9w0c.js} +11183 -8806
- package/dist/cli/{chunk-124fvmzq.js.map → chunk-r5nm9w0c.js.map} +82 -66
- package/dist/cli/{chunk-ckrcm08h.js → chunk-rtvgmg2j.js} +48 -62
- package/dist/cli/{chunk-ckrcm08h.js.map → chunk-rtvgmg2j.js.map} +4 -5
- package/dist/cli/{chunk-297ajdcv.js → chunk-t2h8pwy1.js} +6 -6
- package/dist/cli/{chunk-297ajdcv.js.map → chunk-t2h8pwy1.js.map} +3 -3
- package/dist/cli/{chunk-gxtg6ed2.js → chunk-x60e15st.js} +21 -21
- package/dist/cli/{chunk-gxtg6ed2.js.map → chunk-x60e15st.js.map} +3 -3
- package/dist/cli/{chunk-58bt3hag.js → chunk-x7bh6d9j.js} +4 -4
- package/dist/cli/{chunk-hvcxng5f.js → chunk-ydqzkhjn.js} +6 -6
- package/dist/cli/{chunk-kdpzw38a.js → chunk-yg8ckc3g.js} +95 -7
- package/dist/cli/chunk-yg8ckc3g.js.map +11 -0
- package/dist/cli/{chunk-0pmb4tr4.js → chunk-zxd5jrgx.js} +1205 -222
- package/dist/cli/chunk-zxd5jrgx.js.map +44 -0
- package/dist/cli/index.js +78 -42
- package/dist/cli/index.js.map +7 -6
- package/dist/types/ai/changelog-components.d.ts +18 -0
- package/dist/types/ai/changelog-markdown.d.ts +12 -0
- package/dist/types/ai/openapi-components.d.ts +7 -7
- package/dist/types/ai/operation-details.d.ts +39 -0
- package/dist/types/ai/relative-links.d.ts +3 -1
- package/dist/types/ai/serializers.d.ts +6 -4
- package/dist/types/analytics/head.d.ts +4 -2
- package/dist/types/analytics/script.d.ts +8 -2
- package/dist/types/components/content/youtube.d.ts +20 -0
- package/dist/types/components/layout/nav-utils.d.ts +8 -0
- package/dist/types/components/openapi/example-panels.d.ts +33 -0
- package/dist/types/components/openapi/helpers.d.ts +53 -11
- package/dist/types/components/openapi/snippets.d.ts +7 -1
- package/dist/types/core/alert-diagnostics.d.ts +10 -0
- package/dist/types/core/builtin-tags.d.ts +16 -0
- package/dist/types/core/changelog-list.d.ts +48 -0
- package/dist/types/core/closest-match.d.ts +6 -0
- package/dist/types/core/code-fence-diagnostics.d.ts +18 -0
- package/dist/types/core/code-fences.d.ts +8 -1
- package/dist/types/core/config-input.d.ts +38 -6
- package/dist/types/core/content-assets.d.ts +16 -18
- package/dist/types/core/data.d.ts +6 -2
- package/dist/types/core/diagnostics.d.ts +14 -0
- package/dist/types/core/directive-diagnostics.d.ts +22 -8
- package/dist/types/core/former-routes.d.ts +14 -0
- package/dist/types/core/github.d.ts +5 -4
- package/dist/types/core/heading-markers.d.ts +65 -2
- package/dist/types/core/hidden-pages.d.ts +3 -0
- package/dist/types/core/includes.d.ts +23 -0
- package/dist/types/core/last-modified.d.ts +18 -6
- package/dist/types/core/links.d.ts +42 -2
- package/dist/types/core/load-module.d.ts +19 -4
- package/dist/types/core/manifest.d.ts +14 -1
- package/dist/types/core/markdown-mirrors.d.ts +22 -0
- package/dist/types/core/mcp-clients.d.ts +47 -0
- package/dist/types/core/mdx-elements.d.ts +32 -0
- package/dist/types/core/mdx-syntax.d.ts +100 -0
- package/dist/types/core/meta-diagnostics.d.ts +7 -0
- package/dist/types/core/meta.d.ts +32 -5
- package/dist/types/core/nav-diagnostics.d.ts +16 -2
- package/dist/types/core/navigation.d.ts +13 -0
- package/dist/types/core/ordering-prefix.d.ts +6 -0
- package/dist/types/core/pinned-ids.d.ts +23 -0
- package/dist/types/core/project-graph.d.ts +9 -1
- package/dist/types/core/redirect-patterns.d.ts +18 -0
- package/dist/types/core/relative-files.d.ts +31 -0
- package/dist/types/core/schema.d.ts +322 -11
- package/dist/types/core/sources/normalize.d.ts +101 -9
- package/dist/types/core/sources/types.d.ts +16 -0
- package/dist/types/core/static-files.d.ts +10 -0
- package/dist/types/core/static-host.d.ts +42 -0
- package/dist/types/core/svg-images.d.ts +26 -0
- package/dist/types/core/syntax-diagnostics.d.ts +14 -0
- package/dist/types/core/types.d.ts +42 -1
- package/dist/types/deploy/generated-files.d.ts +41 -0
- package/dist/types/deploy/redirects.d.ts +21 -7
- package/dist/types/markdown/code-title.d.ts +9 -5
- package/dist/types/markdown/directives.d.ts +8 -0
- package/dist/types/markdown/fence-language.d.ts +51 -0
- package/dist/types/markdown/fence-meta.d.ts +5 -0
- package/dist/types/markdown/github-alerts.d.ts +35 -0
- package/dist/types/openapi/asyncapi.d.ts +6 -5
- package/dist/types/openapi/checks.d.ts +10 -5
- package/dist/types/openapi/model.d.ts +55 -8
- package/dist/types/openapi/parse.d.ts +4 -1
- package/dist/types/ratelimit/index.d.ts +2 -0
- package/dist/types/ratelimit/memory.d.ts +1 -1
- package/dist/types/ratelimit/schema.d.ts +40 -0
- package/dist/types/ratelimit/unkey.d.ts +48 -0
- package/dist/types/sources/filesystem.d.ts +14 -4
- package/dist/types/sources/mdx-remote.d.ts +6 -3
- package/dist/types/sources/registry.d.ts +3 -3
- package/dist/types/theme/color.d.ts +33 -0
- package/dist/types/theme/palette.d.ts +122 -0
- package/docs/01-quickstart.mdx +1 -1
- package/docs/02-deployment.mdx +24 -8
- package/docs/04-migrating.mdx +16 -4
- package/docs/advanced/changelog.mdx +27 -1
- package/docs/advanced/skills.mdx +1 -1
- package/docs/cli/audit.mdx +1 -1
- package/docs/cli/doctor.mdx +2 -2
- package/docs/cli/evals.mdx +1 -1
- package/docs/cli/index.mdx +4 -2
- package/docs/cli/validate.mdx +10 -7
- package/docs/configuration/analytics.mdx +2 -0
- package/docs/configuration/customization.mdx +3 -1
- package/docs/configuration/index.mdx +7 -6
- package/docs/configuration/rate-limiting.mdx +20 -1
- package/docs/configuration/theming.mdx +5 -1
- package/docs/content/components.mdx +26 -6
- package/docs/content/frontmatter.mdx +1 -1
- package/docs/content/i18n.mdx +1 -1
- package/docs/content/includes.mdx +6 -2
- package/docs/content/index.mdx +11 -1
- package/docs/content/islands.mdx +2 -0
- package/docs/content/meta.mdx +9 -3
- package/docs/content/navigation.mdx +14 -6
- package/docs/content/sources/obsidian.mdx +1 -1
- package/docs/content/sources/remote-mdx.mdx +3 -1
- package/docs/content/syntax.mdx +76 -8
- package/docs/content/variables.mdx +3 -1
- package/docs/discoverability/agent-discovery.mdx +1 -1
- package/docs/discoverability/json-api.mdx +1 -1
- package/docs/discoverability/llms-txt.mdx +1 -1
- package/docs/discoverability/markdown.mdx +2 -2
- package/docs/discoverability/mcp.mdx +40 -8
- package/docs/discoverability/open-graph.mdx +1 -1
- package/docs/discoverability/sitemap-and-robots.mdx +1 -1
- package/docs/references/graphql.mdx +2 -0
- package/docs/references/openapi.mdx +45 -7
- package/package.json +4 -4
- package/skills/blume/SKILL.md +2 -2
- package/skills/blume-migrate/SKILL.md +51 -29
- package/skills/blume-migrate/references/docsify.md +262 -0
- package/skills/blume-migrate/references/docus.md +298 -0
- package/skills/blume-migrate/references/docusaurus.md +5 -5
- package/skills/blume-migrate/references/fern.md +327 -0
- package/skills/blume-migrate/references/fumadocs.md +1 -1
- package/skills/blume-migrate/references/gitbook.md +267 -0
- package/skills/blume-migrate/references/github-wiki.md +259 -0
- package/skills/blume-migrate/references/jekyll.md +253 -0
- package/skills/blume-migrate/references/mdbook.md +256 -0
- package/skills/blume-migrate/references/mintlify.md +5 -5
- package/skills/blume-migrate/references/mkdocs.md +236 -0
- package/skills/blume-migrate/references/monorepo.md +20 -8
- package/skills/blume-migrate/references/nextra.md +5 -5
- package/skills/blume-migrate/references/readme.md +257 -0
- package/skills/blume-migrate/references/redocly.md +198 -0
- package/skills/blume-migrate/references/starlight.md +3 -3
- package/skills/blume-migrate/references/vitepress.md +204 -0
- package/skills/blume-migrate/references/vuepress.md +271 -0
- package/skills/blume-migrate/scripts/docsify-codemod.mjs +2387 -0
- package/skills/blume-migrate/scripts/docus-codemod.mjs +2542 -0
- package/skills/blume-migrate/scripts/fern-codemod.mjs +2633 -0
- package/skills/blume-migrate/scripts/github-wiki-codemod.mjs +2808 -0
- package/skills/blume-migrate/scripts/include-excerpts.mjs +649 -0
- package/skills/blume-migrate/scripts/jekyll-codemod.mjs +3649 -0
- package/skills/blume-migrate/scripts/mintlify-codemod.mjs +17 -13
- package/skills/blume-migrate/scripts/mkdocs-codemod.mjs +2526 -0
- package/skills/blume-migrate/scripts/operation-routes.mjs +508 -0
- package/skills/blume-migrate/scripts/pin-heading-ids.mjs +1049 -0
- package/skills/blume-migrate/scripts/readme-codemod.mjs +4139 -0
- package/skills/blume-migrate/scripts/vitepress-codemod.mjs +1511 -0
- package/src/ai/changelog-components.ts +24 -0
- package/src/ai/changelog-markdown.ts +45 -41
- package/src/ai/component-markdown.ts +22 -9
- package/src/ai/llms.ts +36 -5
- package/src/ai/markdown.ts +2 -2
- package/src/ai/openapi-components.ts +25 -9
- package/src/ai/operation-details.ts +208 -0
- package/src/ai/relative-links.ts +48 -8
- package/src/ai/serializers.ts +7 -6
- package/src/ai/site-skill.ts +6 -2
- package/src/analytics/head.ts +11 -5
- package/src/analytics/script.ts +13 -3
- package/src/astro/generate.ts +47 -11
- package/src/astro/index.ts +1 -0
- package/src/astro/integration.ts +27 -1
- package/src/astro/mdx-source-errors.ts +46 -0
- package/src/astro/templates.ts +93 -189
- package/src/audit/checks/redirects.ts +5 -1
- package/src/audit/redirects.ts +36 -19
- package/src/audit/report.ts +22 -9
- package/src/audit/run.ts +12 -28
- package/src/audit/terms.ts +23 -0
- package/src/audit/url.ts +2 -2
- package/src/cli/build-failure.ts +256 -7
- package/src/cli/command-meta.ts +1 -1
- package/src/cli/commands/audit.ts +1 -1
- package/src/cli/commands/build.ts +12 -3
- package/src/cli/commands/check.ts +13 -2
- package/src/cli/commands/dev.ts +1 -1
- package/src/cli/commands/doctor.ts +4 -2
- package/src/cli/commands/init.ts +3 -3
- package/src/cli/commands/preview.ts +17 -1
- package/src/cli/commands/validate.ts +22 -10
- package/src/cli/prepare.ts +1 -1
- package/src/cli/preview-pages.ts +161 -0
- package/src/cli/required-secrets.ts +0 -1
- package/src/cli/unknown-flags.ts +1 -42
- package/src/components/code-copy.ts +51 -0
- package/src/components/code-language.ts +75 -0
- package/src/components/content/AccordionItem.astro +16 -1
- package/src/components/content/Callout.astro +11 -1
- package/src/components/content/Changelog.astro +189 -0
- package/src/components/content/CodeBlock.astro +8 -11
- package/src/components/content/Tabs.astro +16 -2
- package/src/components/content/YouTube.astro +6 -4
- package/src/components/content/code-block.ts +33 -0
- package/src/components/content/content-strings.ts +5 -1
- package/src/components/content/inline-markdown.ts +35 -8
- package/src/components/content/youtube.ts +49 -7
- package/src/components/layout/Analytics.astro +5 -1
- package/src/components/layout/NavTree.astro +8 -3
- package/src/components/layout/PageActions.astro +81 -23
- package/src/components/layout/RootLayout.astro +35 -32
- package/src/components/layout/SiteFooter.astro +31 -8
- package/src/components/layout/nav-utils.ts +14 -0
- package/src/components/layout/search/pagefind.ts +2 -1
- package/src/components/openapi/Operation.astro +4 -0
- package/src/components/openapi/PanelTabs.astro +9 -3
- package/src/components/openapi/RequestBody.astro +42 -8
- package/src/components/openapi/RequestPanel.astro +34 -53
- package/src/components/openapi/example-panels.ts +110 -0
- package/src/components/openapi/helpers.ts +195 -20
- package/src/components/openapi/operation-model.ts +63 -26
- package/src/components/openapi/request.ts +13 -0
- package/src/components/openapi/snippets.ts +14 -2
- package/src/core/alert-diagnostics.ts +89 -0
- package/src/core/builtin-tags.ts +76 -0
- package/src/core/changelog-list.ts +87 -0
- package/src/core/closest-match.ts +41 -0
- package/src/core/code-fence-diagnostics.ts +267 -0
- package/src/core/code-fences.ts +43 -7
- package/src/core/component-diagnostics.ts +65 -12
- package/src/core/config-input.ts +39 -5
- package/src/core/config.ts +46 -1
- package/src/core/content-assets.ts +64 -144
- package/src/core/data.ts +10 -3
- package/src/core/diagnostics.ts +36 -3
- package/src/core/directive-diagnostics.ts +265 -47
- package/src/core/former-routes.ts +46 -0
- package/src/core/git-ignored.ts +53 -0
- package/src/core/github.ts +5 -4
- package/src/core/heading-markers.ts +156 -2
- package/src/core/hidden-pages.ts +64 -0
- package/src/core/includes.ts +181 -41
- package/src/core/last-modified.ts +47 -10
- package/src/core/links.ts +438 -83
- package/src/core/load-module.ts +98 -9
- package/src/core/manifest.ts +12 -9
- package/src/core/markdown-mirrors.ts +52 -0
- package/src/core/mcp-clients.ts +87 -0
- package/src/core/mdx-elements.ts +153 -0
- package/src/core/mdx-syntax.ts +377 -0
- package/src/core/meta-diagnostics.ts +134 -0
- package/src/core/meta.ts +154 -55
- package/src/core/nav-diagnostics.ts +41 -4
- package/src/core/navigation.ts +70 -10
- package/src/core/ordering-prefix.ts +22 -2
- package/src/core/pinned-ids.ts +141 -0
- package/src/core/project-graph.ts +221 -29
- package/src/core/redirect-patterns.ts +41 -0
- package/src/core/relative-files.ts +145 -0
- package/src/core/schema.ts +110 -6
- package/src/core/sources/mdx-remote.ts +75 -14
- package/src/core/sources/normalize.ts +885 -179
- package/src/core/sources/notion.ts +5 -4
- package/src/core/sources/obsidian.ts +2 -5
- package/src/core/sources/types.ts +17 -0
- package/src/core/static-files.ts +40 -0
- package/src/core/static-host.ts +125 -0
- package/src/core/svg-images.ts +98 -0
- package/src/core/syntax-diagnostics.ts +491 -0
- package/src/core/types.ts +43 -1
- package/src/deploy/artifacts.ts +2 -28
- package/src/deploy/generated-files.ts +128 -0
- package/src/deploy/platforms/vercel.ts +25 -1
- package/src/deploy/redirects.ts +43 -16
- package/src/deploy/sitemap.ts +2 -1
- package/src/markdown/base-links.ts +87 -6
- package/src/markdown/code-title.ts +29 -13
- package/src/markdown/content-assets.ts +210 -0
- package/src/markdown/directives.ts +69 -5
- package/src/markdown/fence-language.ts +106 -0
- package/src/markdown/fence-meta.ts +42 -0
- package/src/markdown/github-alerts.ts +172 -0
- package/src/markdown/heading-anchors.ts +265 -56
- package/src/markdown/include.ts +30 -3
- package/src/markdown/index.ts +145 -40
- package/src/markdown/prompt-text.ts +95 -0
- package/src/markdown/relative-links.ts +37 -2
- package/src/markdown/route-snapshot.ts +22 -12
- package/src/markdown/svg-fallback.ts +51 -0
- package/src/markdown/title-heading.ts +134 -0
- package/src/migrate/migrate.ts +127 -2
- package/src/og/card.ts +14 -4
- package/src/openapi/asyncapi.ts +14 -6
- package/src/openapi/checks.ts +160 -15
- package/src/openapi/model.ts +172 -33
- package/src/openapi/parse.ts +13 -4
- package/src/openapi/render-mdx.ts +55 -9
- package/src/openapi/source.ts +87 -6
- package/src/ratelimit/index.ts +2 -0
- package/src/ratelimit/memory.ts +1 -1
- package/src/ratelimit/runtime.ts +81 -0
- package/src/ratelimit/schema.ts +2 -0
- package/src/ratelimit/unkey.ts +61 -0
- package/src/registry/eject.ts +0 -1
- package/src/registry/registry.ts +1 -1
- package/src/search/documents.ts +10 -2
- package/src/sources/filesystem.ts +28 -3
- package/src/sources/mdx-remote.ts +7 -15
- package/src/theme/color.ts +14 -0
- package/src/theme/entry.ts +22 -1
- package/src/theme/palette.ts +74 -1
- package/dist/cli/chunk-0pmb4tr4.js.map +0 -35
- package/dist/cli/chunk-0w6hs479.js.map +0 -10
- package/dist/cli/chunk-150jk7km.js +0 -52
- package/dist/cli/chunk-150jk7km.js.map +0 -10
- package/dist/cli/chunk-36bxs9c7.js.map +0 -10
- package/dist/cli/chunk-53jqw8z0.js +0 -89
- package/dist/cli/chunk-53jqw8z0.js.map +0 -10
- package/dist/cli/chunk-60hz265r.js.map +0 -10
- package/dist/cli/chunk-desvm72z.js.map +0 -14
- package/dist/cli/chunk-dpy8qdjf.js.map +0 -17
- package/dist/cli/chunk-es8h0v3j.js +0 -441
- package/dist/cli/chunk-es8h0v3j.js.map +0 -11
- package/dist/cli/chunk-kdpzw38a.js.map +0 -11
- package/dist/cli/chunk-nbyvgnnm.js.map +0 -36
- package/dist/cli/chunk-s0bdnc7v.js.map +0 -10
- package/dist/cli/chunk-twy7psdz.js.map +0 -10
- package/dist/cli/chunk-ydp3065p.js +0 -64
- package/dist/cli/chunk-ydp3065p.js.map +0 -10
- /package/dist/cli/{chunk-y4msrwm9.js.map → chunk-080mfch6.js.map} +0 -0
- /package/dist/cli/{chunk-9qzgg6mj.js.map → chunk-34wap3ed.js.map} +0 -0
- /package/dist/cli/{chunk-1f882900.js.map → chunk-c5bjxq8v.js.map} +0 -0
- /package/dist/cli/{chunk-bxwhtvw8.js.map → chunk-f260jdrn.js.map} +0 -0
- /package/dist/cli/{chunk-74wfhv79.js.map → chunk-fnxgtjeq.js.map} +0 -0
- /package/dist/cli/{chunk-dhwtqnnd.js.map → chunk-gxhcf2hs.js.map} +0 -0
- /package/dist/cli/{chunk-tfycddbt.js.map → chunk-h0qwdbem.js.map} +0 -0
- /package/dist/cli/{chunk-j1x92mx9.js.map → chunk-j4nfgn2j.js.map} +0 -0
- /package/dist/cli/{chunk-ave1wcbr.js.map → chunk-qcyxkj44.js.map} +0 -0
- /package/dist/cli/{chunk-58bt3hag.js.map → chunk-x7bh6d9j.js.map} +0 -0
- /package/dist/cli/{chunk-hvcxng5f.js.map → chunk-ydqzkhjn.js.map} +0 -0
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
import { EN_UI } from "../../core/i18n-ui.ts";
|
|
3
3
|
import type { UIStrings } from "../../core/i18n-ui.ts";
|
|
4
|
+
import {
|
|
5
|
+
isBuiltInMcpClient,
|
|
6
|
+
mcpClients,
|
|
7
|
+
mcpMenuRows,
|
|
8
|
+
} from "../../core/mcp-clients.ts";
|
|
9
|
+
import type { McpMenuEntry } from "../../core/mcp-clients.ts";
|
|
4
10
|
import { NEW_TAB_ATTRS } from "../../core/new-tab.ts";
|
|
5
11
|
import { openInChatProviders } from "../../core/open-in-chat.ts";
|
|
6
12
|
import type { OpenInChatProvider } from "../../core/open-in-chat.ts";
|
|
@@ -18,6 +24,11 @@ interface Props {
|
|
|
18
24
|
mcpUrl?: string | null;
|
|
19
25
|
/** Display name of the MCP server (defaults to the site title). */
|
|
20
26
|
mcpName?: string | null;
|
|
27
|
+
/**
|
|
28
|
+
* "Connect to MCP" clients to list after "Copy server URL", in order, with
|
|
29
|
+
* custom labels resolved; omitting the prop lists every built-in client.
|
|
30
|
+
*/
|
|
31
|
+
mcpMenu?: readonly McpMenuEntry[];
|
|
21
32
|
/**
|
|
22
33
|
* "Open in chat" providers to list, in order; an empty list hides the
|
|
23
34
|
* action, and omitting the prop shows every provider.
|
|
@@ -40,6 +51,7 @@ const {
|
|
|
40
51
|
exportEpub,
|
|
41
52
|
mcpUrl,
|
|
42
53
|
mcpName,
|
|
54
|
+
mcpMenu,
|
|
43
55
|
openInChat,
|
|
44
56
|
strings,
|
|
45
57
|
divider = true,
|
|
@@ -89,6 +101,10 @@ const providers = (openInChat ?? openInChatProviders).map((key) => ({
|
|
|
89
101
|
// keep that separator only while a configured list preserves v0 first.
|
|
90
102
|
const chatSeparator = providers.length > 1 && providers[0]?.key === "v0";
|
|
91
103
|
|
|
104
|
+
// `agents.mcp.clients` picks and orders the clients after "Copy server URL",
|
|
105
|
+
// with a rule between the commands to copy and the install links.
|
|
106
|
+
const mcpRows = mcpMenuRows(mcpMenu ?? mcpClients);
|
|
107
|
+
|
|
92
108
|
// The block renders once, for the right rail. Below `xl` the script moves it
|
|
93
109
|
// into the mobile "On this page" dropdown, and the global styles below the
|
|
94
110
|
// markup restyle it there from that container.
|
|
@@ -230,29 +246,57 @@ const panelClass =
|
|
|
230
246
|
{a.copyServerUrl}
|
|
231
247
|
</span>
|
|
232
248
|
</button>
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
{
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
249
|
+
{mcpRows.map(({ client, rule }) => (
|
|
250
|
+
<>
|
|
251
|
+
{rule && <hr class="my-1 border-border border-t" />}
|
|
252
|
+
{client === "claude-code" && (
|
|
253
|
+
<button
|
|
254
|
+
class={menuRowClass}
|
|
255
|
+
data-mcp-copy-claude
|
|
256
|
+
type="button"
|
|
257
|
+
>
|
|
258
|
+
<span set:html={LOGOS.claude} />
|
|
259
|
+
<span class="flex-1" data-mcp-claude-label>
|
|
260
|
+
{a.copyClaudeCode}
|
|
261
|
+
</span>
|
|
262
|
+
</button>
|
|
263
|
+
)}
|
|
264
|
+
{client === "codex" && (
|
|
265
|
+
<button class={menuRowClass} data-mcp-copy-codex type="button">
|
|
266
|
+
<span set:html={LOGOS.codex} />
|
|
267
|
+
<span class="flex-1" data-mcp-codex-label>
|
|
268
|
+
{a.copyCodex}
|
|
269
|
+
</span>
|
|
270
|
+
</button>
|
|
271
|
+
)}
|
|
272
|
+
{client === "cursor" && (
|
|
273
|
+
<a class={menuRowClass} data-mcp-cursor rel="noreferrer">
|
|
274
|
+
<span set:html={LOGOS.cursor} />
|
|
275
|
+
<span class="flex-1">{a.addToCursor}</span>
|
|
276
|
+
<Icon name="external-link" size={13} />
|
|
277
|
+
</a>
|
|
278
|
+
)}
|
|
279
|
+
{client === "vscode" && (
|
|
280
|
+
<a class={menuRowClass} data-mcp-vscode rel="noreferrer">
|
|
281
|
+
<Icon name="code" size={16} />
|
|
282
|
+
<span class="flex-1">{a.addToVscode}</span>
|
|
283
|
+
<Icon name="external-link" size={13} />
|
|
284
|
+
</a>
|
|
285
|
+
)}
|
|
286
|
+
{!isBuiltInMcpClient(client) && (
|
|
287
|
+
<button
|
|
288
|
+
class={menuRowClass}
|
|
289
|
+
data-mcp-copy-command={client.command}
|
|
290
|
+
type="button"
|
|
291
|
+
>
|
|
292
|
+
<Icon name={client.icon ?? "terminal"} size={16} />
|
|
293
|
+
<span class="flex-1" data-mcp-command-label>
|
|
294
|
+
{client.label}
|
|
295
|
+
</span>
|
|
296
|
+
</button>
|
|
297
|
+
)}
|
|
298
|
+
</>
|
|
299
|
+
))}
|
|
256
300
|
</div>
|
|
257
301
|
</details>
|
|
258
302
|
)
|
|
@@ -299,6 +343,7 @@ const panelClass =
|
|
|
299
343
|
</style>
|
|
300
344
|
|
|
301
345
|
<script>
|
|
346
|
+
import { mcpClientCommand } from "../../core/mcp-clients.ts";
|
|
302
347
|
import { copyDeferredText, copyText, flashLabel } from "../copy-feedback.ts";
|
|
303
348
|
import { installDropdownDismiss } from "../dropdown-dismiss.ts";
|
|
304
349
|
import { mountBase } from "../islands/base-path.ts";
|
|
@@ -572,6 +617,19 @@ hr { border: 0; border-top: 1px solid #ddd; margin: 2em 0; }`;
|
|
|
572
617
|
root.querySelector("[data-mcp-codex-label]")
|
|
573
618
|
)
|
|
574
619
|
);
|
|
620
|
+
for (const button of root.querySelectorAll<HTMLElement>(
|
|
621
|
+
"[data-mcp-copy-command]"
|
|
622
|
+
)) {
|
|
623
|
+
button.addEventListener("click", () =>
|
|
624
|
+
copy(
|
|
625
|
+
mcpClientCommand(button.dataset.mcpCopyCommand ?? "", {
|
|
626
|
+
name: id,
|
|
627
|
+
url: mcpUrl,
|
|
628
|
+
}),
|
|
629
|
+
button.querySelector("[data-mcp-command-label]")
|
|
630
|
+
)
|
|
631
|
+
);
|
|
632
|
+
}
|
|
575
633
|
}
|
|
576
634
|
|
|
577
635
|
const label = root.querySelector("[data-blume-copy-label]");
|
|
@@ -9,6 +9,8 @@ import type { UIStrings } from "../../core/i18n-ui.ts";
|
|
|
9
9
|
import { resolveDateFormatOptions } from "../../core/date-format.ts";
|
|
10
10
|
import type { ResolvedDateFormat } from "../../core/schema.ts";
|
|
11
11
|
import type { OpenInChatProvider } from "../../core/open-in-chat.ts";
|
|
12
|
+
import { mcpMenuEntries } from "../../core/mcp-clients.ts";
|
|
13
|
+
import type { McpClientEntry } from "../../core/mcp-clients.ts";
|
|
12
14
|
import type {
|
|
13
15
|
BlumeBanner,
|
|
14
16
|
BlumeClientData,
|
|
@@ -114,7 +116,15 @@ interface Props {
|
|
|
114
116
|
banner?: BlumeBanner | null;
|
|
115
117
|
analytics?: BlumeDataConfig["analytics"] | null;
|
|
116
118
|
navigation: Navigation;
|
|
117
|
-
|
|
119
|
+
/**
|
|
120
|
+
* The hosted MCP server. `clients` lists the "Connect to MCP" menu's
|
|
121
|
+
* clients in order, and defaults to every built-in one.
|
|
122
|
+
*/
|
|
123
|
+
mcp?: {
|
|
124
|
+
clients?: readonly McpClientEntry[];
|
|
125
|
+
name: string;
|
|
126
|
+
route: string;
|
|
127
|
+
} | null;
|
|
118
128
|
page: { title: string; description?: string; route: string };
|
|
119
129
|
headings: Heading[];
|
|
120
130
|
imageZoom?: boolean;
|
|
@@ -471,6 +481,11 @@ const markdownMirror = isBare
|
|
|
471
481
|
// Needs a configured site to be useful, so the menu is hidden without one.
|
|
472
482
|
const mcpUrl =
|
|
473
483
|
mcp && siteUrl ? new URL(withMountedBase(mcp.route), siteUrl).href : null;
|
|
484
|
+
// Custom clients' labels resolve to the page's locale. Without a list,
|
|
485
|
+
// PageActions shows every built-in client.
|
|
486
|
+
const mcpMenu = mcp?.clients
|
|
487
|
+
? mcpMenuEntries(mcp.clients, locale, data.config.i18n?.defaultLocale)
|
|
488
|
+
: undefined;
|
|
474
489
|
|
|
475
490
|
// Scope the sidebar (and the breadcrumbs/pagination derived from it) to the
|
|
476
491
|
// active tab's section, so a multi-section site drills each tab into its own
|
|
@@ -910,14 +925,16 @@ const localeRedirect = localeTargets
|
|
|
910
925
|
<slot />
|
|
911
926
|
</article>
|
|
912
927
|
{
|
|
913
|
-
|
|
928
|
+
showChrome && (
|
|
914
929
|
<div
|
|
915
930
|
class:list={[
|
|
916
931
|
// Aligned with the content column, not centered under the
|
|
917
|
-
// prose measure:
|
|
918
|
-
// page's wider
|
|
919
|
-
|
|
920
|
-
|
|
932
|
+
// prose measure: an API page's (beside its example or
|
|
933
|
+
// request column), a wide page's, or a center page's wider
|
|
934
|
+
// one.
|
|
935
|
+
isApiLayout && "xl:pe-[30.5rem]",
|
|
936
|
+
(isApiLayout || modeLayout.width === "full") &&
|
|
937
|
+
"[&>*]:max-w-none",
|
|
921
938
|
modeLayout.width === "center" && "[&>*]:max-w-[54rem]",
|
|
922
939
|
]}
|
|
923
940
|
data-blume-page-end
|
|
@@ -966,6 +983,7 @@ const localeRedirect = localeTargets
|
|
|
966
983
|
editUrl={editUrl}
|
|
967
984
|
exportEpub={exportEpub}
|
|
968
985
|
exportPdf={exportPdf}
|
|
986
|
+
mcpMenu={mcpMenu}
|
|
969
987
|
mcpName={mcp?.name}
|
|
970
988
|
mcpUrl={mcpUrl}
|
|
971
989
|
openInChat={openInChat}
|
|
@@ -1005,6 +1023,8 @@ const localeRedirect = localeTargets
|
|
|
1005
1023
|
></button>
|
|
1006
1024
|
<script>
|
|
1007
1025
|
import type { Zoom } from "medium-zoom";
|
|
1026
|
+
import { copyableCode } from "../code-copy.ts";
|
|
1027
|
+
import { languageLabel } from "../code-language.ts";
|
|
1008
1028
|
import { copyText, createCopyFlash } from "../copy-feedback.ts";
|
|
1009
1029
|
import { syncDrawerInert } from "./drawer-inert.ts";
|
|
1010
1030
|
import { chromeIcons as icons } from "../../theme/chrome-icons.ts";
|
|
@@ -1081,27 +1101,6 @@ const localeRedirect = localeTargets
|
|
|
1081
1101
|
return panel.matches("pre") ? panel : panel.querySelector("pre");
|
|
1082
1102
|
};
|
|
1083
1103
|
|
|
1084
|
-
const languageLabels: Record<string, string> = {
|
|
1085
|
-
astro: "Astro",
|
|
1086
|
-
bash: "Bash",
|
|
1087
|
-
css: "CSS",
|
|
1088
|
-
html: "HTML",
|
|
1089
|
-
js: "JavaScript",
|
|
1090
|
-
json: "JSON",
|
|
1091
|
-
jsx: "JSX",
|
|
1092
|
-
md: "Markdown",
|
|
1093
|
-
mdx: "MDX",
|
|
1094
|
-
plaintext: "Text",
|
|
1095
|
-
sh: "Shell",
|
|
1096
|
-
shell: "Shell",
|
|
1097
|
-
ts: "TypeScript",
|
|
1098
|
-
tsx: "TSX",
|
|
1099
|
-
txt: "Text",
|
|
1100
|
-
yaml: "YAML",
|
|
1101
|
-
yml: "YAML",
|
|
1102
|
-
zsh: "Zsh",
|
|
1103
|
-
};
|
|
1104
|
-
|
|
1105
1104
|
// Per-page setup, run on the initial load and again after every
|
|
1106
1105
|
// client-router swap (which replaces the body with server-rendered
|
|
1107
1106
|
// markup that has none of this applied). Everything in here binds to
|
|
@@ -1176,7 +1175,14 @@ const localeRedirect = localeTargets
|
|
|
1176
1175
|
};
|
|
1177
1176
|
const flash = createCopyFlash(setChecked, copiedLabel);
|
|
1178
1177
|
button.addEventListener("click", async () => {
|
|
1179
|
-
|
|
1178
|
+
// A terminal session copies its commands alone (see
|
|
1179
|
+
// code-copy.ts), keyed off the fence's own language id.
|
|
1180
|
+
const pre = readPre();
|
|
1181
|
+
const language =
|
|
1182
|
+
pre instanceof HTMLElement
|
|
1183
|
+
? (pre.dataset.blumeLanguage ?? pre.dataset.language)
|
|
1184
|
+
: undefined;
|
|
1185
|
+
if (await copyText(copyableCode(codeText(pre), language))) {
|
|
1180
1186
|
flash();
|
|
1181
1187
|
}
|
|
1182
1188
|
});
|
|
@@ -1277,10 +1283,7 @@ const localeRedirect = localeTargets
|
|
|
1277
1283
|
if (pre instanceof HTMLElement) {
|
|
1278
1284
|
pre.dataset.blumeLanguage = language;
|
|
1279
1285
|
}
|
|
1280
|
-
pre.setAttribute(
|
|
1281
|
-
"data-language",
|
|
1282
|
-
languageLabels[language.toLowerCase()] ?? language
|
|
1283
|
-
);
|
|
1286
|
+
pre.setAttribute("data-language", languageLabel(language));
|
|
1284
1287
|
}
|
|
1285
1288
|
pre.classList.add("group", "relative");
|
|
1286
1289
|
// The code element is the scroll container (see the theme entry), but
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
// The site footer, below the content on every page: one row, as tall as the
|
|
3
|
-
// header, with `footer.links` on one side
|
|
4
|
-
// other. The site's repository
|
|
5
|
-
// is the first icon; the footer is the only place it's linked. With `consent` configured the links end with the
|
|
3
|
+
// header, with `footer.links` on one side, the social profile icons on the
|
|
4
|
+
// other, and `footer.copyright` centered between them. The site's repository
|
|
5
|
+
// (`github`, unless `navigation.repo` hides it) is the first icon; the footer is the only place it's linked. With `consent` configured the links end with the
|
|
6
6
|
// Cookie settings link, which reopens the reader's consent choices. Renders
|
|
7
7
|
// nothing when there's none of these; a `components.ts` `Footer` replaces it.
|
|
8
8
|
import data from "blume:data";
|
|
@@ -12,6 +12,7 @@ import type { Navigation } from "../../core/types.ts";
|
|
|
12
12
|
import { EN_UI } from "../../core/i18n-ui.ts";
|
|
13
13
|
import type { UIStrings } from "../../core/i18n-ui.ts";
|
|
14
14
|
import { routeSetFor } from "../../core/locale-links.ts";
|
|
15
|
+
import { resolveLocalizable } from "../../core/localizable.ts";
|
|
15
16
|
import { newTabAttrs } from "../../core/new-tab.ts";
|
|
16
17
|
import Icon from "../Icon.astro";
|
|
17
18
|
import { withBase } from "../islands/base-path.ts";
|
|
@@ -21,8 +22,9 @@ import { footerSocialLinks } from "./footer-socials.ts";
|
|
|
21
22
|
interface Props {
|
|
22
23
|
footer?: BlumeDataConfig["footer"];
|
|
23
24
|
/**
|
|
24
|
-
* Active locale of the page: labels written as
|
|
25
|
-
* entry, and internal links move into it (see
|
|
25
|
+
* Active locale of the page: the copyright and labels written as
|
|
26
|
+
* per-locale maps show its entry, and internal links move into it (see
|
|
27
|
+
* `footer-links.ts`).
|
|
26
28
|
*/
|
|
27
29
|
locale?: string;
|
|
28
30
|
/** The page's navigation: its `repoUrl` is the repository link. */
|
|
@@ -40,6 +42,14 @@ const socials = footerSocialLinks(
|
|
|
40
42
|
? { href: repoUrl, label: { ...EN_UI.nav, ...ui?.nav }.githubRepository }
|
|
41
43
|
: null
|
|
42
44
|
);
|
|
45
|
+
const copyright =
|
|
46
|
+
footer?.copyright === undefined
|
|
47
|
+
? null
|
|
48
|
+
: resolveLocalizable(
|
|
49
|
+
footer.copyright,
|
|
50
|
+
locale,
|
|
51
|
+
data.config.i18n?.defaultLocale
|
|
52
|
+
);
|
|
43
53
|
const links = footerLinks(footer?.links ?? [], {
|
|
44
54
|
basePath: data.config.basePath,
|
|
45
55
|
i18n: data.config.i18n,
|
|
@@ -58,9 +68,17 @@ const hasLinks = links.length > 0 || consentSettings !== null;
|
|
|
58
68
|
---
|
|
59
69
|
|
|
60
70
|
{
|
|
61
|
-
(hasLinks || socials.length > 0) && (
|
|
71
|
+
(copyright !== null || hasLinks || socials.length > 0) && (
|
|
62
72
|
<footer class="border-border border-t px-4 md:px-6" data-blume-footer>
|
|
63
|
-
|
|
73
|
+
{/* With a copyright, three columns from `md`, the outer two sharing
|
|
74
|
+
what it leaves so it sits at the true center; without one, the
|
|
75
|
+
links keep the row's full width. Narrower, the row wraps. */}
|
|
76
|
+
<div
|
|
77
|
+
class:list={[
|
|
78
|
+
"flex min-h-16 flex-wrap items-center gap-x-6 gap-y-3 py-3",
|
|
79
|
+
copyright !== null && "md:grid md:grid-cols-[1fr_auto_1fr]",
|
|
80
|
+
]}
|
|
81
|
+
>
|
|
64
82
|
{hasLinks && (
|
|
65
83
|
<ul class="flex flex-wrap items-center gap-x-5 gap-y-2 text-sm">
|
|
66
84
|
{links.map((link) => (
|
|
@@ -87,10 +105,15 @@ const hasLinks = links.length > 0 || consentSettings !== null;
|
|
|
87
105
|
)}
|
|
88
106
|
</ul>
|
|
89
107
|
)}
|
|
108
|
+
{copyright !== null && (
|
|
109
|
+
<p class="text-muted-foreground text-sm md:col-start-2">
|
|
110
|
+
{copyright}
|
|
111
|
+
</p>
|
|
112
|
+
)}
|
|
90
113
|
{/* Pulled out by the buttons' padding, so the glyphs line up with the
|
|
91
114
|
footer's edge, and pushed to the far side even with no links. */}
|
|
92
115
|
{socials.length > 0 && (
|
|
93
|
-
<ul class="-me-[9px] -my-[9px] ms-auto flex flex-wrap items-center gap-1">
|
|
116
|
+
<ul class="-me-[9px] -my-[9px] ms-auto flex flex-wrap items-center gap-1 md:col-start-3">
|
|
94
117
|
{socials.map((social) => (
|
|
95
118
|
<li>
|
|
96
119
|
<a
|
|
@@ -273,6 +273,20 @@ export const getPagination = (flat: FlatPage[], route: string) => {
|
|
|
273
273
|
/** A group node in the sidebar tree. */
|
|
274
274
|
export type NavGroup = Extract<NavNode, { kind: "group" }>;
|
|
275
275
|
|
|
276
|
+
/**
|
|
277
|
+
* Whether a `group`-mode disclosure renders open: it holds the current page,
|
|
278
|
+
* its meta forces it open (`collapsed: false`), or it is the only row at the
|
|
279
|
+
* top of the sidebar, where starting closed would leave a sidebar of one row
|
|
280
|
+
* to click before any link shows (a wrapper folder around every page). An
|
|
281
|
+
* explicit `collapsed: true` keeps that lone group closed.
|
|
282
|
+
*/
|
|
283
|
+
export const groupStartsOpen = (
|
|
284
|
+
group: NavGroup,
|
|
285
|
+
active: boolean,
|
|
286
|
+
lone: boolean
|
|
287
|
+
): boolean =>
|
|
288
|
+
active || group.collapsed === false || (lone && group.collapsed !== true);
|
|
289
|
+
|
|
276
290
|
/**
|
|
277
291
|
* The group whose own page `route` is, when that page lists the group's
|
|
278
292
|
* pages: its `directory` (inherited when the group sets none) is `card` or
|
|
@@ -32,7 +32,8 @@ interface PagefindEntry {
|
|
|
32
32
|
|
|
33
33
|
// Pagefind names each page after its built file (`quickstart/index.html`), so
|
|
34
34
|
// its URLs end in a slash. Blume serves pages without one (`trailingSlash:
|
|
35
|
-
// "never"`):
|
|
35
|
+
// "never"`): Vercel, `blume dev`, and `blume preview` redirect the slashed
|
|
36
|
+
// URL, so linking it costs a hop.
|
|
36
37
|
const TRAILING_SLASH = /(?<=.)\/(?=[#?]|$)/u;
|
|
37
38
|
|
|
38
39
|
/**
|
|
@@ -159,6 +159,7 @@ const model =
|
|
|
159
159
|
parameters: params,
|
|
160
160
|
path: ref.path,
|
|
161
161
|
requestBody,
|
|
162
|
+
responses,
|
|
162
163
|
schemas,
|
|
163
164
|
security,
|
|
164
165
|
// An operation's own `servers` override its path item's, which
|
|
@@ -268,6 +269,7 @@ const callbackParts = (entry: CallbackEntry) => ({
|
|
|
268
269
|
<ParametersTable parameters={params} schemas={schemas} />
|
|
269
270
|
{requestBody && (
|
|
270
271
|
<RequestBody
|
|
272
|
+
components={components}
|
|
271
273
|
direction={bodyDirection}
|
|
272
274
|
expandAll={spec.expandSchemas}
|
|
273
275
|
requestBody={requestBody}
|
|
@@ -321,9 +323,11 @@ const callbackParts = (entry: CallbackEntry) => ({
|
|
|
321
323
|
/>
|
|
322
324
|
{parts.requestBody && (
|
|
323
325
|
<RequestBody
|
|
326
|
+
components={components}
|
|
324
327
|
direction="response"
|
|
325
328
|
expandAll={spec.expandSchemas}
|
|
326
329
|
level={4}
|
|
330
|
+
name={`callback-${entry.key}`}
|
|
327
331
|
requestBody={parts.requestBody}
|
|
328
332
|
schemas={schemas}
|
|
329
333
|
/>
|
|
@@ -28,16 +28,22 @@ interface Props {
|
|
|
28
28
|
copy?: boolean;
|
|
29
29
|
/** Render tab labels in a monospace face (status codes). */
|
|
30
30
|
mono?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Names this tab set in its element ids, for a heading that repeats on
|
|
33
|
+
* the page (a callback's request body examples). Defaults to the heading.
|
|
34
|
+
*/
|
|
35
|
+
name?: string;
|
|
31
36
|
}
|
|
32
37
|
|
|
33
|
-
const { heading, panels, copy = false, mono = false } =
|
|
38
|
+
const { heading, panels, copy = false, mono = false, name = heading } =
|
|
39
|
+
Astro.props;
|
|
34
40
|
|
|
35
41
|
// A stable per-instance id prefix so tab/tabpanel pairs can reference each
|
|
36
42
|
// other without colliding across the multiple PanelTabs on one page (the
|
|
37
|
-
//
|
|
43
|
+
// name is unique per tab set; panel keys are unique within a set).
|
|
38
44
|
const NON_ID = /[^a-z0-9]+/gu;
|
|
39
45
|
const idFor = (kind: "tab" | "panel", key: string): string =>
|
|
40
|
-
["panel-tabs",
|
|
46
|
+
["panel-tabs", name, kind, key]
|
|
41
47
|
.map((part) => part.toLowerCase().replace(NON_ID, "-"))
|
|
42
48
|
.join("-");
|
|
43
49
|
|
|
@@ -1,22 +1,31 @@
|
|
|
1
1
|
---
|
|
2
|
+
import data from "blume:data";
|
|
3
|
+
|
|
4
|
+
import { highlightCode } from "../../markdown/index.ts";
|
|
2
5
|
import Description from "./Description.astro";
|
|
3
|
-
import
|
|
6
|
+
import { preferredMedia } from "./example-panels.ts";
|
|
7
|
+
import {
|
|
8
|
+
type ComponentsLike,
|
|
9
|
+
type MediaLike,
|
|
10
|
+
namedExamples,
|
|
11
|
+
type SchemaLike,
|
|
12
|
+
toJson,
|
|
13
|
+
} from "./helpers.ts";
|
|
14
|
+
import PanelTabs from "./PanelTabs.astro";
|
|
4
15
|
import type { SchemaDirection } from "./schema-tree.ts";
|
|
5
16
|
import SchemaTable from "./SchemaTable.astro";
|
|
6
17
|
|
|
7
|
-
interface MediaTypeLike {
|
|
8
|
-
schema?: SchemaLike;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
18
|
interface RequestBodyLike {
|
|
12
19
|
description?: string;
|
|
13
20
|
required?: boolean;
|
|
14
|
-
content?: Record<string,
|
|
21
|
+
content?: Record<string, MediaLike>;
|
|
15
22
|
}
|
|
16
23
|
|
|
17
24
|
interface Props {
|
|
18
25
|
requestBody: RequestBodyLike;
|
|
19
26
|
schemas: Record<string, SchemaLike>;
|
|
27
|
+
/** The document's `components`, which `$ref`'d examples resolve against. */
|
|
28
|
+
components?: ComponentsLike;
|
|
20
29
|
expandAll?: boolean;
|
|
21
30
|
/** The heading's level: 2 on an operation, deeper inside a callback. */
|
|
22
31
|
level?: number;
|
|
@@ -25,20 +34,38 @@ interface Props {
|
|
|
25
34
|
* callback, which the API sends, reads like a response instead.
|
|
26
35
|
*/
|
|
27
36
|
direction?: SchemaDirection;
|
|
37
|
+
/** Names the body's example tabs in their element ids (one per callback). */
|
|
38
|
+
name?: string;
|
|
28
39
|
}
|
|
29
40
|
|
|
30
41
|
const {
|
|
31
42
|
requestBody,
|
|
32
43
|
schemas,
|
|
44
|
+
components,
|
|
33
45
|
expandAll = false,
|
|
34
46
|
level = 2,
|
|
35
47
|
direction = "request",
|
|
48
|
+
name = "request-body",
|
|
36
49
|
} = Astro.props;
|
|
37
50
|
|
|
38
|
-
const
|
|
39
|
-
const chosen = entries.find(([type]) => type.includes("json")) ?? entries[0];
|
|
51
|
+
const chosen = preferredMedia(requestBody.content);
|
|
40
52
|
const contentType = chosen?.[0] ?? "application/json";
|
|
41
53
|
const schema = chosen?.[1]?.schema ?? {};
|
|
54
|
+
|
|
55
|
+
// A body whose `examples` map names two or more shows each, under its name:
|
|
56
|
+
// the code samples and Try it start from the first one only.
|
|
57
|
+
const examplePanels = await Promise.all(
|
|
58
|
+
(chosen ? namedExamples(chosen[1], schemas, direction, components) : []).map(
|
|
59
|
+
async (example) => ({
|
|
60
|
+
html: await highlightCode(toJson(example.value), "json", {
|
|
61
|
+
icons: false,
|
|
62
|
+
themes: data.config.codeThemes,
|
|
63
|
+
}),
|
|
64
|
+
key: example.key,
|
|
65
|
+
label: example.label,
|
|
66
|
+
})
|
|
67
|
+
)
|
|
68
|
+
);
|
|
42
69
|
---
|
|
43
70
|
|
|
44
71
|
<section class:list={[level > 2 ? "mt-5" : "mt-8"]}>
|
|
@@ -72,4 +99,11 @@ const schema = chosen?.[1]?.schema ?? {};
|
|
|
72
99
|
schemas={schemas}
|
|
73
100
|
/>
|
|
74
101
|
</div>
|
|
102
|
+
{
|
|
103
|
+
examplePanels.length > 0 && (
|
|
104
|
+
<div class="not-prose mt-4">
|
|
105
|
+
<PanelTabs copy heading="Examples" name={`${name}-examples`} panels={examplePanels} />
|
|
106
|
+
</div>
|
|
107
|
+
)
|
|
108
|
+
}
|
|
75
109
|
</section>
|
|
@@ -4,27 +4,21 @@ import data from "blume:data";
|
|
|
4
4
|
import { highlightCode } from "../../markdown/index.ts";
|
|
5
5
|
import {
|
|
6
6
|
type ComponentsLike,
|
|
7
|
-
|
|
7
|
+
type MediaLike,
|
|
8
8
|
type SchemaLike,
|
|
9
|
-
type SpecValue,
|
|
10
9
|
toJson,
|
|
11
10
|
} from "./helpers.ts";
|
|
12
11
|
import type { CustomCodeSample } from "./code-samples.ts";
|
|
12
|
+
import {
|
|
13
|
+
type ExamplePanel,
|
|
14
|
+
payloadPanels as payloadExamples,
|
|
15
|
+
type ResponseLike,
|
|
16
|
+
responsePanels as responseExamples,
|
|
17
|
+
} from "./example-panels.ts";
|
|
13
18
|
import { languageSamplePanels } from "./sample-panels.ts";
|
|
14
19
|
import PanelTabs from "./PanelTabs.astro";
|
|
15
20
|
import type { RequestSample, SampleLanguage } from "./snippets.ts";
|
|
16
21
|
|
|
17
|
-
interface MediaTypeLike {
|
|
18
|
-
schema?: SchemaLike;
|
|
19
|
-
example?: SpecValue;
|
|
20
|
-
examples?: SpecValue;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
interface ResponseLike {
|
|
24
|
-
description?: string;
|
|
25
|
-
content?: Record<string, MediaTypeLike>;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
22
|
interface Props {
|
|
29
23
|
/** The document's `components`, which `$ref`'d examples resolve against. */
|
|
30
24
|
components?: ComponentsLike;
|
|
@@ -34,7 +28,7 @@ interface Props {
|
|
|
34
28
|
* A webhook's body: the rail shows it as a "Payload" example per media
|
|
35
29
|
* type in place of client code, since the API sends the request.
|
|
36
30
|
*/
|
|
37
|
-
payload?: Record<string,
|
|
31
|
+
payload?: Record<string, MediaLike>;
|
|
38
32
|
sample?: RequestSample;
|
|
39
33
|
languages?: SampleLanguage[];
|
|
40
34
|
responses: Record<string, ResponseLike>;
|
|
@@ -51,18 +45,26 @@ const {
|
|
|
51
45
|
schemas,
|
|
52
46
|
} = Astro.props;
|
|
53
47
|
|
|
54
|
-
/**
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
const
|
|
61
|
-
return
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
48
|
+
/**
|
|
49
|
+
* One example tab, highlighted. A payload that isn't JSON shows a string
|
|
50
|
+
* example as written; a response example always reads as JSON.
|
|
51
|
+
*/
|
|
52
|
+
const highlightPanel = async (panel: ExamplePanel, asText: boolean) => {
|
|
53
|
+
const { value } = panel;
|
|
54
|
+
const text = asText && typeof value === "string";
|
|
55
|
+
return {
|
|
56
|
+
html:
|
|
57
|
+
value === undefined || value === null
|
|
58
|
+
? null
|
|
59
|
+
: await highlightCode(
|
|
60
|
+
text ? value : toJson(value),
|
|
61
|
+
text ? "text" : "json",
|
|
62
|
+
{ icons: false, themes: data.config.codeThemes }
|
|
63
|
+
),
|
|
64
|
+
key: panel.key,
|
|
65
|
+
label: panel.label,
|
|
66
|
+
text: panel.text,
|
|
67
|
+
};
|
|
66
68
|
};
|
|
67
69
|
|
|
68
70
|
// Hand-written samples carry no `lang` key, so the playground leaves them
|
|
@@ -78,12 +80,9 @@ const customPanels = await Promise.all(
|
|
|
78
80
|
}))
|
|
79
81
|
);
|
|
80
82
|
const payloadPanels = await Promise.all(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
label: type,
|
|
85
|
-
text: "No example payload.",
|
|
86
|
-
}))
|
|
83
|
+
payloadExamples(payload, schemas, components).map((panel) =>
|
|
84
|
+
highlightPanel(panel, !panel.type.includes("json"))
|
|
85
|
+
)
|
|
87
86
|
);
|
|
88
87
|
const requestPanels = [
|
|
89
88
|
...customPanels,
|
|
@@ -91,28 +90,10 @@ const requestPanels = [
|
|
|
91
90
|
? await languageSamplePanels(languages, sample, data.config.codeThemes)
|
|
92
91
|
: []),
|
|
93
92
|
];
|
|
94
|
-
|
|
95
93
|
const responsePanels = await Promise.all(
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
type.includes("json")
|
|
100
|
-
)?.[1] ?? Object.values(response.content ?? {})[0];
|
|
101
|
-
const example = media ? responseExample(media, schemas, components) : undefined;
|
|
102
|
-
const html =
|
|
103
|
-
example === undefined || example === null
|
|
104
|
-
? null
|
|
105
|
-
: await highlightCode(toJson(example), "json", {
|
|
106
|
-
icons: false,
|
|
107
|
-
themes: data.config.codeThemes,
|
|
108
|
-
});
|
|
109
|
-
return {
|
|
110
|
-
html,
|
|
111
|
-
key: status,
|
|
112
|
-
label: status,
|
|
113
|
-
text: response.description || "No example response.",
|
|
114
|
-
};
|
|
115
|
-
})
|
|
94
|
+
responseExamples(responses, schemas, components).map((panel) =>
|
|
95
|
+
highlightPanel(panel, false)
|
|
96
|
+
)
|
|
116
97
|
);
|
|
117
98
|
---
|
|
118
99
|
|