blume 2.0.1 → 2.0.3
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/CHANGELOG.md +147 -0
- package/dist/cli/{chunk-qwsrynx5.js → chunk-1d7ve1dm.js} +38 -19
- package/dist/cli/{chunk-qwsrynx5.js.map → chunk-1d7ve1dm.js.map} +4 -4
- package/dist/cli/{chunk-s6jhgk0q.js → chunk-2eytanqx.js} +2 -2
- package/dist/cli/{chunk-kdp5q7ke.js → chunk-2hsdwb9n.js} +18 -19
- package/dist/cli/{chunk-kdp5q7ke.js.map → chunk-2hsdwb9n.js.map} +2 -2
- package/dist/cli/{chunk-hdpx1tax.js → chunk-2z928egk.js} +5 -5
- package/dist/cli/{chunk-jwyddg7y.js → chunk-35d4wj9f.js} +30 -24
- package/dist/cli/chunk-35d4wj9f.js.map +15 -0
- package/dist/cli/{chunk-ah61y8py.js → chunk-364znk6q.js} +2 -2
- package/dist/cli/{chunk-jts8mvcz.js → chunk-3em5wd2y.js} +25 -6
- package/dist/cli/{chunk-jts8mvcz.js.map → chunk-3em5wd2y.js.map} +3 -3
- package/dist/cli/{chunk-s1p84fyh.js → chunk-5f86nr5m.js} +63 -22
- package/dist/cli/chunk-5f86nr5m.js.map +11 -0
- package/dist/cli/{chunk-2hn4b8z7.js → chunk-5m5nmvyq.js} +170 -76
- package/dist/cli/chunk-5m5nmvyq.js.map +13 -0
- package/dist/cli/{chunk-epjnccmv.js → chunk-5xvm6tfj.js} +18 -15
- package/dist/cli/chunk-5xvm6tfj.js.map +10 -0
- package/dist/cli/{chunk-fz5wtpmh.js → chunk-6dsbexzp.js} +18 -15
- package/dist/cli/chunk-6dsbexzp.js.map +10 -0
- package/dist/cli/{chunk-vtk4a6dg.js → chunk-8ktnccpt.js} +1 -1
- package/dist/cli/{chunk-6hsn950k.js → chunk-9t7a85s3.js} +178 -48
- package/dist/cli/chunk-9t7a85s3.js.map +10 -0
- package/dist/cli/{chunk-fxypxtvm.js → chunk-a58773jm.js} +2 -2
- package/dist/cli/{chunk-mb2919y2.js → chunk-acanzt5p.js} +17 -6
- package/dist/cli/chunk-acanzt5p.js.map +10 -0
- package/dist/cli/{chunk-27g6wdth.js → chunk-akbpwfxc.js} +90 -26
- package/dist/cli/chunk-akbpwfxc.js.map +10 -0
- package/dist/cli/{chunk-wm7js3j9.js → chunk-b07cmahc.js} +2 -2
- package/dist/cli/{chunk-wgm7m9qk.js → chunk-c8chx29p.js} +179 -51
- package/dist/cli/chunk-c8chx29p.js.map +36 -0
- package/dist/cli/{chunk-qs4q5p4e.js → chunk-crgn1q09.js} +32 -14
- package/dist/cli/chunk-crgn1q09.js.map +10 -0
- package/dist/cli/chunk-e04dxsz1.js +39 -0
- package/dist/cli/chunk-e04dxsz1.js.map +10 -0
- package/dist/cli/{chunk-yt5n7ppj.js → chunk-ey84smr6.js} +17 -7
- package/dist/cli/chunk-ey84smr6.js.map +10 -0
- package/dist/cli/{chunk-f2z5v128.js → chunk-g4hq16wv.js} +14 -15
- package/dist/cli/{chunk-f2z5v128.js.map → chunk-g4hq16wv.js.map} +2 -2
- package/dist/cli/{chunk-fa25z98p.js → chunk-ga0pf4aj.js} +9 -8
- package/dist/cli/chunk-ga0pf4aj.js.map +11 -0
- package/dist/cli/{chunk-kpf8rrjc.js → chunk-hm3vjy5s.js} +109 -58
- package/dist/cli/chunk-hm3vjy5s.js.map +19 -0
- package/dist/cli/{chunk-fs23ddbb.js → chunk-j85vccga.js} +625 -750
- package/dist/cli/chunk-j85vccga.js.map +36 -0
- package/dist/cli/{chunk-ch6g3ar0.js → chunk-p3v96n38.js} +6 -6
- package/dist/cli/{chunk-ch6g3ar0.js.map → chunk-p3v96n38.js.map} +3 -3
- package/dist/cli/{chunk-q5163e60.js → chunk-p73c0m7w.js} +21 -19
- package/dist/cli/chunk-p73c0m7w.js.map +11 -0
- package/dist/cli/{chunk-dh8cwk36.js → chunk-pehfxfta.js} +24 -9
- package/dist/cli/chunk-pehfxfta.js.map +10 -0
- package/dist/cli/{chunk-qkqwkpte.js → chunk-pv29h0wf.js} +3688 -1313
- package/dist/cli/chunk-pv29h0wf.js.map +190 -0
- package/dist/cli/{chunk-6vm74dry.js → chunk-q58y5e6a.js} +10 -10
- package/dist/cli/{chunk-6vm74dry.js.map → chunk-q58y5e6a.js.map} +3 -3
- package/dist/cli/{chunk-zxcczpyx.js → chunk-r20tn01b.js} +1 -1
- package/dist/cli/{chunk-m3vmjgmq.js → chunk-r9rcc4w7.js} +16 -8
- package/dist/cli/chunk-r9rcc4w7.js.map +10 -0
- package/dist/cli/{chunk-5shv93fd.js → chunk-tkacnehg.js} +2 -2
- package/dist/cli/{chunk-zxh4d9vy.js → chunk-tzmab476.js} +4 -4
- package/dist/cli/{chunk-yw7dm696.js → chunk-vg9r4eb9.js} +24 -11
- package/dist/cli/chunk-vg9r4eb9.js.map +14 -0
- package/dist/cli/{chunk-79jhk4py.js → chunk-wrr3j9w9.js} +260 -132
- package/dist/cli/chunk-wrr3j9w9.js.map +35 -0
- package/dist/cli/{chunk-6crbhc3x.js → chunk-yfyb25rh.js} +54 -27
- package/dist/cli/chunk-yfyb25rh.js.map +14 -0
- package/dist/cli/index.js +162 -35
- package/dist/cli/index.js.map +4 -4
- package/dist/types/ai/agent-surface.d.ts +32 -0
- package/dist/types/ai/api-catalog.d.ts +7 -1
- package/dist/types/ai/ask-context.d.ts +7 -0
- package/dist/types/ai/component-markdown.d.ts +4 -4
- package/dist/types/ai/link-headers.d.ts +8 -1
- package/dist/types/ai/openapi-components.d.ts +5 -2
- package/dist/types/ai/relative-links.d.ts +11 -4
- package/dist/types/ai/skills.d.ts +4 -1
- package/dist/types/ai/static-expression.d.ts +28 -0
- package/dist/types/ai/tar.d.ts +1 -3
- package/dist/types/analytics/databuddy.d.ts +43 -0
- package/dist/types/analytics/index.d.ts +4 -0
- package/dist/types/analytics/one-dollar-stats.d.ts +48 -0
- package/dist/types/analytics/schema.d.ts +28 -0
- package/dist/types/astro/integration.d.ts +3 -2
- package/dist/types/cli/env.d.ts +5 -0
- package/dist/types/cli/init/scaffold.d.ts +19 -3
- package/dist/types/cli/init/starter-spec.d.ts +11 -0
- package/dist/types/core/base-path.d.ts +24 -1
- package/dist/types/core/config-input.d.ts +13 -11
- package/dist/types/core/config.d.ts +2 -2
- package/dist/types/core/directive-diagnostics.d.ts +12 -0
- package/dist/types/core/graph.d.ts +2 -0
- package/dist/types/core/heading-markers.d.ts +5 -7
- package/dist/types/core/i18n-ui.d.ts +31 -0
- package/dist/types/core/i18n.d.ts +9 -1
- package/dist/types/core/last-modified.d.ts +10 -0
- package/dist/types/core/links.d.ts +3 -1
- package/dist/types/core/load-module.d.ts +10 -0
- package/dist/types/core/locale-links.d.ts +12 -2
- package/dist/types/core/meta.d.ts +13 -1
- package/dist/types/core/nav-diagnostics.d.ts +10 -0
- package/dist/types/core/navigation.d.ts +38 -0
- package/dist/types/core/ordering-prefix.d.ts +4 -0
- package/dist/types/core/safe-links.d.ts +3 -1
- package/dist/types/core/schema.d.ts +59 -13
- package/dist/types/core/sources/github-releases.d.ts +5 -0
- package/dist/types/core/sources/lower.d.ts +38 -13
- package/dist/types/core/sources/normalize.d.ts +23 -2
- package/dist/types/core/sources/remote.d.ts +11 -1
- package/dist/types/core/sources/resolve.d.ts +12 -0
- package/dist/types/core/sources/types.d.ts +31 -0
- package/dist/types/core/sources/watch.d.ts +12 -5
- package/dist/types/core/standard-schema.d.ts +5 -0
- package/dist/types/core/types.d.ts +9 -0
- package/dist/types/deploy/adapters/node.d.ts +5 -2
- package/dist/types/deploy/adapters/types.d.ts +7 -0
- package/dist/types/deploy/artifacts.d.ts +6 -4
- package/dist/types/deploy/cloudflare-negotiation.d.ts +3 -2
- package/dist/types/deploy/headers.d.ts +36 -7
- package/dist/types/deploy/node-headers.d.ts +43 -8
- package/dist/types/deploy/platforms/netlify.d.ts +27 -2
- package/dist/types/deploy/platforms/node.d.ts +6 -5
- package/dist/types/deploy/platforms/types.d.ts +15 -0
- package/dist/types/deploy/platforms/vercel.d.ts +3 -2
- package/dist/types/deploy/redirects.d.ts +31 -15
- package/dist/types/deploy/vercel-negotiation.d.ts +3 -2
- package/dist/types/markdown/directives.d.ts +62 -0
- package/dist/types/markdown/features.d.ts +21 -0
- package/dist/types/markdown/mdast.d.ts +63 -0
- package/dist/types/openapi/asyncapi.d.ts +4 -2
- package/dist/types/openapi/model.d.ts +20 -6
- package/dist/types/search/sync/algolia.d.ts +3 -1
- package/docs/01-quickstart.mdx +3 -2
- package/docs/02-deployment.mdx +20 -9
- package/docs/08-faq.mdx +10 -3
- package/docs/advanced/changelog.mdx +1 -1
- package/docs/advanced/custom-pages.mdx +7 -5
- package/docs/cli/audit.mdx +19 -3
- package/docs/cli/doctor.mdx +2 -2
- package/docs/cli/evals.mdx +4 -4
- package/docs/cli/index.mdx +4 -1
- package/docs/cli/translate.mdx +4 -4
- package/docs/cli/version.mdx +1 -1
- package/docs/configuration/analytics.mdx +42 -2
- package/docs/configuration/assistant.mdx +1 -1
- package/docs/configuration/customization.mdx +6 -3
- package/docs/configuration/index.mdx +5 -3
- package/docs/configuration/search.mdx +2 -2
- package/docs/content/components.mdx +2 -2
- package/docs/content/frontmatter.mdx +5 -1
- package/docs/content/i18n.mdx +3 -1
- package/docs/content/index.mdx +8 -4
- package/docs/content/islands.mdx +1 -1
- package/docs/content/meta.mdx +7 -3
- package/docs/content/navigation.mdx +29 -4
- package/docs/content/sources.mdx +18 -16
- package/docs/content/syntax.mdx +14 -0
- package/docs/content/versioning.mdx +2 -1
- package/docs/discoverability/agent-discovery.mdx +22 -8
- package/docs/discoverability/index.mdx +4 -3
- package/docs/discoverability/llms-txt.mdx +2 -5
- package/docs/discoverability/markdown.mdx +6 -4
- package/docs/discoverability/mcp.mdx +4 -0
- package/docs/discoverability/metadata.mdx +3 -2
- package/docs/discoverability/open-graph.mdx +8 -4
- package/docs/discoverability/rss.mdx +4 -2
- package/docs/references/asyncapi.mdx +2 -2
- package/docs/references/graphql.mdx +2 -2
- package/docs/references/openapi.mdx +6 -4
- package/package.json +1 -1
- package/skills/blume-migrate/SKILL.md +6 -6
- package/skills/blume-migrate/references/docusaurus.md +6 -6
- package/skills/blume-migrate/references/fumadocs.md +1 -1
- package/skills/blume-migrate/references/mintlify.md +3 -3
- package/skills/blume-migrate/references/monorepo.md +1 -1
- package/skills/blume-migrate/references/nextra.md +2 -2
- package/skills/blume-migrate/references/starlight.md +5 -5
- package/skills/blume-migrate/scripts/mintlify-codemod.mjs +9 -4
- package/skills/blume-update-docs/references/audit-checklist.md +1 -1
- package/src/ai/agent-readability.ts +2 -2
- package/src/ai/agent-surface.ts +56 -0
- package/src/ai/ai-catalog.ts +6 -2
- package/src/ai/api/handlers.ts +2 -2
- package/src/ai/api/spec.ts +17 -4
- package/src/ai/api-catalog.ts +13 -3
- package/src/ai/ask-context.ts +14 -2
- package/src/ai/ask-data.ts +26 -12
- package/src/ai/changelog-markdown.ts +2 -2
- package/src/ai/component-markdown.ts +43 -37
- package/src/ai/link-headers.ts +22 -8
- package/src/ai/llms.ts +22 -10
- package/src/ai/markdown.ts +23 -11
- package/src/ai/mcp/discovery.ts +2 -2
- package/src/ai/mcp/query.ts +2 -2
- package/src/ai/mcp/server.ts +80 -9
- package/src/ai/openapi-components.ts +22 -6
- package/src/ai/relative-links.ts +99 -15
- package/src/ai/serializers.ts +2 -1
- package/src/ai/skills.ts +14 -1
- package/src/ai/static-expression.ts +416 -0
- package/src/ai/tar.ts +139 -12
- package/src/ai/visibility.ts +45 -14
- package/src/analytics/databuddy.ts +67 -0
- package/src/analytics/head.ts +8 -0
- package/src/analytics/index.ts +7 -0
- package/src/analytics/one-dollar-stats.ts +86 -0
- package/src/analytics/posthog.ts +21 -3
- package/src/analytics/schema.ts +4 -0
- package/src/astro/generate.ts +72 -28
- package/src/astro/include-hmr.ts +31 -12
- package/src/astro/include-refresh.ts +19 -8
- package/src/astro/integration.ts +108 -14
- package/src/astro/runtime-modules.ts +28 -13
- package/src/astro/templates.ts +139 -57
- package/src/audit/catalog.ts +2 -2
- package/src/audit/checks/assets.ts +25 -5
- package/src/audit/checks/content.ts +20 -2
- package/src/audit/checks/i18n.ts +46 -8
- package/src/audit/checks/indexability.ts +39 -19
- package/src/audit/checks/links.ts +22 -1
- package/src/audit/checks/llms.ts +6 -3
- package/src/audit/checks/network.ts +3 -1
- package/src/audit/checks/og-image.ts +10 -0
- package/src/audit/checks/robots.ts +6 -1
- package/src/audit/checks/sitemap.ts +56 -31
- package/src/audit/checks/social.ts +21 -2
- package/src/audit/crawl.ts +88 -15
- package/src/audit/graph.ts +3 -1
- package/src/audit/report.ts +54 -17
- package/src/audit/run.ts +13 -9
- package/src/audit/snapshot.ts +5 -0
- package/src/audit/types.ts +18 -0
- package/src/audit/url.ts +37 -6
- package/src/cli/args.ts +32 -0
- package/src/cli/build-failure.ts +50 -0
- package/src/cli/commands/audit.ts +11 -1
- package/src/cli/commands/build.ts +19 -5
- package/src/cli/commands/check.ts +2 -0
- package/src/cli/commands/doctor.ts +3 -1
- package/src/cli/commands/eval.ts +20 -18
- package/src/cli/commands/init.ts +15 -5
- package/src/cli/commands/preview.ts +15 -0
- package/src/cli/commands/sync.ts +2 -0
- package/src/cli/commands/translate.ts +18 -18
- package/src/cli/commands/upgrade.ts +11 -0
- package/src/cli/commands/validate.ts +3 -1
- package/src/cli/dev-lock.ts +157 -37
- package/src/cli/eject-scripts.ts +32 -7
- package/src/cli/env.ts +12 -1
- package/src/cli/init/scaffold.ts +117 -11
- package/src/cli/init/starter-spec.ts +235 -0
- package/src/cli/report-format.ts +11 -6
- package/src/components/colors.ts +19 -0
- package/src/components/content/AccordionItem.astro +26 -22
- package/src/components/content/Badge.astro +7 -12
- package/src/components/content/Card.astro +2 -2
- package/src/components/content/Component.astro +11 -5
- package/src/components/content/Expandable.astro +5 -1
- package/src/components/content/Frame.astro +2 -7
- package/src/components/content/GithubInfo.astro +12 -2
- package/src/components/content/Prompt.astro +2 -7
- package/src/components/content/Tab.astro +0 -1
- package/src/components/content/Tabs.astro +58 -5
- package/src/components/content/Tile.astro +1 -1
- package/src/components/content/Tooltip.astro +69 -7
- package/src/components/content/Tree.astro +7 -2
- package/src/components/content/TypeTable.astro +10 -5
- package/src/components/content/Update.astro +8 -2
- package/src/components/content/auto-type-table.ts +4 -1
- package/src/components/content/badge-color.ts +20 -0
- package/src/components/content/base-href.ts +14 -22
- package/src/components/content/inline-markdown.ts +27 -7
- package/src/components/copy-feedback.ts +35 -8
- package/src/components/islands/assistant.tsx +37 -6
- package/src/components/islands/base-path.ts +47 -10
- package/src/components/islands/hooks.ts +42 -21
- package/src/components/islands/webmcp.ts +16 -10
- package/src/components/layout/Banner.astro +23 -4
- package/src/components/layout/Breadcrumbs.astro +5 -2
- package/src/components/layout/DiscoveryLinks.astro +9 -5
- package/src/components/layout/Header.astro +23 -10
- package/src/components/layout/LanguageSwitcher.astro +2 -2
- package/src/components/layout/Logo.astro +5 -0
- package/src/components/layout/NavSelector.astro +8 -3
- package/src/components/layout/NavTabMenu.astro +133 -0
- package/src/components/layout/NavTree.astro +31 -12
- package/src/components/layout/NavTreeCache.astro +5 -2
- package/src/components/layout/NavTreeScript.astro +45 -5
- package/src/components/layout/PageActions.astro +4 -3
- package/src/components/layout/PageLayout.astro +28 -13
- package/src/components/layout/Pagination.astro +3 -3
- package/src/components/layout/ReferenceLayout.astro +4 -1
- package/src/components/layout/RootLayout.astro +25 -12
- package/src/components/layout/Search.astro +38 -14
- package/src/components/layout/VersionBanner.astro +2 -2
- package/src/components/layout/analytics-client.ts +14 -0
- package/src/components/layout/toc-active.ts +41 -0
- package/src/components/layout/toc-element.ts +8 -14
- package/src/components/openapi/ApiTagOperations.astro +2 -2
- package/src/components/openapi/AsyncApiOperation.astro +7 -4
- package/src/components/openapi/GraphqlChip.astro +2 -2
- package/src/components/openapi/GraphqlType.astro +11 -3
- package/src/components/openapi/MessageComposer.astro +1 -1
- package/src/components/openapi/Operation.astro +23 -5
- package/src/components/openapi/PanelTabs.astro +4 -1
- package/src/components/openapi/Playground.astro +8 -2
- package/src/components/openapi/RequestPanel.astro +13 -6
- package/src/components/openapi/SchemaProperty.astro +11 -33
- package/src/components/openapi/SchemaTable.astro +34 -52
- package/src/components/openapi/async.ts +38 -6
- package/src/components/openapi/helpers.ts +100 -12
- package/src/components/openapi/message-composer.ts +14 -1
- package/src/components/openapi/message-model.ts +12 -2
- package/src/components/openapi/message.ts +21 -3
- package/src/components/openapi/operation-model.ts +119 -17
- package/src/components/openapi/panel.ts +31 -5
- package/src/components/openapi/param-style.ts +181 -0
- package/src/components/openapi/playground-client.ts +110 -23
- package/src/components/openapi/playground-schema.ts +25 -6
- package/src/components/openapi/request.ts +192 -26
- package/src/components/openapi/schema-tree.ts +209 -0
- package/src/components/openapi/snippets.ts +113 -19
- package/src/components/openapi/validate-json.ts +1 -1
- package/src/components/openapi/ws-client.ts +18 -2
- package/src/core/base-path.ts +69 -8
- package/src/core/config-input.ts +13 -11
- package/src/core/config.ts +18 -4
- package/src/core/diagnostics.ts +219 -30
- package/src/core/directive-diagnostics.ts +99 -0
- package/src/core/frontmatter.ts +21 -18
- package/src/core/graph.ts +120 -11
- package/src/core/heading-markers.ts +5 -18
- package/src/core/i18n-ui.ts +39 -2
- package/src/core/i18n.ts +44 -5
- package/src/core/last-modified.ts +25 -3
- package/src/core/links.ts +7 -4
- package/src/core/load-module.ts +20 -0
- package/src/core/locale-links.ts +22 -18
- package/src/core/manifest.ts +3 -2
- package/src/core/meta.ts +89 -12
- package/src/core/nav-diagnostics.ts +56 -1
- package/src/core/navigation.ts +272 -83
- package/src/core/ordering-prefix.ts +27 -0
- package/src/core/project-graph.ts +50 -6
- package/src/core/safe-href.ts +53 -1
- package/src/core/safe-links.ts +11 -2
- package/src/core/schema.ts +94 -18
- package/src/core/sources/assets.ts +83 -41
- package/src/core/sources/contentful-rich-text.ts +28 -20
- package/src/core/sources/contentful.ts +25 -12
- package/src/core/sources/filesystem.ts +25 -3
- package/src/core/sources/github-releases.ts +131 -11
- package/src/core/sources/lexical.ts +30 -20
- package/src/core/sources/lower.ts +276 -56
- package/src/core/sources/mdx-remote.ts +52 -16
- package/src/core/sources/normalize.ts +456 -119
- package/src/core/sources/notion.ts +77 -34
- package/src/core/sources/obsidian.ts +40 -9
- package/src/core/sources/payload.ts +1 -0
- package/src/core/sources/portable-text.ts +85 -49
- package/src/core/sources/remote.ts +18 -2
- package/src/core/sources/resolve.ts +52 -33
- package/src/core/sources/sanity.ts +1 -0
- package/src/core/sources/strapi-blocks.ts +28 -19
- package/src/core/sources/strapi.ts +1 -0
- package/src/core/sources/types.ts +31 -0
- package/src/core/sources/watch.ts +20 -7
- package/src/core/standard-schema.ts +10 -6
- package/src/core/types.ts +9 -0
- package/src/core/ui-packs/ar.ts +13 -0
- package/src/core/ui-packs/bg.ts +13 -0
- package/src/core/ui-packs/bn.ts +13 -0
- package/src/core/ui-packs/ca.ts +13 -0
- package/src/core/ui-packs/cs.ts +13 -0
- package/src/core/ui-packs/da.ts +13 -0
- package/src/core/ui-packs/de.ts +13 -0
- package/src/core/ui-packs/el.ts +13 -0
- package/src/core/ui-packs/es.ts +13 -0
- package/src/core/ui-packs/fa.ts +13 -0
- package/src/core/ui-packs/fi.ts +13 -0
- package/src/core/ui-packs/fr.ts +13 -0
- package/src/core/ui-packs/he.ts +13 -0
- package/src/core/ui-packs/hi.ts +13 -0
- package/src/core/ui-packs/hr.ts +13 -0
- package/src/core/ui-packs/hu.ts +13 -0
- package/src/core/ui-packs/id.ts +13 -0
- package/src/core/ui-packs/it.ts +13 -0
- package/src/core/ui-packs/ja.ts +13 -0
- package/src/core/ui-packs/ko.ts +13 -0
- package/src/core/ui-packs/nl.ts +13 -0
- package/src/core/ui-packs/no.ts +13 -0
- package/src/core/ui-packs/pl.ts +13 -0
- package/src/core/ui-packs/pt-br.ts +13 -0
- package/src/core/ui-packs/pt.ts +13 -0
- package/src/core/ui-packs/ro.ts +13 -0
- package/src/core/ui-packs/ru.ts +13 -0
- package/src/core/ui-packs/sk.ts +13 -0
- package/src/core/ui-packs/sr.ts +13 -0
- package/src/core/ui-packs/sv.ts +13 -0
- package/src/core/ui-packs/th.ts +13 -0
- package/src/core/ui-packs/tr.ts +13 -0
- package/src/core/ui-packs/uk.ts +13 -0
- package/src/core/ui-packs/vi.ts +13 -0
- package/src/core/ui-packs/zh-tw.ts +13 -0
- package/src/core/ui-packs/zh.ts +13 -0
- package/src/core/version-cut.ts +69 -17
- package/src/core/versions.ts +4 -1
- package/src/deploy/adapters/node.ts +5 -2
- package/src/deploy/adapters/registry.ts +2 -1
- package/src/deploy/adapters/types.ts +13 -1
- package/src/deploy/artifacts.ts +52 -11
- package/src/deploy/cloudflare-negotiation.ts +27 -16
- package/src/deploy/headers.ts +75 -55
- package/src/deploy/node-headers.ts +148 -27
- package/src/deploy/platforms/cloudflare.ts +13 -3
- package/src/deploy/platforms/netlify.ts +83 -5
- package/src/deploy/platforms/node.ts +8 -5
- package/src/deploy/platforms/static.ts +2 -0
- package/src/deploy/platforms/types.ts +15 -0
- package/src/deploy/platforms/vercel.ts +10 -3
- package/src/deploy/redirects.ts +68 -21
- package/src/deploy/robots.ts +2 -2
- package/src/deploy/rss.ts +4 -3
- package/src/deploy/sitemap.ts +7 -5
- package/src/deploy/vercel-negotiation.ts +35 -3
- package/src/eval/agents.ts +10 -2
- package/src/eval/run.ts +25 -0
- package/src/markdown/base-links.ts +74 -29
- package/src/markdown/directives.ts +242 -36
- package/src/markdown/features.ts +17 -0
- package/src/markdown/index.ts +13 -9
- package/src/markdown/mdast.ts +5 -2
- package/src/markdown/relative-links.ts +15 -27
- package/src/markdown/route-snapshot.ts +37 -0
- package/src/og/card.ts +149 -9
- package/src/og/derive.ts +156 -5
- package/src/og/index.ts +1 -0
- package/src/openapi/asyncapi.ts +4 -2
- package/src/openapi/graphql-build.ts +28 -2
- package/src/openapi/model.ts +99 -27
- package/src/openapi/proxy.ts +63 -10
- package/src/openapi/render-mdx.ts +51 -3
- package/src/registry/eject.ts +297 -43
- package/src/search/adapters/version-scope.ts +30 -0
- package/src/search/documents.ts +89 -27
- package/src/search/popular.ts +2 -1
- package/src/search/sync/algolia.ts +36 -2
- package/src/seo/jsonld.ts +7 -3
- package/src/sources/registry.ts +5 -0
- package/src/theme/entry.ts +11 -4
- package/src/translate/agents.ts +6 -1
- package/src/translate/ledger.ts +26 -3
- package/src/translate/meta.ts +76 -24
- package/src/translate/run.ts +14 -8
- package/src/translate/validate.ts +14 -2
- package/src/translate/work-list.ts +91 -19
- package/src/upgrade/upgrade.ts +36 -4
- package/dist/cli/chunk-27g6wdth.js.map +0 -10
- package/dist/cli/chunk-2hn4b8z7.js.map +0 -12
- package/dist/cli/chunk-6crbhc3x.js.map +0 -14
- package/dist/cli/chunk-6hsn950k.js.map +0 -10
- package/dist/cli/chunk-79jhk4py.js.map +0 -35
- package/dist/cli/chunk-82bbrxdn.js +0 -51
- package/dist/cli/chunk-82bbrxdn.js.map +0 -10
- package/dist/cli/chunk-abh8yjkn.js +0 -31
- package/dist/cli/chunk-abh8yjkn.js.map +0 -10
- package/dist/cli/chunk-ce574jw2.js +0 -23
- package/dist/cli/chunk-ce574jw2.js.map +0 -10
- package/dist/cli/chunk-dh8cwk36.js.map +0 -10
- package/dist/cli/chunk-epjnccmv.js.map +0 -10
- package/dist/cli/chunk-fa25z98p.js.map +0 -11
- package/dist/cli/chunk-fs23ddbb.js.map +0 -35
- package/dist/cli/chunk-fz5wtpmh.js.map +0 -10
- package/dist/cli/chunk-jwyddg7y.js.map +0 -15
- package/dist/cli/chunk-kpf8rrjc.js.map +0 -19
- package/dist/cli/chunk-m3vmjgmq.js.map +0 -10
- package/dist/cli/chunk-mb2919y2.js.map +0 -10
- package/dist/cli/chunk-q5163e60.js.map +0 -11
- package/dist/cli/chunk-qkqwkpte.js.map +0 -182
- package/dist/cli/chunk-qs4q5p4e.js.map +0 -10
- package/dist/cli/chunk-s1p84fyh.js.map +0 -10
- package/dist/cli/chunk-wgm7m9qk.js.map +0 -36
- package/dist/cli/chunk-yt5n7ppj.js.map +0 -10
- package/dist/cli/chunk-yw7dm696.js.map +0 -14
- /package/dist/cli/{chunk-s6jhgk0q.js.map → chunk-2eytanqx.js.map} +0 -0
- /package/dist/cli/{chunk-hdpx1tax.js.map → chunk-2z928egk.js.map} +0 -0
- /package/dist/cli/{chunk-ah61y8py.js.map → chunk-364znk6q.js.map} +0 -0
- /package/dist/cli/{chunk-vtk4a6dg.js.map → chunk-8ktnccpt.js.map} +0 -0
- /package/dist/cli/{chunk-fxypxtvm.js.map → chunk-a58773jm.js.map} +0 -0
- /package/dist/cli/{chunk-wm7js3j9.js.map → chunk-b07cmahc.js.map} +0 -0
- /package/dist/cli/{chunk-zxcczpyx.js.map → chunk-r20tn01b.js.map} +0 -0
- /package/dist/cli/{chunk-5shv93fd.js.map → chunk-tkacnehg.js.map} +0 -0
- /package/dist/cli/{chunk-zxh4d9vy.js.map → chunk-tzmab476.js.map} +0 -0
package/src/ai/tar.ts
CHANGED
|
@@ -22,42 +22,169 @@ export interface TarEntry {
|
|
|
22
22
|
path: string;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
/** ustar `name` field capacity
|
|
25
|
+
/** ustar `name` field capacity. */
|
|
26
26
|
const NAME_MAX = 100;
|
|
27
|
+
/** ustar `prefix` field capacity; `prefix/name` reaches 255 bytes. */
|
|
28
|
+
const PREFIX_MAX = 155;
|
|
29
|
+
|
|
30
|
+
/** ustar header byte offsets nanotar leaves for us to patch. */
|
|
31
|
+
const CHECKSUM_OFFSET = 148;
|
|
32
|
+
const CHECKSUM_SIZE = 8;
|
|
33
|
+
const TYPEFLAG_OFFSET = 156;
|
|
34
|
+
const PREFIX_OFFSET = 345;
|
|
35
|
+
const BLOCK_SIZE = 512;
|
|
36
|
+
|
|
37
|
+
/** The two zero blocks that mark the end of an archive. */
|
|
38
|
+
const END_OF_ARCHIVE = 2 * BLOCK_SIZE;
|
|
39
|
+
/** tar's default record size (20 blocks), which the archive is padded to. */
|
|
40
|
+
const RECORD_SIZE = 20 * BLOCK_SIZE;
|
|
41
|
+
|
|
42
|
+
/** The PAX extended-header typeflag (`x`). */
|
|
43
|
+
const PAX_TYPEFLAG = 0x78;
|
|
27
44
|
|
|
28
45
|
const encoder = new TextEncoder();
|
|
29
46
|
|
|
47
|
+
const byteLength = (value: string): number => encoder.encode(value).byteLength;
|
|
48
|
+
|
|
49
|
+
/** `value` cut to at most `max` UTF-8 bytes, on a character boundary. */
|
|
50
|
+
const truncateBytes = (value: string, max: number): string =>
|
|
51
|
+
value.slice(0, encoder.encodeInto(value, new Uint8Array(max)).read);
|
|
52
|
+
|
|
53
|
+
/** One header nanotar writes, plus the fields it cannot. */
|
|
54
|
+
interface Block {
|
|
55
|
+
content: Uint8Array;
|
|
56
|
+
mode: string;
|
|
57
|
+
name: string;
|
|
58
|
+
/** The PAX extended header ahead of an over-long path. */
|
|
59
|
+
pax?: boolean;
|
|
60
|
+
/** ustar `prefix`, joined to `name` with a `/` by readers. */
|
|
61
|
+
prefix?: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Split a path over the `name` field at a `/` so the head fits `prefix` and
|
|
66
|
+
* the tail fits `name`. The longest head that fits leaves the shortest tail,
|
|
67
|
+
* so if that tail is still too long no split works.
|
|
68
|
+
*/
|
|
69
|
+
const splitUstar = (
|
|
70
|
+
path: string
|
|
71
|
+
): { name: string; prefix: string } | undefined => {
|
|
72
|
+
let slash = path.lastIndexOf("/");
|
|
73
|
+
while (slash > 0 && byteLength(path.slice(0, slash)) > PREFIX_MAX) {
|
|
74
|
+
slash = path.lastIndexOf("/", slash - 1);
|
|
75
|
+
}
|
|
76
|
+
const name = path.slice(slash + 1);
|
|
77
|
+
if (slash <= 0 || byteLength(name) > NAME_MAX) {
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
return { name, prefix: path.slice(0, slash) };
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* A PAX `path` record: `"<length> path=<value>\n"`, where the decimal length
|
|
85
|
+
* counts the whole record including its own digits.
|
|
86
|
+
*/
|
|
87
|
+
const paxPathRecord = (path: string): Uint8Array => {
|
|
88
|
+
const body = ` path=${path}\n`;
|
|
89
|
+
const size = byteLength(body);
|
|
90
|
+
const length = size + String(size + String(size).length).length;
|
|
91
|
+
return encoder.encode(`${length}${body}`);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* The header blocks for one entry. A path that fits `name` is written as is;
|
|
96
|
+
* up to 255 bytes it splits across `prefix` and `name`; beyond that (or with
|
|
97
|
+
* no usable split) a PAX extended header carries the full path and the ustar
|
|
98
|
+
* `name` holds a truncated fallback for readers that ignore PAX.
|
|
99
|
+
*/
|
|
100
|
+
const entryBlocks = (entry: TarEntry): Block[] => {
|
|
101
|
+
const mode = entry.executable ? "755" : "644";
|
|
102
|
+
const file = { content: entry.content, mode };
|
|
103
|
+
if (byteLength(entry.path) <= NAME_MAX) {
|
|
104
|
+
return [{ ...file, name: entry.path }];
|
|
105
|
+
}
|
|
106
|
+
const split = splitUstar(entry.path);
|
|
107
|
+
if (split) {
|
|
108
|
+
return [{ ...file, ...split }];
|
|
109
|
+
}
|
|
110
|
+
const base = entry.path.slice(entry.path.lastIndexOf("/") + 1);
|
|
111
|
+
return [
|
|
112
|
+
{
|
|
113
|
+
content: paxPathRecord(entry.path),
|
|
114
|
+
mode: "644",
|
|
115
|
+
name: truncateBytes(`PaxHeader/${base}`, NAME_MAX),
|
|
116
|
+
pax: true,
|
|
117
|
+
},
|
|
118
|
+
{ ...file, name: truncateBytes(base, NAME_MAX) },
|
|
119
|
+
];
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
/** Recompute a patched header's checksum (nanotar's octal format). */
|
|
123
|
+
const writeChecksum = (header: Uint8Array): void => {
|
|
124
|
+
header.fill(0x20, CHECKSUM_OFFSET, CHECKSUM_OFFSET + CHECKSUM_SIZE);
|
|
125
|
+
const sum = header.reduce((total, byte) => total + byte, 0);
|
|
126
|
+
header.fill(0, CHECKSUM_OFFSET, CHECKSUM_OFFSET + CHECKSUM_SIZE);
|
|
127
|
+
encoder.encodeInto(
|
|
128
|
+
sum.toString(8),
|
|
129
|
+
header.subarray(CHECKSUM_OFFSET, CHECKSUM_OFFSET + CHECKSUM_SIZE)
|
|
130
|
+
);
|
|
131
|
+
};
|
|
132
|
+
|
|
30
133
|
/**
|
|
31
134
|
* Build a gzipped ustar archive of the given files, in the given order. Paths
|
|
32
|
-
*
|
|
33
|
-
* surface a programming error — nanotar would silently truncate an oversized
|
|
34
|
-
* name into a corrupt archive, so the validation stays here.
|
|
135
|
+
* escaping the archive root throw to surface a programming error.
|
|
35
136
|
*/
|
|
36
137
|
export const buildTarGz = (entries: readonly TarEntry[]): Uint8Array => {
|
|
37
138
|
for (const entry of entries) {
|
|
38
|
-
if (encoder.encode(entry.path).byteLength > NAME_MAX) {
|
|
39
|
-
throw new Error(`tar path exceeds ${NAME_MAX} bytes: ${entry.path}`);
|
|
40
|
-
}
|
|
41
139
|
if (entry.path.startsWith("/") || entry.path.split("/").includes("..")) {
|
|
42
140
|
throw new Error(`tar path must be archive-relative: ${entry.path}`);
|
|
43
141
|
}
|
|
44
142
|
}
|
|
143
|
+
const blocks = entries.flatMap(entryBlocks);
|
|
45
144
|
const tar = createTar(
|
|
46
|
-
|
|
145
|
+
blocks.map((block) => ({
|
|
47
146
|
// Root-owned, epoch-mtime, empty owner names: every field a rebuild
|
|
48
147
|
// could vary is pinned so the archive bytes are a function of content.
|
|
49
148
|
attrs: {
|
|
50
149
|
gid: 0,
|
|
51
150
|
group: "",
|
|
52
|
-
mode:
|
|
151
|
+
mode: block.mode,
|
|
53
152
|
mtime: 0,
|
|
54
153
|
uid: 0,
|
|
55
154
|
user: "",
|
|
56
155
|
},
|
|
57
|
-
data:
|
|
58
|
-
name:
|
|
156
|
+
data: block.content,
|
|
157
|
+
name: block.name,
|
|
59
158
|
}))
|
|
60
159
|
);
|
|
160
|
+
// nanotar writes neither `prefix` nor the PAX typeflag, so patch those
|
|
161
|
+
// headers in place and re-sum them.
|
|
162
|
+
let offset = 0;
|
|
163
|
+
for (const block of blocks) {
|
|
164
|
+
const header = tar.subarray(offset, offset + BLOCK_SIZE);
|
|
165
|
+
if (block.prefix) {
|
|
166
|
+
encoder.encodeInto(
|
|
167
|
+
block.prefix,
|
|
168
|
+
header.subarray(PREFIX_OFFSET, PREFIX_OFFSET + PREFIX_MAX)
|
|
169
|
+
);
|
|
170
|
+
writeChecksum(header);
|
|
171
|
+
}
|
|
172
|
+
if (block.pax) {
|
|
173
|
+
header[TYPEFLAG_OFFSET] = PAX_TYPEFLAG;
|
|
174
|
+
writeChecksum(header);
|
|
175
|
+
}
|
|
176
|
+
offset +=
|
|
177
|
+
BLOCK_SIZE * (1 + Math.ceil(block.content.byteLength / BLOCK_SIZE));
|
|
178
|
+
}
|
|
179
|
+
// nanotar pads the entries to a whole record but writes no end-of-archive
|
|
180
|
+
// marker, so entries ending within two blocks of a record boundary leave
|
|
181
|
+
// fewer than the two zero blocks readers expect (GNU tar warns "A lone zero
|
|
182
|
+
// block"). Pad to the first record that fits both; for every other archive
|
|
183
|
+
// that is the size nanotar already wrote, so its bytes are unchanged.
|
|
184
|
+
const archive = new Uint8Array(
|
|
185
|
+
Math.ceil((offset + END_OF_ARCHIVE) / RECORD_SIZE) * RECORD_SIZE
|
|
186
|
+
);
|
|
187
|
+
archive.set(tar.subarray(0, offset));
|
|
61
188
|
// Sync gzip with a pinned level; Node writes no timestamp into the header.
|
|
62
|
-
return new Uint8Array(gzipSync(
|
|
189
|
+
return new Uint8Array(gzipSync(archive, { level: 9 }));
|
|
63
190
|
};
|
package/src/ai/visibility.ts
CHANGED
|
@@ -1,10 +1,44 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { nextFenceState } from "../core/code-fences.ts";
|
|
2
|
+
import type { FenceState } from "../core/code-fences.ts";
|
|
3
|
+
|
|
4
|
+
/** An inline code span on one line, as the other source scanners read it. */
|
|
5
|
+
const INLINE_CODE = /`[^`\n]*`/gu;
|
|
5
6
|
// NUL delimiters cannot appear in authored markdown, so tokens never collide.
|
|
6
7
|
// oxlint-disable-next-line no-control-regex -- the NUL is the collision guard.
|
|
7
|
-
const
|
|
8
|
+
const CODE_TOKEN = /\u0000blume-code-(?<index>\d+)\u0000/gu;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Swap every code sample for a one-line token — fenced blocks at any indent
|
|
12
|
+
* (a fence inside a `<Tab>` or `<Step>` is indented under it) and inline code
|
|
13
|
+
* spans — so markup that *shows* `<Visibility>` keeps showing what the author
|
|
14
|
+
* wrote. An unclosed fence runs to the end, as CommonMark reads it.
|
|
15
|
+
*/
|
|
16
|
+
const maskCode = (markdown: string, stash: string[]): string => {
|
|
17
|
+
const token = (code: string): string => {
|
|
18
|
+
stash.push(code);
|
|
19
|
+
return `\u0000blume-code-${stash.length - 1}\u0000`;
|
|
20
|
+
};
|
|
21
|
+
const lines: string[] = [];
|
|
22
|
+
let fence: FenceState = null;
|
|
23
|
+
let block: string[] = [];
|
|
24
|
+
for (const line of markdown.split("\n")) {
|
|
25
|
+
const next = nextFenceState(line, fence);
|
|
26
|
+
if (fence === null && next === null) {
|
|
27
|
+
lines.push(line.replaceAll(INLINE_CODE, token));
|
|
28
|
+
} else {
|
|
29
|
+
block.push(line);
|
|
30
|
+
if (next === null) {
|
|
31
|
+
lines.push(token(block.join("\n")));
|
|
32
|
+
block = [];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
fence = next;
|
|
36
|
+
}
|
|
37
|
+
if (block.length > 0) {
|
|
38
|
+
lines.push(token(block.join("\n")));
|
|
39
|
+
}
|
|
40
|
+
return lines.join("\n");
|
|
41
|
+
};
|
|
8
42
|
|
|
9
43
|
/** The audience an output surface serves — the component's two `for` values. */
|
|
10
44
|
export type VisibilityAudience = "agents" | "web";
|
|
@@ -36,12 +70,9 @@ export const applyAudienceVisibility = (
|
|
|
36
70
|
markdown: string,
|
|
37
71
|
audience: VisibilityAudience
|
|
38
72
|
): string => {
|
|
39
|
-
// Mask
|
|
40
|
-
const
|
|
41
|
-
const masked = markdown
|
|
42
|
-
fences.push(block);
|
|
43
|
-
return `\u0000blume-fence-${fences.length - 1}\u0000`;
|
|
44
|
-
});
|
|
73
|
+
// Mask code so documentation *about* Visibility survives.
|
|
74
|
+
const code: string[] = [];
|
|
75
|
+
const masked = maskCode(markdown, code);
|
|
45
76
|
|
|
46
77
|
let touched = false;
|
|
47
78
|
const filtered = masked
|
|
@@ -56,12 +87,12 @@ export const applyAudienceVisibility = (
|
|
|
56
87
|
|
|
57
88
|
// Removing/unwrapping block-level tags leaves runs of blank lines behind;
|
|
58
89
|
// collapse them only when something matched so untouched files round-trip
|
|
59
|
-
// exactly.
|
|
90
|
+
// exactly. Code is masked as single-line tokens, so it is unaffected.
|
|
60
91
|
const tidied = touched ? filtered.replaceAll(/\n{3,}/gu, "\n\n") : filtered;
|
|
61
92
|
|
|
62
93
|
return tidied.replaceAll(
|
|
63
|
-
|
|
64
|
-
(token, index) =>
|
|
94
|
+
CODE_TOKEN,
|
|
95
|
+
(token, index) => code[Number(index)] ?? token
|
|
65
96
|
);
|
|
66
97
|
};
|
|
67
98
|
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
import type { AdapterDescriptor } from "../core/adapter.ts";
|
|
4
|
+
import { adapterDescriptorSchema } from "../core/adapter.ts";
|
|
5
|
+
import type { HeadScript } from "./head.ts";
|
|
6
|
+
|
|
7
|
+
/** The script Databuddy's install snippet loads. */
|
|
8
|
+
export const DATABUDDY_SCRIPT_SRC = "https://cdn.databuddy.cc/databuddy.js";
|
|
9
|
+
|
|
10
|
+
/** The options {@link databuddy} maps itself. */
|
|
11
|
+
export interface DatabuddyNamedOptions {
|
|
12
|
+
/** Client ID, from the website's settings in the Databuddy dashboard. */
|
|
13
|
+
clientId: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Options for {@link databuddy}: the client ID plus any other tracker setting,
|
|
18
|
+
* forwarded as a `data-` attribute on the tag (`"track-web-vitals"` →
|
|
19
|
+
* `data-track-web-vitals`, `"track-errors"`, `"track-outgoing-links"`,
|
|
20
|
+
* `"api-url"`, …).
|
|
21
|
+
*/
|
|
22
|
+
export type DatabuddyOptions = DatabuddyNamedOptions & {
|
|
23
|
+
[setting: string]: string;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const databuddyOptionsSchema = z
|
|
27
|
+
.object({
|
|
28
|
+
clientId: z.string().min(1),
|
|
29
|
+
})
|
|
30
|
+
.catchall(z.string());
|
|
31
|
+
|
|
32
|
+
export type DatabuddyAdapter = AdapterDescriptor<"databuddy", DatabuddyOptions>;
|
|
33
|
+
|
|
34
|
+
export const databuddyAdapterSchema = adapterDescriptorSchema(
|
|
35
|
+
"databuddy",
|
|
36
|
+
databuddyOptionsSchema
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Databuddy. The client ID is public — it's in the tag on every page.
|
|
41
|
+
*/
|
|
42
|
+
export const databuddy = (options: DatabuddyOptions): DatabuddyAdapter => ({
|
|
43
|
+
kind: "databuddy",
|
|
44
|
+
options,
|
|
45
|
+
requiredSecrets: [],
|
|
46
|
+
runtimeDeps: [],
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* The async tag from the install instructions, with `clientId` as
|
|
51
|
+
* `data-client-id` and every other option as its own `data-` attribute. The
|
|
52
|
+
* tracker skips setup when `window.databuddy` already exists, so there is no
|
|
53
|
+
* queue stub. Databuddy's script tracks history changes on its own, so
|
|
54
|
+
* client-router navigations need no extra hook.
|
|
55
|
+
*/
|
|
56
|
+
export const databuddyHead = (options: DatabuddyOptions): HeadScript[] => {
|
|
57
|
+
const { clientId, ...settings } = options;
|
|
58
|
+
const attributes: HeadScript["attributes"] = {};
|
|
59
|
+
for (const [setting, value] of Object.entries(settings)) {
|
|
60
|
+
attributes[`data-${setting}`] = value;
|
|
61
|
+
}
|
|
62
|
+
attributes["data-client-id"] = clientId;
|
|
63
|
+
attributes.async = true;
|
|
64
|
+
attributes.crossorigin = "anonymous";
|
|
65
|
+
attributes.src = DATABUDDY_SCRIPT_SRC;
|
|
66
|
+
return [{ attributes, content: null }];
|
|
67
|
+
};
|
package/src/analytics/head.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { amplitudeHead } from "./amplitude.ts";
|
|
|
3
3
|
import { clarityHead } from "./clarity.ts";
|
|
4
4
|
import { clearbitHead } from "./clearbit.ts";
|
|
5
5
|
import { cloudflareHead } from "./cloudflare.ts";
|
|
6
|
+
import { databuddyHead } from "./databuddy.ts";
|
|
6
7
|
import { fathomHead } from "./fathom.ts";
|
|
7
8
|
import { googleAnalyticsHead } from "./google-analytics.ts";
|
|
8
9
|
import { googleTagManagerHead } from "./google-tag-manager.ts";
|
|
@@ -11,6 +12,7 @@ import { hightouchHead } from "./hightouch.ts";
|
|
|
11
12
|
import { hotjarHead } from "./hotjar.ts";
|
|
12
13
|
import { logrocketHead } from "./logrocket.ts";
|
|
13
14
|
import { mixpanelHead } from "./mixpanel.ts";
|
|
15
|
+
import { oneDollarStatsHead } from "./one-dollar-stats.ts";
|
|
14
16
|
import { pirschHead } from "./pirsch.ts";
|
|
15
17
|
import { plausibleHead } from "./plausible.ts";
|
|
16
18
|
import { posthogHead } from "./posthog.ts";
|
|
@@ -64,6 +66,9 @@ const adapterScripts = (
|
|
|
64
66
|
case "cloudflare": {
|
|
65
67
|
return cloudflareHead(adapter.options);
|
|
66
68
|
}
|
|
69
|
+
case "databuddy": {
|
|
70
|
+
return databuddyHead(adapter.options);
|
|
71
|
+
}
|
|
67
72
|
case "fathom": {
|
|
68
73
|
return fathomHead(adapter.options);
|
|
69
74
|
}
|
|
@@ -88,6 +93,9 @@ const adapterScripts = (
|
|
|
88
93
|
case "mixpanel": {
|
|
89
94
|
return mixpanelHead(adapter.options);
|
|
90
95
|
}
|
|
96
|
+
case "one-dollar-stats": {
|
|
97
|
+
return oneDollarStatsHead(adapter.options);
|
|
98
|
+
}
|
|
91
99
|
case "pirsch": {
|
|
92
100
|
return pirschHead(adapter.options);
|
|
93
101
|
}
|
package/src/analytics/index.ts
CHANGED
|
@@ -30,6 +30,8 @@ export { clearbit } from "./clearbit.ts";
|
|
|
30
30
|
export type { ClearbitAdapter, ClearbitOptions } from "./clearbit.ts";
|
|
31
31
|
export { cloudflare } from "./cloudflare.ts";
|
|
32
32
|
export type { CloudflareAdapter, CloudflareOptions } from "./cloudflare.ts";
|
|
33
|
+
export { databuddy } from "./databuddy.ts";
|
|
34
|
+
export type { DatabuddyAdapter, DatabuddyOptions } from "./databuddy.ts";
|
|
33
35
|
export { fathom } from "./fathom.ts";
|
|
34
36
|
export type { FathomAdapter, FathomOptions } from "./fathom.ts";
|
|
35
37
|
export { googleAnalytics } from "./google-analytics.ts";
|
|
@@ -56,6 +58,11 @@ export type {
|
|
|
56
58
|
MixpanelOptions,
|
|
57
59
|
MixpanelRegion,
|
|
58
60
|
} from "./mixpanel.ts";
|
|
61
|
+
export { oneDollarStats } from "./one-dollar-stats.ts";
|
|
62
|
+
export type {
|
|
63
|
+
OneDollarStatsAdapter,
|
|
64
|
+
OneDollarStatsOptions,
|
|
65
|
+
} from "./one-dollar-stats.ts";
|
|
59
66
|
export { pirsch } from "./pirsch.ts";
|
|
60
67
|
export type { PirschAdapter, PirschOptions } from "./pirsch.ts";
|
|
61
68
|
export { plausible } from "./plausible.ts";
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
import type { AdapterDescriptor } from "../core/adapter.ts";
|
|
4
|
+
import { adapterDescriptorSchema } from "../core/adapter.ts";
|
|
5
|
+
import type { HeadScript } from "./head.ts";
|
|
6
|
+
|
|
7
|
+
/** The script OneDollarStats' install snippet loads. */
|
|
8
|
+
export const ONE_DOLLAR_STATS_SCRIPT_SRC =
|
|
9
|
+
"https://assets.onedollarstats.com/stonks.js";
|
|
10
|
+
|
|
11
|
+
/** The options {@link oneDollarStats} checks itself. */
|
|
12
|
+
export interface OneDollarStatsNamedOptions {
|
|
13
|
+
/**
|
|
14
|
+
* A bare host name, e.g. `docs.example.com`. The tracker reports every
|
|
15
|
+
* event under it on every host, not just `localhost`.
|
|
16
|
+
*/
|
|
17
|
+
hostname?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Options for {@link oneDollarStats}: any tracker setting, forwarded as a
|
|
22
|
+
* `data-` attribute on the tag (`hostname` → `data-hostname`, `devmode`,
|
|
23
|
+
* `url`, `autocollect`, `"hash-routing"`, …).
|
|
24
|
+
*/
|
|
25
|
+
export type OneDollarStatsOptions = OneDollarStatsNamedOptions & {
|
|
26
|
+
[setting: string]: string;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const oneDollarStatsOptionsSchema = z
|
|
30
|
+
.object({
|
|
31
|
+
hostname: z
|
|
32
|
+
.string()
|
|
33
|
+
.regex(/^[\p{L}\p{N}-]+(?:\.[\p{L}\p{N}-]+)*(?::\d+)?$/u, {
|
|
34
|
+
message:
|
|
35
|
+
"`hostname` must be a bare host name like `docs.example.com`, without `https://`, a path, a query, or a fragment.",
|
|
36
|
+
})
|
|
37
|
+
.optional(),
|
|
38
|
+
})
|
|
39
|
+
.catchall(z.string());
|
|
40
|
+
|
|
41
|
+
export type OneDollarStatsAdapter = AdapterDescriptor<
|
|
42
|
+
"one-dollar-stats",
|
|
43
|
+
OneDollarStatsOptions
|
|
44
|
+
>;
|
|
45
|
+
|
|
46
|
+
export const oneDollarStatsAdapterSchema = adapterDescriptorSchema(
|
|
47
|
+
"one-dollar-stats",
|
|
48
|
+
oneDollarStatsOptionsSchema
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* OneDollarStats. Needs no keys — the dashboard matches events to a site by
|
|
53
|
+
* the domain they come from.
|
|
54
|
+
*/
|
|
55
|
+
export const oneDollarStats = (
|
|
56
|
+
options: OneDollarStatsOptions = {}
|
|
57
|
+
): OneDollarStatsAdapter => ({
|
|
58
|
+
kind: "one-dollar-stats",
|
|
59
|
+
options,
|
|
60
|
+
requiredSecrets: [],
|
|
61
|
+
runtimeDeps: [],
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* The deferred tag from the install instructions, with every option as its
|
|
66
|
+
* own `data-` attribute. The tracker reads them from `document.currentScript`,
|
|
67
|
+
* so the tag stays a classic external script. It hooks `pushState` and
|
|
68
|
+
* `popstate` itself, so client-router navigations need no extra hook.
|
|
69
|
+
*
|
|
70
|
+
* The tracker turns hash routing on whenever `data-hash-routing` is present,
|
|
71
|
+
* whatever its value, so `"hash-routing": "false"` leaves the attribute off.
|
|
72
|
+
*/
|
|
73
|
+
export const oneDollarStatsHead = (
|
|
74
|
+
options: OneDollarStatsOptions
|
|
75
|
+
): HeadScript[] => {
|
|
76
|
+
const attributes: HeadScript["attributes"] = {};
|
|
77
|
+
for (const [setting, value] of Object.entries(options)) {
|
|
78
|
+
if (setting === "hash-routing" && value === "false") {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
attributes[`data-${setting}`] = value;
|
|
82
|
+
}
|
|
83
|
+
attributes.defer = true;
|
|
84
|
+
attributes.src = ONE_DOLLAR_STATS_SCRIPT_SRC;
|
|
85
|
+
return [{ attributes, content: null }];
|
|
86
|
+
};
|
package/src/analytics/posthog.ts
CHANGED
|
@@ -54,13 +54,30 @@ export const posthog = (options: PosthogOptions): PosthogAdapter => ({
|
|
|
54
54
|
const POSTHOG_LOADER =
|
|
55
55
|
'!function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.crossOrigin="anonymous",p.async=!0,p.src=s.api_host.replace(".i.posthog.com","-assets.i.posthog.com")+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="init capture register register_once register_for_session unregister unregister_for_session getFeatureFlag getFeatureFlagPayload isFeatureEnabled reloadFeatureFlags updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures on onFeatureFlags onSessionId getSurveys getActiveMatchingSurveys renderSurvey canRenderSurvey getNextSurveyStep identify setPersonProperties group resetGroups setPersonPropertiesForFlags resetPersonPropertiesForFlags setGroupPropertiesForFlags resetGroupPropertiesForFlags reset get_distinct_id getGroups get_session_id get_session_replay_url alias set_config startSessionRecording stopSessionRecording sessionRecordingStarted captureException loadToolbar get_property getSessionProperty createPersonProfile opt_in_capturing opt_out_capturing has_opted_in_capturing has_opted_out_capturing clear_opt_in_out_capturing debug getPageViewId captureTraceFeedback captureTraceMetric".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);';
|
|
56
56
|
|
|
57
|
-
// PostHog's
|
|
58
|
-
// router's in-place swaps are captured here.
|
|
57
|
+
// With PostHog's classic pageview setting its loader captures one pageview
|
|
58
|
+
// per real page load, so the client router's in-place swaps are captured here.
|
|
59
59
|
const POSTHOG_SPA_PAGEVIEWS = spaPageviews(
|
|
60
60
|
"__blumePosthogPath",
|
|
61
61
|
'posthog.capture("$pageview");'
|
|
62
62
|
);
|
|
63
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Whether Blume should capture client-router navigations itself, given the
|
|
66
|
+
* `posthog.init` options. Only when PostHog captures load-time pageviews and
|
|
67
|
+
* nothing more: `capture_pageview: false` turns pageviews off, and
|
|
68
|
+
* `capture_pageview: "history_change"` — the default under any `defaults`
|
|
69
|
+
* snapshot (`defaults: "2025-05-24"` in PostHog's current snippet), unless
|
|
70
|
+
* `capture_pageview` says otherwise — already captures every navigation, so
|
|
71
|
+
* sending another would count each one twice.
|
|
72
|
+
*/
|
|
73
|
+
const capturesNavigations = (init: Record<string, JsonValue>): boolean => {
|
|
74
|
+
const setting = init.capture_pageview;
|
|
75
|
+
if (setting === undefined) {
|
|
76
|
+
return init.defaults === undefined || init.defaults === "unset";
|
|
77
|
+
}
|
|
78
|
+
return setting !== false && setting !== "history_change";
|
|
79
|
+
};
|
|
80
|
+
|
|
64
81
|
/**
|
|
65
82
|
* The inline loader-plus-init snippet. `key` and `host` are the options Blume
|
|
66
83
|
* maps (`host` becomes `api_host`); everything else lands in `posthog.init`'s
|
|
@@ -69,10 +86,11 @@ const POSTHOG_SPA_PAGEVIEWS = spaPageviews(
|
|
|
69
86
|
export const posthogHead = (options: PosthogOptions): HeadScript[] => {
|
|
70
87
|
const { host, key, ...init } = options;
|
|
71
88
|
const initOptions = { api_host: host ?? POSTHOG_DEFAULT_HOST, ...init };
|
|
89
|
+
const pageviews = capturesNavigations(init) ? POSTHOG_SPA_PAGEVIEWS : "";
|
|
72
90
|
return [
|
|
73
91
|
{
|
|
74
92
|
attributes: {},
|
|
75
|
-
content: `${POSTHOG_LOADER}posthog.init(${inlineJson(key)},${inlineJson(initOptions)});${
|
|
93
|
+
content: `${POSTHOG_LOADER}posthog.init(${inlineJson(key)},${inlineJson(initOptions)});${pageviews}`,
|
|
76
94
|
},
|
|
77
95
|
];
|
|
78
96
|
};
|
package/src/analytics/schema.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { amplitudeAdapterSchema } from "./amplitude.ts";
|
|
|
5
5
|
import { clarityAdapterSchema } from "./clarity.ts";
|
|
6
6
|
import { clearbitAdapterSchema } from "./clearbit.ts";
|
|
7
7
|
import { cloudflareAdapterSchema } from "./cloudflare.ts";
|
|
8
|
+
import { databuddyAdapterSchema } from "./databuddy.ts";
|
|
8
9
|
import { fathomAdapterSchema } from "./fathom.ts";
|
|
9
10
|
import { googleAnalyticsAdapterSchema } from "./google-analytics.ts";
|
|
10
11
|
import { googleTagManagerAdapterSchema } from "./google-tag-manager.ts";
|
|
@@ -13,6 +14,7 @@ import { hightouchAdapterSchema } from "./hightouch.ts";
|
|
|
13
14
|
import { hotjarAdapterSchema } from "./hotjar.ts";
|
|
14
15
|
import { logrocketAdapterSchema } from "./logrocket.ts";
|
|
15
16
|
import { mixpanelAdapterSchema } from "./mixpanel.ts";
|
|
17
|
+
import { oneDollarStatsAdapterSchema } from "./one-dollar-stats.ts";
|
|
16
18
|
import { pirschAdapterSchema } from "./pirsch.ts";
|
|
17
19
|
import { plausibleAdapterSchema } from "./plausible.ts";
|
|
18
20
|
import { posthogAdapterSchema } from "./posthog.ts";
|
|
@@ -27,6 +29,7 @@ export const analyticsAdapterSchema = z.discriminatedUnion("kind", [
|
|
|
27
29
|
clarityAdapterSchema,
|
|
28
30
|
clearbitAdapterSchema,
|
|
29
31
|
cloudflareAdapterSchema,
|
|
32
|
+
databuddyAdapterSchema,
|
|
30
33
|
fathomAdapterSchema,
|
|
31
34
|
googleAnalyticsAdapterSchema,
|
|
32
35
|
googleTagManagerAdapterSchema,
|
|
@@ -35,6 +38,7 @@ export const analyticsAdapterSchema = z.discriminatedUnion("kind", [
|
|
|
35
38
|
hotjarAdapterSchema,
|
|
36
39
|
logrocketAdapterSchema,
|
|
37
40
|
mixpanelAdapterSchema,
|
|
41
|
+
oneDollarStatsAdapterSchema,
|
|
38
42
|
pirschAdapterSchema,
|
|
39
43
|
plausibleAdapterSchema,
|
|
40
44
|
posthogAdapterSchema,
|