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
|
@@ -9,17 +9,18 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import type { JsonObject } from "./json.ts";
|
|
11
11
|
import { asString, getPath, objectsIn } from "./json.ts";
|
|
12
|
-
import type { InlineMarks } from "./lower.ts";
|
|
12
|
+
import type { InlineMarks, InlinePart } from "./lower.ts";
|
|
13
13
|
import {
|
|
14
14
|
absoluteUrl,
|
|
15
15
|
blockquote,
|
|
16
|
+
guardBlockStart,
|
|
16
17
|
headingPrefix,
|
|
17
18
|
image,
|
|
18
19
|
joinBlocks,
|
|
20
|
+
linkParts,
|
|
19
21
|
listItem,
|
|
20
22
|
markdownDocument,
|
|
21
23
|
renderInline,
|
|
22
|
-
renderLink,
|
|
23
24
|
unsupported,
|
|
24
25
|
writesMdx,
|
|
25
26
|
} from "./lower.ts";
|
|
@@ -138,45 +139,50 @@ const embeddedEntry = (
|
|
|
138
139
|
);
|
|
139
140
|
};
|
|
140
141
|
|
|
141
|
-
const
|
|
142
|
+
const inlineParts = (
|
|
142
143
|
nodes: JsonObject[],
|
|
143
144
|
options: ContentfulRichTextOptions
|
|
144
|
-
):
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
.map((node) => renderInlineNode(node, options))
|
|
148
|
-
.join("");
|
|
145
|
+
): InlinePart[] =>
|
|
146
|
+
// oxlint-disable-next-line no-use-before-define -- mutual recursion: a link's label is itself inline content
|
|
147
|
+
nodes.flatMap((node) => inlineNodeParts(node, options));
|
|
149
148
|
|
|
150
|
-
const
|
|
149
|
+
const inlineNodeParts = (
|
|
151
150
|
node: JsonObject,
|
|
152
151
|
options: ContentfulRichTextOptions
|
|
153
|
-
):
|
|
152
|
+
): InlinePart[] => {
|
|
154
153
|
switch (asString(node.nodeType)) {
|
|
155
154
|
case "text": {
|
|
156
|
-
return
|
|
155
|
+
return [{ marks: marksOf(node), text: asString(node.value) ?? "" }];
|
|
157
156
|
}
|
|
158
157
|
case "hyperlink": {
|
|
159
|
-
return
|
|
160
|
-
|
|
158
|
+
return linkParts(
|
|
159
|
+
inlineParts(children(node), options),
|
|
161
160
|
asString(getPath(node, "data.uri"))
|
|
162
161
|
);
|
|
163
162
|
}
|
|
164
163
|
case "asset-hyperlink": {
|
|
165
|
-
return
|
|
166
|
-
|
|
164
|
+
return linkParts(
|
|
165
|
+
inlineParts(children(node), options),
|
|
167
166
|
linkedAsset(node, options)?.url
|
|
168
167
|
);
|
|
169
168
|
}
|
|
170
169
|
case "embedded-entry-inline": {
|
|
171
|
-
return embeddedEntry(node, options);
|
|
170
|
+
return [{ markdown: embeddedEntry(node, options) }];
|
|
172
171
|
}
|
|
173
172
|
default: {
|
|
174
173
|
// entry-hyperlink (no route to point at) and anything unknown: the label.
|
|
175
|
-
return
|
|
174
|
+
return inlineParts(children(node), options);
|
|
176
175
|
}
|
|
177
176
|
}
|
|
178
177
|
};
|
|
179
178
|
|
|
179
|
+
/** A block's inline children as Markdown, guarded as one block. */
|
|
180
|
+
const blockText = (
|
|
181
|
+
node: JsonObject,
|
|
182
|
+
options: ContentfulRichTextOptions
|
|
183
|
+
): string =>
|
|
184
|
+
guardBlockStart(renderInline(inlineParts(children(node), options)));
|
|
185
|
+
|
|
180
186
|
const renderList = (
|
|
181
187
|
items: JsonObject[],
|
|
182
188
|
marker: (index: number) => string,
|
|
@@ -197,12 +203,14 @@ const renderList = (
|
|
|
197
203
|
)
|
|
198
204
|
.join("\n");
|
|
199
205
|
|
|
206
|
+
// Each of a cell's paragraphs is a block as much as a page's is, so it goes
|
|
207
|
+
// through the same guard: two struck runs in one still meet as `~~~~`.
|
|
200
208
|
const cellText = (
|
|
201
209
|
cell: JsonObject,
|
|
202
210
|
options: ContentfulRichTextOptions
|
|
203
211
|
): string =>
|
|
204
212
|
children(cell)
|
|
205
|
-
.map((paragraph) =>
|
|
213
|
+
.map((paragraph) => blockText(paragraph, options))
|
|
206
214
|
.join(" ")
|
|
207
215
|
.replaceAll(CELL_BREAK, " ")
|
|
208
216
|
.replaceAll(CELL_PIPE, String.raw`\|`);
|
|
@@ -234,11 +242,11 @@ const renderBlock = (
|
|
|
234
242
|
const type = asString(node.nodeType) ?? "";
|
|
235
243
|
const heading = HEADING.exec(type)?.groups?.level;
|
|
236
244
|
if (heading) {
|
|
237
|
-
return `${headingPrefix(Number(heading))}${
|
|
245
|
+
return `${headingPrefix(Number(heading))}${blockText(node, options)}`;
|
|
238
246
|
}
|
|
239
247
|
switch (type) {
|
|
240
248
|
case "paragraph": {
|
|
241
|
-
return
|
|
249
|
+
return blockText(node, options);
|
|
242
250
|
}
|
|
243
251
|
case "blockquote": {
|
|
244
252
|
return blockquote(
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { BlumeError } from "../diagnostics.ts";
|
|
1
2
|
import {
|
|
2
3
|
assetFromEntry,
|
|
3
4
|
contentfulRichTextToMarkdown,
|
|
@@ -111,19 +112,29 @@ export const contentfulSource = (
|
|
|
111
112
|
);
|
|
112
113
|
};
|
|
113
114
|
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
115
|
+
const preview = ctx?.preview ?? false;
|
|
116
|
+
const previewToken = (): string | undefined =>
|
|
117
|
+
options.previewToken ?? process.env.CONTENTFUL_PREVIEW_TOKEN;
|
|
118
|
+
|
|
119
|
+
// The Preview API rejects delivery tokens, so falling back to one would
|
|
120
|
+
// only trade a clear config error for a 401. Checked before the cache, so
|
|
121
|
+
// a warm snapshot can't stand in for the drafts `--preview` asked for.
|
|
122
|
+
const assertConfigured = (): void => {
|
|
123
|
+
if (preview && !previewToken()) {
|
|
124
|
+
throw new BlumeError({
|
|
125
|
+
code: "BLUME_SOURCE_MISCONFIGURED",
|
|
126
|
+
message: `Source "${options.name}": Contentful --preview needs a Preview API token.`,
|
|
127
|
+
severity: "error",
|
|
128
|
+
suggestion:
|
|
129
|
+
"Set previewToken on contentfulSource, or the CONTENTFUL_PREVIEW_TOKEN environment variable.",
|
|
130
|
+
});
|
|
125
131
|
}
|
|
126
|
-
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const fetchEntries = async (): Promise<SourceEntry[]> => {
|
|
135
|
+
const token = preview
|
|
136
|
+
? previewToken()
|
|
137
|
+
: (options.token ?? process.env.CONTENTFUL_ACCESS_TOKEN);
|
|
127
138
|
const client: RestClient = {
|
|
128
139
|
fetchImpl: options.fetchImpl,
|
|
129
140
|
headers: token ? { authorization: `Bearer ${token}` } : {},
|
|
@@ -163,10 +174,12 @@ export const contentfulSource = (
|
|
|
163
174
|
|
|
164
175
|
return remoteSource(
|
|
165
176
|
{
|
|
177
|
+
assertConfigured,
|
|
166
178
|
fetchEntries,
|
|
167
179
|
name: options.name,
|
|
168
180
|
pollInterval: options.pollInterval,
|
|
169
181
|
prefix: options.prefix,
|
|
182
|
+
withContext: (next) => contentfulSource(options, next),
|
|
170
183
|
},
|
|
171
184
|
ctx
|
|
172
185
|
);
|
|
@@ -6,6 +6,8 @@ import { glob } from "tinyglobby";
|
|
|
6
6
|
|
|
7
7
|
import { BlumeError } from "../diagnostics.ts";
|
|
8
8
|
import matter from "../frontmatter.ts";
|
|
9
|
+
import type { Diagnostic } from "../types.ts";
|
|
10
|
+
import { unloadablePathDiagnostic } from "./normalize.ts";
|
|
9
11
|
import type { ContentSource, SourceEntry, SourceLoadResult } from "./types.ts";
|
|
10
12
|
import {
|
|
11
13
|
baselineScanIgnore,
|
|
@@ -54,8 +56,24 @@ export const filesystemSource = (
|
|
|
54
56
|
});
|
|
55
57
|
files.sort();
|
|
56
58
|
|
|
59
|
+
// A file Astro's content loader can't read would publish a route that
|
|
60
|
+
// only ever renders "Page not found"; it is reported and left out.
|
|
61
|
+
const diagnostics: Diagnostic[] = [];
|
|
62
|
+
const loadable: string[] = [];
|
|
63
|
+
for (const file of files) {
|
|
64
|
+
const unloadable = unloadablePathDiagnostic(
|
|
65
|
+
relative(contentRoot, file),
|
|
66
|
+
file
|
|
67
|
+
);
|
|
68
|
+
if (unloadable) {
|
|
69
|
+
diagnostics.push(unloadable);
|
|
70
|
+
} else {
|
|
71
|
+
loadable.push(file);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
57
75
|
const entries = await Promise.all(
|
|
58
|
-
|
|
76
|
+
loadable.map(async (file): Promise<SourceEntry> => {
|
|
59
77
|
const source = await readFile(file, "utf-8");
|
|
60
78
|
const ext = extname(file).toLowerCase();
|
|
61
79
|
const format = ext === ".mdx" ? "mdx" : "md";
|
|
@@ -73,7 +91,7 @@ export const filesystemSource = (
|
|
|
73
91
|
})
|
|
74
92
|
);
|
|
75
93
|
|
|
76
|
-
return { diagnostics
|
|
94
|
+
return { diagnostics, entries };
|
|
77
95
|
};
|
|
78
96
|
|
|
79
97
|
const validate = (): void => {
|
|
@@ -83,7 +101,9 @@ export const filesystemSource = (
|
|
|
83
101
|
file: contentRoot,
|
|
84
102
|
message: `Content root not found: ${options.root}`,
|
|
85
103
|
severity: "error",
|
|
86
|
-
|
|
104
|
+
// `content.root` is rejected beside `content.sources`, so the hint
|
|
105
|
+
// names both places a root is set.
|
|
106
|
+
suggestion: `Create a "${options.root}" folder with at least one .md or .mdx file, or point Blume at your docs folder: content.root in blume.config.ts, or the filesystem() source's root when you list content.sources.`,
|
|
87
107
|
});
|
|
88
108
|
}
|
|
89
109
|
};
|
|
@@ -113,6 +133,8 @@ export const filesystemSource = (
|
|
|
113
133
|
|
|
114
134
|
return {
|
|
115
135
|
contentRoot,
|
|
136
|
+
exclude: options.exclude,
|
|
137
|
+
include: options.include,
|
|
116
138
|
load,
|
|
117
139
|
name: options.name,
|
|
118
140
|
prefix: options.prefix,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Heading, Nodes } from "mdast";
|
|
1
|
+
import type { Definition, Heading, Link, Nodes } from "mdast";
|
|
2
2
|
import { fromMarkdown } from "mdast-util-from-markdown";
|
|
3
3
|
import { gfmFromMarkdown } from "mdast-util-gfm";
|
|
4
4
|
import { toString as mdastToString } from "mdast-util-to-string";
|
|
@@ -15,6 +15,8 @@ import {
|
|
|
15
15
|
pollingWatch,
|
|
16
16
|
snapshotCache,
|
|
17
17
|
} from "./cache.ts";
|
|
18
|
+
import { destination, escapeMarkdownText } from "./lower.ts";
|
|
19
|
+
import { REMOTE_TIMEOUT_MS } from "./remote.ts";
|
|
18
20
|
import type {
|
|
19
21
|
ContentSource,
|
|
20
22
|
SourceContext,
|
|
@@ -43,6 +45,11 @@ export interface GithubReleasesSourceOptions {
|
|
|
43
45
|
prereleases?: boolean;
|
|
44
46
|
/** Repository name. */
|
|
45
47
|
repo: string;
|
|
48
|
+
/**
|
|
49
|
+
* The site's own URL (`deployment.site`). A link in the notes back to it
|
|
50
|
+
* becomes root-relative, the way a page links to another page.
|
|
51
|
+
*/
|
|
52
|
+
site?: string;
|
|
46
53
|
}
|
|
47
54
|
|
|
48
55
|
/** The subset of the GitHub release payload the adapter reads. */
|
|
@@ -164,6 +171,92 @@ const liftHeadings = (body: string): string => {
|
|
|
164
171
|
return lifted;
|
|
165
172
|
};
|
|
166
173
|
|
|
174
|
+
const WEB_PROTOCOL = /^https?:$/u;
|
|
175
|
+
const TITLE_SPECIALS = /["\\]/gu;
|
|
176
|
+
|
|
177
|
+
/** The origin of an http(s) site URL, or null when there is none. */
|
|
178
|
+
const webOrigin = (site?: string): string | null => {
|
|
179
|
+
const parsed = site ? URL.parse(site) : null;
|
|
180
|
+
return parsed && WEB_PROTOCOL.test(parsed.protocol) ? parsed.origin : null;
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
/** A link title as Markdown carries it, or nothing when there is none. */
|
|
184
|
+
const titleSuffix = (title?: string | null): string =>
|
|
185
|
+
title ? ` "${title.replaceAll(TITLE_SPECIALS, String.raw`\$&`)}"` : "";
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* The Markdown a link or definition to one of the site's own pages becomes,
|
|
189
|
+
* pointing at `path` instead. An inline link keeps its label as written, and
|
|
190
|
+
* an autolink keeps showing the URL it was written as.
|
|
191
|
+
*/
|
|
192
|
+
const rewrittenLink = (
|
|
193
|
+
markdown: string,
|
|
194
|
+
node: Definition | Link,
|
|
195
|
+
path: string
|
|
196
|
+
): string => {
|
|
197
|
+
const target = `${destination(path)}${titleSuffix(node.title)}`;
|
|
198
|
+
if (node.type === "definition") {
|
|
199
|
+
return `[${node.label ?? node.identifier}]: ${target}`;
|
|
200
|
+
}
|
|
201
|
+
const start = node.position?.start.offset ?? 0;
|
|
202
|
+
if (markdown[start] !== "[") {
|
|
203
|
+
return `[${escapeMarkdownText(mdastToString(node))}](${target})`;
|
|
204
|
+
}
|
|
205
|
+
const first = node.children.at(0)?.position?.start.offset ?? start + 1;
|
|
206
|
+
const last = node.children.at(-1)?.position?.end.offset ?? first;
|
|
207
|
+
return `[${markdown.slice(first, last)}](${target})`;
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Point the notes' links to the site itself (`https://acme.dev/docs/x` when
|
|
212
|
+
* `deployment.site` is `https://acme.dev`) at the root-relative path, as a
|
|
213
|
+
* page on the site links to another: an absolute link hardcodes production,
|
|
214
|
+
* so it leaves a preview deploy and trips `blume audit`'s own-origin check.
|
|
215
|
+
*/
|
|
216
|
+
const relativizeOwnLinks = (markdown: string, site?: string): string => {
|
|
217
|
+
const origin = webOrigin(site);
|
|
218
|
+
if (!origin) {
|
|
219
|
+
return markdown;
|
|
220
|
+
}
|
|
221
|
+
const spans: { end: number; start: number; text: string }[] = [];
|
|
222
|
+
const visit = (node: Nodes): void => {
|
|
223
|
+
if (node.type === "link" || node.type === "definition") {
|
|
224
|
+
const parsed = URL.parse(node.url);
|
|
225
|
+
if (parsed?.origin === origin) {
|
|
226
|
+
spans.push({
|
|
227
|
+
// fromMarkdown stamps every node's position.
|
|
228
|
+
end: node.position?.end.offset ?? 0,
|
|
229
|
+
start: node.position?.start.offset ?? 0,
|
|
230
|
+
text: rewrittenLink(
|
|
231
|
+
markdown,
|
|
232
|
+
node,
|
|
233
|
+
`${parsed.pathname}${parsed.search}${parsed.hash}`
|
|
234
|
+
),
|
|
235
|
+
});
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
if ("children" in node) {
|
|
240
|
+
for (const child of node.children) {
|
|
241
|
+
visit(child);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
visit(
|
|
246
|
+
fromMarkdown(markdown, {
|
|
247
|
+
extensions: [gfm()],
|
|
248
|
+
mdastExtensions: [gfmFromMarkdown()],
|
|
249
|
+
})
|
|
250
|
+
);
|
|
251
|
+
let out = "";
|
|
252
|
+
let cursor = 0;
|
|
253
|
+
for (const span of spans) {
|
|
254
|
+
out += markdown.slice(cursor, span.start) + span.text;
|
|
255
|
+
cursor = span.end;
|
|
256
|
+
}
|
|
257
|
+
return out + markdown.slice(cursor);
|
|
258
|
+
};
|
|
259
|
+
|
|
167
260
|
/** Slugify a tag into a stable, URL-safe source ref (`v1.2.0` -> `v1-2-0`). */
|
|
168
261
|
const slugifyTag = (tag: string): string =>
|
|
169
262
|
tag.toLowerCase().replaceAll(NON_SLUG, "-").replaceAll(EDGE_DASHES, "");
|
|
@@ -197,16 +290,22 @@ interface ChangelogFrontmatter {
|
|
|
197
290
|
* generated `/changelog` timeline and RSS feed, and a summary derived from the
|
|
198
291
|
* notes becomes the release page's meta description.
|
|
199
292
|
*/
|
|
200
|
-
const releaseToEntry = (release: GithubRelease): SourceEntry => {
|
|
293
|
+
const releaseToEntry = (release: GithubRelease, site?: string): SourceEntry => {
|
|
201
294
|
const version = release.tag_name.replace(LEADING_V, "");
|
|
202
295
|
const title = release.name?.trim() || release.tag_name;
|
|
203
296
|
const date = release.published_at ?? release.created_at;
|
|
204
297
|
const category = release.prerelease ? "Prerelease" : "Release";
|
|
205
298
|
// Release notes are the repository's content, not the site author's, so a
|
|
206
299
|
// link whose destination isn't a web, mail, or relative address
|
|
207
|
-
// (`javascript:`, `data:`) keeps only its label (see `safe-links.ts`)
|
|
300
|
+
// (`javascript:`, `data:`) keeps only its label (see `safe-links.ts`), and
|
|
301
|
+
// a link back to the site becomes root-relative.
|
|
208
302
|
const body = liftHeadings(
|
|
209
|
-
|
|
303
|
+
relativizeOwnLinks(
|
|
304
|
+
neutralizeUnsafeLinks(
|
|
305
|
+
(release.body ?? "").replaceAll("\r\n", "\n")
|
|
306
|
+
).trim(),
|
|
307
|
+
site
|
|
308
|
+
)
|
|
210
309
|
);
|
|
211
310
|
// A summary in `seo.description` gives each release page a unique meta
|
|
212
311
|
// description (instead of the site-wide fallback) without also rendering the
|
|
@@ -260,15 +359,33 @@ export const githubReleasesSource = (
|
|
|
260
359
|
(options.drafts || !release.draft) &&
|
|
261
360
|
(options.prereleases || !release.prerelease);
|
|
262
361
|
|
|
362
|
+
// Each page gets {@link REMOTE_TIMEOUT_MS}, body included: an API that
|
|
363
|
+
// accepts the connection and never answers would otherwise hold the scan,
|
|
364
|
+
// and so the build or every dev rescan, indefinitely. The timeout's error
|
|
365
|
+
// names the URL and the limit, so the empty-changelog warning says what
|
|
366
|
+
// stalled instead of only that an operation was aborted.
|
|
263
367
|
const fetchPage = async (page: number): Promise<GithubRelease[]> => {
|
|
264
368
|
const url = `${base}/repos/${options.owner}/${options.repo}/releases?per_page=${PER_PAGE}&page=${page}`;
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
369
|
+
try {
|
|
370
|
+
const res = await doFetch(url, {
|
|
371
|
+
headers: githubHeaders(),
|
|
372
|
+
signal: AbortSignal.timeout(REMOTE_TIMEOUT_MS),
|
|
373
|
+
});
|
|
374
|
+
if (!res.ok) {
|
|
375
|
+
throw new Error(`${url} -> ${res.status}`);
|
|
376
|
+
}
|
|
377
|
+
// SAFETY: GitHub's releases endpoint returns a JSON array of release
|
|
378
|
+
// objects; `GithubRelease` models only the fields the adapter reads.
|
|
379
|
+
return (await res.json()) as GithubRelease[];
|
|
380
|
+
} catch (error) {
|
|
381
|
+
if (error instanceof DOMException && error.name === "TimeoutError") {
|
|
382
|
+
throw new Error(
|
|
383
|
+
`${url} did not respond within ${REMOTE_TIMEOUT_MS / 1000}s`,
|
|
384
|
+
{ cause: error }
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
throw error;
|
|
268
388
|
}
|
|
269
|
-
// SAFETY: GitHub's releases endpoint returns a JSON array of release
|
|
270
|
-
// objects; `GithubRelease` models only the fields the adapter reads.
|
|
271
|
-
return (await res.json()) as GithubRelease[];
|
|
272
389
|
};
|
|
273
390
|
|
|
274
391
|
const fetchReleases = async (): Promise<GithubRelease[]> => {
|
|
@@ -295,7 +412,9 @@ export const githubReleasesSource = (
|
|
|
295
412
|
cache,
|
|
296
413
|
async () => {
|
|
297
414
|
const releases = await fetchReleases();
|
|
298
|
-
return releases.map(
|
|
415
|
+
return releases.map((release) =>
|
|
416
|
+
releaseToEntry(release, options.site)
|
|
417
|
+
);
|
|
299
418
|
},
|
|
300
419
|
refresh
|
|
301
420
|
);
|
|
@@ -347,5 +466,6 @@ export const githubReleasesSource = (
|
|
|
347
466
|
() => load()
|
|
348
467
|
)
|
|
349
468
|
: undefined,
|
|
469
|
+
withContext: (next) => githubReleasesSource(options, next),
|
|
350
470
|
};
|
|
351
471
|
};
|
|
@@ -7,17 +7,18 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import type { JsonObject } from "./json.ts";
|
|
9
9
|
import { asNumber, asObject, asString, getPath, objectsIn } from "./json.ts";
|
|
10
|
-
import type { InlineMarks } from "./lower.ts";
|
|
10
|
+
import type { InlineMarks, InlinePart } from "./lower.ts";
|
|
11
11
|
import {
|
|
12
12
|
absoluteUrl,
|
|
13
13
|
blockquote,
|
|
14
|
+
guardBlockStart,
|
|
14
15
|
headingPrefix,
|
|
15
16
|
image,
|
|
16
17
|
indent,
|
|
18
|
+
linkParts,
|
|
17
19
|
listItem,
|
|
18
20
|
markdownDocument,
|
|
19
21
|
renderInline,
|
|
20
|
-
renderLink,
|
|
21
22
|
unsupported,
|
|
22
23
|
writesMdx,
|
|
23
24
|
} from "./lower.ts";
|
|
@@ -66,45 +67,54 @@ const customBlock = (node: JsonObject, options: LexicalOptions): string => {
|
|
|
66
67
|
);
|
|
67
68
|
};
|
|
68
69
|
|
|
69
|
-
const
|
|
70
|
-
nodes
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
const inlineParts = (
|
|
71
|
+
nodes: JsonObject[],
|
|
72
|
+
options: LexicalOptions
|
|
73
|
+
): InlinePart[] =>
|
|
74
|
+
// oxlint-disable-next-line no-use-before-define -- mutual recursion: a link's label is itself inline content
|
|
75
|
+
nodes.flatMap((node) => inlineNodeParts(node, options));
|
|
74
76
|
|
|
75
|
-
const
|
|
77
|
+
const inlineNodeParts = (
|
|
76
78
|
node: JsonObject,
|
|
77
79
|
options: LexicalOptions
|
|
78
|
-
):
|
|
80
|
+
): InlinePart[] => {
|
|
79
81
|
switch (typeOf(node)) {
|
|
80
82
|
case "text": {
|
|
81
|
-
return
|
|
83
|
+
return [{ marks: marksOf(node), text: asString(node.text) ?? "" }];
|
|
82
84
|
}
|
|
83
85
|
case "linebreak": {
|
|
84
|
-
return "\n";
|
|
86
|
+
return [{ markdown: "\n" }];
|
|
85
87
|
}
|
|
86
88
|
case "tab": {
|
|
87
|
-
return "\t";
|
|
89
|
+
return [{ markdown: "\t" }];
|
|
88
90
|
}
|
|
89
91
|
case "link":
|
|
90
92
|
case "autolink": {
|
|
91
93
|
// `fields.url` on Payload 3; `url` on older Lexical payloads. An
|
|
92
94
|
// internal link (`linkType: "internal"`) carries a document, not a
|
|
93
95
|
// URL, so its label stays.
|
|
94
|
-
return
|
|
95
|
-
|
|
96
|
+
return linkParts(
|
|
97
|
+
inlineParts(children(node), options),
|
|
96
98
|
asString(getPath(node, "fields.url")) ?? asString(node.url)
|
|
97
99
|
);
|
|
98
100
|
}
|
|
99
101
|
case "inlineBlock": {
|
|
100
|
-
return customBlock(node, options);
|
|
102
|
+
return [{ markdown: customBlock(node, options) }];
|
|
101
103
|
}
|
|
102
104
|
default: {
|
|
103
|
-
return
|
|
105
|
+
return inlineParts(children(node), options);
|
|
104
106
|
}
|
|
105
107
|
}
|
|
106
108
|
};
|
|
107
109
|
|
|
110
|
+
/** Inline nodes as Markdown, guarded as one block. */
|
|
111
|
+
const inlineText = (nodes: JsonObject[], options: LexicalOptions): string =>
|
|
112
|
+
guardBlockStart(renderInline(inlineParts(nodes, options)));
|
|
113
|
+
|
|
114
|
+
/** A text block's inline children, joined and guarded as one block. */
|
|
115
|
+
const blockText = (node: JsonObject, options: LexicalOptions): string =>
|
|
116
|
+
inlineText(children(node), options);
|
|
117
|
+
|
|
108
118
|
const renderUpload = (node: JsonObject, options: LexicalOptions): string => {
|
|
109
119
|
const value = asObject(node.value);
|
|
110
120
|
const url = value ? asString(value.url) : undefined;
|
|
@@ -140,7 +150,7 @@ const renderList = (node: JsonObject, options: LexicalOptions): string => {
|
|
|
140
150
|
if (listType === "check") {
|
|
141
151
|
check = item.checked === true ? "[x] " : "[ ] ";
|
|
142
152
|
}
|
|
143
|
-
const line = `${check}${
|
|
153
|
+
const line = `${check}${inlineText(inline, options)}`;
|
|
144
154
|
items.push(listItem(lastMarker, sub ? `${line}\n${sub}` : line));
|
|
145
155
|
index += 1;
|
|
146
156
|
}
|
|
@@ -150,14 +160,14 @@ const renderList = (node: JsonObject, options: LexicalOptions): string => {
|
|
|
150
160
|
const renderBlock = (node: JsonObject, options: LexicalOptions): string => {
|
|
151
161
|
switch (typeOf(node)) {
|
|
152
162
|
case "paragraph": {
|
|
153
|
-
return
|
|
163
|
+
return blockText(node, options);
|
|
154
164
|
}
|
|
155
165
|
case "heading": {
|
|
156
166
|
const level = Number((asString(node.tag) ?? "h1").slice(1));
|
|
157
|
-
return `${headingPrefix(level)}${
|
|
167
|
+
return `${headingPrefix(level)}${blockText(node, options)}`;
|
|
158
168
|
}
|
|
159
169
|
case "quote": {
|
|
160
|
-
return blockquote(
|
|
170
|
+
return blockquote(blockText(node, options));
|
|
161
171
|
}
|
|
162
172
|
case "list": {
|
|
163
173
|
return renderList(node, options);
|