blume 1.7.3 → 2.0.0
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 +217 -0
- package/README.md +34 -21
- package/dist/cli/chunk-11j0384y.js +148 -0
- package/dist/cli/chunk-11j0384y.js.map +10 -0
- package/dist/cli/{chunk-rqy0s5wh.js → chunk-1w8dp3qb.js} +17 -16
- package/dist/cli/{chunk-rqy0s5wh.js.map → chunk-1w8dp3qb.js.map} +3 -3
- package/dist/cli/chunk-2q1dwty4.js +75 -0
- package/dist/cli/chunk-2q1dwty4.js.map +11 -0
- package/dist/cli/chunk-41za066z.js +122 -0
- package/dist/cli/chunk-41za066z.js.map +11 -0
- package/dist/cli/chunk-5a2z0198.js +133 -0
- package/dist/cli/chunk-5a2z0198.js.map +10 -0
- package/dist/cli/{chunk-5g0w1e2c.js → chunk-6k8vp3ta.js} +25 -13
- package/dist/cli/{chunk-5g0w1e2c.js.map → chunk-6k8vp3ta.js.map} +4 -4
- package/dist/cli/{chunk-5qk08vmp.js → chunk-79njf86q.js} +133 -54
- package/dist/cli/chunk-79njf86q.js.map +11 -0
- package/dist/cli/{chunk-e7f42gdj.js → chunk-7ez8ny0t.js} +2 -2
- package/dist/cli/{chunk-nn13znc2.js → chunk-88cpgt6h.js} +1 -1
- package/dist/cli/chunk-a9kptbw5.js +361 -0
- package/dist/cli/chunk-a9kptbw5.js.map +14 -0
- package/dist/cli/chunk-abh8yjkn.js +31 -0
- package/dist/cli/chunk-abh8yjkn.js.map +10 -0
- package/dist/cli/chunk-b5aj94ah.js +91 -0
- package/dist/cli/chunk-b5aj94ah.js.map +10 -0
- package/dist/cli/{chunk-b27xqwn9.js → chunk-bctazmbk.js} +9 -5
- package/dist/cli/chunk-bctazmbk.js.map +10 -0
- package/dist/cli/chunk-beat36xx.js +279 -0
- package/dist/cli/chunk-beat36xx.js.map +10 -0
- package/dist/cli/chunk-bnbmcwfb.js +145 -0
- package/dist/cli/chunk-bnbmcwfb.js.map +11 -0
- package/dist/cli/{chunk-0xjyb285.js → chunk-bw22s759.js} +15 -5
- package/dist/cli/{chunk-0xjyb285.js.map → chunk-bw22s759.js.map} +4 -4
- package/dist/cli/chunk-by2290sx.js +39 -0
- package/dist/cli/chunk-by2290sx.js.map +10 -0
- package/dist/cli/chunk-d1tadaw7.js +79 -0
- package/dist/cli/chunk-d1tadaw7.js.map +10 -0
- package/dist/cli/{chunk-ahnw3kxw.js → chunk-d80hr03s.js} +24 -19
- package/dist/cli/chunk-d80hr03s.js.map +15 -0
- package/dist/cli/chunk-ernrthtr.js +97 -0
- package/dist/cli/chunk-ernrthtr.js.map +10 -0
- package/dist/cli/chunk-f2972sbt.js +374 -0
- package/dist/cli/chunk-f2972sbt.js.map +10 -0
- package/dist/cli/{chunk-vacwm2hv.js → chunk-f7t03s3g.js} +2 -2
- package/dist/cli/{chunk-2z47ypj8.js → chunk-fa25z98p.js} +16 -3
- package/dist/cli/chunk-fa25z98p.js.map +11 -0
- package/dist/cli/{chunk-cjtn640a.js → chunk-fh5hj5jt.js} +43 -20
- package/dist/cli/chunk-fh5hj5jt.js.map +10 -0
- package/dist/cli/{chunk-yg63d42r.js → chunk-j8mw0za6.js} +86 -57
- package/dist/cli/chunk-j8mw0za6.js.map +35 -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-ps4m1xh4.js → chunk-mnqj32sj.js} +505 -542
- package/dist/cli/chunk-mnqj32sj.js.map +12 -0
- package/dist/cli/{chunk-8cjtbafj.js → chunk-mwt1k8n7.js} +100 -374
- package/dist/cli/chunk-mwt1k8n7.js.map +10 -0
- package/dist/cli/chunk-nk3ts2xk.js +51 -0
- package/dist/cli/chunk-nk3ts2xk.js.map +10 -0
- package/dist/cli/{chunk-3r45185y.js → chunk-pat2zzwc.js} +9 -11
- package/dist/cli/{chunk-3r45185y.js.map → chunk-pat2zzwc.js.map} +2 -2
- package/dist/cli/chunk-pnnvybbk.js +176 -0
- package/dist/cli/chunk-pnnvybbk.js.map +11 -0
- package/dist/cli/{chunk-4x36ddpw.js → chunk-sqn5t4q0.js} +81 -87
- package/dist/cli/chunk-sqn5t4q0.js.map +10 -0
- package/dist/cli/{chunk-bvwwhd84.js → chunk-tzne8qfq.js} +15 -15
- package/dist/cli/{chunk-bvwwhd84.js.map → chunk-tzne8qfq.js.map} +1 -1
- package/dist/cli/chunk-xaz13gwg.js +12449 -0
- package/dist/cli/chunk-xaz13gwg.js.map +182 -0
- package/dist/cli/chunk-y3e45rc8.js +102 -0
- package/dist/cli/chunk-y3e45rc8.js.map +10 -0
- package/dist/cli/chunk-z01ze5c1.js +261 -0
- package/dist/cli/chunk-z01ze5c1.js.map +10 -0
- package/dist/cli/{chunk-k79xp7av.js → chunk-z1f5arsg.js} +219 -689
- package/dist/cli/chunk-z1f5arsg.js.map +36 -0
- package/dist/cli/{chunk-1jefwnfs.js → chunk-zg2gtj10.js} +1076 -2592
- package/dist/cli/chunk-zg2gtj10.js.map +35 -0
- package/dist/cli/{chunk-dwgcp5sm.js → chunk-zxccj738.js} +1 -1
- 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.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 +186 -515
- package/dist/types/core/config.d.ts +60 -34
- 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 +27 -12
- 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 +6 -2
- 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 +2282 -452
- 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/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 +50 -26
- package/docs/03-upgrading.mdx +351 -0
- package/docs/04-migrating.mdx +58 -0
- package/docs/08-faq.mdx +3 -3
- package/docs/advanced/blog.mdx +13 -6
- package/docs/advanced/changelog.mdx +23 -35
- package/docs/advanced/custom-pages.mdx +20 -8
- 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} +9 -8
- package/docs/cli/index.mdx +105 -0
- package/docs/cli/meta.ts +7 -0
- package/docs/{reference → cli}/translate.mdx +1 -1
- package/docs/cli/validate.mdx +41 -0
- package/docs/cli/version.mdx +40 -0
- package/docs/configuration/analytics.mdx +350 -59
- package/docs/configuration/ask-ai.mdx +162 -61
- package/docs/configuration/customization.mdx +15 -9
- package/docs/configuration/index.mdx +50 -31
- package/docs/configuration/search.mdx +75 -54
- 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 +8 -6
- package/docs/content/includes.mdx +2 -4
- package/docs/content/index.mdx +1 -1
- package/docs/content/islands.mdx +10 -5
- 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 +11 -11
- 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 +2 -2
- 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 +21 -8
- 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 +21 -22
- package/src/ai/ai-catalog.ts +50 -32
- package/src/ai/api/handlers.ts +46 -11
- package/src/ai/api-catalog.ts +8 -8
- package/src/ai/ask-data.ts +1 -1
- package/src/ai/ask.ts +624 -100
- package/src/ai/changelog-markdown.ts +91 -0
- package/src/ai/component-markdown.ts +328 -12
- 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 +4 -1
- package/src/ai/relative-links.ts +170 -0
- package/src/ai/serializers.ts +2 -2
- package/src/ai/skills.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 +112 -345
- package/src/astro/integration.ts +2 -6
- 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 +554 -541
- 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/cli/command-meta.ts +10 -0
- package/src/cli/commands/audit.ts +39 -20
- 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 +90 -14
- package/src/cli/commands/eject.ts +44 -7
- package/src/cli/commands/eval.ts +2 -2
- 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 +2 -2
- 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 +38 -11
- 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/islands/hooks.ts +25 -2
- 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 +83 -20
- 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 +52 -5
- package/src/components/layout/ReferenceLayout.astro +21 -12
- package/src/components/layout/RootLayout.astro +69 -66
- package/src/components/layout/Search.astro +30 -6
- package/src/components/layout/WebMcp.astro +1 -1
- package/src/components/layout/analytics-client.ts +72 -15
- 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/playground-client.ts +79 -10
- package/src/core/changelog-index.ts +24 -0
- package/src/core/component-overrides.ts +399 -154
- package/src/core/config-input.ts +188 -553
- package/src/core/config.ts +130 -41
- package/src/core/custom-pages.ts +105 -0
- package/src/core/data.ts +31 -12
- 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 +6 -2
- 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 +517 -739
- package/src/core/server-features.ts +8 -9
- 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 +6 -2
- package/src/core/ui-packs/bg.ts +6 -2
- package/src/core/ui-packs/bn.ts +6 -2
- package/src/core/ui-packs/ca.ts +3 -1
- package/src/core/ui-packs/cs.ts +6 -2
- package/src/core/ui-packs/da.ts +6 -2
- package/src/core/ui-packs/de.ts +6 -2
- package/src/core/ui-packs/el.ts +3 -1
- package/src/core/ui-packs/es.ts +3 -1
- package/src/core/ui-packs/fa.ts +6 -2
- package/src/core/ui-packs/fi.ts +6 -2
- package/src/core/ui-packs/fr.ts +3 -1
- package/src/core/ui-packs/he.ts +6 -2
- package/src/core/ui-packs/hi.ts +6 -2
- package/src/core/ui-packs/hr.ts +6 -2
- package/src/core/ui-packs/hu.ts +6 -2
- package/src/core/ui-packs/id.ts +6 -2
- package/src/core/ui-packs/it.ts +3 -1
- package/src/core/ui-packs/ja.ts +3 -1
- package/src/core/ui-packs/ko.ts +3 -1
- package/src/core/ui-packs/nl.ts +6 -2
- package/src/core/ui-packs/no.ts +6 -2
- package/src/core/ui-packs/pl.ts +6 -2
- package/src/core/ui-packs/pt-br.ts +3 -1
- package/src/core/ui-packs/pt.ts +3 -1
- package/src/core/ui-packs/ro.ts +6 -2
- package/src/core/ui-packs/ru.ts +6 -2
- package/src/core/ui-packs/sk.ts +6 -2
- package/src/core/ui-packs/sr.ts +6 -2
- package/src/core/ui-packs/sv.ts +6 -2
- package/src/core/ui-packs/th.ts +3 -1
- package/src/core/ui-packs/tr.ts +6 -2
- package/src/core/ui-packs/uk.ts +6 -2
- package/src/core/ui-packs/vi.ts +3 -1
- package/src/core/ui-packs/zh-tw.ts +3 -1
- package/src/core/ui-packs/zh.ts +3 -1
- 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 +97 -42
- 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 +6 -0
- 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/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-e7f42gdj.js.map → chunk-7ez8ny0t.js.map} +0 -0
- /package/dist/cli/{chunk-nn13znc2.js.map → chunk-88cpgt6h.js.map} +0 -0
- /package/dist/cli/{chunk-vacwm2hv.js.map → chunk-f7t03s3g.js.map} +0 -0
- /package/dist/cli/{chunk-dwgcp5sm.js.map → chunk-zxccj738.js.map} +0 -0
|
@@ -6,6 +6,7 @@ import { join } from "pathe";
|
|
|
6
6
|
import { parseYouTubeId } from "../../components/content/youtube.ts";
|
|
7
7
|
import { BlumeError } from "../diagnostics.ts";
|
|
8
8
|
import matter from "../frontmatter.ts";
|
|
9
|
+
import { nodeRequire } from "../node-require.ts";
|
|
9
10
|
import type { Diagnostic } from "../types.ts";
|
|
10
11
|
import { materializeAssets } from "./assets.ts";
|
|
11
12
|
import {
|
|
@@ -14,6 +15,7 @@ import {
|
|
|
14
15
|
pollingWatch,
|
|
15
16
|
snapshotCache,
|
|
16
17
|
} from "./cache.ts";
|
|
18
|
+
import { codeFence, image, renderInline, renderLink } from "./lower.ts";
|
|
17
19
|
import { slugifyPath } from "./normalize.ts";
|
|
18
20
|
import type {
|
|
19
21
|
ContentSource,
|
|
@@ -152,24 +154,25 @@ interface NotionFrontmatter {
|
|
|
152
154
|
[key: string]: boolean | string | { order: number } | undefined;
|
|
153
155
|
}
|
|
154
156
|
|
|
157
|
+
/**
|
|
158
|
+
* Rich text as Markdown for an MDX body. Each run goes through the shared
|
|
159
|
+
* lowering, so a literal `{`, `<`, `*`, or `[` typed in Notion renders as
|
|
160
|
+
* itself instead of opening a JSX expression, a tag, or emphasis, and a code
|
|
161
|
+
* run keeps its text verbatim inside a long-enough code span.
|
|
162
|
+
*/
|
|
155
163
|
const richToMarkdown = (rich: NotionRichText[] = []): string =>
|
|
156
164
|
rich
|
|
157
|
-
.map((
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
if (node.annotations?.strikethrough) {
|
|
169
|
-
text = `~~${text}~~`;
|
|
170
|
-
}
|
|
171
|
-
return node.href ? `[${text}](${node.href})` : text;
|
|
172
|
-
})
|
|
165
|
+
.map(({ annotations = {}, href, plain_text: text }) =>
|
|
166
|
+
renderLink(
|
|
167
|
+
renderInline(text, {
|
|
168
|
+
bold: annotations.bold,
|
|
169
|
+
code: annotations.code,
|
|
170
|
+
italic: annotations.italic,
|
|
171
|
+
strike: annotations.strikethrough,
|
|
172
|
+
}),
|
|
173
|
+
href ?? undefined
|
|
174
|
+
)
|
|
175
|
+
)
|
|
173
176
|
.join("");
|
|
174
177
|
|
|
175
178
|
const isBlockPayload = (
|
|
@@ -334,11 +337,12 @@ const renderLeaf = (block: NotionBlock): string | null => {
|
|
|
334
337
|
return "---";
|
|
335
338
|
}
|
|
336
339
|
case "code": {
|
|
337
|
-
|
|
340
|
+
// The code's own text, verbatim: escapes would show inside the fence.
|
|
341
|
+
return codeFence(richToPlain(blockField(block)), data.language ?? "");
|
|
338
342
|
}
|
|
339
343
|
case "image": {
|
|
340
344
|
const url = data.external?.url ?? data.file?.url;
|
|
341
|
-
return url ?
|
|
345
|
+
return url ? image(richToPlain(data.caption), url) : "";
|
|
342
346
|
}
|
|
343
347
|
case "video": {
|
|
344
348
|
return renderVideo(data);
|
|
@@ -369,6 +373,8 @@ export const notionSource = (
|
|
|
369
373
|
// limited API, and a slow video must not hold API slots. One gate per source
|
|
370
374
|
// bounds the fan-out across every page, not just within one.
|
|
371
375
|
const downloads = pLimit(ASSET_DOWNLOAD_CONCURRENCY);
|
|
376
|
+
// Shared with the gate so two pages naming one asset share one download.
|
|
377
|
+
const inFlight = new Map<string, Promise<string>>();
|
|
372
378
|
// Every Notion API call goes through the limiter, inside the retry — so a
|
|
373
379
|
// call sleeping through a backoff doesn't hold a slot while it waits.
|
|
374
380
|
const notionCall = <T>(call: () => Promise<T>): Promise<T> =>
|
|
@@ -381,16 +387,18 @@ export const notionSource = (
|
|
|
381
387
|
const assetsBaseUrl = ctx?.assetsBaseUrl ?? `/blume-assets/${options.name}`;
|
|
382
388
|
let snapshot = new Map<string, SourceEntry>();
|
|
383
389
|
|
|
384
|
-
const resolveClient =
|
|
390
|
+
const resolveClient = (): NotionClientLike => {
|
|
385
391
|
if (options.client) {
|
|
386
392
|
return options.client;
|
|
387
393
|
}
|
|
388
394
|
let Client: new (config: { auth?: string }) => NotionClientLike;
|
|
389
395
|
try {
|
|
390
|
-
//
|
|
391
|
-
//
|
|
392
|
-
//
|
|
393
|
-
|
|
396
|
+
// `require`, not `import()`: an ejected app scans in
|
|
397
|
+
// `astro:build:done` (see `core/node-require.ts`). The module is
|
|
398
|
+
// widened first because the SDK's response unions are broader than the
|
|
399
|
+
// NotionClientLike slice, so a direct assertion is rejected as
|
|
400
|
+
// non-overlapping.
|
|
401
|
+
const sdk: unknown = nodeRequire("@notionhq/client");
|
|
394
402
|
// SAFETY: `@notionhq/client` exports a `Client` class constructable with
|
|
395
403
|
// an `auth` token whose instances cover the NotionClientLike slice; the
|
|
396
404
|
// local type keeps the SDK mockable without importing its types.
|
|
@@ -438,7 +446,8 @@ export const notionSource = (
|
|
|
438
446
|
return `<Callout>\n${body}\n</Callout>`;
|
|
439
447
|
}
|
|
440
448
|
if (block.type === "toggle") {
|
|
441
|
-
|
|
449
|
+
// The item's title renders as text, not Markdown.
|
|
450
|
+
const title = jsxString(richToPlain(blockField(block)));
|
|
442
451
|
return `<Accordion>\n<AccordionItem title=${title}>\n${await children(block)}\n</AccordionItem>\n</Accordion>`;
|
|
443
452
|
}
|
|
444
453
|
if (block.type === "column_list") {
|
|
@@ -532,11 +541,12 @@ export const notionSource = (
|
|
|
532
541
|
|
|
533
542
|
const frontmatter = (page: NotionPage) => {
|
|
534
543
|
const data: NotionFrontmatter = {};
|
|
535
|
-
|
|
544
|
+
// Frontmatter holds plain text: Markdown marks or escapes would show.
|
|
545
|
+
const title = richToPlain(titleProperty(page)?.title);
|
|
536
546
|
if (title) {
|
|
537
547
|
data.title = title;
|
|
538
548
|
}
|
|
539
|
-
const description =
|
|
549
|
+
const description = richToPlain(
|
|
540
550
|
page.properties[props.description ?? "Description"]?.rich_text
|
|
541
551
|
);
|
|
542
552
|
if (description) {
|
|
@@ -549,7 +559,7 @@ export const notionSource = (
|
|
|
549
559
|
if (order !== undefined) {
|
|
550
560
|
data.sidebar = { order };
|
|
551
561
|
}
|
|
552
|
-
const slugProp =
|
|
562
|
+
const slugProp = richToPlain(
|
|
553
563
|
page.properties[props.slug ?? "Slug"]?.rich_text
|
|
554
564
|
);
|
|
555
565
|
// Path-aware: a `guides/setup` slug keeps its `/` (per-segment slugging)
|
|
@@ -568,6 +578,7 @@ export const notionSource = (
|
|
|
568
578
|
assetsBaseUrl,
|
|
569
579
|
assetsDir,
|
|
570
580
|
fetchImpl: options.fetchImpl,
|
|
581
|
+
inFlight,
|
|
571
582
|
limit: downloads,
|
|
572
583
|
});
|
|
573
584
|
const raw = matter.stringify(assets.markdown, data);
|
|
@@ -625,7 +636,7 @@ export const notionSource = (
|
|
|
625
636
|
options.name,
|
|
626
637
|
cache,
|
|
627
638
|
async () => {
|
|
628
|
-
const client =
|
|
639
|
+
const client = resolveClient();
|
|
629
640
|
const dataSourceId = await resolveDataSource(client);
|
|
630
641
|
const pages = await collectAll((cursor) =>
|
|
631
642
|
queryDataSource(client, dataSourceId, cursor)
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import type { JsonObject } from "./json.ts";
|
|
2
|
+
import { asObject, asString, isJsonObject, objectsIn } from "./json.ts";
|
|
3
|
+
import { lexicalToMarkdown } from "./lexical.ts";
|
|
4
|
+
import { writesMdx } from "./lower.ts";
|
|
5
|
+
import type { RemoteFieldMap, RestClient } from "./remote.ts";
|
|
6
|
+
import {
|
|
7
|
+
documentEntry,
|
|
8
|
+
fetchJson,
|
|
9
|
+
queryString,
|
|
10
|
+
remoteSource,
|
|
11
|
+
} from "./remote.ts";
|
|
12
|
+
import type { ContentSource, SourceContext, SourceEntry } from "./types.ts";
|
|
13
|
+
|
|
14
|
+
export interface PayloadSourceOptions {
|
|
15
|
+
name: string;
|
|
16
|
+
prefix?: string;
|
|
17
|
+
/** The Payload app's origin (`https://cms.acme.dev`); its REST API is at `/api`. */
|
|
18
|
+
url: string;
|
|
19
|
+
/** The collection slug whose documents become pages. */
|
|
20
|
+
collection: string;
|
|
21
|
+
/**
|
|
22
|
+
* The auth-enabled collection the API key belongs to; default `users`. It
|
|
23
|
+
* names the scheme in the `Authorization` header (`users API-Key <key>`).
|
|
24
|
+
*/
|
|
25
|
+
authCollection?: string;
|
|
26
|
+
/** Relationship depth to populate; default `1`, enough for upload URLs. */
|
|
27
|
+
depth?: number;
|
|
28
|
+
/**
|
|
29
|
+
* Field paths mapping a document onto Blume meta + body. Defaults:
|
|
30
|
+
* `title`, `description`, `slug`, `content`, `updatedAt`.
|
|
31
|
+
*/
|
|
32
|
+
fields?: RemoteFieldMap;
|
|
33
|
+
/** Extra query parameters for the collection request (`where[...]`, `sort`). */
|
|
34
|
+
params?: Record<string, string>;
|
|
35
|
+
/** Serializers for `block`/`inlineBlock` nodes, keyed by `blockType`. */
|
|
36
|
+
serializers?: Record<string, (fields: JsonObject) => string>;
|
|
37
|
+
/** API key; defaults to `PAYLOAD_API_KEY`. */
|
|
38
|
+
token?: string;
|
|
39
|
+
/** Opt-in dev polling interval (seconds); omit to freeze for the session. */
|
|
40
|
+
pollInterval?: number;
|
|
41
|
+
/** Injected for tests; defaults to the global `fetch`. */
|
|
42
|
+
fetchImpl?: typeof fetch;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const PAGE_SIZE = 100;
|
|
46
|
+
|
|
47
|
+
const DEFAULT_FIELDS: Required<RemoteFieldMap> = {
|
|
48
|
+
body: "content",
|
|
49
|
+
description: "description",
|
|
50
|
+
lastModified: "updatedAt",
|
|
51
|
+
slug: "slug",
|
|
52
|
+
title: "title",
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Payload content source. Pages through a collection's REST endpoint, maps
|
|
57
|
+
* each document's fields to frontmatter, and lowers its Lexical body to
|
|
58
|
+
* Markdown. Published documents only, unless `--preview` asks for drafts.
|
|
59
|
+
*/
|
|
60
|
+
export const payloadSource = (
|
|
61
|
+
options: PayloadSourceOptions,
|
|
62
|
+
ctx?: SourceContext
|
|
63
|
+
): ContentSource => {
|
|
64
|
+
const fields = { ...DEFAULT_FIELDS, ...options.fields };
|
|
65
|
+
const origin = options.url.replace(/\/+$/u, "");
|
|
66
|
+
|
|
67
|
+
const lower = (body: JsonObject): string =>
|
|
68
|
+
lexicalToMarkdown(body, {
|
|
69
|
+
baseUrl: origin,
|
|
70
|
+
serializers: options.serializers,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const fetchEntries = async (): Promise<SourceEntry[]> => {
|
|
74
|
+
const preview = ctx?.preview ?? false;
|
|
75
|
+
const token = options.token ?? process.env.PAYLOAD_API_KEY;
|
|
76
|
+
const client: RestClient = {
|
|
77
|
+
fetchImpl: options.fetchImpl,
|
|
78
|
+
headers: token
|
|
79
|
+
? {
|
|
80
|
+
authorization: `${options.authCollection ?? "users"} API-Key ${token}`,
|
|
81
|
+
}
|
|
82
|
+
: {},
|
|
83
|
+
};
|
|
84
|
+
const base = `${origin}/api/${options.collection}`;
|
|
85
|
+
const entries: SourceEntry[] = [];
|
|
86
|
+
let page = 1;
|
|
87
|
+
let more = true;
|
|
88
|
+
while (more) {
|
|
89
|
+
// The user's params go first so the paging controls always win — a
|
|
90
|
+
// `params` key that shadowed them would refetch the same page forever.
|
|
91
|
+
const query = queryString({
|
|
92
|
+
...options.params,
|
|
93
|
+
depth: String(options.depth ?? 1),
|
|
94
|
+
draft: preview ? "true" : undefined,
|
|
95
|
+
limit: String(PAGE_SIZE),
|
|
96
|
+
page: String(page),
|
|
97
|
+
});
|
|
98
|
+
// oxlint-disable-next-line no-await-in-loop -- pages are sequential: each response says whether another exists.
|
|
99
|
+
const result = asObject(await fetchJson(`${base}?${query}`, client));
|
|
100
|
+
if (!result) {
|
|
101
|
+
throw new Error("Payload returned a non-object response");
|
|
102
|
+
}
|
|
103
|
+
for (const doc of objectsIn(result.docs)) {
|
|
104
|
+
const draft = asString(doc._status) === "draft";
|
|
105
|
+
if (draft && !preview) {
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
const id = asString(doc.id) ?? String(doc.id ?? "");
|
|
109
|
+
entries.push(
|
|
110
|
+
documentEntry(
|
|
111
|
+
doc,
|
|
112
|
+
fields,
|
|
113
|
+
id,
|
|
114
|
+
(body) => (isJsonObject(body) ? lower(body) : ""),
|
|
115
|
+
draft,
|
|
116
|
+
writesMdx(options.serializers)
|
|
117
|
+
)
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
more = result.hasNextPage === true;
|
|
121
|
+
page += 1;
|
|
122
|
+
}
|
|
123
|
+
return entries;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
return remoteSource(
|
|
127
|
+
{
|
|
128
|
+
fetchEntries,
|
|
129
|
+
name: options.name,
|
|
130
|
+
pollInterval: options.pollInterval,
|
|
131
|
+
prefix: options.prefix,
|
|
132
|
+
},
|
|
133
|
+
ctx
|
|
134
|
+
);
|
|
135
|
+
};
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* user-supplied serializer or are skipped with a noted comment. Output is
|
|
5
5
|
* Markdown text that flows through Blume's normal pipeline.
|
|
6
6
|
*/
|
|
7
|
+
import { escapeMarkdownText, image, unsupported, writesMdx } from "./lower.ts";
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* A field value on a Portable Text node: the arbitrary JSON the CMS query
|
|
@@ -49,7 +50,10 @@ interface PortableTextMarkDef {
|
|
|
49
50
|
export interface PortableTextOptions {
|
|
50
51
|
/** Resolve an image block to a URL (the adapter knows project/dataset). */
|
|
51
52
|
imageUrl?: (block: PortableTextBlock) => string | null;
|
|
52
|
-
/**
|
|
53
|
+
/**
|
|
54
|
+
* Custom block-type serializers, keyed by `_type`; return Markdown or MDX.
|
|
55
|
+
* Setting any writes the source's entries as MDX.
|
|
56
|
+
*/
|
|
53
57
|
serializers?: Record<string, (block: PortableTextBlock) => string>;
|
|
54
58
|
}
|
|
55
59
|
|
|
@@ -62,18 +66,6 @@ const HEADING_STYLES = new Map([
|
|
|
62
66
|
["h6", "###### "],
|
|
63
67
|
]);
|
|
64
68
|
|
|
65
|
-
// Markdown/raw-HTML structure characters. Portable Text spans are *plain
|
|
66
|
-
// text* — formatting arrives as marks, never as syntax in the text — so a
|
|
67
|
-
// literal `*`, `_`, `[`, backtick, `~`, or `<` typed in the CMS must render
|
|
68
|
-
// as itself. Unescaped, it opened emphasis or a code span mid-paragraph, and
|
|
69
|
-
// `<` let CMS prose inject raw HTML into the rendered page. CommonMark
|
|
70
|
-
// backslash-escapes every ASCII punctuation character, so `\*` is always the
|
|
71
|
-
// literal asterisk.
|
|
72
|
-
const MARKDOWN_SPECIALS = /[\\`*_[\]~<]/gu;
|
|
73
|
-
|
|
74
|
-
const escapeText = (text: string): string =>
|
|
75
|
-
text.replaceAll(MARKDOWN_SPECIALS, String.raw`\$&`);
|
|
76
|
-
|
|
77
69
|
/** Wrap a span's text in Markdown for its marks (decorators + link defs). */
|
|
78
70
|
const renderSpan = (
|
|
79
71
|
span: PortableTextSpan,
|
|
@@ -82,7 +74,7 @@ const renderSpan = (
|
|
|
82
74
|
// Code spans stay verbatim: their text is literal inside the backticks,
|
|
83
75
|
// and backslash escapes would render as backslashes.
|
|
84
76
|
const isCode = span.marks?.includes("code") ?? false;
|
|
85
|
-
let text = isCode ? (span.text ?? "") :
|
|
77
|
+
let text = isCode ? (span.text ?? "") : escapeMarkdownText(span.text ?? "");
|
|
86
78
|
if (!span.marks || span.marks.length === 0) {
|
|
87
79
|
return text;
|
|
88
80
|
}
|
|
@@ -140,10 +132,13 @@ const renderBlock = (
|
|
|
140
132
|
if (block._type === "image") {
|
|
141
133
|
const url = options.imageUrl?.(block);
|
|
142
134
|
const alt = isAltText(block.alt) ? block.alt : "";
|
|
143
|
-
return url ?
|
|
135
|
+
return url ? image(alt, url) : "";
|
|
144
136
|
}
|
|
145
137
|
if (block._type !== "block") {
|
|
146
|
-
return
|
|
138
|
+
return unsupported(
|
|
139
|
+
`Portable Text block: ${block._type}`,
|
|
140
|
+
writesMdx(options.serializers)
|
|
141
|
+
);
|
|
147
142
|
}
|
|
148
143
|
|
|
149
144
|
const inline = renderChildren(block);
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { join } from "pathe";
|
|
2
|
+
|
|
3
|
+
import matter from "../frontmatter.ts";
|
|
4
|
+
import {
|
|
5
|
+
hashText,
|
|
6
|
+
loadWithCache,
|
|
7
|
+
pollingWatch,
|
|
8
|
+
snapshotCache,
|
|
9
|
+
} from "./cache.ts";
|
|
10
|
+
import type { JsonObject, JsonValue } from "./json.ts";
|
|
11
|
+
import { asString, getPath, isStringValue } from "./json.ts";
|
|
12
|
+
import { slugify, slugifyPath } from "./normalize.ts";
|
|
13
|
+
import type {
|
|
14
|
+
ContentSource,
|
|
15
|
+
SourceContext,
|
|
16
|
+
SourceEntry,
|
|
17
|
+
SourceLoadResult,
|
|
18
|
+
} from "./types.ts";
|
|
19
|
+
|
|
20
|
+
/** What every REST-backed CMS source needs to be a staged, cached source. */
|
|
21
|
+
export interface RemoteSourceOptions {
|
|
22
|
+
/** Pull every entry from the API; called on refresh and on each poll. */
|
|
23
|
+
fetchEntries: () => Promise<SourceEntry[]>;
|
|
24
|
+
name: string;
|
|
25
|
+
/** Opt-in dev polling interval (seconds); omit to freeze for the session. */
|
|
26
|
+
pollInterval?: number;
|
|
27
|
+
prefix?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The staged-source scaffolding a CMS adapter shares: a snapshot cache under
|
|
32
|
+
* `.blume/cache/<source>/` (or a name-derived dir when constructed directly
|
|
33
|
+
* as a custom source, without a context), cache-first dev loads, offline
|
|
34
|
+
* fallback, `read()` for raw export, and an opt-in polling `watch`.
|
|
35
|
+
*/
|
|
36
|
+
export const remoteSource = (
|
|
37
|
+
options: RemoteSourceOptions,
|
|
38
|
+
ctx?: SourceContext
|
|
39
|
+
): ContentSource => {
|
|
40
|
+
const cache = snapshotCache(
|
|
41
|
+
ctx?.cacheDir ?? join(".blume", "cache", options.name)
|
|
42
|
+
);
|
|
43
|
+
let snapshot = new Map<string, SourceEntry>();
|
|
44
|
+
|
|
45
|
+
const load = async (
|
|
46
|
+
refresh = ctx?.refresh ?? true
|
|
47
|
+
): Promise<SourceLoadResult> => {
|
|
48
|
+
const result = await loadWithCache(
|
|
49
|
+
options.name,
|
|
50
|
+
cache,
|
|
51
|
+
options.fetchEntries,
|
|
52
|
+
refresh
|
|
53
|
+
);
|
|
54
|
+
snapshot = new Map(result.entries.map((entry) => [entry.ref, entry]));
|
|
55
|
+
return result;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const read = async (ref: string): Promise<string> => {
|
|
59
|
+
const cached = snapshot.get(ref);
|
|
60
|
+
if (cached) {
|
|
61
|
+
return cached.raw ?? cached.body.text;
|
|
62
|
+
}
|
|
63
|
+
const all = await cache.read();
|
|
64
|
+
return all.find((entry) => entry.ref === ref)?.raw ?? "";
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
load,
|
|
69
|
+
name: options.name,
|
|
70
|
+
prefix: options.prefix,
|
|
71
|
+
read,
|
|
72
|
+
staged: true,
|
|
73
|
+
watch: options.pollInterval
|
|
74
|
+
? pollingWatch(
|
|
75
|
+
() => load(true),
|
|
76
|
+
options.pollInterval,
|
|
77
|
+
() => load()
|
|
78
|
+
)
|
|
79
|
+
: undefined,
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
/** The frontmatter a CMS document maps to. */
|
|
84
|
+
export interface RemoteFrontmatter {
|
|
85
|
+
description?: string;
|
|
86
|
+
draft?: boolean;
|
|
87
|
+
title?: string;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* A staged entry: Markdown body plus the frontmatter it was mapped from,
|
|
92
|
+
* written as `.mdx` when the body carries serializer output (see
|
|
93
|
+
* `writesMdx`).
|
|
94
|
+
*/
|
|
95
|
+
export const stagedEntry = (
|
|
96
|
+
slug: string,
|
|
97
|
+
data: RemoteFrontmatter,
|
|
98
|
+
markdown: string,
|
|
99
|
+
lastModified: string | undefined,
|
|
100
|
+
format: "md" | "mdx" = "md"
|
|
101
|
+
): SourceEntry => {
|
|
102
|
+
const raw = matter.stringify(markdown, data);
|
|
103
|
+
return {
|
|
104
|
+
body: { format, text: markdown },
|
|
105
|
+
// Spread into a fresh literal: `SourceEntry.data` wants an
|
|
106
|
+
// index-signature type, which the named interface lacks.
|
|
107
|
+
data: { ...data },
|
|
108
|
+
hash: hashText(raw),
|
|
109
|
+
lastModified,
|
|
110
|
+
raw,
|
|
111
|
+
ref: `${slug}.${format}`,
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/** How a source calls its CMS: the API's auth headers and an injectable fetch. */
|
|
116
|
+
export interface RestClient {
|
|
117
|
+
/** Injected for tests; defaults to the global `fetch`. */
|
|
118
|
+
fetchImpl?: typeof fetch;
|
|
119
|
+
headers?: Record<string, string>;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* How long one CMS request may take before the source gives up on it. A
|
|
124
|
+
* stalled CMS would otherwise hold `scanProject()` — and every `blume dev`
|
|
125
|
+
* rescan — indefinitely, and the cache fallback can only kick in once the
|
|
126
|
+
* request rejects.
|
|
127
|
+
*/
|
|
128
|
+
export const REMOTE_TIMEOUT_MS = 30_000;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* GET a JSON endpoint. A non-2xx response is an error naming the status, so
|
|
132
|
+
* the source's cache fallback reports why (`401 Unauthorized`) instead of a
|
|
133
|
+
* parse failure on an error body; a request past {@link REMOTE_TIMEOUT_MS}
|
|
134
|
+
* rejects with a `TimeoutError`.
|
|
135
|
+
*/
|
|
136
|
+
export const fetchJson = async (
|
|
137
|
+
url: string,
|
|
138
|
+
client: RestClient
|
|
139
|
+
): Promise<JsonValue> => {
|
|
140
|
+
const doFetch = client.fetchImpl ?? globalThis.fetch;
|
|
141
|
+
const res = await doFetch(url, {
|
|
142
|
+
headers: { accept: "application/json", ...client.headers },
|
|
143
|
+
signal: AbortSignal.timeout(REMOTE_TIMEOUT_MS),
|
|
144
|
+
});
|
|
145
|
+
if (!res.ok) {
|
|
146
|
+
throw new Error(`${url} responded ${res.status} ${res.statusText}`.trim());
|
|
147
|
+
}
|
|
148
|
+
// SAFETY: the endpoint answered 2xx with a JSON body; whatever shape it
|
|
149
|
+
// holds is narrowed by the caller's predicates before use.
|
|
150
|
+
return (await res.json()) as JsonValue;
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
/** A query string from the fixed params plus a user's extra ones. */
|
|
154
|
+
export const queryString = (
|
|
155
|
+
params: Record<string, string | undefined>
|
|
156
|
+
): string => {
|
|
157
|
+
const search = new URLSearchParams();
|
|
158
|
+
for (const [key, value] of Object.entries(params)) {
|
|
159
|
+
if (value !== undefined) {
|
|
160
|
+
search.set(key, value);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return search.toString();
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
/** Field paths mapping a CMS document onto Blume meta + body. */
|
|
167
|
+
export interface RemoteFieldMap {
|
|
168
|
+
/** Field holding the renderable body (rich text, or a Markdown string). */
|
|
169
|
+
body?: string;
|
|
170
|
+
/** Field holding the page description. */
|
|
171
|
+
description?: string;
|
|
172
|
+
/** Field holding the last-modified ISO date. */
|
|
173
|
+
lastModified?: string;
|
|
174
|
+
/** Field holding the route slug. */
|
|
175
|
+
slug?: string;
|
|
176
|
+
/** Field holding the page title. */
|
|
177
|
+
title?: string;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Map a document to a staged entry. The slug falls back to the document's id
|
|
182
|
+
* when the slug field is missing or slugifies to nothing (pure punctuation),
|
|
183
|
+
* so distinct documents never collapse onto one `untitled.md`; a slashed
|
|
184
|
+
* slug keeps its segments. A string body is Markdown and passes through as
|
|
185
|
+
* `.md`; any other shape goes to the CMS's lowerer, and is written as `.mdx`
|
|
186
|
+
* when `lowersToMdx` (the source has serializers, see `writesMdx`).
|
|
187
|
+
*/
|
|
188
|
+
export const documentEntry = (
|
|
189
|
+
doc: JsonObject,
|
|
190
|
+
fields: Required<RemoteFieldMap>,
|
|
191
|
+
id: string,
|
|
192
|
+
lower: (body: JsonValue) => string,
|
|
193
|
+
draft = false,
|
|
194
|
+
lowersToMdx = false
|
|
195
|
+
): SourceEntry => {
|
|
196
|
+
const slugValue = asString(getPath(doc, fields.slug)) ?? id;
|
|
197
|
+
const slug = slugifyPath(slugValue) || slugify(id) || "untitled";
|
|
198
|
+
const data: RemoteFrontmatter = {};
|
|
199
|
+
const title = asString(getPath(doc, fields.title));
|
|
200
|
+
const description = asString(getPath(doc, fields.description));
|
|
201
|
+
if (title) {
|
|
202
|
+
data.title = title;
|
|
203
|
+
}
|
|
204
|
+
if (description) {
|
|
205
|
+
data.description = description;
|
|
206
|
+
}
|
|
207
|
+
if (draft) {
|
|
208
|
+
data.draft = true;
|
|
209
|
+
}
|
|
210
|
+
const body = getPath(doc, fields.body);
|
|
211
|
+
let markdown = "";
|
|
212
|
+
let format: "md" | "mdx" = "md";
|
|
213
|
+
if (isStringValue(body)) {
|
|
214
|
+
markdown = `${body.trimEnd()}\n`;
|
|
215
|
+
} else if (body !== undefined) {
|
|
216
|
+
markdown = lower(body);
|
|
217
|
+
format = lowersToMdx ? "mdx" : "md";
|
|
218
|
+
}
|
|
219
|
+
return stagedEntry(
|
|
220
|
+
slug,
|
|
221
|
+
data,
|
|
222
|
+
markdown,
|
|
223
|
+
asString(getPath(doc, fields.lastModified)),
|
|
224
|
+
format
|
|
225
|
+
);
|
|
226
|
+
};
|