blume 2.0.3 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -0
- package/CHANGELOG.md +142 -0
- package/README.md +1 -1
- package/dist/cli/{chunk-5f86nr5m.js → chunk-073rdvgb.js} +21 -48
- package/dist/cli/{chunk-5f86nr5m.js.map → chunk-073rdvgb.js.map} +4 -5
- package/dist/cli/{chunk-ga0pf4aj.js → chunk-0n9xkp3d.js} +12 -3
- package/dist/cli/{chunk-ga0pf4aj.js.map → chunk-0n9xkp3d.js.map} +3 -3
- package/dist/cli/chunk-150jk7km.js +52 -0
- package/dist/cli/chunk-150jk7km.js.map +10 -0
- package/dist/cli/{chunk-9t7a85s3.js → chunk-313vnn40.js} +30 -19
- package/dist/cli/chunk-313vnn40.js.map +10 -0
- package/dist/cli/{chunk-tkacnehg.js → chunk-3v3ffbrj.js} +2 -2
- package/dist/cli/{chunk-q58y5e6a.js → chunk-3x6x3pph.js} +46 -24
- package/dist/cli/chunk-3x6x3pph.js.map +10 -0
- package/dist/cli/{chunk-1d7ve1dm.js → chunk-42t4jxdx.js} +37 -5
- package/dist/cli/chunk-42t4jxdx.js.map +12 -0
- package/dist/cli/{chunk-8ktnccpt.js → chunk-54ztw1nj.js} +21 -2
- package/dist/cli/chunk-54ztw1nj.js.map +10 -0
- package/dist/cli/{chunk-hm3vjy5s.js → chunk-5vjtgs6e.js} +28 -10
- package/dist/cli/{chunk-hm3vjy5s.js.map → chunk-5vjtgs6e.js.map} +4 -4
- package/dist/cli/chunk-66w9j7p6.js +322 -0
- package/dist/cli/chunk-66w9j7p6.js.map +14 -0
- package/dist/cli/{chunk-2hsdwb9n.js → chunk-7ppf1rva.js} +34 -18
- package/dist/cli/chunk-7ppf1rva.js.map +10 -0
- package/dist/cli/{chunk-r9rcc4w7.js → chunk-8y2kmjv8.js} +7 -7
- package/dist/cli/{chunk-r20tn01b.js → chunk-c1y538kd.js} +8 -2
- package/dist/cli/{chunk-r20tn01b.js.map → chunk-c1y538kd.js.map} +3 -3
- package/dist/cli/{chunk-2eytanqx.js → chunk-c887fj0s.js} +2 -2
- package/dist/cli/{chunk-p3v96n38.js → chunk-cfyg47zg.js} +16 -6
- package/dist/cli/chunk-cfyg47zg.js.map +10 -0
- package/dist/cli/chunk-cm89scdv.js +443 -0
- package/dist/cli/chunk-cm89scdv.js.map +11 -0
- package/dist/cli/{chunk-akbpwfxc.js → chunk-dzwehpy7.js} +2 -2
- package/dist/cli/{chunk-wrr3j9w9.js → chunk-e6atmn4h.js} +299 -72
- package/dist/cli/chunk-e6atmn4h.js.map +36 -0
- package/dist/cli/{chunk-tzmab476.js → chunk-e8xw9qkh.js} +8 -6
- package/dist/cli/{chunk-tzmab476.js.map → chunk-e8xw9qkh.js.map} +3 -3
- package/dist/cli/{chunk-6dsbexzp.js → chunk-e9q7a2ak.js} +17 -15
- package/dist/cli/{chunk-6dsbexzp.js.map → chunk-e9q7a2ak.js.map} +2 -2
- package/dist/cli/{chunk-pv29h0wf.js → chunk-ehweg4fr.js} +5155 -1249
- package/dist/cli/chunk-ehweg4fr.js.map +218 -0
- package/dist/cli/{chunk-c8chx29p.js → chunk-ep6nd0rn.js} +390 -318
- package/dist/cli/chunk-ep6nd0rn.js.map +36 -0
- package/dist/cli/{chunk-p73c0m7w.js → chunk-fdrkhpjy.js} +18 -15
- package/dist/cli/{chunk-p73c0m7w.js.map → chunk-fdrkhpjy.js.map} +3 -3
- package/dist/cli/{chunk-2z928egk.js → chunk-ft9vfys6.js} +5 -5
- package/dist/cli/{chunk-5m5nmvyq.js → chunk-gb420vvz.js} +316 -79
- package/dist/cli/chunk-gb420vvz.js.map +17 -0
- package/dist/cli/{chunk-vg9r4eb9.js → chunk-hebn0tpx.js} +86 -13
- package/dist/cli/chunk-hebn0tpx.js.map +14 -0
- package/dist/cli/{chunk-35d4wj9f.js → chunk-htrwgabr.js} +41 -23
- package/dist/cli/chunk-htrwgabr.js.map +15 -0
- package/dist/cli/{chunk-g4hq16wv.js → chunk-hx3xqnk9.js} +16 -14
- package/dist/cli/{chunk-g4hq16wv.js.map → chunk-hx3xqnk9.js.map} +2 -2
- package/dist/cli/chunk-j134vrp2.js +65 -0
- package/dist/cli/chunk-j134vrp2.js.map +10 -0
- package/dist/cli/{chunk-a58773jm.js → chunk-kma9f6sf.js} +2 -2
- package/dist/cli/chunk-kwrg63tm.js +31 -0
- package/dist/cli/chunk-kwrg63tm.js.map +10 -0
- package/dist/cli/{chunk-ey84smr6.js → chunk-mrcccgnh.js} +6 -6
- package/dist/cli/{chunk-ey84smr6.js.map → chunk-mrcccgnh.js.map} +1 -1
- package/dist/cli/{chunk-yfyb25rh.js → chunk-n0v7m8ry.js} +24 -8
- package/dist/cli/chunk-n0v7m8ry.js.map +14 -0
- package/dist/cli/{chunk-j85vccga.js → chunk-ncj7w596.js} +576 -367
- package/dist/cli/chunk-ncj7w596.js.map +35 -0
- package/dist/cli/{chunk-5xvm6tfj.js → chunk-nq1d20w2.js} +17 -15
- package/dist/cli/{chunk-5xvm6tfj.js.map → chunk-nq1d20w2.js.map} +2 -2
- package/dist/cli/{chunk-pehfxfta.js → chunk-nrns10mj.js} +6 -98
- package/dist/cli/chunk-nrns10mj.js.map +10 -0
- package/dist/cli/{chunk-crgn1q09.js → chunk-sds923fa.js} +4 -4
- package/dist/cli/chunk-t2m5j4pr.js +104 -0
- package/dist/cli/chunk-t2m5j4pr.js.map +11 -0
- package/dist/cli/{chunk-acanzt5p.js → chunk-tdqhyxfz.js} +6 -6
- package/dist/cli/chunk-tphac74f.js +126 -0
- package/dist/cli/chunk-tphac74f.js.map +11 -0
- package/dist/cli/chunk-w1r4vase.js +18 -0
- package/dist/cli/chunk-w1r4vase.js.map +10 -0
- package/dist/cli/{chunk-3em5wd2y.js → chunk-zccbjcj0.js} +4 -3
- package/dist/cli/{chunk-3em5wd2y.js.map → chunk-zccbjcj0.js.map} +2 -2
- package/dist/cli/index.js +31 -20
- package/dist/cli/index.js.map +5 -5
- package/dist/types/ai/agent-surface.d.ts +8 -7
- package/dist/types/ai/ai-catalog.d.ts +7 -0
- package/dist/types/ai/ask-context.d.ts +26 -0
- package/dist/types/ai/ask.d.ts +271 -58
- package/dist/types/ai/component-markdown.d.ts +2 -0
- package/dist/types/ai/index.d.ts +2 -2
- package/dist/types/ai/openapi-components.d.ts +4 -1
- package/dist/types/ai/site-skill.d.ts +26 -0
- package/dist/types/ai/skills.d.ts +16 -0
- package/dist/types/astro/integration.d.ts +9 -0
- package/dist/types/astro/markdown-negotiation.d.ts +3 -0
- package/dist/types/astro/pages.d.ts +10 -0
- package/dist/types/captcha/hcaptcha.d.ts +27 -0
- package/dist/types/captcha/index.d.ts +28 -0
- package/dist/types/captcha/schema.d.ts +29 -0
- package/dist/types/captcha/turnstile.d.ts +28 -0
- package/dist/types/cli/init/scaffold.d.ts +1 -1
- package/dist/types/components/content/api-field.d.ts +62 -0
- package/dist/types/components/content/api-page.d.ts +100 -0
- package/dist/types/components/layout/nav-utils.d.ts +26 -0
- package/dist/types/components/openapi/code-samples.d.ts +29 -0
- package/dist/types/components/openapi/helpers.d.ts +158 -0
- package/dist/types/components/openapi/security.d.ts +95 -0
- package/dist/types/components/openapi/snippets.d.ts +60 -0
- package/dist/types/consent/ethyca.d.ts +48 -0
- package/dist/types/consent/index.d.ts +37 -0
- package/dist/types/consent/native.d.ts +28 -0
- package/dist/types/consent/osano.d.ts +42 -0
- package/dist/types/consent/schema.d.ts +110 -0
- package/dist/types/core/changelog-index.d.ts +8 -0
- package/dist/types/core/config-input.d.ts +217 -23
- package/dist/types/core/data.d.ts +53 -4
- package/dist/types/core/footer.d.ts +8 -0
- package/dist/types/core/i18n-ui.d.ts +88 -0
- package/dist/types/core/includes.d.ts +8 -2
- package/dist/types/core/links.d.ts +8 -0
- package/dist/types/core/localizable.d.ts +7 -0
- package/dist/types/core/page-modes.d.ts +29 -0
- package/dist/types/core/probe.d.ts +2 -0
- package/dist/types/core/project-graph.d.ts +6 -0
- package/dist/types/core/redirect-patterns.d.ts +152 -0
- package/dist/types/core/related.d.ts +40 -0
- package/dist/types/core/schema.d.ts +670 -56
- package/dist/types/core/sources/cache.d.ts +3 -0
- package/dist/types/core/sources/contentful-rich-text.d.ts +11 -2
- package/dist/types/core/sources/contentful.d.ts +17 -1
- package/dist/types/core/sources/lexical.d.ts +5 -0
- package/dist/types/core/sources/normalize.d.ts +20 -1
- package/dist/types/core/sources/read.d.ts +5 -0
- package/dist/types/core/sources/remote.d.ts +37 -10
- package/dist/types/core/sources/sanity.d.ts +1 -1
- package/dist/types/core/types.d.ts +18 -1
- package/dist/types/core/variables.d.ts +42 -0
- package/dist/types/deploy/adapter-output.d.ts +2 -1
- package/dist/types/deploy/adapters/cloudflare.d.ts +7 -5
- package/dist/types/deploy/adapters/node.d.ts +58 -23
- package/dist/types/deploy/adapters/registry.d.ts +10 -0
- package/dist/types/deploy/adapters/types.d.ts +3 -2
- package/dist/types/deploy/node-headers.d.ts +13 -2
- package/dist/types/deploy/platforms/cloudflare.d.ts +15 -7
- package/dist/types/deploy/platforms/netlify.d.ts +7 -0
- package/dist/types/deploy/platforms/node.d.ts +3 -1
- package/dist/types/deploy/platforms/types.d.ts +18 -7
- package/dist/types/deploy/platforms/vercel.d.ts +26 -1
- package/dist/types/deploy/redirects.d.ts +55 -11
- package/dist/types/deploy/sitemap.d.ts +2 -1
- package/dist/types/deploy/vercel-negotiation.d.ts +51 -21
- package/dist/types/markdown/code-title.d.ts +17 -0
- package/dist/types/markdown/features.d.ts +3 -2
- package/dist/types/narration/build.d.ts +70 -0
- package/dist/types/narration/provider.d.ts +26 -0
- package/dist/types/narration/script.d.ts +154 -0
- package/dist/types/openapi/checks.d.ts +27 -0
- package/dist/types/openapi/graphql.d.ts +6 -0
- package/dist/types/openapi/model.d.ts +27 -10
- package/dist/types/openapi/overlay.d.ts +54 -0
- package/dist/types/openapi/parse.d.ts +16 -0
- package/dist/types/openapi/references.d.ts +30 -4
- package/dist/types/ratelimit/cloudflare.d.ts +39 -0
- package/dist/types/ratelimit/index.d.ts +27 -0
- package/dist/types/ratelimit/memory.d.ts +36 -0
- package/dist/types/ratelimit/schema.d.ts +119 -0
- package/dist/types/ratelimit/upstash.d.ts +46 -0
- package/dist/types/ratelimit/wrangler.d.ts +23 -0
- package/dist/types/reference/asyncapi.d.ts +10 -10
- package/dist/types/reference/graphql.d.ts +89 -11
- package/dist/types/reference/index.d.ts +1 -1
- package/dist/types/reference/openapi.d.ts +33 -12
- package/dist/types/reference/options.d.ts +82 -6
- package/dist/types/reference/scalar.d.ts +13 -0
- package/dist/types/reference/schema.d.ts +144 -36
- package/dist/types/search/adapters/registry.d.ts +3 -0
- package/dist/types/search/adapters/typesense.d.ts +14 -4
- package/dist/types/search/build.d.ts +3 -1
- package/dist/types/search/documents.d.ts +12 -1
- package/dist/types/search/orama-index.d.ts +13 -9
- package/dist/types/search/sync/algolia.d.ts +5 -2
- package/dist/types/search/sync/index.d.ts +3 -1
- package/dist/types/search/sync/typesense.d.ts +11 -7
- package/dist/types/seo/metatags.d.ts +20 -0
- package/dist/types/sources/contentful.d.ts +16 -0
- package/dist/types/sources/github-releases.d.ts +8 -1
- package/dist/types/sources/payload.d.ts +2 -0
- package/dist/types/sources/registry.d.ts +54 -0
- package/dist/types/sources/shared.d.ts +3 -0
- package/dist/types/sources/strapi.d.ts +2 -0
- package/docs/01-quickstart.mdx +4 -2
- package/docs/02-deployment.mdx +71 -17
- package/docs/03-upgrading.mdx +4 -4
- package/docs/04-migrating.mdx +1 -1
- package/docs/advanced/changelog.mdx +13 -2
- package/docs/advanced/skills.mdx +15 -1
- package/docs/cli/audit.mdx +51 -8
- package/docs/cli/doctor.mdx +5 -1
- package/docs/cli/evals.mdx +4 -4
- package/docs/cli/index.mdx +1 -0
- package/docs/cli/translate.mdx +1 -0
- package/docs/cli/validate.mdx +4 -3
- package/docs/configuration/analytics.mdx +3 -1
- package/docs/configuration/assistant.mdx +194 -38
- package/docs/configuration/consent.mdx +100 -0
- package/docs/configuration/customization.mdx +8 -6
- package/docs/configuration/export.mdx +5 -3
- package/docs/configuration/index.mdx +64 -5
- package/docs/configuration/meta.ts +3 -0
- package/docs/configuration/narration.mdx +119 -0
- package/docs/configuration/rate-limiting.mdx +90 -0
- package/docs/configuration/search.mdx +63 -12
- package/docs/configuration/theming.mdx +3 -1
- package/docs/content/components.mdx +108 -2
- package/docs/content/frontmatter.mdx +80 -2
- package/docs/content/i18n.mdx +39 -4
- package/docs/content/includes.mdx +16 -0
- package/docs/content/meta.mdx +1 -0
- package/docs/content/meta.ts +1 -0
- package/docs/content/navigation.mdx +32 -10
- package/docs/content/sources/contentful.mdx +35 -0
- package/docs/content/sources/custom.mdx +43 -0
- package/docs/content/sources/github-releases.mdx +39 -0
- package/docs/content/sources/index.mdx +91 -0
- package/docs/content/sources/meta.ts +16 -0
- package/docs/content/sources/notion.mdx +32 -0
- package/docs/content/sources/obsidian.mdx +37 -0
- package/docs/content/sources/payload.mdx +31 -0
- package/docs/content/sources/remote-mdx.mdx +44 -0
- package/docs/content/sources/sanity.mdx +29 -0
- package/docs/content/sources/strapi.mdx +32 -0
- package/docs/content/syntax.mdx +69 -4
- package/docs/content/variables.mdx +41 -0
- package/docs/discoverability/agent-discovery.mdx +29 -2
- package/docs/discoverability/index.mdx +2 -2
- package/docs/discoverability/json-api.mdx +2 -0
- package/docs/discoverability/llms-txt.mdx +2 -2
- package/docs/discoverability/markdown.mdx +3 -1
- package/docs/discoverability/mcp.mdx +4 -0
- package/docs/discoverability/metadata.mdx +17 -0
- package/docs/discoverability/sitemap-and-robots.mdx +1 -1
- package/docs/references/api-pages.mdx +74 -0
- package/docs/references/asyncapi.mdx +4 -2
- package/docs/references/graphql.mdx +14 -2
- package/docs/references/meta.ts +1 -1
- package/docs/references/openapi.mdx +148 -7
- package/docs/references/scalar.mdx +3 -1
- package/package.json +43 -8
- package/skills/blume/SKILL.md +3 -0
- package/skills/blume-migrate/SKILL.md +6 -6
- package/skills/blume-migrate/references/docusaurus.md +7 -7
- package/skills/blume-migrate/references/fumadocs.md +17 -13
- package/skills/blume-migrate/references/mintlify.md +37 -19
- package/skills/blume-migrate/references/nextra.md +10 -7
- package/skills/blume-migrate/references/starlight.md +11 -8
- package/skills/blume-migrate/scripts/mintlify-codemod.mjs +60 -14
- package/skills/blume-write-skill/SKILL.md +82 -0
- package/src/ai/agent-readability.ts +2 -1
- package/src/ai/agent-surface.ts +9 -7
- package/src/ai/ai-catalog.ts +6 -3
- package/src/ai/ask-context.ts +103 -20
- package/src/ai/ask-data.ts +6 -0
- package/src/ai/ask-limits.ts +13 -0
- package/src/ai/ask-tools.ts +142 -0
- package/src/ai/ask.ts +354 -76
- package/src/ai/changelog-markdown.ts +11 -6
- package/src/ai/component-markdown.ts +76 -1
- package/src/ai/cors.ts +14 -3
- package/src/ai/index.ts +12 -0
- package/src/ai/llms.ts +6 -2
- package/src/ai/markdown.ts +2 -1
- package/src/ai/mcp/data.ts +6 -0
- package/src/ai/mcp/query.ts +14 -6
- package/src/ai/openapi-components.ts +36 -6
- package/src/ai/relative-links.ts +4 -38
- package/src/ai/site-skill.ts +274 -0
- package/src/ai/skills.ts +35 -2
- package/src/ai/write-skill.ts +97 -0
- package/src/astro/generate.ts +210 -66
- package/src/astro/index.ts +1 -0
- package/src/astro/integration.ts +42 -4
- package/src/astro/markdown-negotiation.ts +3 -0
- package/src/astro/module-types.ts +9 -1
- package/src/astro/pages.ts +23 -0
- package/src/astro/templates.ts +406 -108
- package/src/astro/variables.ts +31 -0
- package/src/audit/catalog.ts +38 -3
- package/src/audit/checks/contrast.ts +183 -0
- package/src/audit/checks/i18n.ts +2 -3
- package/src/audit/checks/indexability.ts +2 -3
- package/src/audit/checks/links.ts +19 -13
- package/src/audit/checks/network.ts +110 -6
- package/src/audit/checks/redirects.ts +6 -4
- package/src/audit/checks/robots.ts +58 -2
- package/src/audit/checks/sitemap.ts +2 -3
- package/src/audit/redirects.ts +46 -15
- package/src/audit/run.ts +5 -0
- package/src/audit/types.ts +4 -1
- package/src/audit/url.ts +14 -5
- package/src/blume-modules.d.ts +12 -1
- package/src/captcha/client.ts +152 -0
- package/src/captcha/hcaptcha.ts +36 -0
- package/src/captcha/index.ts +28 -0
- package/src/captcha/schema.ts +32 -0
- package/src/captcha/turnstile.ts +38 -0
- package/src/captcha/verify.ts +71 -0
- package/src/cli/args.ts +51 -0
- package/src/cli/build-failure.ts +23 -0
- package/src/cli/command-meta.ts +5 -0
- package/src/cli/commands/audit.ts +10 -1
- package/src/cli/commands/dev.ts +18 -2
- package/src/cli/commands/doctor.ts +67 -28
- package/src/cli/commands/eval.ts +36 -4
- package/src/cli/commands/init.ts +6 -4
- package/src/cli/commands/skill.ts +96 -0
- package/src/cli/commands/validate.ts +10 -1
- package/src/cli/index.ts +5 -0
- package/src/cli/init/scaffold.ts +3 -3
- package/src/cli/prepare.ts +6 -3
- package/src/cli/required-secrets.ts +72 -30
- package/src/components/BlumePage.astro +2 -0
- package/src/components/content/ApiEndpoint.astro +18 -0
- package/src/components/content/ApiField.astro +79 -0
- package/src/components/content/ApiPlayground.astro +66 -0
- package/src/components/content/ApiRail.astro +19 -0
- package/src/components/content/Color.astro +1 -0
- package/src/components/content/FileTree.astro +1 -0
- package/src/components/content/GithubInfo.astro +1 -0
- package/src/components/content/Panel.astro +1 -0
- package/src/components/content/ParamField.astro +25 -0
- package/src/components/content/RequestExample.astro +17 -0
- package/src/components/content/ResponseExample.astro +17 -0
- package/src/components/content/ResponseField.astro +32 -0
- package/src/components/content/Step.astro +1 -0
- package/src/components/content/Tile.astro +1 -0
- package/src/components/content/Tooltip.astro +1 -0
- package/src/components/content/Tree.astro +1 -0
- package/src/components/content/TypeTable.astro +4 -1
- package/src/components/content/View.astro +21 -0
- package/src/components/content/ViewSwitcher.astro +168 -0
- package/src/components/content/api-field.ts +103 -0
- package/src/components/content/api-page.ts +248 -0
- package/src/components/content/mermaid-element.ts +15 -1
- package/src/components/content/view-switcher.ts +71 -0
- package/src/components/index.ts +2 -0
- package/src/components/islands/Assistant.astro +10 -1
- package/src/components/islands/assistant.tsx +104 -14
- package/src/components/islands/code-question.ts +62 -0
- package/src/components/islands/hooks.ts +136 -21
- package/src/components/islands/support-link.ts +68 -0
- package/src/components/layout/Analytics.astro +11 -2
- package/src/components/layout/Banner.astro +14 -10
- package/src/components/layout/Breadcrumbs.astro +6 -2
- package/src/components/layout/ConsentBanner.astro +62 -0
- package/src/components/layout/ConsentHead.astro +38 -0
- package/src/components/layout/Directory.astro +94 -0
- package/src/components/layout/DrawerSwitchers.astro +51 -0
- package/src/components/layout/Empty.astro +2 -2
- package/src/components/layout/Header.astro +122 -80
- package/src/components/layout/LanguageSwitcher.astro +48 -15
- package/src/components/layout/NarrationPlayer.astro +1085 -0
- package/src/components/layout/NavSelector.astro +33 -7
- package/src/components/layout/PageActions.astro +139 -24
- package/src/components/layout/PageFeedback.astro +54 -49
- package/src/components/layout/PageLayout.astro +71 -3
- package/src/components/layout/ReferenceLayout.astro +17 -6
- package/src/components/layout/RelatedPages.astro +42 -0
- package/src/components/layout/RootLayout.astro +318 -47
- package/src/components/layout/Search.astro +47 -19
- package/src/components/layout/SiteFooter.astro +124 -0
- package/src/components/layout/SiteMetatags.astro +16 -0
- package/src/components/layout/TableOfContents.astro +24 -17
- package/src/components/layout/consent/native.ts +79 -0
- package/src/components/layout/consent/types.ts +37 -0
- package/src/components/layout/footer-links.ts +53 -0
- package/src/components/layout/footer-socials.ts +87 -0
- package/src/components/layout/head-scripts.ts +6 -1
- package/src/components/layout/locale-redirect.ts +107 -0
- package/src/components/layout/nav-utils.ts +83 -0
- package/src/components/layout/page-feedback.ts +96 -0
- package/src/components/layout/search/algolia.ts +10 -1
- package/src/components/layout/search/analytics.ts +126 -0
- package/src/components/layout/search/endpoint.ts +48 -5
- package/src/components/layout/search/flexsearch.ts +17 -5
- package/src/components/layout/search/orama-cloud.ts +26 -14
- package/src/components/layout/search/pagefind.ts +114 -5
- package/src/components/layout/search/types.ts +32 -0
- package/src/components/layout/search/typesense.ts +19 -3
- package/src/components/openapi/AsyncApiOperation.astro +14 -7
- package/src/components/openapi/Authorization.astro +10 -0
- package/src/components/openapi/GraphqlOperation.astro +5 -0
- package/src/components/openapi/Operation.astro +184 -13
- package/src/components/openapi/ParametersTable.astro +8 -4
- package/src/components/openapi/Playground.astro +7 -1
- package/src/components/openapi/RequestBody.astro +24 -5
- package/src/components/openapi/RequestPanel.astro +59 -7
- package/src/components/openapi/Responses.astro +7 -4
- package/src/components/openapi/SchemaTable.astro +15 -3
- package/src/components/openapi/async-snippets.ts +65 -9
- package/src/components/openapi/async.ts +123 -29
- package/src/components/openapi/code-samples.ts +97 -0
- package/src/components/openapi/graphql-helpers.ts +35 -12
- package/src/components/openapi/helpers.ts +36 -2
- package/src/components/openapi/message-model.ts +54 -11
- package/src/components/openapi/message.ts +14 -4
- package/src/components/openapi/operation-model.ts +16 -7
- package/src/components/openapi/playground-client.ts +24 -5
- package/src/components/openapi/playground-schema.ts +1 -1
- package/src/components/openapi/schema-tree.ts +44 -14
- package/src/components/openapi/security.ts +16 -3
- package/src/components/openapi/snippets.ts +873 -10
- package/src/components/openapi/validate-json.ts +4 -3
- package/src/components/props.ts +6 -0
- package/src/consent/client.ts +95 -0
- package/src/consent/clients.ts +19 -0
- package/src/consent/ethyca.ts +71 -0
- package/src/consent/head.ts +24 -0
- package/src/consent/index.ts +37 -0
- package/src/consent/init.ts +29 -0
- package/src/consent/native.ts +36 -0
- package/src/consent/osano.ts +59 -0
- package/src/consent/schema.ts +30 -0
- package/src/core/builtin-tags.ts +5 -0
- package/src/core/changelog-index.ts +31 -1
- package/src/core/client-address.ts +19 -0
- package/src/core/component-diagnostics.ts +53 -0
- package/src/core/component-overrides.ts +32 -0
- package/src/core/config-input.ts +225 -23
- package/src/core/data.ts +46 -4
- package/src/core/diagnostics.ts +8 -2
- package/src/core/footer.ts +26 -0
- package/src/core/graph.ts +39 -36
- package/src/core/i18n-ui.ts +84 -2
- package/src/core/includes.ts +21 -4
- package/src/core/links.ts +63 -19
- package/src/core/localizable.ts +26 -0
- package/src/core/navigation.ts +43 -12
- package/src/core/page-modes.ts +56 -0
- package/src/core/probe.ts +26 -6
- package/src/core/project-graph.ts +163 -16
- package/src/core/redirect-patterns.ts +520 -0
- package/src/core/related.ts +131 -0
- package/src/core/schema.ts +339 -66
- package/src/core/sources/cache.ts +6 -0
- package/src/core/sources/contentful-rich-text.ts +29 -6
- package/src/core/sources/contentful.ts +135 -25
- package/src/core/sources/filesystem.ts +26 -4
- package/src/core/sources/github-releases.ts +12 -1
- package/src/core/sources/lexical.ts +15 -10
- package/src/core/sources/mdx-remote.ts +62 -10
- package/src/core/sources/normalize.ts +228 -41
- package/src/core/sources/notion.ts +7 -1
- package/src/core/sources/obsidian.ts +16 -3
- package/src/core/sources/payload.ts +38 -15
- package/src/core/sources/read.ts +8 -3
- package/src/core/sources/remote.ts +72 -15
- package/src/core/sources/resolve.ts +11 -1
- package/src/core/sources/sanity.ts +43 -25
- package/src/core/sources/strapi.ts +2 -2
- package/src/core/types.ts +19 -1
- package/src/core/ui-packs/ar.ts +44 -0
- package/src/core/ui-packs/bg.ts +46 -0
- package/src/core/ui-packs/bn.ts +44 -0
- package/src/core/ui-packs/ca.ts +47 -0
- package/src/core/ui-packs/cs.ts +45 -0
- package/src/core/ui-packs/da.ts +46 -0
- package/src/core/ui-packs/de.ts +47 -0
- package/src/core/ui-packs/el.ts +46 -0
- package/src/core/ui-packs/es.ts +47 -0
- package/src/core/ui-packs/fa.ts +46 -0
- package/src/core/ui-packs/fi.ts +46 -0
- package/src/core/ui-packs/fr.ts +47 -0
- package/src/core/ui-packs/he.ts +44 -0
- package/src/core/ui-packs/hi.ts +45 -0
- package/src/core/ui-packs/hr.ts +46 -0
- package/src/core/ui-packs/hu.ts +45 -0
- package/src/core/ui-packs/id.ts +46 -0
- package/src/core/ui-packs/it.ts +46 -0
- package/src/core/ui-packs/ja.ts +46 -0
- package/src/core/ui-packs/ko.ts +45 -0
- package/src/core/ui-packs/nl.ts +47 -0
- package/src/core/ui-packs/no.ts +45 -0
- package/src/core/ui-packs/pl.ts +46 -0
- package/src/core/ui-packs/pt-br.ts +47 -0
- package/src/core/ui-packs/pt.ts +46 -0
- package/src/core/ui-packs/ro.ts +46 -0
- package/src/core/ui-packs/ru.ts +46 -0
- package/src/core/ui-packs/sk.ts +45 -0
- package/src/core/ui-packs/sr.ts +46 -0
- package/src/core/ui-packs/sv.ts +45 -0
- package/src/core/ui-packs/th.ts +44 -0
- package/src/core/ui-packs/tr.ts +46 -0
- package/src/core/ui-packs/uk.ts +46 -0
- package/src/core/ui-packs/vi.ts +46 -0
- package/src/core/ui-packs/zh-tw.ts +44 -0
- package/src/core/ui-packs/zh.ts +44 -0
- package/src/core/variables.ts +103 -0
- package/src/deploy/adapter-output.ts +7 -2
- package/src/deploy/adapters/cloudflare.ts +7 -5
- package/src/deploy/adapters/node.ts +47 -9
- package/src/deploy/adapters/types.ts +7 -3
- package/src/deploy/artifacts.ts +79 -9
- package/src/deploy/cloudflare-negotiation.ts +35 -5
- package/src/deploy/headers.ts +2 -1
- package/src/deploy/node-headers.ts +63 -9
- package/src/deploy/platforms/cloudflare.ts +45 -9
- package/src/deploy/platforms/netlify.ts +35 -2
- package/src/deploy/platforms/node.ts +12 -2
- package/src/deploy/platforms/types.ts +21 -7
- package/src/deploy/platforms/vercel.ts +149 -17
- package/src/deploy/redirects.ts +151 -24
- package/src/deploy/rss.ts +3 -1
- package/src/deploy/sitemap.ts +39 -5
- package/src/deploy/vercel-negotiation.ts +326 -102
- package/src/eval/agents.ts +18 -1
- package/src/eval/prompts.ts +6 -3
- package/src/eval/report.ts +34 -13
- package/src/eval/run.ts +5 -0
- package/src/markdown/api-rail.ts +259 -0
- package/src/markdown/code-title.ts +35 -9
- package/src/markdown/features.ts +3 -2
- package/src/markdown/fence-meta.ts +2 -0
- package/src/markdown/include.ts +11 -1
- package/src/markdown/index.ts +28 -5
- package/src/markdown/math.ts +4 -4
- package/src/markdown/relative-links.ts +3 -2
- package/src/markdown/variables.ts +56 -0
- package/src/markdown/views.ts +82 -0
- package/src/narration/build.ts +412 -0
- package/src/narration/player.ts +249 -0
- package/src/narration/provider.ts +29 -0
- package/src/narration/script.ts +592 -0
- package/src/og/card.ts +7 -6
- package/src/openapi/checks.ts +273 -0
- package/src/openapi/graphql-build.ts +21 -0
- package/src/openapi/graphql.ts +11 -0
- package/src/openapi/model.ts +72 -27
- package/src/openapi/overlay.ts +256 -0
- package/src/openapi/parse.ts +182 -4
- package/src/openapi/references.ts +64 -8
- package/src/openapi/render-mdx.ts +5 -1
- package/src/openapi/scalar.ts +40 -6
- package/src/openapi/source.ts +40 -15
- package/src/ratelimit/cloudflare.ts +54 -0
- package/src/ratelimit/index.ts +30 -0
- package/src/ratelimit/memory.ts +45 -0
- package/src/ratelimit/runtime.ts +247 -0
- package/src/ratelimit/schema.ts +28 -0
- package/src/ratelimit/upstash.ts +60 -0
- package/src/ratelimit/wrangler.ts +70 -0
- package/src/reference/asyncapi.ts +2 -2
- package/src/reference/graphql.ts +20 -3
- package/src/reference/index.ts +1 -0
- package/src/reference/openapi.ts +21 -7
- package/src/reference/options.ts +80 -8
- package/src/reference/scalar.ts +33 -8
- package/src/registry/eject.ts +23 -5
- package/src/registry/registry.ts +7 -0
- package/src/search/adapters/locale-scope.ts +30 -0
- package/src/search/adapters/typesense.ts +14 -4
- package/src/search/build.ts +21 -3
- package/src/search/documents.ts +26 -2
- package/src/search/orama-index.ts +191 -34
- package/src/search/pagefind-ranking.ts +39 -0
- package/src/search/source-pages.ts +29 -0
- package/src/search/sync/algolia.ts +111 -10
- package/src/search/sync/index.ts +52 -13
- package/src/search/sync/orama-cloud.ts +3 -0
- package/src/search/sync/typesense.ts +76 -26
- package/src/seo/metatags.ts +67 -0
- package/src/sources/contentful.ts +12 -0
- package/src/sources/github-releases.ts +7 -1
- package/src/sources/shared.ts +3 -0
- package/src/theme/chrome-icons.ts +1 -0
- package/src/theme/color.ts +500 -0
- package/src/theme/entry.ts +85 -6
- package/src/theme/palette.ts +121 -45
- package/src/translate/prompts.ts +1 -0
- package/src/translate/validate.ts +31 -3
- package/src/upgrade/upgrade.ts +4 -171
- package/dist/cli/chunk-1d7ve1dm.js.map +0 -12
- package/dist/cli/chunk-2hsdwb9n.js.map +0 -10
- package/dist/cli/chunk-35d4wj9f.js.map +0 -15
- package/dist/cli/chunk-364znk6q.js +0 -75
- package/dist/cli/chunk-364znk6q.js.map +0 -11
- package/dist/cli/chunk-5m5nmvyq.js.map +0 -13
- package/dist/cli/chunk-8ktnccpt.js.map +0 -10
- package/dist/cli/chunk-9t7a85s3.js.map +0 -10
- package/dist/cli/chunk-b07cmahc.js +0 -145
- package/dist/cli/chunk-b07cmahc.js.map +0 -11
- package/dist/cli/chunk-c8chx29p.js.map +0 -36
- package/dist/cli/chunk-e04dxsz1.js +0 -39
- package/dist/cli/chunk-e04dxsz1.js.map +0 -10
- package/dist/cli/chunk-j85vccga.js.map +0 -36
- package/dist/cli/chunk-p3v96n38.js.map +0 -10
- package/dist/cli/chunk-pehfxfta.js.map +0 -10
- package/dist/cli/chunk-pv29h0wf.js.map +0 -190
- package/dist/cli/chunk-q58y5e6a.js.map +0 -10
- package/dist/cli/chunk-vg9r4eb9.js.map +0 -14
- package/dist/cli/chunk-wrr3j9w9.js.map +0 -35
- package/dist/cli/chunk-yfyb25rh.js.map +0 -14
- package/docs/content/sources.mdx +0 -334
- /package/dist/cli/{chunk-tkacnehg.js.map → chunk-3v3ffbrj.js.map} +0 -0
- /package/dist/cli/{chunk-r9rcc4w7.js.map → chunk-8y2kmjv8.js.map} +0 -0
- /package/dist/cli/{chunk-2eytanqx.js.map → chunk-c887fj0s.js.map} +0 -0
- /package/dist/cli/{chunk-akbpwfxc.js.map → chunk-dzwehpy7.js.map} +0 -0
- /package/dist/cli/{chunk-2z928egk.js.map → chunk-ft9vfys6.js.map} +0 -0
- /package/dist/cli/{chunk-a58773jm.js.map → chunk-kma9f6sf.js.map} +0 -0
- /package/dist/cli/{chunk-crgn1q09.js.map → chunk-sds923fa.js.map} +0 -0
- /package/dist/cli/{chunk-acanzt5p.js.map → chunk-tdqhyxfz.js.map} +0 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { PageView } from "../../markdown/views.ts";
|
|
3
|
+
import Icon from "../Icon.astro";
|
|
4
|
+
import { VIEW_INIT_SCRIPT, viewStyle } from "./view-switcher.ts";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The picker for a page written in `<View>` blocks, rendered above the
|
|
8
|
+
* content with the page's views (collected by `markdown/views.ts`). The
|
|
9
|
+
* style hides every other view's blocks and table of contents entries, and
|
|
10
|
+
* the inline script applies a linked or remembered choice before the views
|
|
11
|
+
* paint (see `view-switcher.ts`).
|
|
12
|
+
*/
|
|
13
|
+
interface Props {
|
|
14
|
+
/** The select's accessible name (`content.selectView`). */
|
|
15
|
+
label: string;
|
|
16
|
+
views: PageView[];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const { label, views } = Astro.props;
|
|
20
|
+
const titles = views.map((view) => view.title);
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
<blume-view-switcher
|
|
24
|
+
class="not-prose mt-4 mb-8 flex items-center gap-2"
|
|
25
|
+
data-views={JSON.stringify(titles)}
|
|
26
|
+
>
|
|
27
|
+
<style is:inline set:html={viewStyle(titles)} />
|
|
28
|
+
{
|
|
29
|
+
views.map(
|
|
30
|
+
(view) =>
|
|
31
|
+
view.icon && (
|
|
32
|
+
<span
|
|
33
|
+
class="inline-flex shrink-0 text-muted-foreground"
|
|
34
|
+
data-blume-view={view.title}
|
|
35
|
+
>
|
|
36
|
+
<Icon name={view.icon} size={16} />
|
|
37
|
+
</span>
|
|
38
|
+
)
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
<select
|
|
42
|
+
aria-label={label}
|
|
43
|
+
class="cursor-pointer rounded-blume border border-border bg-background px-3 py-1.5 font-medium text-foreground text-sm"
|
|
44
|
+
>
|
|
45
|
+
{views.map((view) => <option value={view.title}>{view.title}</option>)}
|
|
46
|
+
</select>
|
|
47
|
+
<script is:inline set:html={VIEW_INIT_SCRIPT} />
|
|
48
|
+
</blume-view-switcher>
|
|
49
|
+
|
|
50
|
+
<script>
|
|
51
|
+
import {
|
|
52
|
+
chooseView,
|
|
53
|
+
VIEW_PARAM,
|
|
54
|
+
VIEW_STORAGE_KEY,
|
|
55
|
+
} from "./view-switcher.ts";
|
|
56
|
+
|
|
57
|
+
const HEADINGS = "h2[id], h3[id], h4[id], h5[id], h6[id]";
|
|
58
|
+
|
|
59
|
+
const stored = (): string | null => {
|
|
60
|
+
try {
|
|
61
|
+
return localStorage.getItem(VIEW_STORAGE_KEY);
|
|
62
|
+
} catch {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/** The view holding the element a `#hash` link points at, if any. */
|
|
68
|
+
const linkedView = (): string | undefined => {
|
|
69
|
+
const id = decodeURIComponent(location.hash.slice(1));
|
|
70
|
+
const target = id ? document.getElementById(id) : null;
|
|
71
|
+
return (
|
|
72
|
+
target?.closest<HTMLElement>("article [data-blume-view]")?.dataset
|
|
73
|
+
.blumeView ?? undefined
|
|
74
|
+
);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Tag each table of contents entry with the view its heading is in, so the
|
|
79
|
+
* page's view style hides it with the view.
|
|
80
|
+
*/
|
|
81
|
+
const tagTableOfContents = () => {
|
|
82
|
+
const views = new Map<string, string>();
|
|
83
|
+
for (const view of document.querySelectorAll<HTMLElement>(
|
|
84
|
+
"article [data-blume-view]"
|
|
85
|
+
)) {
|
|
86
|
+
for (const heading of view.querySelectorAll(HEADINGS)) {
|
|
87
|
+
views.set(heading.id, view.dataset.blumeView ?? "");
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
for (const link of document.querySelectorAll<HTMLAnchorElement>(
|
|
91
|
+
'blume-toc a[href^="#"]'
|
|
92
|
+
)) {
|
|
93
|
+
const id = decodeURIComponent(link.getAttribute("href")?.slice(1) ?? "");
|
|
94
|
+
const item = link.closest("li");
|
|
95
|
+
const title = views.get(id);
|
|
96
|
+
if (item && title) {
|
|
97
|
+
item.dataset.blumeView = title;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
class BlumeViewSwitcher extends HTMLElement {
|
|
103
|
+
#titles: string[] = [];
|
|
104
|
+
|
|
105
|
+
connectedCallback() {
|
|
106
|
+
try {
|
|
107
|
+
this.#titles = JSON.parse(this.dataset.views ?? "[]");
|
|
108
|
+
} catch {
|
|
109
|
+
this.#titles = [];
|
|
110
|
+
}
|
|
111
|
+
tagTableOfContents();
|
|
112
|
+
this.#show(
|
|
113
|
+
chooseView(this.#titles, [
|
|
114
|
+
linkedView(),
|
|
115
|
+
new URL(location.href).searchParams.get(VIEW_PARAM),
|
|
116
|
+
stored(),
|
|
117
|
+
])
|
|
118
|
+
);
|
|
119
|
+
this.querySelector("select")?.addEventListener("change", this.#onPick);
|
|
120
|
+
window.addEventListener("hashchange", this.#onHash);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
disconnectedCallback() {
|
|
124
|
+
this.querySelector("select")?.removeEventListener("change", this.#onPick);
|
|
125
|
+
window.removeEventListener("hashchange", this.#onHash);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
#show(title: string | undefined) {
|
|
129
|
+
if (title === undefined) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
document.body.dataset.blumeView = title;
|
|
133
|
+
const select = this.querySelector("select");
|
|
134
|
+
if (select) {
|
|
135
|
+
select.value = title;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
#onPick = (event: Event) => {
|
|
140
|
+
// SAFETY: the listener is only added to this picker's <select>.
|
|
141
|
+
const { value } = event.currentTarget as HTMLSelectElement;
|
|
142
|
+
this.#show(value);
|
|
143
|
+
try {
|
|
144
|
+
localStorage.setItem(VIEW_STORAGE_KEY, value);
|
|
145
|
+
} catch {
|
|
146
|
+
// Storage can be off; the choice still holds for this page.
|
|
147
|
+
}
|
|
148
|
+
// replaceState: the link stays shareable without a history entry per
|
|
149
|
+
// pick, and the client router needs the entry's state kept.
|
|
150
|
+
const url = new URL(location.href);
|
|
151
|
+
url.searchParams.set(VIEW_PARAM, value);
|
|
152
|
+
history.replaceState(history.state, "", url);
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
// An in-page link to a heading in another view switches to that view.
|
|
156
|
+
#onHash = () => {
|
|
157
|
+
const view = linkedView();
|
|
158
|
+
if (view && view !== document.body.dataset.blumeView) {
|
|
159
|
+
this.#show(view);
|
|
160
|
+
document.getElementById(decodeURIComponent(location.hash.slice(1)))?.scrollIntoView();
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (!customElements.get("blume-view-switcher")) {
|
|
166
|
+
customElements.define("blume-view-switcher", BlumeViewSwitcher);
|
|
167
|
+
}
|
|
168
|
+
</script>
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The props `<ParamField>` and `<ResponseField>` take, in Mintlify's shape: a
|
|
3
|
+
* parameter names its location with the attribute that carries its name
|
|
4
|
+
* (`<ParamField query="limit">`), and both take `type`, `required`,
|
|
5
|
+
* `deprecated`, and `default`; a response field adds `pre` and `post` labels
|
|
6
|
+
* around its name. Pure, so the Markdown downlevel and the playground can
|
|
7
|
+
* read fields the way the components render them.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** Where a `<ParamField>` parameter goes, in the order the attributes are checked. */
|
|
11
|
+
export const PARAM_LOCATIONS = ["path", "query", "header", "body"] as const;
|
|
12
|
+
|
|
13
|
+
/** A parameter's location. */
|
|
14
|
+
export type ParamLocation = (typeof PARAM_LOCATIONS)[number];
|
|
15
|
+
|
|
16
|
+
/** A literal value as MDX passes it: a string attribute, or an expression's data. */
|
|
17
|
+
export type FieldValue =
|
|
18
|
+
| string
|
|
19
|
+
| number
|
|
20
|
+
| boolean
|
|
21
|
+
| null
|
|
22
|
+
| undefined
|
|
23
|
+
| FieldValue[]
|
|
24
|
+
| { [key: string]: FieldValue };
|
|
25
|
+
|
|
26
|
+
/** A boolean prop: MDX shorthand (`required`) is `true`, `required="true"` a string. */
|
|
27
|
+
export type FlagProp = boolean | string;
|
|
28
|
+
|
|
29
|
+
/** What both field components take. */
|
|
30
|
+
export interface FieldProps {
|
|
31
|
+
/** The value used when none is given. */
|
|
32
|
+
default?: FieldValue;
|
|
33
|
+
deprecated?: FlagProp;
|
|
34
|
+
required?: FlagProp;
|
|
35
|
+
/** Free text: `string`, `integer`, `string[]`, `object`. */
|
|
36
|
+
type?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** `<ParamField>`: a request parameter, named by its location attribute. */
|
|
40
|
+
export interface ParamFieldProps extends FieldProps {
|
|
41
|
+
body?: string;
|
|
42
|
+
header?: string;
|
|
43
|
+
/** The name, for a field with no location attribute. */
|
|
44
|
+
name?: string;
|
|
45
|
+
path?: string;
|
|
46
|
+
/**
|
|
47
|
+
* An example value: the one the playground and request samples start
|
|
48
|
+
* with, not an input's placeholder hint (see `fieldSchema`).
|
|
49
|
+
*/
|
|
50
|
+
placeholder?: string;
|
|
51
|
+
query?: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** `<ResponseField>`: a field of the response. */
|
|
55
|
+
export interface ResponseFieldProps extends FieldProps {
|
|
56
|
+
name: string;
|
|
57
|
+
/** Labels after the name. */
|
|
58
|
+
post?: string | string[];
|
|
59
|
+
/** Labels before the name. */
|
|
60
|
+
pre?: string | string[];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Whether a flag prop is on. */
|
|
64
|
+
export const isOn = (value?: FlagProp): boolean =>
|
|
65
|
+
value === true || value === "true";
|
|
66
|
+
|
|
67
|
+
/** Where a parameter goes, and what it's called. */
|
|
68
|
+
export interface ParamFieldName {
|
|
69
|
+
location?: ParamLocation;
|
|
70
|
+
name?: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** A parameter's location and name: the first location attribute set, else `name`. */
|
|
74
|
+
export const paramField = (props: ParamFieldProps): ParamFieldName => {
|
|
75
|
+
for (const location of PARAM_LOCATIONS) {
|
|
76
|
+
const name = props[location];
|
|
77
|
+
if (name !== undefined) {
|
|
78
|
+
return { location, name };
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return { name: props.name };
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const isText = (value: FieldValue): value is string =>
|
|
85
|
+
typeof value === "string";
|
|
86
|
+
|
|
87
|
+
/** A default value as shown: text as written, anything else as JSON; `null` when there is none. */
|
|
88
|
+
export const defaultLabel = (value?: FieldValue): string | null => {
|
|
89
|
+
if (value === undefined || value === null || value === "") {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
return isText(value) ? value : JSON.stringify(value);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/** `pre`/`post` labels as a list, whether one was written or several. */
|
|
96
|
+
export const fieldLabels = (value?: string | string[]): string[] => {
|
|
97
|
+
if (value === undefined) {
|
|
98
|
+
return [];
|
|
99
|
+
}
|
|
100
|
+
return (Array.isArray(value) ? value : [value]).filter(
|
|
101
|
+
(label) => label !== ""
|
|
102
|
+
);
|
|
103
|
+
};
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { exampleValue } from "../openapi/helpers.ts";
|
|
2
|
+
import type { ParameterLike, SchemaLike } from "../openapi/helpers.ts";
|
|
3
|
+
import { resolveSecurity } from "../openapi/security.ts";
|
|
4
|
+
import type { OperationSecurity } from "../openapi/security.ts";
|
|
5
|
+
import type { FieldValue, ParamLocation } from "./api-field.ts";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A hand-written API page's endpoint, as its `api` frontmatter and its
|
|
9
|
+
* `<ParamField>`s describe it, turned into the OpenAPI-shaped pieces the
|
|
10
|
+
* operation playground and code samples are built from: a page with
|
|
11
|
+
* `api: "POST /v1/users"` gets the same Try it panel and request samples as
|
|
12
|
+
* a spec'd operation, with no spec. Mintlify's frontmatter, so migrated pages
|
|
13
|
+
* keep it as written.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/** How a hand-written endpoint authenticates (`authMethod`, `api.auth.method`). */
|
|
17
|
+
export const AUTH_METHODS = ["bearer", "basic", "key", "none"] as const;
|
|
18
|
+
export type AuthMethod = (typeof AUTH_METHODS)[number];
|
|
19
|
+
|
|
20
|
+
/** What a page's playground shows: all of it, the samples only, or none. */
|
|
21
|
+
export const PLAYGROUND_MODES = ["interactive", "simple", "none"] as const;
|
|
22
|
+
export type PlaygroundMode = (typeof PLAYGROUND_MODES)[number];
|
|
23
|
+
|
|
24
|
+
/** `api` frontmatter: an HTTP method, then a path or a full URL. */
|
|
25
|
+
export const API_ENDPOINT =
|
|
26
|
+
/^(?<method>GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS|TRACE)\s+(?<target>\S+)$/iu;
|
|
27
|
+
|
|
28
|
+
/** The site's default auth for hand-written endpoints (`api.auth`). */
|
|
29
|
+
export interface EndpointAuth {
|
|
30
|
+
method: AuthMethod;
|
|
31
|
+
/** The header an API key goes in. */
|
|
32
|
+
name?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** One `<ParamField>`, as the page's plugin collected it. */
|
|
36
|
+
export interface EndpointField {
|
|
37
|
+
default?: FieldValue;
|
|
38
|
+
deprecated?: boolean;
|
|
39
|
+
/** Body fields nested in this one's `<Expandable>`. */
|
|
40
|
+
fields?: EndpointField[];
|
|
41
|
+
location: ParamLocation;
|
|
42
|
+
name: string;
|
|
43
|
+
placeholder?: string;
|
|
44
|
+
required?: boolean;
|
|
45
|
+
type?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** What the page's plugin hands the endpoint components. */
|
|
49
|
+
export interface EndpointSpec {
|
|
50
|
+
authMethod?: AuthMethod;
|
|
51
|
+
fields: EndpointField[];
|
|
52
|
+
method: string;
|
|
53
|
+
playground?: PlaygroundMode;
|
|
54
|
+
/** The page has a `<RequestExample>`, which stands in for generated samples. */
|
|
55
|
+
requestExample: boolean;
|
|
56
|
+
/** The `api` target as written: a path, or a full URL. */
|
|
57
|
+
target: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** The method and target of an `api` value, or `null` when it isn't one. */
|
|
61
|
+
export const parseApiEndpoint = (
|
|
62
|
+
value: string
|
|
63
|
+
): { method: string; target: string } | null => {
|
|
64
|
+
const groups = API_ENDPOINT.exec(value.trim())?.groups;
|
|
65
|
+
return groups?.method && groups.target
|
|
66
|
+
? { method: groups.method.toUpperCase(), target: groups.target }
|
|
67
|
+
: null;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const ABSOLUTE_URL = /^(?<origin>https?:\/\/[^/?#]+)(?<rest>.*)$/iu;
|
|
71
|
+
|
|
72
|
+
/** An endpoint's target, split the way the operation model takes it. */
|
|
73
|
+
export interface EndpointTarget {
|
|
74
|
+
path: string;
|
|
75
|
+
servers: { url: string }[];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* The target split into a server and a path: a full URL is its own server,
|
|
80
|
+
* and a path joins the site's `api.server`, or stays relative to the docs
|
|
81
|
+
* when there is none.
|
|
82
|
+
*/
|
|
83
|
+
export const endpointTarget = (
|
|
84
|
+
target: string,
|
|
85
|
+
server?: string
|
|
86
|
+
): EndpointTarget => {
|
|
87
|
+
const absolute = ABSOLUTE_URL.exec(target)?.groups;
|
|
88
|
+
if (absolute?.origin) {
|
|
89
|
+
return {
|
|
90
|
+
path: absolute.rest || "/",
|
|
91
|
+
servers: [{ url: absolute.origin }],
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
path: target.startsWith("/") ? target : `/${target}`,
|
|
96
|
+
servers: server ? [{ url: server.replace(/\/+$/u, "") }] : [],
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const PRIMITIVES = new Set([
|
|
101
|
+
"string",
|
|
102
|
+
"number",
|
|
103
|
+
"integer",
|
|
104
|
+
"boolean",
|
|
105
|
+
"object",
|
|
106
|
+
]);
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* A field's JSON schema from its `type`: `string[]` an array of strings, a
|
|
110
|
+
* field with nested fields an object with those properties, and anything
|
|
111
|
+
* that isn't a JSON type (`enum<string>`, `Date`) a string, which is what it
|
|
112
|
+
* goes over the wire as. A default and placeholder carry over, the
|
|
113
|
+
* placeholder as the example the samples show.
|
|
114
|
+
*/
|
|
115
|
+
export const fieldSchema = (field: EndpointField): SchemaLike => {
|
|
116
|
+
const type = field.type?.trim().toLowerCase() ?? "";
|
|
117
|
+
if (type.endsWith("[]")) {
|
|
118
|
+
return {
|
|
119
|
+
items: fieldSchema({
|
|
120
|
+
...field,
|
|
121
|
+
default: undefined,
|
|
122
|
+
type: type.slice(0, -2),
|
|
123
|
+
}),
|
|
124
|
+
type: "array",
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
const nested = field.fields ?? [];
|
|
128
|
+
const schema: SchemaLike =
|
|
129
|
+
nested.length > 0
|
|
130
|
+
? {
|
|
131
|
+
properties: Object.fromEntries(
|
|
132
|
+
nested.map((child) => [child.name, fieldSchema(child)])
|
|
133
|
+
),
|
|
134
|
+
type: "object",
|
|
135
|
+
}
|
|
136
|
+
: { type: PRIMITIVES.has(type) ? type : "string" };
|
|
137
|
+
const required = nested
|
|
138
|
+
.filter((child) => child.required)
|
|
139
|
+
.map((child) => child.name);
|
|
140
|
+
if (required.length > 0) {
|
|
141
|
+
schema.required = required;
|
|
142
|
+
}
|
|
143
|
+
if (field.default !== undefined) {
|
|
144
|
+
schema.default = field.default;
|
|
145
|
+
}
|
|
146
|
+
if (field.placeholder) {
|
|
147
|
+
schema.example = field.placeholder;
|
|
148
|
+
}
|
|
149
|
+
if (field.deprecated) {
|
|
150
|
+
schema.deprecated = true;
|
|
151
|
+
}
|
|
152
|
+
return schema;
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
/** The path, query, and header fields as OpenAPI parameters. */
|
|
156
|
+
export const endpointParameters = (fields: EndpointField[]): ParameterLike[] =>
|
|
157
|
+
fields.flatMap((field) =>
|
|
158
|
+
field.location === "body"
|
|
159
|
+
? []
|
|
160
|
+
: [
|
|
161
|
+
{
|
|
162
|
+
deprecated: field.deprecated === true,
|
|
163
|
+
in: field.location,
|
|
164
|
+
name: field.name,
|
|
165
|
+
// A path parameter is always required.
|
|
166
|
+
required: field.location === "path" || field.required === true,
|
|
167
|
+
schema: fieldSchema(field),
|
|
168
|
+
},
|
|
169
|
+
]
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
/** Whether a field, or one nested in it, has a `default` or `placeholder`. */
|
|
173
|
+
const hasValue = (field: EndpointField): boolean =>
|
|
174
|
+
field.default !== undefined ||
|
|
175
|
+
Boolean(field.placeholder) ||
|
|
176
|
+
(field.fields ?? []).some(hasValue);
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* The fields a request starts with: required ones, and ones with a value to
|
|
180
|
+
* send. An optional field with neither is left for the reader to fill,
|
|
181
|
+
* rather than sent as the sampler's `"string"`, `0`, or `true`.
|
|
182
|
+
*/
|
|
183
|
+
const sentFields = (fields: EndpointField[]): EndpointField[] =>
|
|
184
|
+
fields
|
|
185
|
+
.filter((field) => field.required === true || hasValue(field))
|
|
186
|
+
.map((field) => ({ ...field, fields: sentFields(field.fields ?? []) }));
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* The body fields as a JSON request body, or `undefined` when there are none.
|
|
190
|
+
* Its example, which the playground and samples start from, holds only the
|
|
191
|
+
* {@link sentFields}.
|
|
192
|
+
*/
|
|
193
|
+
export const endpointBody = (fields: EndpointField[]) => {
|
|
194
|
+
const body = fields.filter((field) => field.location === "body");
|
|
195
|
+
const object = (members: EndpointField[]): SchemaLike =>
|
|
196
|
+
fieldSchema({
|
|
197
|
+
fields: members,
|
|
198
|
+
location: "body",
|
|
199
|
+
name: "",
|
|
200
|
+
type: "object",
|
|
201
|
+
});
|
|
202
|
+
return body.length > 0
|
|
203
|
+
? {
|
|
204
|
+
content: {
|
|
205
|
+
"application/json": {
|
|
206
|
+
example: exampleValue(object(sentFields(body)), {}),
|
|
207
|
+
schema: object(body),
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
}
|
|
211
|
+
: undefined;
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* The security an endpoint enforces: its page's `authMethod`, else the
|
|
216
|
+
* site's `api.auth`, else none. An API key goes in the configured header,
|
|
217
|
+
* `x-api-key` when none is named.
|
|
218
|
+
*/
|
|
219
|
+
export const endpointSecurity = (
|
|
220
|
+
authMethod?: AuthMethod,
|
|
221
|
+
siteAuth?: EndpointAuth
|
|
222
|
+
): OperationSecurity => {
|
|
223
|
+
const method = authMethod ?? siteAuth?.method ?? "none";
|
|
224
|
+
if (method === "none") {
|
|
225
|
+
return { alternatives: [], optional: false };
|
|
226
|
+
}
|
|
227
|
+
if (method === "key") {
|
|
228
|
+
return resolveSecurity([{ apiKey: [] }], {
|
|
229
|
+
apiKey: {
|
|
230
|
+
in: "header",
|
|
231
|
+
name: siteAuth?.name ?? "x-api-key",
|
|
232
|
+
type: "apiKey",
|
|
233
|
+
},
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
return resolveSecurity([{ [method]: [] }], {
|
|
237
|
+
[method]: { scheme: method, type: "http" },
|
|
238
|
+
});
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* The endpoint spec the page's plugin wrote into the `spec` attribute of
|
|
243
|
+
* `<ApiEndpoint>` and `<ApiPlayground>`.
|
|
244
|
+
*/
|
|
245
|
+
export const readEndpointSpec = (json: string): EndpointSpec =>
|
|
246
|
+
// SAFETY: the attribute is `JSON.stringify` of an `EndpointSpec`, written
|
|
247
|
+
// by `markdown/api-rail.ts` at build; authors never write it.
|
|
248
|
+
JSON.parse(json) as EndpointSpec;
|
|
@@ -55,6 +55,9 @@ export class BlumeMermaid extends HTMLElement {
|
|
|
55
55
|
look: "classic",
|
|
56
56
|
securityLevel: "strict",
|
|
57
57
|
startOnLoad: false,
|
|
58
|
+
// Without this, a diagram that fails to parse leaves Mermaid's own
|
|
59
|
+
// "Syntax error in text" graphic appended to <body>, below the page.
|
|
60
|
+
suppressErrorRendering: true,
|
|
58
61
|
theme: prefersDark() ? "dark" : "default",
|
|
59
62
|
});
|
|
60
63
|
try {
|
|
@@ -71,13 +74,24 @@ export class BlumeMermaid extends HTMLElement {
|
|
|
71
74
|
// oxlint-disable-next-line github/no-inner-html -- Mermaid-generated SVG must be injected as HTML
|
|
72
75
|
output.innerHTML = svg;
|
|
73
76
|
}
|
|
74
|
-
} catch {
|
|
77
|
+
} catch (error) {
|
|
75
78
|
// Localized message stamped on <body> by RootLayout's markup (the
|
|
76
79
|
// data-attribute channel); English fallback when the attribute is
|
|
77
80
|
// missing (a stale snapshot or a custom layout).
|
|
78
81
|
output.textContent =
|
|
79
82
|
document.body.dataset.i18nDiagramError ||
|
|
80
83
|
"Could not render this diagram.";
|
|
84
|
+
// Readers get only the message above; the writer needs Mermaid's
|
|
85
|
+
// parser error (line and expected token) to fix the source. It goes
|
|
86
|
+
// to the console, and `blume dev` also shows it under the message.
|
|
87
|
+
console.error("[blume] Mermaid could not render a diagram:", error);
|
|
88
|
+
if (import.meta.env.DEV) {
|
|
89
|
+
const detail = document.createElement("pre");
|
|
90
|
+
detail.className =
|
|
91
|
+
"mt-2 overflow-x-auto text-muted-foreground text-xs";
|
|
92
|
+
detail.textContent = String(error);
|
|
93
|
+
output.append(detail);
|
|
94
|
+
}
|
|
81
95
|
}
|
|
82
96
|
output.removeAttribute("aria-busy");
|
|
83
97
|
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The page view picker's logic (see `ViewSwitcher.astro`). A page written in
|
|
3
|
+
* `<View title>` blocks shows one view at a time. The choice sits on
|
|
4
|
+
* `<body data-blume-view>`, which each page brings fresh, and a per-page style
|
|
5
|
+
* hides everything tagged with another view: the `<View>` blocks, the
|
|
6
|
+
* picker's icons, and the table of contents entries for their headings.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Where a reader's last-picked view is remembered, across pages. The init
|
|
11
|
+
* script below spells it out, as it does {@link VIEW_PARAM}.
|
|
12
|
+
*/
|
|
13
|
+
export const VIEW_STORAGE_KEY = "blume-view";
|
|
14
|
+
|
|
15
|
+
/** The query parameter a shared link picks a view with (`?view=Python`). */
|
|
16
|
+
export const VIEW_PARAM = "view";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The view to show: the first of the candidates the page has, most specific
|
|
20
|
+
* first (a linked heading's view, the link's `?view=`, the reader's last
|
|
21
|
+
* pick), else the page's first view.
|
|
22
|
+
*/
|
|
23
|
+
export const chooseView = (
|
|
24
|
+
titles: readonly string[],
|
|
25
|
+
candidates: readonly (string | null | undefined)[]
|
|
26
|
+
): string | undefined =>
|
|
27
|
+
candidates.find(
|
|
28
|
+
(candidate): candidate is string =>
|
|
29
|
+
candidate !== null &&
|
|
30
|
+
candidate !== undefined &&
|
|
31
|
+
titles.includes(candidate)
|
|
32
|
+
) ?? titles[0];
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* A CSS string for `value`, safe inside a `<style>` element: quotes and
|
|
36
|
+
* backslashes escaped, `<` as a hex escape so the text can't close the
|
|
37
|
+
* element, and line breaks (which a CSS string can't hold) as spaces.
|
|
38
|
+
*/
|
|
39
|
+
const cssString = (value: string): string =>
|
|
40
|
+
`"${value
|
|
41
|
+
.replaceAll(/["\\]/gu, String.raw`\$&`)
|
|
42
|
+
.replaceAll("<", String.raw`\3c `)
|
|
43
|
+
.replaceAll(/[\n\r\f]/gu, " ")}"`;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The page's view CSS: with a view chosen on `<body>`, everything tagged with
|
|
47
|
+
* another is hidden; before a choice, everything but the first view is.
|
|
48
|
+
*/
|
|
49
|
+
export const viewStyle = (titles: readonly string[]): string => {
|
|
50
|
+
const [first] = titles;
|
|
51
|
+
if (first === undefined) {
|
|
52
|
+
return "";
|
|
53
|
+
}
|
|
54
|
+
const other = (title: string): string =>
|
|
55
|
+
`[data-blume-view]:not([data-blume-view=${cssString(title)}])`;
|
|
56
|
+
const selectors = [
|
|
57
|
+
`body:not([data-blume-view]) ${other(first)}`,
|
|
58
|
+
...titles.map(
|
|
59
|
+
(title) => `body[data-blume-view=${cssString(title)}] ${other(title)}`
|
|
60
|
+
),
|
|
61
|
+
];
|
|
62
|
+
return `${selectors.join(",")}{display:none!important}`;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Runs inline as the picker is parsed, ahead of the views it controls, so a
|
|
67
|
+
* link's `?view=` or the reader's last pick applies before anything paints.
|
|
68
|
+
* Inline scripts run once per session under the client router; after that
|
|
69
|
+
* the picker element applies the choice as each page swaps in.
|
|
70
|
+
*/
|
|
71
|
+
export const VIEW_INIT_SCRIPT = `(()=>{const s=document.currentScript;const p=s&&s.closest("blume-view-switcher");if(!p)return;let t=[];try{t=JSON.parse(p.getAttribute("data-views")||"[]")}catch{}let r=null;try{r=localStorage.getItem("blume-view")}catch{}const l=new URLSearchParams(location.search).get("view");const v=[l,r].find((c)=>c&&t.includes(c))||t[0];if(!v)return;document.body.setAttribute("data-blume-view",v);const e=p.querySelector("select");if(e)e.value=v;})();`;
|
package/src/components/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
+
import type { CaptchaSettings } from "../../captcha/schema.ts";
|
|
2
3
|
import type { UIStrings } from "../../core/i18n-ui.ts";
|
|
3
4
|
import { resolveIcon } from "../../theme/icons.ts";
|
|
4
5
|
import Assistant from "./assistant.tsx";
|
|
@@ -9,12 +10,17 @@ interface Suggestion {
|
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
interface Props {
|
|
13
|
+
/** The bot check's public settings (`ai.assistant.captcha`). */
|
|
14
|
+
captcha?: CaptchaSettings;
|
|
12
15
|
endpoint?: string;
|
|
13
16
|
strings?: UIStrings["assistant"];
|
|
14
17
|
suggestions?: Suggestion[];
|
|
18
|
+
/** The Contact support link (`ai.assistant.support`). */
|
|
19
|
+
support?: string;
|
|
15
20
|
}
|
|
16
21
|
|
|
17
|
-
const { endpoint, strings, suggestions = [] } =
|
|
22
|
+
const { captcha, endpoint, strings, suggestions = [], support } =
|
|
23
|
+
Astro.props;
|
|
18
24
|
|
|
19
25
|
// Icons resolve to inline SVG here (server-only module), so the client island
|
|
20
26
|
// gets ready-to-render markup rather than a name it can't resolve. Bare Lucide
|
|
@@ -41,6 +47,7 @@ const icons = {
|
|
|
41
47
|
clear: bodyFor("trash-2"),
|
|
42
48
|
close: bodyFor("chevrons-right"),
|
|
43
49
|
copy: bodyFor("copy"),
|
|
50
|
+
remove: bodyFor("x"),
|
|
44
51
|
};
|
|
45
52
|
---
|
|
46
53
|
|
|
@@ -50,11 +57,13 @@ const icons = {
|
|
|
50
57
|
panel and re-stamps the body push attribute itself on astro:after-swap
|
|
51
58
|
(see assistant.tsx), since the swap replaces <body> wholesale. */}
|
|
52
59
|
<Assistant
|
|
60
|
+
captcha={captcha}
|
|
53
61
|
client:load
|
|
54
62
|
endpoint={endpoint}
|
|
55
63
|
icons={icons}
|
|
56
64
|
strings={strings}
|
|
57
65
|
suggestions={items}
|
|
66
|
+
support={support}
|
|
58
67
|
transition:persist="blume-assistant"
|
|
59
68
|
/>
|
|
60
69
|
|