blume 1.7.3 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +19 -0
- package/CHANGELOG.md +245 -0
- package/README.md +34 -21
- package/dist/cli/{chunk-vacwm2hv.js → chunk-27g6wdth.js} +2 -2
- package/dist/cli/{chunk-ps4m1xh4.js → chunk-2hn4b8z7.js} +513 -550
- package/dist/cli/chunk-2hn4b8z7.js.map +12 -0
- package/dist/cli/chunk-5shv93fd.js +39 -0
- package/dist/cli/chunk-5shv93fd.js.map +10 -0
- package/dist/cli/chunk-6crbhc3x.js +361 -0
- package/dist/cli/chunk-6crbhc3x.js.map +14 -0
- package/dist/cli/{chunk-8cjtbafj.js → chunk-6hsn950k.js} +109 -383
- package/dist/cli/chunk-6hsn950k.js.map +10 -0
- package/dist/cli/chunk-6vm74dry.js +148 -0
- package/dist/cli/chunk-6vm74dry.js.map +10 -0
- package/dist/cli/{chunk-yg63d42r.js → chunk-79jhk4py.js} +87 -58
- package/dist/cli/chunk-79jhk4py.js.map +35 -0
- package/dist/cli/chunk-82bbrxdn.js +51 -0
- package/dist/cli/chunk-82bbrxdn.js.map +10 -0
- package/dist/cli/chunk-abh8yjkn.js +31 -0
- package/dist/cli/chunk-abh8yjkn.js.map +10 -0
- package/dist/cli/chunk-ah61y8py.js +75 -0
- package/dist/cli/chunk-ah61y8py.js.map +11 -0
- package/dist/cli/{chunk-dwgcp5sm.js → chunk-ce574jw2.js} +1 -1
- package/dist/cli/chunk-ch6g3ar0.js +102 -0
- package/dist/cli/chunk-ch6g3ar0.js.map +10 -0
- package/dist/cli/chunk-dh8cwk36.js +279 -0
- package/dist/cli/chunk-dh8cwk36.js.map +10 -0
- package/dist/cli/{chunk-rqy0s5wh.js → chunk-epjnccmv.js} +17 -16
- package/dist/cli/{chunk-rqy0s5wh.js.map → chunk-epjnccmv.js.map} +3 -3
- package/dist/cli/chunk-f2z5v128.js +97 -0
- package/dist/cli/chunk-f2z5v128.js.map +10 -0
- package/dist/cli/{chunk-2z47ypj8.js → chunk-fa25z98p.js} +16 -3
- package/dist/cli/chunk-fa25z98p.js.map +11 -0
- package/dist/cli/{chunk-1jefwnfs.js → chunk-fs23ddbb.js} +1076 -2592
- package/dist/cli/chunk-fs23ddbb.js.map +35 -0
- package/dist/cli/{chunk-e7f42gdj.js → chunk-fxypxtvm.js} +2 -2
- package/dist/cli/{chunk-bvwwhd84.js → chunk-fz5wtpmh.js} +15 -15
- package/dist/cli/{chunk-bvwwhd84.js.map → chunk-fz5wtpmh.js.map} +1 -1
- package/dist/cli/chunk-hdpx1tax.js +91 -0
- package/dist/cli/chunk-hdpx1tax.js.map +10 -0
- package/dist/cli/{chunk-ct47dqpx.js → chunk-jts8mvcz.js} +67 -7
- package/dist/cli/{chunk-2mzebbbz.js.map → chunk-jts8mvcz.js.map} +6 -4
- package/dist/cli/{chunk-ahnw3kxw.js → chunk-jwyddg7y.js} +27 -22
- package/dist/cli/chunk-jwyddg7y.js.map +15 -0
- package/dist/cli/{chunk-cjtn640a.js → chunk-kdp5q7ke.js} +43 -20
- package/dist/cli/chunk-kdp5q7ke.js.map +10 -0
- package/dist/cli/{chunk-5g0w1e2c.js → chunk-kpf8rrjc.js} +28 -16
- package/dist/cli/{chunk-5g0w1e2c.js.map → chunk-kpf8rrjc.js.map} +4 -4
- package/dist/cli/chunk-m3vmjgmq.js +133 -0
- package/dist/cli/chunk-m3vmjgmq.js.map +10 -0
- package/dist/cli/{chunk-b27xqwn9.js → chunk-mb2919y2.js} +9 -5
- package/dist/cli/chunk-mb2919y2.js.map +10 -0
- package/dist/cli/{chunk-5qk08vmp.js → chunk-q5163e60.js} +133 -54
- package/dist/cli/chunk-q5163e60.js.map +11 -0
- package/dist/cli/chunk-qkqwkpte.js +12437 -0
- package/dist/cli/chunk-qkqwkpte.js.map +182 -0
- package/dist/cli/{chunk-4x36ddpw.js → chunk-qs4q5p4e.js} +81 -87
- package/dist/cli/chunk-qs4q5p4e.js.map +10 -0
- package/dist/cli/{chunk-0xjyb285.js → chunk-qwsrynx5.js} +15 -5
- package/dist/cli/{chunk-0xjyb285.js.map → chunk-qwsrynx5.js.map} +4 -4
- package/dist/cli/chunk-s1p84fyh.js +261 -0
- package/dist/cli/chunk-s1p84fyh.js.map +10 -0
- package/dist/cli/chunk-s6jhgk0q.js +176 -0
- package/dist/cli/chunk-s6jhgk0q.js.map +11 -0
- package/dist/cli/chunk-vtk4a6dg.js +374 -0
- package/dist/cli/chunk-vtk4a6dg.js.map +10 -0
- package/dist/cli/{chunk-k79xp7av.js → chunk-wgm7m9qk.js} +230 -700
- package/dist/cli/chunk-wgm7m9qk.js.map +36 -0
- package/dist/cli/chunk-wm7js3j9.js +145 -0
- package/dist/cli/chunk-wm7js3j9.js.map +11 -0
- package/dist/cli/chunk-yt5n7ppj.js +79 -0
- package/dist/cli/chunk-yt5n7ppj.js.map +10 -0
- package/dist/cli/{chunk-3r45185y.js → chunk-yw7dm696.js} +9 -11
- package/dist/cli/{chunk-3r45185y.js.map → chunk-yw7dm696.js.map} +3 -3
- package/dist/cli/{chunk-nn13znc2.js → chunk-zxcczpyx.js} +1 -1
- package/dist/cli/chunk-zxh4d9vy.js +122 -0
- package/dist/cli/chunk-zxh4d9vy.js.map +11 -0
- package/dist/cli/index.js +214 -57
- package/dist/cli/index.js.map +8 -7
- package/dist/types/ai/agent-readability.d.ts +52 -0
- package/dist/types/ai/ai-catalog.d.ts +42 -0
- package/dist/types/ai/api/paths.d.ts +17 -0
- package/dist/types/ai/api-catalog.d.ts +18 -0
- package/dist/types/ai/ask-context.d.ts +7 -7
- package/dist/types/ai/ask.d.ts +368 -0
- package/dist/types/ai/changelog-markdown.d.ts +2 -0
- package/dist/types/ai/component-markdown.d.ts +2 -2
- package/dist/types/ai/index.d.ts +24 -0
- package/dist/types/ai/link-headers.d.ts +24 -0
- package/dist/types/ai/llms.d.ts +25 -0
- package/dist/types/ai/markdown.d.ts +45 -0
- package/dist/types/ai/mcp/discovery.d.ts +68 -0
- package/dist/types/ai/mcp/tools.d.ts +16 -0
- package/dist/types/ai/openapi-components.d.ts +43 -0
- package/dist/types/ai/relative-links.d.ts +26 -0
- package/dist/types/ai/serializers.d.ts +15 -0
- package/dist/types/ai/skills.d.ts +42 -0
- package/dist/types/ai/tar.d.ts +25 -0
- package/dist/types/ai/visibility.d.ts +17 -0
- package/dist/types/ai/web-bot-auth.d.ts +16 -0
- package/dist/types/analytics/adobe.d.ts +35 -0
- package/dist/types/analytics/amplitude.d.ts +50 -0
- package/dist/types/analytics/clarity.d.ts +31 -0
- package/dist/types/analytics/clearbit.d.ts +29 -0
- package/dist/types/analytics/cloudflare.d.ts +41 -0
- package/dist/types/analytics/fathom.d.ts +41 -0
- package/dist/types/analytics/google-analytics.d.ts +44 -0
- package/dist/types/analytics/google-tag-manager.d.ts +40 -0
- package/dist/types/analytics/head.d.ts +30 -0
- package/dist/types/analytics/heap.d.ts +40 -0
- package/dist/types/analytics/hightouch.d.ts +44 -0
- package/dist/types/analytics/hotjar.d.ts +33 -0
- package/dist/types/analytics/index.d.ts +61 -0
- package/dist/types/analytics/inline.d.ts +17 -0
- package/dist/types/analytics/logrocket.d.ts +44 -0
- package/dist/types/analytics/mixpanel.d.ts +67 -0
- package/dist/types/analytics/pirsch.d.ts +42 -0
- package/dist/types/analytics/plausible.d.ts +56 -0
- package/dist/types/analytics/posthog.d.ts +45 -0
- package/dist/types/analytics/schema.d.ts +320 -0
- package/dist/types/analytics/script.d.ts +46 -0
- package/dist/types/analytics/segment.d.ts +50 -0
- package/dist/types/analytics/vercel.d.ts +48 -0
- package/dist/types/astro/integration.d.ts +76 -0
- package/dist/types/astro/markdown-negotiation.d.ts +23 -0
- package/dist/types/astro/module-types.d.ts +14 -0
- package/dist/types/astro/pages.d.ts +44 -0
- package/dist/types/cli/env.d.ts +12 -0
- package/dist/types/cli/init/scaffold.d.ts +154 -0
- package/dist/types/components/layout/nav-utils.d.ts +11 -0
- package/dist/types/core/adapter.d.ts +47 -0
- package/dist/types/core/api-name.d.ts +7 -0
- package/dist/types/core/changelog-index.d.ts +13 -0
- package/dist/types/core/config-input.d.ts +197 -526
- package/dist/types/core/config.d.ts +61 -35
- package/dist/types/core/content-assets.d.ts +76 -0
- package/dist/types/core/custom-pages.d.ts +33 -0
- package/dist/types/core/data.d.ts +30 -15
- package/dist/types/core/define-components.d.ts +12 -9
- package/dist/types/core/deployment-env.d.ts +6 -11
- package/dist/types/core/frontmatter.d.ts +10 -0
- package/dist/types/core/graph.d.ts +18 -0
- package/dist/types/core/heading-markers.d.ts +54 -0
- package/dist/types/core/i18n-ui.d.ts +12 -10
- package/dist/types/core/i18n.d.ts +87 -0
- package/dist/types/core/includes.d.ts +138 -0
- package/dist/types/core/last-modified.d.ts +47 -0
- package/dist/types/core/links.d.ts +95 -0
- package/dist/types/core/locale-links.d.ts +60 -0
- package/dist/types/core/manifest.d.ts +17 -0
- package/dist/types/core/meta.d.ts +38 -0
- package/dist/types/core/nav-diagnostics.d.ts +26 -0
- package/dist/types/core/navigation.d.ts +6 -0
- package/dist/types/core/node-require.d.ts +19 -0
- package/dist/types/core/package-json.d.ts +13 -0
- package/dist/types/core/probe.d.ts +42 -0
- package/dist/types/core/project-graph.d.ts +51 -0
- package/dist/types/core/project.d.ts +2 -0
- package/dist/types/core/safe-href.d.ts +2 -0
- package/dist/types/core/safe-links.d.ts +26 -0
- package/dist/types/core/schema.d.ts +2284 -454
- package/dist/types/core/site-url.d.ts +16 -0
- package/dist/types/core/sources/assets.d.ts +36 -0
- package/dist/types/core/sources/cache.d.ts +37 -0
- package/dist/types/core/sources/collection.d.ts +28 -0
- package/dist/types/core/sources/contentful-rich-text.d.ts +31 -0
- package/dist/types/core/sources/contentful.d.ts +40 -0
- package/dist/types/core/sources/filesystem.d.ts +24 -0
- package/dist/types/core/sources/github-releases.d.ts +31 -0
- package/dist/types/core/sources/json.d.ts +30 -0
- package/dist/types/core/sources/lexical.d.ts +19 -0
- package/dist/types/core/sources/lower.d.ts +75 -0
- package/dist/types/core/sources/mdx-remote.d.ts +28 -0
- package/dist/types/core/sources/normalize.d.ts +147 -0
- package/dist/types/core/sources/notion.d.ts +131 -0
- package/dist/types/core/sources/obsidian.d.ts +46 -0
- package/dist/types/core/sources/payload.d.ts +39 -0
- package/dist/types/core/sources/portable-text.d.ts +42 -0
- package/dist/types/core/sources/read.d.ts +23 -0
- package/dist/types/core/sources/remote.d.ts +74 -0
- package/dist/types/core/sources/resolve.d.ts +19 -0
- package/dist/types/core/sources/sanity.d.ts +43 -0
- package/dist/types/core/sources/strapi-blocks.d.ts +12 -0
- package/dist/types/core/sources/strapi.d.ts +33 -0
- package/dist/types/core/sources/types.d.ts +7 -0
- package/dist/types/core/sources/watch.d.ts +45 -0
- package/dist/types/core/text-width.d.ts +11 -0
- package/dist/types/core/types.d.ts +15 -1
- package/dist/types/core/unrecognized-keys.d.ts +7 -0
- package/dist/types/core/versions.d.ts +72 -0
- package/dist/types/core/yaml.d.ts +9 -0
- package/dist/types/deploy/adapter-output.d.ts +45 -0
- package/dist/types/deploy/adapters/cloudflare.d.ts +40 -0
- package/dist/types/deploy/adapters/index.d.ts +29 -0
- package/dist/types/deploy/adapters/netlify.d.ts +37 -0
- package/dist/types/deploy/adapters/node.d.ts +37 -0
- package/dist/types/deploy/adapters/registry.d.ts +133 -0
- package/dist/types/deploy/adapters/types.d.ts +71 -0
- package/dist/types/deploy/adapters/vercel.d.ts +38 -0
- package/dist/types/deploy/artifacts.d.ts +65 -0
- package/dist/types/deploy/cloudflare-negotiation.d.ts +196 -0
- package/dist/types/deploy/function-bundle.d.ts +80 -0
- package/dist/types/deploy/headers.d.ts +50 -0
- package/dist/types/deploy/node-headers.d.ts +42 -0
- package/dist/types/deploy/platforms/cloudflare.d.ts +40 -0
- package/dist/types/deploy/platforms/index.d.ts +18 -0
- package/dist/types/deploy/platforms/netlify.d.ts +13 -0
- package/dist/types/deploy/platforms/node.d.ts +11 -0
- package/dist/types/deploy/platforms/paths.d.ts +27 -0
- package/dist/types/deploy/platforms/static.d.ts +10 -0
- package/dist/types/deploy/platforms/types.d.ts +104 -0
- package/dist/types/deploy/platforms/vercel.d.ts +32 -0
- package/dist/types/deploy/redirects.d.ts +53 -0
- package/dist/types/deploy/robots.d.ts +8 -0
- package/dist/types/deploy/rss.d.ts +31 -0
- package/dist/types/deploy/sitemap.d.ts +21 -0
- package/dist/types/deploy/vercel-negotiation.d.ts +109 -0
- package/dist/types/markdown/code-title.d.ts +32 -0
- package/dist/types/markdown/fence-meta.d.ts +23 -0
- package/dist/types/markdown/themes.d.ts +3 -3
- package/dist/types/openapi/asyncapi.d.ts +129 -0
- package/dist/types/openapi/graphql-build.d.ts +8 -0
- package/dist/types/openapi/graphql.d.ts +122 -0
- package/dist/types/openapi/model.d.ts +158 -0
- package/dist/types/openapi/parse.d.ts +57 -0
- package/dist/types/openapi/references.d.ts +37 -25
- package/dist/types/openapi/render-mdx.d.ts +33 -0
- package/dist/types/openapi/sentence.d.ts +7 -0
- package/dist/types/openapi/signature.d.ts +10 -0
- package/dist/types/openapi/source.d.ts +22 -0
- package/dist/types/openapi/spec-dependency-error.d.ts +10 -0
- package/dist/types/reference/asyncapi.d.ts +166 -0
- package/dist/types/reference/graphql.d.ts +181 -0
- package/dist/types/reference/index.d.ts +32 -0
- package/dist/types/reference/openapi.d.ts +165 -0
- package/dist/types/reference/options.d.ts +157 -0
- package/dist/types/reference/scalar.d.ts +136 -0
- package/dist/types/reference/schema.d.ts +630 -0
- package/dist/types/search/adapters/algolia.d.ts +32 -0
- package/dist/types/search/adapters/flexsearch.d.ts +12 -0
- package/dist/types/search/adapters/index.d.ts +31 -0
- package/dist/types/search/adapters/mixedbread.d.ts +22 -0
- package/dist/types/search/adapters/orama-cloud.d.ts +33 -0
- package/dist/types/search/adapters/orama.d.ts +13 -0
- package/dist/types/search/adapters/pagefind.d.ts +12 -0
- package/dist/types/search/adapters/registry.d.ts +228 -0
- package/dist/types/search/adapters/types.d.ts +34 -0
- package/dist/types/search/adapters/typesense.d.ts +42 -0
- package/dist/types/search/build.d.ts +23 -0
- package/dist/types/search/documents.d.ts +90 -0
- package/dist/types/search/facets.d.ts +3 -0
- package/dist/types/search/orama-index.d.ts +1 -1
- package/dist/types/search/sync/algolia.d.ts +14 -0
- package/dist/types/search/sync/index.d.ts +14 -0
- package/dist/types/search/sync/orama-cloud.d.ts +10 -0
- package/dist/types/search/sync/typesense.d.ts +14 -0
- package/dist/types/sources/contentful.d.ts +68 -0
- package/dist/types/sources/custom.d.ts +20 -0
- package/dist/types/sources/filesystem.d.ts +42 -0
- package/dist/types/sources/github-releases.d.ts +46 -0
- package/dist/types/sources/index.d.ts +48 -0
- package/dist/types/sources/mdx-remote.d.ts +63 -0
- package/dist/types/sources/notion.d.ts +65 -0
- package/dist/types/sources/obsidian.d.ts +34 -0
- package/dist/types/sources/payload.d.ts +68 -0
- package/dist/types/sources/registry.d.ts +1414 -0
- package/dist/types/sources/sanity.d.ts +69 -0
- package/dist/types/sources/shared.d.ts +46 -0
- package/dist/types/sources/strapi.d.ts +66 -0
- package/dist/types/theme/icon-kind.d.ts +11 -0
- package/dist/types/theme/icons.d.ts +20 -0
- package/docs/01-quickstart.mdx +18 -18
- package/docs/02-deployment.mdx +52 -28
- package/docs/03-upgrading.mdx +364 -0
- package/docs/04-migrating.mdx +58 -0
- package/docs/08-faq.mdx +5 -5
- package/docs/advanced/blog.mdx +13 -6
- package/docs/advanced/changelog.mdx +23 -35
- package/docs/advanced/custom-pages.mdx +22 -10
- package/docs/advanced/meta.ts +1 -8
- package/docs/advanced/skills.mdx +8 -0
- package/docs/cli/audit.mdx +646 -0
- package/docs/cli/doctor.mdx +29 -0
- package/docs/{reference/eval.mdx → cli/evals.mdx} +12 -11
- package/docs/cli/index.mdx +105 -0
- package/docs/cli/meta.ts +7 -0
- package/docs/{reference → cli}/translate.mdx +9 -9
- package/docs/cli/validate.mdx +41 -0
- package/docs/cli/version.mdx +40 -0
- package/docs/configuration/analytics.mdx +350 -59
- package/docs/configuration/assistant.mdx +357 -0
- package/docs/configuration/customization.mdx +16 -10
- package/docs/configuration/index.mdx +50 -31
- package/docs/configuration/meta.ts +1 -1
- package/docs/configuration/search.mdx +76 -55
- package/docs/configuration/theming.mdx +24 -15
- package/docs/content/components.mdx +21 -5
- package/docs/{reference → content}/frontmatter.mdx +35 -1
- package/docs/content/i18n.mdx +9 -7
- package/docs/content/includes.mdx +2 -4
- package/docs/content/index.mdx +1 -1
- package/docs/content/islands.mdx +11 -6
- package/docs/content/meta.mdx +1 -1
- package/docs/content/meta.ts +1 -0
- package/docs/content/navigation.mdx +9 -7
- package/docs/content/sources.mdx +145 -50
- package/docs/content/syntax.mdx +16 -12
- package/docs/content/versioning.mdx +3 -3
- package/docs/discoverability/agent-discovery.mdx +12 -12
- package/docs/discoverability/index.mdx +4 -4
- package/docs/discoverability/json-api.mdx +4 -4
- package/docs/discoverability/llms-txt.mdx +6 -6
- package/docs/discoverability/markdown.mdx +4 -4
- package/docs/discoverability/mcp.mdx +11 -11
- package/docs/discoverability/sitemap-and-robots.mdx +3 -3
- package/docs/index.mdx +4 -4
- package/docs/references/asyncapi.mdx +59 -0
- package/docs/{advanced → references}/graphql.mdx +45 -32
- package/docs/{reference → references}/meta.ts +2 -2
- package/docs/references/openapi.mdx +171 -0
- package/docs/references/scalar.mdx +64 -0
- package/package.json +42 -8
- package/skills/blume/SKILL.md +23 -10
- package/skills/blume-migrate/SKILL.md +22 -21
- package/skills/blume-migrate/assets/oxfmt@0.67.0.patch +49 -0
- package/skills/blume-migrate/references/docusaurus.md +5 -4
- package/skills/blume-migrate/references/fumadocs.md +4 -4
- package/skills/blume-migrate/references/mintlify.md +23 -8
- package/skills/blume-migrate/references/monorepo.md +6 -6
- package/skills/blume-migrate/references/starlight.md +4 -4
- package/src/ai/agent-readability.ts +25 -26
- package/src/ai/ai-catalog.ts +50 -32
- package/src/ai/api/handlers.ts +46 -11
- package/src/ai/api/paths.ts +1 -1
- package/src/ai/api-catalog.ts +8 -8
- package/src/ai/ask-context.ts +7 -7
- package/src/ai/ask-data.ts +3 -3
- package/src/ai/ask.ts +637 -100
- package/src/ai/changelog-markdown.ts +91 -0
- package/src/ai/component-markdown.ts +328 -12
- package/src/ai/cors.ts +3 -3
- package/src/ai/index.ts +45 -0
- package/src/ai/link-headers.ts +7 -6
- package/src/ai/llms.ts +20 -15
- package/src/ai/markdown.ts +35 -5
- package/src/ai/mcp/data.ts +9 -5
- package/src/ai/openapi-components.ts +5 -2
- package/src/ai/relative-links.ts +170 -0
- package/src/ai/serializers.ts +3 -3
- package/src/ai/skills.ts +1 -1
- package/src/ai/visibility.ts +1 -1
- package/src/ai/web-bot-auth.ts +2 -2
- package/src/analytics/adobe.ts +46 -0
- package/src/analytics/amplitude.ts +79 -0
- package/src/analytics/clarity.ts +46 -0
- package/src/analytics/clearbit.ts +47 -0
- package/src/analytics/cloudflare.ts +67 -0
- package/src/analytics/fathom.ts +64 -0
- package/src/analytics/google-analytics.ts +84 -0
- package/src/analytics/google-tag-manager.ts +61 -0
- package/src/analytics/head.ts +130 -0
- package/src/analytics/heap.ts +65 -0
- package/src/analytics/hightouch.ts +77 -0
- package/src/analytics/hotjar.ts +47 -0
- package/src/analytics/index.ts +71 -0
- package/src/analytics/inline.ts +21 -0
- package/src/analytics/logrocket.ts +71 -0
- package/src/analytics/mixpanel.ts +92 -0
- package/src/analytics/pirsch.ts +66 -0
- package/src/analytics/plausible.ts +83 -0
- package/src/analytics/posthog.ts +78 -0
- package/src/analytics/schema.ts +60 -0
- package/src/analytics/script.ts +60 -0
- package/src/analytics/segment.ts +85 -0
- package/src/analytics/vercel.ts +50 -0
- package/src/astro/adapter-root.ts +7 -9
- package/src/astro/component-slots.ts +131 -91
- package/src/astro/generate.ts +129 -361
- package/src/astro/integration.ts +2 -6
- package/src/astro/module-types.ts +1 -1
- package/src/astro/pages.ts +13 -101
- package/src/astro/render-deps.ts +379 -0
- package/src/astro/runtime-deps.ts +201 -0
- package/src/astro/templates.ts +575 -562
- package/src/audit/agent.ts +24 -0
- package/src/audit/catalog.ts +2 -2
- package/src/audit/checks/assets.ts +2 -2
- package/src/audit/checks/dns-aid.ts +1 -1
- package/src/audit/checks/duplicates.ts +3 -1
- package/src/audit/checks/i18n.ts +1 -1
- package/src/audit/checks/indexability.ts +7 -7
- package/src/audit/checks/links.ts +2 -2
- package/src/audit/checks/llms.ts +6 -6
- package/src/audit/checks/network.ts +3 -3
- package/src/audit/checks/og-image.ts +2 -2
- package/src/audit/checks/robots.ts +1 -1
- package/src/audit/checks/sitemap.ts +2 -2
- package/src/audit/checks/social.ts +1 -1
- package/src/audit/run.ts +4 -3
- package/src/audit/terms.ts +31 -0
- package/src/audit/url.ts +13 -13
- package/src/blume-modules.d.ts +2 -2
- package/src/cli/command-meta.ts +10 -0
- package/src/cli/commands/audit.ts +40 -21
- package/src/cli/commands/build.ts +71 -316
- package/src/cli/commands/check.ts +1 -0
- package/src/cli/commands/dev.ts +40 -1
- package/src/cli/commands/doctor.ts +92 -14
- package/src/cli/commands/eject.ts +44 -7
- package/src/cli/commands/eval.ts +5 -5
- package/src/cli/commands/init.ts +161 -41
- package/src/cli/commands/migrate.ts +121 -0
- package/src/cli/commands/preview.ts +7 -1
- package/src/cli/commands/translate.ts +5 -5
- package/src/cli/commands/upgrade.ts +141 -0
- package/src/cli/commands/version.ts +57 -44
- package/src/cli/eject-scripts.ts +121 -6
- package/src/cli/index.ts +11 -1
- package/src/cli/init/install.ts +70 -0
- package/src/cli/init/questions.ts +7 -0
- package/src/cli/init/scaffold.ts +459 -75
- package/src/cli/lazy-command.ts +37 -1
- package/src/cli/prepare.ts +40 -6
- package/src/cli/required-secrets.ts +39 -12
- package/src/cli/unknown-flags.ts +266 -0
- package/src/cli/yarn-pnp.ts +52 -0
- package/src/components/content/AccordionItem.astro +7 -1
- package/src/components/content/Card.astro +4 -3
- package/src/components/content/ColorItem.astro +22 -4
- package/src/components/content/GithubInfo.astro +2 -2
- package/src/components/content/Prompt.astro +25 -25
- package/src/components/content/Tabs.astro +3 -1
- package/src/components/content/Tile.astro +2 -3
- package/src/components/content/Tooltip.astro +57 -9
- package/src/components/content/content-strings.ts +34 -0
- package/src/components/content/diff.ts +1 -1
- package/src/components/content/mermaid-element.ts +13 -2
- package/src/components/content/prompt-markdown.ts +292 -0
- package/src/components/content/tooltip-id.ts +41 -0
- package/src/components/copy-feedback.ts +1 -1
- package/src/components/islands/{AskAI.astro → Assistant.astro} +10 -10
- package/src/components/islands/{ask-ai.tsx → assistant.tsx} +23 -23
- package/src/components/islands/hooks.ts +36 -11
- package/src/components/layout/Analytics.astro +21 -79
- package/src/components/layout/Banner.astro +3 -1
- package/src/components/layout/DiscoveryLinks.astro +69 -0
- package/src/components/layout/Header.astro +93 -30
- package/src/components/layout/LanguageSwitcher.astro +4 -1
- package/src/components/layout/Logo.astro +23 -2
- package/src/components/layout/NavSelector.astro +13 -2
- package/src/components/layout/NavTree.astro +12 -3
- package/src/components/layout/NavTreeScript.astro +17 -3
- package/src/components/layout/PageActions.astro +3 -3
- package/src/components/layout/PageFeedback.astro +11 -1
- package/src/components/layout/PageLayout.astro +58 -11
- package/src/components/layout/Pagination.astro +7 -7
- package/src/components/layout/ReferenceLayout.astro +22 -13
- package/src/components/layout/RootLayout.astro +75 -72
- package/src/components/layout/Search.astro +43 -19
- package/src/components/layout/WebMcp.astro +1 -1
- package/src/components/layout/analytics-client.ts +73 -16
- package/src/components/layout/drawer-inert.ts +113 -15
- package/src/components/layout/dropdown-clamp.ts +105 -0
- package/src/components/layout/head-scripts.ts +15 -6
- package/src/components/layout/nav-utils.ts +17 -0
- package/src/components/layout/search/algolia.ts +8 -8
- package/src/components/layout/search/orama-cloud.ts +9 -7
- package/src/components/layout/search/typesense.ts +11 -17
- package/src/components/openapi/MessageComposer.astro +2 -2
- package/src/components/openapi/Playground.astro +2 -2
- package/src/components/openapi/description.ts +2 -2
- package/src/components/openapi/playground-client.ts +79 -10
- package/src/core/changelog-index.ts +24 -0
- package/src/core/code-fences.ts +1 -1
- package/src/core/component-overrides.ts +399 -154
- package/src/core/config-input.ts +201 -566
- package/src/core/config.ts +131 -42
- package/src/core/custom-pages.ts +105 -0
- package/src/core/data.ts +34 -15
- package/src/core/define-components.ts +12 -9
- package/src/core/deployment-env.ts +18 -74
- package/src/core/diagnostics.ts +14 -7
- package/src/core/graph.ts +69 -25
- package/src/core/i18n-ui.ts +41 -11
- package/src/core/i18n.ts +17 -0
- package/src/core/includes.ts +156 -38
- package/src/core/last-modified.ts +6 -11
- package/src/core/links.ts +166 -2
- package/src/core/manifest.ts +10 -3
- package/src/core/navigation.ts +115 -16
- package/src/core/new-tab.ts +35 -0
- package/src/core/node-require.ts +21 -0
- package/src/core/project-graph.ts +42 -26
- package/src/core/project.ts +9 -4
- package/src/core/request-body.ts +61 -0
- package/src/core/safe-href.ts +28 -0
- package/src/core/safe-links.ts +68 -0
- package/src/core/schema.ts +528 -745
- package/src/core/server-features.ts +10 -11
- package/src/core/sources/assets.ts +47 -11
- package/src/core/sources/collection.ts +67 -0
- package/src/core/sources/contentful-rich-text.ts +285 -0
- package/src/core/sources/contentful.ts +173 -0
- package/src/core/sources/github-releases.ts +51 -1
- package/src/core/sources/json.ts +71 -0
- package/src/core/sources/lexical.ts +195 -0
- package/src/core/sources/lower.ts +226 -0
- package/src/core/sources/normalize.ts +52 -2
- package/src/core/sources/notion.ts +39 -28
- package/src/core/sources/payload.ts +135 -0
- package/src/core/sources/portable-text.ts +11 -16
- package/src/core/sources/remote.ts +226 -0
- package/src/core/sources/resolve.ts +104 -166
- package/src/core/sources/sanity.ts +16 -49
- package/src/core/sources/strapi-blocks.ts +124 -0
- package/src/core/sources/strapi.ts +191 -0
- package/src/core/sources/types.ts +12 -1
- package/src/core/types.ts +15 -1
- package/src/core/ui-packs/ar.ts +10 -7
- package/src/core/ui-packs/bg.ts +10 -7
- package/src/core/ui-packs/bn.ts +10 -7
- package/src/core/ui-packs/ca.ts +7 -6
- package/src/core/ui-packs/cs.ts +10 -7
- package/src/core/ui-packs/da.ts +10 -7
- package/src/core/ui-packs/de.ts +10 -7
- package/src/core/ui-packs/el.ts +7 -6
- package/src/core/ui-packs/es.ts +7 -6
- package/src/core/ui-packs/fa.ts +10 -7
- package/src/core/ui-packs/fi.ts +10 -7
- package/src/core/ui-packs/fr.ts +7 -6
- package/src/core/ui-packs/he.ts +10 -7
- package/src/core/ui-packs/hi.ts +10 -7
- package/src/core/ui-packs/hr.ts +10 -7
- package/src/core/ui-packs/hu.ts +10 -7
- package/src/core/ui-packs/id.ts +10 -7
- package/src/core/ui-packs/it.ts +7 -6
- package/src/core/ui-packs/ja.ts +7 -6
- package/src/core/ui-packs/ko.ts +7 -6
- package/src/core/ui-packs/nl.ts +10 -7
- package/src/core/ui-packs/no.ts +10 -7
- package/src/core/ui-packs/pl.ts +10 -7
- package/src/core/ui-packs/pt-br.ts +7 -6
- package/src/core/ui-packs/pt.ts +7 -6
- package/src/core/ui-packs/ro.ts +10 -7
- package/src/core/ui-packs/ru.ts +10 -7
- package/src/core/ui-packs/sk.ts +10 -7
- package/src/core/ui-packs/sr.ts +10 -7
- package/src/core/ui-packs/sv.ts +10 -7
- package/src/core/ui-packs/th.ts +7 -6
- package/src/core/ui-packs/tr.ts +10 -7
- package/src/core/ui-packs/uk.ts +10 -7
- package/src/core/ui-packs/vi.ts +7 -6
- package/src/core/ui-packs/zh-tw.ts +7 -6
- package/src/core/ui-packs/zh.ts +7 -6
- package/src/core/unrecognized-keys.ts +10 -0
- package/src/core/version-cut.ts +116 -8
- package/src/deploy/adapter-output.ts +57 -97
- package/src/deploy/adapters/cloudflare.ts +39 -0
- package/src/deploy/adapters/index.ts +41 -0
- package/src/deploy/adapters/netlify.ts +34 -0
- package/src/deploy/adapters/node.ts +34 -0
- package/src/deploy/adapters/registry.ts +127 -0
- package/src/deploy/adapters/types.ts +92 -0
- package/src/deploy/adapters/vercel.ts +35 -0
- package/src/deploy/artifacts.ts +55 -27
- package/src/deploy/cloudflare-negotiation.ts +179 -100
- package/src/deploy/function-bundle.ts +18 -3
- package/src/deploy/headers.ts +124 -23
- package/src/deploy/node-headers.ts +198 -0
- package/src/deploy/platforms/cloudflare.ts +312 -0
- package/src/deploy/platforms/index.ts +67 -0
- package/src/deploy/platforms/netlify.ts +52 -0
- package/src/deploy/platforms/node.ts +40 -0
- package/src/deploy/platforms/paths.ts +42 -0
- package/src/deploy/platforms/static.ts +29 -0
- package/src/deploy/platforms/types.ts +112 -0
- package/src/deploy/platforms/vercel.ts +193 -0
- package/src/deploy/redirects.ts +30 -18
- package/src/deploy/robots.ts +3 -3
- package/src/deploy/rss.ts +2 -2
- package/src/deploy/sitemap.ts +2 -2
- package/src/deploy/vercel-negotiation.ts +2 -2
- package/src/eval/agents.ts +32 -1
- package/src/eval/findings.ts +19 -11
- package/src/eval/report.ts +10 -2
- package/src/markdown/external-links.ts +65 -0
- package/src/markdown/include.ts +45 -27
- package/src/markdown/index.ts +34 -9
- package/src/markdown/inline-code.ts +12 -6
- package/src/markdown/relative-links.ts +324 -0
- package/src/markdown/themes.ts +3 -3
- package/src/migrate/migrate.ts +149 -0
- package/src/openapi/parse.ts +64 -16
- package/src/openapi/proxy.ts +62 -10
- package/src/openapi/references.ts +147 -147
- package/src/openapi/render-mdx.ts +32 -10
- package/src/openapi/scalar.ts +15 -13
- package/src/openapi/sentence.ts +14 -0
- package/src/openapi/source.ts +37 -21
- package/src/openapi/spec-dependency-error.ts +15 -0
- package/src/reference/asyncapi.ts +83 -0
- package/src/reference/graphql.ts +89 -0
- package/src/reference/index.ts +40 -0
- package/src/reference/openapi.ts +83 -0
- package/src/reference/options.ts +201 -0
- package/src/reference/scalar.ts +136 -0
- package/src/reference/schema.ts +88 -0
- package/src/registry/eject.ts +109 -53
- package/src/search/adapters/algolia.ts +46 -0
- package/src/search/adapters/flexsearch.ts +29 -0
- package/src/search/adapters/index.ts +39 -0
- package/src/search/adapters/mixedbread.ts +39 -0
- package/src/search/adapters/orama-cloud.ts +51 -0
- package/src/search/adapters/orama.ts +24 -0
- package/src/search/adapters/pagefind.ts +27 -0
- package/src/search/adapters/registry.ts +131 -0
- package/src/search/adapters/types.ts +46 -0
- package/src/search/adapters/typesense.ts +57 -0
- package/src/search/build.ts +8 -4
- package/src/search/documents.ts +8 -2
- package/src/search/orama-index.ts +1 -1
- package/src/search/sync/algolia.ts +12 -11
- package/src/search/sync/index.ts +35 -20
- package/src/search/sync/orama-cloud.ts +12 -9
- package/src/search/sync/typesense.ts +15 -13
- package/src/sources/contentful.ts +63 -0
- package/src/sources/custom.ts +38 -0
- package/src/sources/filesystem.ts +51 -0
- package/src/sources/github-releases.ts +52 -0
- package/src/sources/index.ts +60 -0
- package/src/sources/mdx-remote.ts +76 -0
- package/src/sources/notion.ts +63 -0
- package/src/sources/obsidian.ts +38 -0
- package/src/sources/payload.ts +60 -0
- package/src/sources/registry.ts +182 -0
- package/src/sources/sanity.ts +66 -0
- package/src/sources/shared.ts +52 -0
- package/src/sources/strapi.ts +58 -0
- package/src/theme/entry.ts +24 -2
- package/src/translate/report.ts +40 -7
- package/src/upgrade/upgrade.ts +499 -0
- package/dist/cli/chunk-0qymqwzz.js +0 -164
- package/dist/cli/chunk-0qymqwzz.js.map +0 -15
- package/dist/cli/chunk-1jefwnfs.js.map +0 -48
- package/dist/cli/chunk-2mzebbbz.js +0 -69
- package/dist/cli/chunk-2z47ypj8.js.map +0 -11
- package/dist/cli/chunk-4x36ddpw.js.map +0 -11
- package/dist/cli/chunk-5093q3n7.js +0 -68
- package/dist/cli/chunk-5093q3n7.js.map +0 -10
- package/dist/cli/chunk-5qk08vmp.js.map +0 -11
- package/dist/cli/chunk-7s8hm3b6.js +0 -5347
- package/dist/cli/chunk-7s8hm3b6.js.map +0 -58
- package/dist/cli/chunk-8cjtbafj.js.map +0 -13
- package/dist/cli/chunk-97r59kpr.js +0 -381
- package/dist/cli/chunk-97r59kpr.js.map +0 -12
- package/dist/cli/chunk-ahnw3kxw.js.map +0 -15
- package/dist/cli/chunk-b27xqwn9.js.map +0 -10
- package/dist/cli/chunk-bf6bt1xt.js +0 -185
- package/dist/cli/chunk-bf6bt1xt.js.map +0 -11
- package/dist/cli/chunk-cjtn640a.js.map +0 -10
- package/dist/cli/chunk-ct47dqpx.js.map +0 -11
- package/dist/cli/chunk-esphfr8p.js +0 -107
- package/dist/cli/chunk-esphfr8p.js.map +0 -11
- package/dist/cli/chunk-ex56aa81.js +0 -1016
- package/dist/cli/chunk-ex56aa81.js.map +0 -13
- package/dist/cli/chunk-garjf5z9.js +0 -30
- package/dist/cli/chunk-garjf5z9.js.map +0 -10
- package/dist/cli/chunk-js7saxwm.js +0 -1045
- package/dist/cli/chunk-js7saxwm.js.map +0 -22
- package/dist/cli/chunk-k79xp7av.js.map +0 -39
- package/dist/cli/chunk-ps4m1xh4.js.map +0 -15
- package/dist/cli/chunk-q4rae3bg.js +0 -60
- package/dist/cli/chunk-q4rae3bg.js.map +0 -10
- package/dist/cli/chunk-rz9jmfhz.js +0 -108
- package/dist/cli/chunk-rz9jmfhz.js.map +0 -10
- package/dist/cli/chunk-vh9w1sgp.js +0 -73
- package/dist/cli/chunk-vh9w1sgp.js.map +0 -10
- package/dist/cli/chunk-vrfp10qk.js +0 -81
- package/dist/cli/chunk-vrfp10qk.js.map +0 -10
- package/dist/cli/chunk-yg63d42r.js.map +0 -34
- package/docs/advanced/api-reference.mdx +0 -240
- package/docs/configuration/ask-ai.mdx +0 -256
- package/docs/reference/cli.mdx +0 -197
- package/skills/blume-migrate/assets/oxfmt@0.55.0.patch +0 -20
- package/src/components/content/changelog-element.ts +0 -69
- package/src/search/providers.ts +0 -91
- /package/dist/cli/{chunk-vacwm2hv.js.map → chunk-27g6wdth.js.map} +0 -0
- /package/dist/cli/{chunk-dwgcp5sm.js.map → chunk-ce574jw2.js.map} +0 -0
- /package/dist/cli/{chunk-e7f42gdj.js.map → chunk-fxypxtvm.js.map} +0 -0
- /package/dist/cli/{chunk-nn13znc2.js.map → chunk-zxcczpyx.js.map} +0 -0
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { needsPlaygroundProxy } from "../openapi/references.ts";
|
|
2
|
-
import { searchProviderMeta } from "../search/providers.ts";
|
|
3
2
|
import type { ResolvedConfig } from "./schema.ts";
|
|
4
3
|
|
|
5
4
|
/**
|
|
@@ -8,23 +7,23 @@ import type { ResolvedConfig } from "./schema.ts";
|
|
|
8
7
|
*/
|
|
9
8
|
export const serverFeatures = (config: ResolvedConfig): string[] => {
|
|
10
9
|
const features: string[] = [];
|
|
11
|
-
if (config.ai.
|
|
12
|
-
features.push("
|
|
10
|
+
if (config.ai.assistant?.enabled && !config.ai.assistant.endpoint) {
|
|
11
|
+
features.push("Assistant");
|
|
13
12
|
}
|
|
14
13
|
// The hosted MCP server is a live JSON-RPC endpoint, so it needs a runtime.
|
|
15
|
-
if (config.
|
|
14
|
+
if (config.agents.mcp.enabled) {
|
|
16
15
|
features.push("MCP server");
|
|
17
16
|
}
|
|
18
|
-
// The built-in playground proxy (`playground.proxy: true` on
|
|
19
|
-
//
|
|
20
|
-
// proxy URL (string) or a proxy-less playground stays fully static.
|
|
17
|
+
// The built-in playground proxy (`playground.proxy: true` on an `openapi()`
|
|
18
|
+
// or `graphql()` adapter) is a live fetch endpoint at `/_api-proxy`; an
|
|
19
|
+
// external proxy URL (string) or a proxy-less playground stays fully static.
|
|
21
20
|
if (needsPlaygroundProxy(config)) {
|
|
22
21
|
features.push("API playground proxy");
|
|
23
22
|
}
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
if (
|
|
27
|
-
features.push(`Search (${config.search.provider})`);
|
|
23
|
+
// A `server` adapter (Mixedbread) proxies queries through a secret server
|
|
24
|
+
// endpoint, so it can't run on a static build.
|
|
25
|
+
if (config.search.provider.mode === "server") {
|
|
26
|
+
features.push(`Search (${config.search.provider.kind})`);
|
|
28
27
|
}
|
|
29
28
|
return features;
|
|
30
29
|
};
|
|
@@ -67,6 +67,13 @@ export interface AssetContext {
|
|
|
67
67
|
* download at once. Defaults to no gate.
|
|
68
68
|
*/
|
|
69
69
|
limit?: <T>(task: () => Promise<T>) => Promise<T>;
|
|
70
|
+
/**
|
|
71
|
+
* Downloads in progress, keyed by asset stem. A source shares one table
|
|
72
|
+
* (alongside `limit`) across every page it materializes, so two pages that
|
|
73
|
+
* reference the same asset share one download instead of racing to publish
|
|
74
|
+
* the same file. Defaults to a table private to this call.
|
|
75
|
+
*/
|
|
76
|
+
inFlight?: Map<string, Promise<string>>;
|
|
70
77
|
/** Abort a download that hasn't completed within this many milliseconds. */
|
|
71
78
|
timeoutMs?: number;
|
|
72
79
|
}
|
|
@@ -128,6 +135,7 @@ export const materializeAssets = async (
|
|
|
128
135
|
): Promise<{ markdown: string; diagnostics: Diagnostic[] }> => {
|
|
129
136
|
const doFetch = ctx.fetchImpl ?? globalThis.fetch;
|
|
130
137
|
const limit = ctx.limit ?? ((task) => task());
|
|
138
|
+
const inFlight = ctx.inFlight ?? new Map<string, Promise<string>>();
|
|
131
139
|
const timeoutMs = ctx.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
132
140
|
const diagnostics: Diagnostic[] = [];
|
|
133
141
|
|
|
@@ -151,13 +159,7 @@ export const materializeAssets = async (
|
|
|
151
159
|
}
|
|
152
160
|
|
|
153
161
|
/** Fetch one asset into the asset dir and return its file name. */
|
|
154
|
-
const download = async (url: string): Promise<string> => {
|
|
155
|
-
// Hash the query-less URL: CMS asset URLs are pre-signed, so the query
|
|
156
|
-
// changes on every fetch of the same file — hashing it would mint a new
|
|
157
|
-
// file each refresh and re-dirty the content digest. Two real assets
|
|
158
|
-
// sharing scheme+host+path and differing only in query are rare enough to
|
|
159
|
-
// accept colliding.
|
|
160
|
-
const stem = hashText(url.split("?")[0] ?? url);
|
|
162
|
+
const download = async (url: string, stem: string): Promise<string> => {
|
|
161
163
|
const urlExt = extFromUrl(url);
|
|
162
164
|
// The name is known up front whenever the path has an extension (every
|
|
163
165
|
// Notion upload does), so a file from an earlier run is reused as is;
|
|
@@ -189,9 +191,8 @@ export const materializeAssets = async (
|
|
|
189
191
|
// megabytes where an image was a hundred kilobytes. Write to a temporary
|
|
190
192
|
// name unique to this attempt and rename on completion, so a download that
|
|
191
193
|
// dies midway never leaves a truncated file the next run would trust as
|
|
192
|
-
// complete
|
|
193
|
-
//
|
|
194
|
-
// both publish identical bytes and the last rename wins.
|
|
194
|
+
// complete. Two pages fetching the same asset at once share one download
|
|
195
|
+
// through `inFlight` (below), so no two attempts ever publish one file.
|
|
195
196
|
const part = `${target}.${randomUUID()}${PART_SUFFIX}`;
|
|
196
197
|
try {
|
|
197
198
|
await writeFile(part, res.body);
|
|
@@ -203,11 +204,46 @@ export const materializeAssets = async (
|
|
|
203
204
|
return file;
|
|
204
205
|
};
|
|
205
206
|
|
|
207
|
+
/**
|
|
208
|
+
* Publish one asset, joining a download another page already has in
|
|
209
|
+
* flight. The gate sits inside the shared promise, so a page waiting on
|
|
210
|
+
* another page's download holds no slot of its own. A waiter whose
|
|
211
|
+
* publisher failed makes its own attempt, exactly as it would have without
|
|
212
|
+
* sharing — one transient error must not fail every page naming the asset.
|
|
213
|
+
*/
|
|
214
|
+
const publish = async (url: string): Promise<string> => {
|
|
215
|
+
// Hash the query-less URL: CMS asset URLs are pre-signed, so the query
|
|
216
|
+
// changes on every fetch of the same file — hashing it would mint a new
|
|
217
|
+
// file each refresh and re-dirty the content digest. Two real assets
|
|
218
|
+
// sharing scheme+host+path and differing only in query are rare enough to
|
|
219
|
+
// accept colliding.
|
|
220
|
+
const stem = hashText(url.split("?")[0] ?? url);
|
|
221
|
+
const pending = inFlight.get(stem);
|
|
222
|
+
if (pending) {
|
|
223
|
+
try {
|
|
224
|
+
return await pending;
|
|
225
|
+
} catch {
|
|
226
|
+
// The failed download has left the table by now: join whichever
|
|
227
|
+
// waiter retried first, or go it alone.
|
|
228
|
+
return await publish(url);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
const own = (async () => {
|
|
232
|
+
try {
|
|
233
|
+
return await limit(() => download(url, stem));
|
|
234
|
+
} finally {
|
|
235
|
+
inFlight.delete(stem);
|
|
236
|
+
}
|
|
237
|
+
})();
|
|
238
|
+
inFlight.set(stem, own);
|
|
239
|
+
return await own;
|
|
240
|
+
};
|
|
241
|
+
|
|
206
242
|
const rewrites = new Map<string, string>();
|
|
207
243
|
await Promise.all(
|
|
208
244
|
[...urls].map(async (url) => {
|
|
209
245
|
try {
|
|
210
|
-
const file = await
|
|
246
|
+
const file = await publish(url);
|
|
211
247
|
rewrites.set(url, `${ctx.assetsBaseUrl}/${file}`);
|
|
212
248
|
} catch (error) {
|
|
213
249
|
// SAFETY: everything thrown in this block is an Error — the manual
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { isAbsolute, join, resolve } from "pathe";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
DEFAULT_CONTENT_EXCLUDE,
|
|
5
|
+
DEFAULT_CONTENT_INCLUDE,
|
|
6
|
+
} from "../../sources/filesystem.ts";
|
|
7
|
+
import type { ContentSourceAdapter } from "../../sources/registry.ts";
|
|
8
|
+
import type { ResolvedConfig } from "../schema.ts";
|
|
9
|
+
|
|
10
|
+
/** Resolve a source `root` against the project root (absolute passes through). */
|
|
11
|
+
export const resolveSourceRoot = (projectRoot: string, root: string): string =>
|
|
12
|
+
isAbsolute(root) ? root : join(resolve(projectRoot), root);
|
|
13
|
+
|
|
14
|
+
/** The configured sources of one adapter `kind`, in config order. */
|
|
15
|
+
export const sourcesOfKind = <Kind extends ContentSourceAdapter["kind"]>(
|
|
16
|
+
config: ResolvedConfig,
|
|
17
|
+
kind: Kind
|
|
18
|
+
): Extract<ContentSourceAdapter, { kind: Kind }>[] =>
|
|
19
|
+
config.content.sources.filter(
|
|
20
|
+
(source): source is Extract<ContentSourceAdapter, { kind: Kind }> =>
|
|
21
|
+
source.kind === kind
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The generated `docs` glob collection: its base directory and the include /
|
|
26
|
+
* exclude globs applied under it. Astro's glob loader ids each entry by its
|
|
27
|
+
* path relative to `base`, and a filesystem source ids each entry relative to
|
|
28
|
+
* its own root — so the two only agree when the collection is rooted at that
|
|
29
|
+
* source. The collection therefore roots at the first `filesystem()` source
|
|
30
|
+
* (the implicit one, for a zero-config project). Further filesystem sources
|
|
31
|
+
* must share that root and partition it with globs: every filesystem source's
|
|
32
|
+
* `include` feeds the collection, and only a pattern every one of them
|
|
33
|
+
* excludes is excluded, so no source's pages are globbed away. A source
|
|
34
|
+
* rooted elsewhere can't share the base and is caught by the entry-id guard in
|
|
35
|
+
* `scanProject`. With no filesystem source at all the collection globs nothing
|
|
36
|
+
* and its base is the default `docs` directory, which only anchors paths.
|
|
37
|
+
*/
|
|
38
|
+
export interface DocsCollection {
|
|
39
|
+
base: string;
|
|
40
|
+
include: string[];
|
|
41
|
+
exclude: string[];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const resolveDocsCollection = (
|
|
45
|
+
config: ResolvedConfig,
|
|
46
|
+
projectRoot: string
|
|
47
|
+
): DocsCollection => {
|
|
48
|
+
const [first, ...rest] = sourcesOfKind(config, "filesystem");
|
|
49
|
+
if (!first) {
|
|
50
|
+
return {
|
|
51
|
+
base: resolveSourceRoot(projectRoot, "docs"),
|
|
52
|
+
exclude: DEFAULT_CONTENT_EXCLUDE,
|
|
53
|
+
include: DEFAULT_CONTENT_INCLUDE,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const include = [
|
|
57
|
+
...new Set([first, ...rest].flatMap((source) => source.options.include)),
|
|
58
|
+
];
|
|
59
|
+
const exclude = first.options.exclude.filter((pattern) =>
|
|
60
|
+
rest.every((source) => source.options.exclude.includes(pattern))
|
|
61
|
+
);
|
|
62
|
+
return {
|
|
63
|
+
base: resolveSourceRoot(projectRoot, first.options.root),
|
|
64
|
+
exclude,
|
|
65
|
+
include,
|
|
66
|
+
};
|
|
67
|
+
};
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contentful rich text → Markdown. Covers the block, inline, and mark types
|
|
3
|
+
* the Rich Text editor emits; embedded entries fall through to a serializer
|
|
4
|
+
* keyed by content type or are noted in a comment. Links to assets and
|
|
5
|
+
* entries arrive unresolved from the Delivery API (`data.target` is a
|
|
6
|
+
* `sys` link), so the source hands in resolvers over the response's
|
|
7
|
+
* `includes`; a document the SDK already resolved (with `fields` inline)
|
|
8
|
+
* lowers the same way.
|
|
9
|
+
*/
|
|
10
|
+
import type { JsonObject } from "./json.ts";
|
|
11
|
+
import { asString, getPath, objectsIn } from "./json.ts";
|
|
12
|
+
import type { InlineMarks } from "./lower.ts";
|
|
13
|
+
import {
|
|
14
|
+
absoluteUrl,
|
|
15
|
+
blockquote,
|
|
16
|
+
headingPrefix,
|
|
17
|
+
image,
|
|
18
|
+
joinBlocks,
|
|
19
|
+
listItem,
|
|
20
|
+
markdownDocument,
|
|
21
|
+
renderInline,
|
|
22
|
+
renderLink,
|
|
23
|
+
unsupported,
|
|
24
|
+
writesMdx,
|
|
25
|
+
} from "./lower.ts";
|
|
26
|
+
|
|
27
|
+
/** An asset's file as a Markdown image needs it. */
|
|
28
|
+
export interface ContentfulAsset {
|
|
29
|
+
description?: string;
|
|
30
|
+
title?: string;
|
|
31
|
+
url: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface ContentfulRichTextOptions {
|
|
35
|
+
/** Resolve an asset link (`data.target.sys.id`) to its file. */
|
|
36
|
+
resolveAsset?: (id: string) => ContentfulAsset | null;
|
|
37
|
+
/** Resolve an entry link to the entry (`sys` plus `fields`). */
|
|
38
|
+
resolveEntry?: (id: string) => JsonObject | null;
|
|
39
|
+
/**
|
|
40
|
+
* Serializers for embedded entries, keyed by content type id; return
|
|
41
|
+
* Markdown or MDX. Setting any writes the source's entries as MDX.
|
|
42
|
+
*/
|
|
43
|
+
serializers?: Record<string, (entry: JsonObject) => string>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const HEADING = /^heading-(?<level>[1-6])$/u;
|
|
47
|
+
const CELL_PIPE = /\|/gu;
|
|
48
|
+
const CELL_BREAK = /\n+/gu;
|
|
49
|
+
|
|
50
|
+
/** The file behind an asset entry, or null when it carries none. */
|
|
51
|
+
export const assetFromEntry = (asset: JsonObject): ContentfulAsset | null => {
|
|
52
|
+
const url = asString(getPath(asset, "fields.file.url"));
|
|
53
|
+
if (!url) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
description: asString(getPath(asset, "fields.description")),
|
|
58
|
+
title: asString(getPath(asset, "fields.title")),
|
|
59
|
+
url: absoluteUrl(url),
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const children = (node: JsonObject): JsonObject[] => objectsIn(node.content);
|
|
64
|
+
|
|
65
|
+
const marksOf = (node: JsonObject): InlineMarks => {
|
|
66
|
+
const marks: InlineMarks = {};
|
|
67
|
+
for (const mark of objectsIn(node.marks)) {
|
|
68
|
+
switch (asString(mark.type)) {
|
|
69
|
+
case "bold": {
|
|
70
|
+
marks.bold = true;
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
case "italic": {
|
|
74
|
+
marks.italic = true;
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
case "code": {
|
|
78
|
+
marks.code = true;
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
case "strikethrough": {
|
|
82
|
+
marks.strike = true;
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
default:
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return marks;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* The linked object a node points at: inline when the document was resolved
|
|
93
|
+
* (`data.target.fields`), else through the resolver by `data.target.sys.id`.
|
|
94
|
+
*/
|
|
95
|
+
const linkedTarget = (
|
|
96
|
+
node: JsonObject,
|
|
97
|
+
resolve?: (id: string) => JsonObject | null
|
|
98
|
+
): JsonObject | null => {
|
|
99
|
+
const target = getPath(node, "data.target");
|
|
100
|
+
if (getPath(node, "data.target.fields") !== undefined) {
|
|
101
|
+
// SAFETY: `data.target.fields` resolved through the object, so `target`
|
|
102
|
+
// is that object.
|
|
103
|
+
return target as JsonObject;
|
|
104
|
+
}
|
|
105
|
+
const id = asString(getPath(node, "data.target.sys.id"));
|
|
106
|
+
return id ? (resolve?.(id) ?? null) : null;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const linkedAsset = (
|
|
110
|
+
node: JsonObject,
|
|
111
|
+
options: ContentfulRichTextOptions
|
|
112
|
+
): ContentfulAsset | null => {
|
|
113
|
+
if (getPath(node, "data.target.fields") !== undefined) {
|
|
114
|
+
const inline = linkedTarget(node);
|
|
115
|
+
return inline ? assetFromEntry(inline) : null;
|
|
116
|
+
}
|
|
117
|
+
const id = asString(getPath(node, "data.target.sys.id"));
|
|
118
|
+
return id ? (options.resolveAsset?.(id) ?? null) : null;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const embeddedEntry = (
|
|
122
|
+
node: JsonObject,
|
|
123
|
+
options: ContentfulRichTextOptions
|
|
124
|
+
): string => {
|
|
125
|
+
const entry = linkedTarget(node, options.resolveEntry);
|
|
126
|
+
const contentType = entry
|
|
127
|
+
? asString(getPath(entry, "sys.contentType.sys.id"))
|
|
128
|
+
: undefined;
|
|
129
|
+
const serializer = contentType
|
|
130
|
+
? options.serializers?.[contentType]
|
|
131
|
+
: undefined;
|
|
132
|
+
if (entry && serializer) {
|
|
133
|
+
return serializer(entry);
|
|
134
|
+
}
|
|
135
|
+
return unsupported(
|
|
136
|
+
`Contentful embedded entry${contentType ? `: ${contentType}` : ""}`,
|
|
137
|
+
writesMdx(options.serializers)
|
|
138
|
+
);
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const renderInlines = (
|
|
142
|
+
nodes: JsonObject[],
|
|
143
|
+
options: ContentfulRichTextOptions
|
|
144
|
+
): string =>
|
|
145
|
+
nodes
|
|
146
|
+
// oxlint-disable-next-line no-use-before-define -- mutual recursion: a link's label is itself inline content
|
|
147
|
+
.map((node) => renderInlineNode(node, options))
|
|
148
|
+
.join("");
|
|
149
|
+
|
|
150
|
+
const renderInlineNode = (
|
|
151
|
+
node: JsonObject,
|
|
152
|
+
options: ContentfulRichTextOptions
|
|
153
|
+
): string => {
|
|
154
|
+
switch (asString(node.nodeType)) {
|
|
155
|
+
case "text": {
|
|
156
|
+
return renderInline(asString(node.value) ?? "", marksOf(node));
|
|
157
|
+
}
|
|
158
|
+
case "hyperlink": {
|
|
159
|
+
return renderLink(
|
|
160
|
+
renderInlines(children(node), options),
|
|
161
|
+
asString(getPath(node, "data.uri"))
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
case "asset-hyperlink": {
|
|
165
|
+
return renderLink(
|
|
166
|
+
renderInlines(children(node), options),
|
|
167
|
+
linkedAsset(node, options)?.url
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
case "embedded-entry-inline": {
|
|
171
|
+
return embeddedEntry(node, options);
|
|
172
|
+
}
|
|
173
|
+
default: {
|
|
174
|
+
// entry-hyperlink (no route to point at) and anything unknown: the label.
|
|
175
|
+
return renderInlines(children(node), options);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const renderList = (
|
|
181
|
+
items: JsonObject[],
|
|
182
|
+
marker: (index: number) => string,
|
|
183
|
+
options: ContentfulRichTextOptions
|
|
184
|
+
): string =>
|
|
185
|
+
items
|
|
186
|
+
.map((item, index) =>
|
|
187
|
+
listItem(
|
|
188
|
+
marker(index),
|
|
189
|
+
// A single newline between an item's paragraph and its nested list
|
|
190
|
+
// keeps the list tight.
|
|
191
|
+
children(item)
|
|
192
|
+
// oxlint-disable-next-line no-use-before-define -- mutual recursion: an item holds blocks, including nested lists
|
|
193
|
+
.map((child) => renderBlock(child, options))
|
|
194
|
+
.filter((block) => block !== "")
|
|
195
|
+
.join("\n")
|
|
196
|
+
)
|
|
197
|
+
)
|
|
198
|
+
.join("\n");
|
|
199
|
+
|
|
200
|
+
const cellText = (
|
|
201
|
+
cell: JsonObject,
|
|
202
|
+
options: ContentfulRichTextOptions
|
|
203
|
+
): string =>
|
|
204
|
+
children(cell)
|
|
205
|
+
.map((paragraph) => renderInlines(children(paragraph), options))
|
|
206
|
+
.join(" ")
|
|
207
|
+
.replaceAll(CELL_BREAK, " ")
|
|
208
|
+
.replaceAll(CELL_PIPE, String.raw`\|`);
|
|
209
|
+
|
|
210
|
+
const tableRow = (cells: string[]): string => `| ${cells.join(" | ")} |`;
|
|
211
|
+
|
|
212
|
+
const renderTable = (
|
|
213
|
+
node: JsonObject,
|
|
214
|
+
options: ContentfulRichTextOptions
|
|
215
|
+
): string => {
|
|
216
|
+
const rows = children(node).map((row) =>
|
|
217
|
+
children(row).map((cell) => cellText(cell, options))
|
|
218
|
+
);
|
|
219
|
+
const [head, ...body] = rows;
|
|
220
|
+
if (!head) {
|
|
221
|
+
return "";
|
|
222
|
+
}
|
|
223
|
+
return [
|
|
224
|
+
tableRow(head),
|
|
225
|
+
tableRow(head.map(() => "---")),
|
|
226
|
+
...body.map((cells) => tableRow(cells)),
|
|
227
|
+
].join("\n");
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
const renderBlock = (
|
|
231
|
+
node: JsonObject,
|
|
232
|
+
options: ContentfulRichTextOptions
|
|
233
|
+
): string => {
|
|
234
|
+
const type = asString(node.nodeType) ?? "";
|
|
235
|
+
const heading = HEADING.exec(type)?.groups?.level;
|
|
236
|
+
if (heading) {
|
|
237
|
+
return `${headingPrefix(Number(heading))}${renderInlines(children(node), options)}`;
|
|
238
|
+
}
|
|
239
|
+
switch (type) {
|
|
240
|
+
case "paragraph": {
|
|
241
|
+
return renderInlines(children(node), options);
|
|
242
|
+
}
|
|
243
|
+
case "blockquote": {
|
|
244
|
+
return blockquote(
|
|
245
|
+
joinBlocks(children(node).map((child) => renderBlock(child, options)))
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
case "unordered-list": {
|
|
249
|
+
return renderList(children(node), () => "-", options);
|
|
250
|
+
}
|
|
251
|
+
case "ordered-list": {
|
|
252
|
+
return renderList(children(node), (index) => `${index + 1}.`, options);
|
|
253
|
+
}
|
|
254
|
+
case "hr": {
|
|
255
|
+
return "---";
|
|
256
|
+
}
|
|
257
|
+
case "embedded-asset-block": {
|
|
258
|
+
const asset = linkedAsset(node, options);
|
|
259
|
+
// Contentful's own rich-text renderer uses the description as alt text
|
|
260
|
+
// and the title only as a fallback.
|
|
261
|
+
return asset
|
|
262
|
+
? image(asset.description ?? asset.title ?? "", asset.url)
|
|
263
|
+
: "";
|
|
264
|
+
}
|
|
265
|
+
case "embedded-entry-block": {
|
|
266
|
+
return embeddedEntry(node, options);
|
|
267
|
+
}
|
|
268
|
+
case "table": {
|
|
269
|
+
return renderTable(node, options);
|
|
270
|
+
}
|
|
271
|
+
default: {
|
|
272
|
+
return unsupported(
|
|
273
|
+
`Contentful node: ${type}`,
|
|
274
|
+
writesMdx(options.serializers)
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
/** Serialize a rich text document (`nodeType: "document"`) to Markdown. */
|
|
281
|
+
export const contentfulRichTextToMarkdown = (
|
|
282
|
+
doc: JsonObject,
|
|
283
|
+
options: ContentfulRichTextOptions = {}
|
|
284
|
+
): string =>
|
|
285
|
+
markdownDocument(children(doc).map((node) => renderBlock(node, options)));
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import {
|
|
2
|
+
assetFromEntry,
|
|
3
|
+
contentfulRichTextToMarkdown,
|
|
4
|
+
} from "./contentful-rich-text.ts";
|
|
5
|
+
import type { JsonObject } from "./json.ts";
|
|
6
|
+
import {
|
|
7
|
+
asNumber,
|
|
8
|
+
asObject,
|
|
9
|
+
asString,
|
|
10
|
+
getPath,
|
|
11
|
+
isJsonObject,
|
|
12
|
+
objectsIn,
|
|
13
|
+
} from "./json.ts";
|
|
14
|
+
import { writesMdx } from "./lower.ts";
|
|
15
|
+
import type { RemoteFieldMap, RestClient } from "./remote.ts";
|
|
16
|
+
import {
|
|
17
|
+
documentEntry,
|
|
18
|
+
fetchJson,
|
|
19
|
+
queryString,
|
|
20
|
+
remoteSource,
|
|
21
|
+
} from "./remote.ts";
|
|
22
|
+
import type { ContentSource, SourceContext, SourceEntry } from "./types.ts";
|
|
23
|
+
|
|
24
|
+
export interface ContentfulSourceOptions {
|
|
25
|
+
name: string;
|
|
26
|
+
prefix?: string;
|
|
27
|
+
/** Space id. */
|
|
28
|
+
space: string;
|
|
29
|
+
/** Environment id; default `master`. */
|
|
30
|
+
environment?: string;
|
|
31
|
+
/** The content type id whose entries become pages. */
|
|
32
|
+
contentType: string;
|
|
33
|
+
/** Locale code to fetch; omit for the space's default locale. */
|
|
34
|
+
locale?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Field ids mapping an entry onto Blume meta + body. Paths resolve against
|
|
37
|
+
* the entry's `fields`, with `sys` reachable as `sys.<key>`. Defaults:
|
|
38
|
+
* `title`, `description`, `slug`, `body`, `sys.updatedAt`.
|
|
39
|
+
*/
|
|
40
|
+
fields?: RemoteFieldMap;
|
|
41
|
+
/** Extra query parameters for the entries request (`fields.section: "sdk"`). */
|
|
42
|
+
params?: Record<string, string>;
|
|
43
|
+
/** Serializers for embedded entries, keyed by content type id. */
|
|
44
|
+
serializers?: Record<string, (entry: JsonObject) => string>;
|
|
45
|
+
/** Delivery API token; defaults to `CONTENTFUL_ACCESS_TOKEN`. */
|
|
46
|
+
token?: string;
|
|
47
|
+
/** Preview API token for `--preview`; defaults to `CONTENTFUL_PREVIEW_TOKEN`. */
|
|
48
|
+
previewToken?: string;
|
|
49
|
+
/** Opt-in dev polling interval (seconds); omit to freeze for the session. */
|
|
50
|
+
pollInterval?: number;
|
|
51
|
+
/** Injected for tests; defaults to the global `fetch`. */
|
|
52
|
+
fetchImpl?: typeof fetch;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const DELIVERY_HOST = "https://cdn.contentful.com";
|
|
56
|
+
const PREVIEW_HOST = "https://preview.contentful.com";
|
|
57
|
+
const PAGE_SIZE = 100;
|
|
58
|
+
|
|
59
|
+
const DEFAULT_FIELDS: Required<RemoteFieldMap> = {
|
|
60
|
+
body: "body",
|
|
61
|
+
description: "description",
|
|
62
|
+
lastModified: "sys.updatedAt",
|
|
63
|
+
slug: "slug",
|
|
64
|
+
title: "title",
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/** The included objects of a page, keyed by `sys.id`. */
|
|
68
|
+
const byId = (objects: JsonObject[]): Map<string, JsonObject> =>
|
|
69
|
+
new Map(
|
|
70
|
+
objects.map((object) => [asString(getPath(object, "sys.id")) ?? "", object])
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Contentful content source. Pages through the Delivery API (the Preview API
|
|
75
|
+
* under `--preview`), maps each entry's fields to frontmatter, and lowers its
|
|
76
|
+
* rich text body to Markdown with the page's `includes` resolving asset and
|
|
77
|
+
* entry links.
|
|
78
|
+
*/
|
|
79
|
+
export const contentfulSource = (
|
|
80
|
+
options: ContentfulSourceOptions,
|
|
81
|
+
ctx?: SourceContext
|
|
82
|
+
): ContentSource => {
|
|
83
|
+
const fields = { ...DEFAULT_FIELDS, ...options.fields };
|
|
84
|
+
|
|
85
|
+
const toEntry = (
|
|
86
|
+
item: JsonObject,
|
|
87
|
+
assets: Map<string, JsonObject>,
|
|
88
|
+
linked: Map<string, JsonObject>
|
|
89
|
+
): SourceEntry => {
|
|
90
|
+
const sys = asObject(item.sys) ?? {};
|
|
91
|
+
const id = asString(sys.id) ?? "";
|
|
92
|
+
// Field paths resolve against the entry's fields, with `sys` beside them.
|
|
93
|
+
const view: JsonObject = { ...asObject(item.fields), sys };
|
|
94
|
+
return documentEntry(
|
|
95
|
+
view,
|
|
96
|
+
fields,
|
|
97
|
+
id,
|
|
98
|
+
(body) =>
|
|
99
|
+
isJsonObject(body)
|
|
100
|
+
? contentfulRichTextToMarkdown(body, {
|
|
101
|
+
resolveAsset: (assetId) => {
|
|
102
|
+
const asset = assets.get(assetId);
|
|
103
|
+
return asset ? assetFromEntry(asset) : null;
|
|
104
|
+
},
|
|
105
|
+
resolveEntry: (entryId) => linked.get(entryId) ?? null,
|
|
106
|
+
serializers: options.serializers,
|
|
107
|
+
})
|
|
108
|
+
: "",
|
|
109
|
+
false,
|
|
110
|
+
writesMdx(options.serializers)
|
|
111
|
+
);
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const fetchEntries = async (): Promise<SourceEntry[]> => {
|
|
115
|
+
const preview = ctx?.preview ?? false;
|
|
116
|
+
const deliveryToken = options.token ?? process.env.CONTENTFUL_ACCESS_TOKEN;
|
|
117
|
+
const previewToken =
|
|
118
|
+
options.previewToken ?? process.env.CONTENTFUL_PREVIEW_TOKEN;
|
|
119
|
+
// The Preview API rejects delivery tokens, so falling back to one would
|
|
120
|
+
// only trade a clear config error for a 401.
|
|
121
|
+
if (preview && !previewToken) {
|
|
122
|
+
throw new Error(
|
|
123
|
+
"Contentful --preview needs a Preview API token: set previewToken or CONTENTFUL_PREVIEW_TOKEN."
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
const token = preview ? previewToken : deliveryToken;
|
|
127
|
+
const client: RestClient = {
|
|
128
|
+
fetchImpl: options.fetchImpl,
|
|
129
|
+
headers: token ? { authorization: `Bearer ${token}` } : {},
|
|
130
|
+
};
|
|
131
|
+
const host = preview ? PREVIEW_HOST : DELIVERY_HOST;
|
|
132
|
+
const base = `${host}/spaces/${options.space}/environments/${options.environment ?? "master"}/entries`;
|
|
133
|
+
const entries: SourceEntry[] = [];
|
|
134
|
+
let skip = 0;
|
|
135
|
+
let more = true;
|
|
136
|
+
while (more) {
|
|
137
|
+
// The user's params go first so the paging controls always win — a
|
|
138
|
+
// `params` key that shadowed them would refetch the same page forever.
|
|
139
|
+
const query = queryString({
|
|
140
|
+
...options.params,
|
|
141
|
+
content_type: options.contentType,
|
|
142
|
+
include: "2",
|
|
143
|
+
limit: String(PAGE_SIZE),
|
|
144
|
+
locale: options.locale,
|
|
145
|
+
skip: String(skip),
|
|
146
|
+
});
|
|
147
|
+
// oxlint-disable-next-line no-await-in-loop -- pages are sequential: each response says whether another exists.
|
|
148
|
+
const page = asObject(await fetchJson(`${base}?${query}`, client));
|
|
149
|
+
if (!page) {
|
|
150
|
+
throw new Error("Contentful returned a non-object response");
|
|
151
|
+
}
|
|
152
|
+
const assets = byId(objectsIn(getPath(page, "includes.Asset")));
|
|
153
|
+
const linked = byId(objectsIn(getPath(page, "includes.Entry")));
|
|
154
|
+
const items = objectsIn(page.items);
|
|
155
|
+
for (const item of items) {
|
|
156
|
+
entries.push(toEntry(item, assets, linked));
|
|
157
|
+
}
|
|
158
|
+
skip += items.length;
|
|
159
|
+
more = items.length > 0 && skip < (asNumber(page.total) ?? 0);
|
|
160
|
+
}
|
|
161
|
+
return entries;
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
return remoteSource(
|
|
165
|
+
{
|
|
166
|
+
fetchEntries,
|
|
167
|
+
name: options.name,
|
|
168
|
+
pollInterval: options.pollInterval,
|
|
169
|
+
prefix: options.prefix,
|
|
170
|
+
},
|
|
171
|
+
ctx
|
|
172
|
+
);
|
|
173
|
+
};
|