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/astro/generate.ts
CHANGED
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
hasDeferrableGroups,
|
|
32
32
|
navVariants,
|
|
33
33
|
} from "../components/layout/nav-utils.ts";
|
|
34
|
-
import { normalizeBasePath } from "../core/base-path.ts";
|
|
34
|
+
import { normalizeBasePath, withBasePath } from "../core/base-path.ts";
|
|
35
35
|
import { validateUsedComponents } from "../core/component-diagnostics.ts";
|
|
36
36
|
import {
|
|
37
37
|
analyzeComponentOverrides,
|
|
@@ -81,7 +81,9 @@ import { ogCacheDir } from "../og/cache.ts";
|
|
|
81
81
|
import { missingFontFiles, resolveOgFonts } from "../og/derive.ts";
|
|
82
82
|
import type { DerivedOgFonts } from "../og/derive.ts";
|
|
83
83
|
import { resolveOgLogo } from "../og/logo.ts";
|
|
84
|
-
import type {
|
|
84
|
+
import type { AsyncApiSpecValue } from "../openapi/asyncapi.ts";
|
|
85
|
+
import type { ApiSpecData, HttpMethod, OpenApiData } from "../openapi/model.ts";
|
|
86
|
+
import { HTTP_METHODS, withServerDefaults } from "../openapi/model.ts";
|
|
85
87
|
import {
|
|
86
88
|
builtinProxyReferences,
|
|
87
89
|
hasScalarReferences,
|
|
@@ -954,6 +956,8 @@ const resolveBanner = (config: ResolvedConfig): BlumeBanner | null => {
|
|
|
954
956
|
if (isStringShorthand(banner)) {
|
|
955
957
|
return { content: banner, dismissible: false, key: banner };
|
|
956
958
|
}
|
|
959
|
+
// `link.href` stays as authored; the link the banner renders is the
|
|
960
|
+
// navigation's `bannerHref`, localized and mounted under `basePath`.
|
|
957
961
|
return {
|
|
958
962
|
content: banner.content,
|
|
959
963
|
dismissible: banner.dismissible,
|
|
@@ -1489,28 +1493,41 @@ const writeApiFiles = async (
|
|
|
1489
1493
|
await Promise.all(writes);
|
|
1490
1494
|
};
|
|
1491
1495
|
|
|
1496
|
+
/** The proxy endpoint's file under the Astro `src/` dir (eject writes it too). */
|
|
1497
|
+
export const PLAYGROUND_PROXY_ENTRY = join("blume-openapi", "api-proxy.ts");
|
|
1498
|
+
|
|
1499
|
+
/** The URL the built-in proxy is injected at (see {@link planPlaygroundProxy}). */
|
|
1500
|
+
export const playgroundProxyPattern = (config: ResolvedConfig): string =>
|
|
1501
|
+
withBasePath(config.basePath, "/_api-proxy");
|
|
1502
|
+
|
|
1492
1503
|
/**
|
|
1493
1504
|
* Decide whether to generate the playground's built-in CORS proxy endpoint.
|
|
1494
1505
|
* Only the Blume renderer's playground with `proxy: true` needs it — a proxy
|
|
1495
1506
|
* URL string points at an external service, and `false` sends requests
|
|
1496
1507
|
* directly. Injected at `/_api-proxy` (rather than written under `pages/`)
|
|
1497
1508
|
* because Astro treats `_`-prefixed page files as private; the endpoint's own
|
|
1498
|
-
* `prerender = false` export wins over the injection default.
|
|
1509
|
+
* `prerender = false` export wins over the injection default. Mounted under
|
|
1510
|
+
* the site `basePath`, at the URL the playground sends to (see
|
|
1511
|
+
* openapi/source.ts); Astro layers `deployment.base` onto both.
|
|
1499
1512
|
*/
|
|
1500
1513
|
const planPlaygroundProxy = (config: ResolvedConfig, srcDir: string) => ({
|
|
1501
1514
|
enabled: needsPlaygroundProxy(config),
|
|
1502
|
-
entrypoint: join(srcDir,
|
|
1503
|
-
pattern:
|
|
1515
|
+
entrypoint: join(srcDir, PLAYGROUND_PROXY_ENTRY),
|
|
1516
|
+
pattern: playgroundProxyPattern(config),
|
|
1504
1517
|
});
|
|
1505
1518
|
|
|
1506
1519
|
/**
|
|
1507
1520
|
* The origins the built-in proxy is allowed to reach: one per absolute
|
|
1508
|
-
* `servers[].url` across the parsed specs
|
|
1509
|
-
*
|
|
1510
|
-
*
|
|
1511
|
-
*
|
|
1521
|
+
* `servers[].url` across the parsed specs — the document's, each path item's,
|
|
1522
|
+
* and each operation's, since an operation's playground sends to the most
|
|
1523
|
+
* specific of those. This is the endpoint's whole trust boundary — the client
|
|
1524
|
+
* sends the target as a query parameter, and a reader's custom base URL is not
|
|
1525
|
+
* a documented server — so it is derived here, at build time, from the same
|
|
1526
|
+
* documents the operation pages render.
|
|
1512
1527
|
*
|
|
1513
|
-
*
|
|
1528
|
+
* A templated URL (`https://{env}.api.example.com`) is allowed as the
|
|
1529
|
+
* playground sends it, with each variable at its declared default. Relative
|
|
1530
|
+
* (`/v1`) URLs, and templates with a variable left undefaulted, carry no
|
|
1514
1531
|
* origin to allow and are skipped; AsyncAPI documents declare `servers` as a
|
|
1515
1532
|
* map and contribute nothing (the proxy is OpenAPI-only).
|
|
1516
1533
|
*/
|
|
@@ -1526,27 +1543,53 @@ const specOriginsOf = (spec: ApiSpecData): string[] => {
|
|
|
1526
1543
|
}
|
|
1527
1544
|
}
|
|
1528
1545
|
// SAFETY: `document` is arbitrary parsed JSON; the assertion only names
|
|
1529
|
-
// the optional `servers`
|
|
1530
|
-
// `Array.isArray
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1546
|
+
// the optional `servers` and `paths` shapes, and every access below
|
|
1547
|
+
// re-checks them — `Array.isArray` guards each list, optional chaining each
|
|
1548
|
+
// path item and operation, and `server.url ?? ""` the url.
|
|
1549
|
+
const document = spec.document as {
|
|
1550
|
+
paths?: Record<string, DocumentPathItem | null | undefined>;
|
|
1551
|
+
servers?: DocumentServer[];
|
|
1552
|
+
};
|
|
1553
|
+
const lists = [document.servers];
|
|
1554
|
+
for (const item of Object.values(document.paths ?? {})) {
|
|
1555
|
+
lists.push(item?.servers);
|
|
1556
|
+
for (const method of HTTP_METHODS) {
|
|
1557
|
+
lists.push(item?.[method]?.servers);
|
|
1539
1558
|
}
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1559
|
+
}
|
|
1560
|
+
for (const servers of lists) {
|
|
1561
|
+
for (const server of Array.isArray(servers) ? servers : []) {
|
|
1562
|
+
const url = withServerDefaults(server.url ?? "", server.variables);
|
|
1563
|
+
// `new URL("https://{region}.api.example.com")` parses — the braces land
|
|
1564
|
+
// in the hostname — so a variable with no default needs an explicit
|
|
1565
|
+
// check or its junk literal becomes an allowlist entry no real request
|
|
1566
|
+
// can match.
|
|
1567
|
+
if (url.includes("{")) {
|
|
1568
|
+
continue;
|
|
1569
|
+
}
|
|
1570
|
+
try {
|
|
1571
|
+
origins.add(new URL(url).origin);
|
|
1572
|
+
} catch {
|
|
1573
|
+
// Not an absolute URL: nothing to allow.
|
|
1574
|
+
}
|
|
1544
1575
|
}
|
|
1545
1576
|
}
|
|
1546
1577
|
return [...origins];
|
|
1547
1578
|
};
|
|
1548
1579
|
|
|
1549
|
-
|
|
1580
|
+
/** A `servers[]` entry as a parsed spec document declares it. */
|
|
1581
|
+
interface DocumentServer {
|
|
1582
|
+
url?: string;
|
|
1583
|
+
variables?: AsyncApiSpecValue;
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
/** An OpenAPI path item: its own `servers` plus one per operation. */
|
|
1587
|
+
type DocumentPathItem = { servers?: DocumentServer[] } & Partial<
|
|
1588
|
+
Record<HttpMethod, { servers?: DocumentServer[] } | null>
|
|
1589
|
+
>;
|
|
1590
|
+
|
|
1591
|
+
/** The built-in proxy's allowlist: every spec's origins, deduped and sorted. */
|
|
1592
|
+
export const specOrigins = (data: OpenApiData): string[] =>
|
|
1550
1593
|
[...new Set(Object.values(data).flatMap(specOriginsOf))].toSorted();
|
|
1551
1594
|
|
|
1552
1595
|
/**
|
|
@@ -1558,7 +1601,7 @@ const specOrigins = (data: OpenApiData): string[] =>
|
|
|
1558
1601
|
* whose own origins came out empty (no absolute `servers[].url`, no absolute
|
|
1559
1602
|
* GraphQL `endpoint`) gets a warning naming it.
|
|
1560
1603
|
*/
|
|
1561
|
-
const proxyAllowlistWarnings = (
|
|
1604
|
+
export const proxyAllowlistWarnings = (
|
|
1562
1605
|
config: ResolvedConfig,
|
|
1563
1606
|
data: OpenApiData
|
|
1564
1607
|
): string[] => {
|
|
@@ -1573,7 +1616,7 @@ const proxyAllowlistWarnings = (
|
|
|
1573
1616
|
warnings.push(
|
|
1574
1617
|
spec.kind === "graphql"
|
|
1575
1618
|
? `The "${spec.label}" GraphQL reference (${spec.route}) has playground.proxy: true, but no absolute endpoint is configured for it, so the built-in proxy has no origin to allow and will refuse every request its playground sends. Set \`endpoint\` on the graphql() adapter (or the source) to the live GraphQL URL, or point playground.proxy at an external proxy URL.`
|
|
1576
|
-
: `The "${spec.label}" reference (${spec.route}) has playground.proxy: true, but its spec declares no absolute servers[].url (relative and templated
|
|
1619
|
+
: `The "${spec.label}" reference (${spec.route}) has playground.proxy: true, but its spec declares no absolute servers[].url (relative URLs, and templated ones with a variable missing its default, carry no origin), so the built-in proxy has no origin to allow and will refuse every request its playground sends. Add an absolute server URL to the spec, or point playground.proxy at an external proxy URL.`
|
|
1577
1620
|
);
|
|
1578
1621
|
}
|
|
1579
1622
|
return warnings;
|
|
@@ -1699,6 +1742,7 @@ export const analyzeComponentsFile = async (
|
|
|
1699
1742
|
const projectOgFonts = (project: BlumeProject): DerivedOgFonts =>
|
|
1700
1743
|
resolveOgFonts(
|
|
1701
1744
|
{
|
|
1745
|
+
locales: fontLocaleCodes(project.config.i18n),
|
|
1702
1746
|
ogFonts: project.config.seo.og.fonts,
|
|
1703
1747
|
themeFonts: project.config.theme.fonts,
|
|
1704
1748
|
themeFontsConfigured: project.themeFontsConfigured,
|
|
@@ -1843,7 +1887,7 @@ export const generateRuntime = async (
|
|
|
1843
1887
|
// `astro.config.mjs` — which would restart the dev server in place.
|
|
1844
1888
|
const contentRoutes = markdownRoutePaths(project);
|
|
1845
1889
|
const homeLinkHeader =
|
|
1846
|
-
buildHomeLinkHeader(config, contentRoutes) ?? undefined;
|
|
1890
|
+
buildHomeLinkHeader(config, contentRoutes, "dev") ?? undefined;
|
|
1847
1891
|
|
|
1848
1892
|
const assistantEnabled = config.ai.assistant?.enabled ?? false;
|
|
1849
1893
|
const exportPdf = config.export.pdf;
|
package/src/astro/include-hmr.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
|
|
3
|
+
import { resolve } from "pathe";
|
|
4
|
+
|
|
3
5
|
import { refreshBlumeContent } from "./integration.ts";
|
|
4
6
|
|
|
5
7
|
/**
|
|
@@ -18,12 +20,21 @@ import { refreshBlumeContent } from "./integration.ts";
|
|
|
18
20
|
*/
|
|
19
21
|
|
|
20
22
|
/** The Vite module-graph slice the plugin touches (structurally typed, like
|
|
21
|
-
* every Blume-authored Vite plugin — see `serverAppResolvePlugin`).
|
|
23
|
+
* every Blume-authored Vite plugin — see `serverAppResolvePlugin`). Every
|
|
24
|
+
* environment keeps its own graph, and the server's own `moduleGraph` only
|
|
25
|
+
* covers `client` and `ssr`: with `@astrojs/cloudflare` the content pages
|
|
26
|
+
* render in the `prerender` environment instead. */
|
|
22
27
|
interface IncludeHmrServer {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
config: { root: string };
|
|
29
|
+
environments: Record<
|
|
30
|
+
string,
|
|
31
|
+
{
|
|
32
|
+
moduleGraph: {
|
|
33
|
+
getModulesByFile: (file: string) => Set<unknown> | undefined;
|
|
34
|
+
invalidateModule: (mod: never) => void;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
>;
|
|
27
38
|
ws: { send: (payload: { type: "full-reload" }) => void };
|
|
28
39
|
}
|
|
29
40
|
|
|
@@ -51,16 +62,24 @@ export const includeHmrPlugin = (graphPath: string): IncludeHmrPlugin => ({
|
|
|
51
62
|
// No graph yet (first run) — nothing to invalidate.
|
|
52
63
|
return;
|
|
53
64
|
}
|
|
54
|
-
|
|
65
|
+
// An ejected app's graph is relative to the project, its Vite root; the
|
|
66
|
+
// hidden runtime's is absolute, which resolving leaves as it is.
|
|
67
|
+
const { config, environments, ws } = ctx.server;
|
|
68
|
+
const includers = Object.entries(graph).find(
|
|
69
|
+
([partial]) => resolve(config.root, partial) === ctx.file
|
|
70
|
+
)?.[1];
|
|
55
71
|
if (!includers || includers.length === 0) {
|
|
56
72
|
return;
|
|
57
73
|
}
|
|
58
|
-
const { moduleGraph
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
74
|
+
for (const { moduleGraph } of Object.values(environments)) {
|
|
75
|
+
for (const includer of includers) {
|
|
76
|
+
for (const mod of moduleGraph.getModulesByFile(
|
|
77
|
+
resolve(config.root, includer)
|
|
78
|
+
) ?? []) {
|
|
79
|
+
// SAFETY: the module came out of this module graph; `never` only
|
|
80
|
+
// reflects that the structural slice doesn't model the node type.
|
|
81
|
+
moduleGraph.invalidateModule(mod as never);
|
|
82
|
+
}
|
|
64
83
|
}
|
|
65
84
|
}
|
|
66
85
|
// Plain `.md` pages have no Vite module: their HTML lives in the
|
|
@@ -29,7 +29,10 @@ type StoreEntry = ReturnType<LoaderContext["store"]["entries"]>[number][1];
|
|
|
29
29
|
/** Meta-store key holding the recorded partials digest of an includer. */
|
|
30
30
|
const stateKey = (id: string): string => `blume:include-state:${id}`;
|
|
31
31
|
|
|
32
|
-
/**
|
|
32
|
+
/**
|
|
33
|
+
* The generated include graph: partial → including pages, absolute in the
|
|
34
|
+
* hidden runtime and relative to the project root in an ejected app.
|
|
35
|
+
*/
|
|
33
36
|
type IncludeGraph = Record<string, string[]>;
|
|
34
37
|
|
|
35
38
|
/**
|
|
@@ -47,14 +50,22 @@ const readGraph = (graphPath: string): IncludeGraph => {
|
|
|
47
50
|
}
|
|
48
51
|
};
|
|
49
52
|
|
|
50
|
-
/**
|
|
51
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Invert the graph: absolute including page → its absolute partials, sorted.
|
|
55
|
+
* Each path resolves against the Astro root, which leaves the hidden runtime's
|
|
56
|
+
* absolute paths as they are.
|
|
57
|
+
*/
|
|
58
|
+
const partialsByPage = (
|
|
59
|
+
graph: IncludeGraph,
|
|
60
|
+
root: string
|
|
61
|
+
): Map<string, string[]> => {
|
|
52
62
|
const byPage = new Map<string, string[]>();
|
|
53
63
|
for (const [partial, pages] of Object.entries(graph)) {
|
|
54
64
|
for (const page of pages) {
|
|
55
|
-
const
|
|
56
|
-
partials.
|
|
57
|
-
|
|
65
|
+
const abs = resolve(root, page);
|
|
66
|
+
const partials = byPage.get(abs) ?? [];
|
|
67
|
+
partials.push(resolve(root, partial));
|
|
68
|
+
byPage.set(abs, partials);
|
|
58
69
|
}
|
|
59
70
|
}
|
|
60
71
|
for (const partials of byPage.values()) {
|
|
@@ -123,11 +134,11 @@ export const evictStaleIncluders = (
|
|
|
123
134
|
context: LoaderContext,
|
|
124
135
|
graphPath: string
|
|
125
136
|
): string[] => {
|
|
126
|
-
const
|
|
137
|
+
const root = fileURLToPath(context.config.root);
|
|
138
|
+
const byPage = partialsByPage(readGraph(graphPath), root);
|
|
127
139
|
if (byPage.size === 0) {
|
|
128
140
|
return [];
|
|
129
141
|
}
|
|
130
|
-
const root = fileURLToPath(context.config.root);
|
|
131
142
|
const evicted: string[] = [];
|
|
132
143
|
for (const [id, entry] of context.store.entries()) {
|
|
133
144
|
if (evictIfStale(context, byPage, root, id, entry)) {
|
package/src/astro/integration.ts
CHANGED
|
@@ -28,13 +28,40 @@ interface OverlayErrorPayload {
|
|
|
28
28
|
|
|
29
29
|
/** The dev server's HMR channel — either `.ws` (Vite ≤5) or `.hot` (Vite 6+). */
|
|
30
30
|
interface OverlayChannel {
|
|
31
|
-
send: (payload: OverlayErrorPayload) => void;
|
|
31
|
+
send: (payload: OverlayErrorPayload | { type: "full-reload" }) => void;
|
|
32
32
|
}
|
|
33
|
-
|
|
33
|
+
|
|
34
|
+
/** A node in a Vite environment's module graph; only its identity matters. */
|
|
35
|
+
interface DevModuleNode {
|
|
36
|
+
id: string | null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The dev-server slice the integration keeps: the overlay channel, and every
|
|
41
|
+
* Vite environment's module graph for the content re-sync (structurally
|
|
42
|
+
* typed, like every Blume-authored Vite plugin).
|
|
43
|
+
*/
|
|
44
|
+
interface DevServer {
|
|
45
|
+
environments: Record<
|
|
46
|
+
string,
|
|
47
|
+
{
|
|
48
|
+
moduleGraph: {
|
|
49
|
+
getModuleById: (id: string) => DevModuleNode | undefined;
|
|
50
|
+
invalidateModule: (mod: never) => void;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
>;
|
|
34
54
|
hot?: OverlayChannel;
|
|
35
55
|
ws?: OverlayChannel;
|
|
36
56
|
}
|
|
37
57
|
|
|
58
|
+
/** The dev server's file watcher, as far as the data-store watch uses it. */
|
|
59
|
+
interface WatchedServer {
|
|
60
|
+
watcher: {
|
|
61
|
+
on: (event: "add" | "change", listener: (path: string) => void) => void;
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
38
65
|
/** The parameters Astro hands `astro:server:setup`. */
|
|
39
66
|
type ServerSetupParams = Parameters<
|
|
40
67
|
NonNullable<AstroIntegration["hooks"]["astro:server:setup"]>
|
|
@@ -74,7 +101,7 @@ interface DevNegotiation {
|
|
|
74
101
|
interface DevServerRegistry {
|
|
75
102
|
buildProject: BlumeProject | null;
|
|
76
103
|
negotiation: DevNegotiation | null;
|
|
77
|
-
overlay:
|
|
104
|
+
overlay: DevServer | null;
|
|
78
105
|
refreshContent: RefreshContent | null;
|
|
79
106
|
}
|
|
80
107
|
|
|
@@ -155,6 +182,64 @@ export const publishDevNegotiation = (
|
|
|
155
182
|
: null;
|
|
156
183
|
};
|
|
157
184
|
|
|
185
|
+
/** A dev server's HMR channel: `.ws`, or `.hot` where only that exists. */
|
|
186
|
+
const overlayChannelOf = (
|
|
187
|
+
server: DevServer | null
|
|
188
|
+
): OverlayChannel | undefined => server?.ws ?? server?.hot;
|
|
189
|
+
|
|
190
|
+
/** Astro's content-layer data store, a virtual module in each environment. */
|
|
191
|
+
const DATA_STORE_MODULE_ID = "\0astro:data-layer-content";
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Invalidate Astro's data store in every Vite environment, then reload the
|
|
195
|
+
* browser. Astro invalidates it after a sync in the `ssr` environment only,
|
|
196
|
+
* which is where pages render on most adapters. With `@astrojs/cloudflare`
|
|
197
|
+
* the `ssr` environment runs in workerd and the prerendered pages (every
|
|
198
|
+
* content page) render in the `prerender` environment, whose copy of the
|
|
199
|
+
* store then stayed at its startup snapshot: a page added in dev resolved
|
|
200
|
+
* its route but `getEntry` still missed it, so it 404ed until a restart.
|
|
201
|
+
*/
|
|
202
|
+
const invalidateDataStore = (server: DevServer): void => {
|
|
203
|
+
for (const { moduleGraph } of Object.values(server.environments)) {
|
|
204
|
+
const mod = moduleGraph.getModuleById(DATA_STORE_MODULE_ID);
|
|
205
|
+
if (mod) {
|
|
206
|
+
// SAFETY: the node came out of this same module graph; `never` only
|
|
207
|
+
// reflects that the structural slice doesn't model the node type.
|
|
208
|
+
moduleGraph.invalidateModule(mod as never);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
// Astro reloaded the browser when the store was written, which can land
|
|
212
|
+
// before the invalidation above; reload again so no page renders the
|
|
213
|
+
// stale copy.
|
|
214
|
+
overlayChannelOf(server)?.send({ type: "full-reload" });
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Where Astro keeps the dev content store: `data-store.json` in the root's
|
|
219
|
+
* `.astro/` directory. Astro reloads its virtual module from this file.
|
|
220
|
+
*/
|
|
221
|
+
const devDataStoreFile = (root: URL): string =>
|
|
222
|
+
fileURLToPath(new URL(".astro/data-store.json", root));
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Invalidate the data store in every environment whenever Astro rewrites it.
|
|
226
|
+
* Astro's own file watcher updates the store on a content edit — a `.md`
|
|
227
|
+
* page's rendered body lives in it — but invalidates the module in `ssr`
|
|
228
|
+
* only, so with `@astrojs/cloudflare` a body edit stayed stale in
|
|
229
|
+
* `prerender` until something structural re-synced it. Keyed on the store
|
|
230
|
+
* write rather than Blume's regeneration, which can finish first.
|
|
231
|
+
*/
|
|
232
|
+
const watchDataStore = (server: DevServer & WatchedServer, root: URL): void => {
|
|
233
|
+
const file = devDataStoreFile(root);
|
|
234
|
+
const onWrite = (path: string): void => {
|
|
235
|
+
if (path === file) {
|
|
236
|
+
invalidateDataStore(server);
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
server.watcher.on("add", onWrite);
|
|
240
|
+
server.watcher.on("change", onWrite);
|
|
241
|
+
};
|
|
242
|
+
|
|
158
243
|
/**
|
|
159
244
|
* Re-run Astro's content-layer loaders against the live dev server. Returns
|
|
160
245
|
* `false` when no server has registered one — before the first
|
|
@@ -165,20 +250,21 @@ export const publishDevNegotiation = (
|
|
|
165
250
|
* stale store and the moved page 404s.
|
|
166
251
|
*/
|
|
167
252
|
export const refreshBlumeContent = async (): Promise<boolean> => {
|
|
168
|
-
const { refreshContent } = registry();
|
|
253
|
+
const { overlay, refreshContent } = registry();
|
|
169
254
|
if (!refreshContent) {
|
|
170
255
|
return false;
|
|
171
256
|
}
|
|
172
257
|
// No loader filter: every collection re-syncs (the docs glob and any
|
|
173
258
|
// staged collection alike).
|
|
174
259
|
await refreshContent({});
|
|
260
|
+
if (overlay) {
|
|
261
|
+
invalidateDataStore(overlay);
|
|
262
|
+
}
|
|
175
263
|
return true;
|
|
176
264
|
};
|
|
177
265
|
|
|
178
|
-
const overlayChannel = (): OverlayChannel | undefined =>
|
|
179
|
-
|
|
180
|
-
return overlay?.ws ?? overlay?.hot;
|
|
181
|
-
};
|
|
266
|
+
const overlayChannel = (): OverlayChannel | undefined =>
|
|
267
|
+
overlayChannelOf(registry().overlay);
|
|
182
268
|
|
|
183
269
|
/**
|
|
184
270
|
* Surface Blume's own diagnostics (config/frontmatter/content errors) in the
|
|
@@ -237,8 +323,9 @@ export interface BlumeIntegrationOptions {
|
|
|
237
323
|
/**
|
|
238
324
|
* Homepage `Link` header value for agent discovery (see
|
|
239
325
|
* `ai/link-headers.ts`); the dev-server counterpart of the `_headers` /
|
|
240
|
-
* Vercel-config emission, so `curl -I` against `blume dev` shows
|
|
241
|
-
*
|
|
326
|
+
* Vercel-config emission, so `curl -I` against `blume dev` shows it too —
|
|
327
|
+
* built for the `"dev"` surface, which leaves out the targets only a build
|
|
328
|
+
* writes. Published the same way as `contentRoutes`.
|
|
242
329
|
*/
|
|
243
330
|
homeLinkHeader?: string;
|
|
244
331
|
/**
|
|
@@ -279,7 +366,8 @@ const isHomeUrl = (rawUrl: string | undefined): boolean => {
|
|
|
279
366
|
* variant falls back to the synthesized llms.txt mirror when it's a landing
|
|
280
367
|
* page (see `markdownRoutePaths`). The same
|
|
281
368
|
* middleware also stamps the homepage agent-discovery `Link` header, mirroring
|
|
282
|
-
* what the deployed site sends via `_headers` / the Vercel routing config
|
|
369
|
+
* what the deployed site sends via `_headers` / the Vercel routing config
|
|
370
|
+
* minus the targets the dev server doesn't serve.
|
|
283
371
|
*
|
|
284
372
|
* Request URLs arrive base-less: Astro unshifts its own dev middlewares (base,
|
|
285
373
|
* trailing slash, route guard) ahead of this one from its post-`configureServer`
|
|
@@ -351,9 +439,11 @@ export const blumeIntegration = (
|
|
|
351
439
|
return;
|
|
352
440
|
}
|
|
353
441
|
// `dir` is what Astro reports as the client output — `dist/`, or
|
|
354
|
-
// `dist/client` for a server build
|
|
355
|
-
//
|
|
356
|
-
//
|
|
442
|
+
// `dist/client` for a server build (`dist/client/<base>/` once
|
|
443
|
+
// `@astrojs/cloudflare` moves it under the base, whose `_headers` the
|
|
444
|
+
// writer places at the root served above it) — which is what the
|
|
445
|
+
// platform serves (the Vercel adapter copies it into its Build Output
|
|
446
|
+
// static tree in a later hook).
|
|
357
447
|
await publishBuildArtifacts(project, fileURLToPath(dir), logger);
|
|
358
448
|
},
|
|
359
449
|
"astro:config:done": ({ config, injectTypes }) => {
|
|
@@ -399,6 +489,10 @@ export const blumeIntegration = (
|
|
|
399
489
|
const shared = registry();
|
|
400
490
|
shared.overlay = server;
|
|
401
491
|
shared.refreshContent = refreshContent ?? null;
|
|
492
|
+
// `astro:config:done` always runs first; the root locates the store.
|
|
493
|
+
if (astroRoot) {
|
|
494
|
+
watchDataStore(server, astroRoot);
|
|
495
|
+
}
|
|
402
496
|
// Prepend so the rewrite happens before Astro's own request handler,
|
|
403
497
|
// letting the rewritten URL resolve to the `.md` endpoint.
|
|
404
498
|
server.middlewares.stack.unshift({
|
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
* generated pages through aliases or relative paths. `generateRuntime` now
|
|
9
9
|
* publishes them here and `runtimeModulesPlugin` serves them to Vite as
|
|
10
10
|
* virtual modules, so a regeneration never round-trips the disk or waits on a
|
|
11
|
-
* file watcher: publishing invalidates the changed modules in every
|
|
12
|
-
* server (Vite walks the importers, so the
|
|
13
|
-
* on the next request) and asks the
|
|
14
|
-
*
|
|
15
|
-
* watch debounce.
|
|
11
|
+
* file watcher: publishing invalidates the changed modules in every Vite
|
|
12
|
+
* environment of every live dev server (Vite walks the importers, so the
|
|
13
|
+
* pages that render them re-evaluate on the next request) and asks the
|
|
14
|
+
* browser to reload — the same effect a JSON file change used to reach
|
|
15
|
+
* through the watcher, minus the write and the watch debounce.
|
|
16
16
|
*
|
|
17
17
|
* The registry hangs off `globalThis`, not module state. On a published
|
|
18
18
|
* install the CLI bundle (`dist/cli`) carries its own copy of this module,
|
|
@@ -61,18 +61,29 @@ interface RuntimeModuleNode {
|
|
|
61
61
|
id: string | null;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
/** One Vite environment's module graph, as far as the registry touches it. */
|
|
65
|
+
interface RuntimeModuleGraph {
|
|
66
|
+
getModuleById: (id: string) => RuntimeModuleNode | undefined;
|
|
67
|
+
invalidateModule: (mod: RuntimeModuleNode) => void;
|
|
68
|
+
}
|
|
69
|
+
|
|
64
70
|
/**
|
|
65
71
|
* The Vite dev-server slice the registry touches (structurally typed, like
|
|
66
72
|
* every Blume-authored Vite plugin — see `includeHmrPlugin`).
|
|
67
73
|
*/
|
|
68
74
|
export interface RuntimeModuleServer {
|
|
75
|
+
/**
|
|
76
|
+
* Every Vite environment, each with its own module graph. `moduleGraph` on
|
|
77
|
+
* the server itself is Vite's backward-compatible view of only `client`
|
|
78
|
+
* and `ssr`, and those are not the only environments that render: with
|
|
79
|
+
* `@astrojs/cloudflare` the `ssr` environment runs in workerd, so Astro
|
|
80
|
+
* renders the prerendered pages (every content page) in its `prerender`
|
|
81
|
+
* environment instead.
|
|
82
|
+
*/
|
|
83
|
+
environments: Record<string, { moduleGraph: RuntimeModuleGraph }>;
|
|
69
84
|
httpServer?: {
|
|
70
85
|
once: (event: "close", listener: () => void) => void;
|
|
71
86
|
} | null;
|
|
72
|
-
moduleGraph: {
|
|
73
|
-
getModuleById: (id: string) => RuntimeModuleNode | undefined;
|
|
74
|
-
invalidateModule: (mod: RuntimeModuleNode) => void;
|
|
75
|
-
};
|
|
76
87
|
ws: { send: (payload: { type: "full-reload" }) => void };
|
|
77
88
|
}
|
|
78
89
|
|
|
@@ -131,10 +142,14 @@ export const publishRuntimeModules = (
|
|
|
131
142
|
return changed;
|
|
132
143
|
}
|
|
133
144
|
for (const server of servers) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
145
|
+
// Every environment that loaded a module holds its own copy, and any of
|
|
146
|
+
// them may be the one rendering pages on this adapter.
|
|
147
|
+
for (const { moduleGraph } of Object.values(server.environments)) {
|
|
148
|
+
for (const id of changed) {
|
|
149
|
+
const mod = moduleGraph.getModuleById(`${RESOLVED_PREFIX}${id}`);
|
|
150
|
+
if (mod) {
|
|
151
|
+
moduleGraph.invalidateModule(mod);
|
|
152
|
+
}
|
|
138
153
|
}
|
|
139
154
|
}
|
|
140
155
|
server.ws.send({ type: "full-reload" });
|