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,115 +1,78 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
getBlumeVersion,
|
|
4
|
-
BlumeError,
|
|
5
|
-
diagnosticsFromIssues,
|
|
6
|
-
diagnosticsFromZod
|
|
7
|
-
} from "./index.js";
|
|
8
|
-
import {
|
|
9
|
-
applyDeploymentEnv,
|
|
10
|
-
slugify,
|
|
11
3
|
blumeReferences,
|
|
12
|
-
|
|
13
|
-
|
|
4
|
+
frontmatter_default,
|
|
5
|
+
resolveDocsCollection,
|
|
6
|
+
CHANGELOG_INDEX_ROUTE,
|
|
7
|
+
hasChangelogIndex,
|
|
8
|
+
discoverPages,
|
|
9
|
+
customStaticRoutes,
|
|
10
|
+
nextFenceState,
|
|
11
|
+
hashText,
|
|
12
|
+
pollingWatch,
|
|
13
|
+
snapshotCache,
|
|
14
|
+
loadWithCache,
|
|
15
|
+
resolveFallbackLocale,
|
|
16
|
+
localizeRoute,
|
|
17
|
+
localizeInternalPath,
|
|
18
|
+
i18nDiagnostics,
|
|
14
19
|
PUBLIC_API_URL,
|
|
15
|
-
UI_PACKS,
|
|
16
20
|
pageMetaSchema,
|
|
17
21
|
folderMetaSchema,
|
|
22
|
+
versionizeRoute,
|
|
23
|
+
versionsDiagnostics,
|
|
24
|
+
slugify,
|
|
25
|
+
slugifyPath,
|
|
26
|
+
extractHeadings,
|
|
27
|
+
strippedLineOffset,
|
|
28
|
+
isStringValue,
|
|
29
|
+
placeEntryRef,
|
|
30
|
+
resolveEntryRoute,
|
|
31
|
+
localizedRoute,
|
|
32
|
+
normalizeEntry,
|
|
33
|
+
hasIncludeStatements,
|
|
34
|
+
expandIncludes,
|
|
35
|
+
parseYouTubeId,
|
|
36
|
+
nodeRequire,
|
|
37
|
+
escapeMarkdownText,
|
|
38
|
+
renderInline,
|
|
39
|
+
renderLink,
|
|
40
|
+
headingPrefix,
|
|
41
|
+
blockquote,
|
|
42
|
+
listItem,
|
|
43
|
+
indent,
|
|
44
|
+
codeFence,
|
|
45
|
+
image,
|
|
46
|
+
writesMdx,
|
|
47
|
+
unsupported,
|
|
48
|
+
joinBlocks,
|
|
49
|
+
markdownDocument,
|
|
50
|
+
absoluteUrl,
|
|
51
|
+
neutralizeUnsafeLinks,
|
|
52
|
+
columnsPrefix,
|
|
53
|
+
openApiSource,
|
|
54
|
+
createModuleLoader,
|
|
55
|
+
resolveProjectContext,
|
|
18
56
|
loadConfig
|
|
19
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-qkqwkpte.js";
|
|
58
|
+
import {
|
|
59
|
+
getBlumeVersion,
|
|
60
|
+
BlumeError,
|
|
61
|
+
diagnosticsFromZod
|
|
62
|
+
} from "./index.js";
|
|
20
63
|
import {
|
|
21
64
|
trimChar,
|
|
22
65
|
isInternalPath,
|
|
23
66
|
withBasePath,
|
|
24
67
|
stripBasePath
|
|
25
|
-
} from "./chunk-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
return i18n.fallbackLocale ?? i18n.defaultLocale;
|
|
36
|
-
};
|
|
37
|
-
var localePrefix = (code, i18n) => code === i18n.defaultLocale && i18n.hideDefaultLocalePrefix ? "" : `/${code}`;
|
|
38
|
-
var localizeRoute = (logicalRoute, code, i18n) => {
|
|
39
|
-
const prefix = localePrefix(code, i18n);
|
|
40
|
-
if (!prefix) {
|
|
41
|
-
return logicalRoute;
|
|
42
|
-
}
|
|
43
|
-
return logicalRoute === "/" ? prefix : `${prefix}${logicalRoute}`;
|
|
44
|
-
};
|
|
45
|
-
var detectLocale = (parts, i18n) => {
|
|
46
|
-
const first = parts[0]?.toLowerCase();
|
|
47
|
-
const matched = i18n.locales.find((locale) => locale.code !== i18n.defaultLocale && locale.code.toLowerCase() === first);
|
|
48
|
-
if (matched) {
|
|
49
|
-
return { locale: matched.code, rest: parts.slice(1) };
|
|
50
|
-
}
|
|
51
|
-
return { locale: i18n.defaultLocale, rest: parts };
|
|
52
|
-
};
|
|
53
|
-
var localePlacement = (rel, ext, i18n) => {
|
|
54
|
-
const base = rel.slice(0, rel.length - ext.length);
|
|
55
|
-
if (base.endsWith(".$")) {
|
|
56
|
-
const shared = `${base.slice(0, -2)}${ext}`;
|
|
57
|
-
return {
|
|
58
|
-
locales: i18n.locales.map((locale) => locale.code),
|
|
59
|
-
navPath: i18n.parser === "dir" ? detectLocale(shared.split("/"), i18n).rest.join("/") : shared
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
if (i18n.parser === "dot") {
|
|
63
|
-
const lastDot = base.lastIndexOf(".");
|
|
64
|
-
if (lastDot > base.lastIndexOf("/")) {
|
|
65
|
-
const suffix = base.slice(lastDot + 1).toLowerCase();
|
|
66
|
-
const matched = i18n.locales.find((locale) => locale.code.toLowerCase() === suffix);
|
|
67
|
-
if (matched) {
|
|
68
|
-
return {
|
|
69
|
-
locales: [matched.code],
|
|
70
|
-
navPath: `${base.slice(0, lastDot)}${ext}`
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
return { locales: [i18n.defaultLocale], navPath: rel };
|
|
75
|
-
}
|
|
76
|
-
const { locale, rest } = detectLocale(rel.split("/"), i18n);
|
|
77
|
-
return { locales: [locale], navPath: rest.join("/") };
|
|
78
|
-
};
|
|
79
|
-
var localeTargetPath = (rel, ext, locale, i18n) => {
|
|
80
|
-
if (i18n.parser === "dot") {
|
|
81
|
-
let base = rel.slice(0, rel.length - ext.length);
|
|
82
|
-
const lastDot = base.lastIndexOf(".");
|
|
83
|
-
if (lastDot > base.lastIndexOf("/")) {
|
|
84
|
-
const suffix = base.slice(lastDot + 1).toLowerCase();
|
|
85
|
-
if (i18n.locales.some((entry) => entry.code.toLowerCase() === suffix)) {
|
|
86
|
-
base = base.slice(0, lastDot);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
return `${base}.${locale}${ext}`;
|
|
90
|
-
}
|
|
91
|
-
return `${locale}/${rel}`;
|
|
92
|
-
};
|
|
93
|
-
var i18nDiagnostics = (pages, i18n, versions) => {
|
|
94
|
-
const configured = new Set(i18n.locales.map((locale) => locale.code.toLowerCase()));
|
|
95
|
-
const versionDirs = new Set(versions?.archived.map((version) => version.id));
|
|
96
|
-
const seen = new Set;
|
|
97
|
-
const diagnostics = [];
|
|
98
|
-
for (const page of pages) {
|
|
99
|
-
const parts = page.source.ref.split("/");
|
|
100
|
-
const first = (parts[0] && versionDirs.has(parts[0]) ? parts[1] : parts[0])?.toLowerCase();
|
|
101
|
-
if (first && !seen.has(first) && KNOWN_LOCALES.has(first) && !configured.has(first)) {
|
|
102
|
-
seen.add(first);
|
|
103
|
-
diagnostics.push({
|
|
104
|
-
code: "BLUME_I18N_UNCONFIGURED_LOCALE",
|
|
105
|
-
message: `Folder "${first}/" looks like a locale, but "${first}" is not in i18n.locales — its pages are treated as "${i18n.defaultLocale}" content at /${first}/….`,
|
|
106
|
-
severity: "warning",
|
|
107
|
-
suggestion: `Add { code: "${first}", label: "…" } to i18n.locales, or rename the folder if it isn't a translation.`
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
return diagnostics;
|
|
112
|
-
};
|
|
68
|
+
} from "./chunk-jts8mvcz.js";
|
|
69
|
+
import {
|
|
70
|
+
BLUME_IGNORE_DIRS,
|
|
71
|
+
baselineScanIgnore,
|
|
72
|
+
BLUME_WATCH_IGNORE_DIRS,
|
|
73
|
+
excludeDirSegments,
|
|
74
|
+
ignoringWatchListener
|
|
75
|
+
} from "./chunk-abh8yjkn.js";
|
|
113
76
|
|
|
114
77
|
// src/core/manifest.ts
|
|
115
78
|
var versionAlternateKey = (versionKey, locale) => `${versionKey}\x00${locale}`;
|
|
@@ -131,7 +94,7 @@ var buildFallbackRoutes = (graph, i18n, alternatesByKey, basePath, versionAltern
|
|
|
131
94
|
if (!fallback) {
|
|
132
95
|
return [];
|
|
133
96
|
}
|
|
134
|
-
const fallbackPages = new Map(graph.pages.flatMap((page) => page.locale === fallback ? [[page.translationKey, page]] : []));
|
|
97
|
+
const fallbackPages = new Map(graph.pages.flatMap((page) => page.locale === fallback && !page.monolingual ? [[page.translationKey, page]] : []));
|
|
135
98
|
const routes = [];
|
|
136
99
|
for (const { code } of i18n.locales) {
|
|
137
100
|
if (code === fallback) {
|
|
@@ -161,6 +124,7 @@ var buildFallbackRoutes = (graph, i18n, alternatesByKey, basePath, versionAltern
|
|
|
161
124
|
indexable: false,
|
|
162
125
|
lastModified: source.lastModified,
|
|
163
126
|
locale: code,
|
|
127
|
+
monolingual: source.monolingual,
|
|
164
128
|
path,
|
|
165
129
|
source: source.source,
|
|
166
130
|
sourcePath: source.sourcePath,
|
|
@@ -174,7 +138,7 @@ var buildFallbackRoutes = (graph, i18n, alternatesByKey, basePath, versionAltern
|
|
|
174
138
|
};
|
|
175
139
|
var buildManifest = (options) => {
|
|
176
140
|
const { context, config, graph } = options;
|
|
177
|
-
const searchEnabled = config.search.provider !== "none";
|
|
141
|
+
const searchEnabled = config.search.provider.mode !== "none";
|
|
178
142
|
const { i18n } = config;
|
|
179
143
|
const alternatesByKey = new Map;
|
|
180
144
|
if (i18n) {
|
|
@@ -203,6 +167,7 @@ var buildManifest = (options) => {
|
|
|
203
167
|
indexable: searchEnabled && contentIndexable(page, config),
|
|
204
168
|
lastModified: page.lastModified,
|
|
205
169
|
locale: page.locale,
|
|
170
|
+
monolingual: page.monolingual,
|
|
206
171
|
path: page.route,
|
|
207
172
|
source: page.source,
|
|
208
173
|
sourcePath: page.sourcePath,
|
|
@@ -223,7 +188,7 @@ var buildManifest = (options) => {
|
|
|
223
188
|
return {
|
|
224
189
|
blumeVersion: getBlumeVersion(),
|
|
225
190
|
contentRoot: context.contentRoot,
|
|
226
|
-
output: config.deployment.output,
|
|
191
|
+
output: config.deployment.options.output,
|
|
227
192
|
projectRoot: context.root,
|
|
228
193
|
routes,
|
|
229
194
|
version: MANIFEST_VERSION
|
|
@@ -231,7 +196,7 @@ var buildManifest = (options) => {
|
|
|
231
196
|
};
|
|
232
197
|
|
|
233
198
|
// src/core/project-graph.ts
|
|
234
|
-
import { isAbsolute as
|
|
199
|
+
import { isAbsolute as isAbsolute3, relative as relative5 } from "pathe";
|
|
235
200
|
|
|
236
201
|
// src/theme/icon-kind.ts
|
|
237
202
|
var IMAGE_ICON = /^(?:https?:\/\/|data:image\/|\/|\.{1,2}\/)|\.(?:avif|gif|jpe?g|png|svg|webp)$/iu;
|
|
@@ -428,7 +393,46 @@ var GROUP_FOLDER = /^\((?<label>.+)\)$/u;
|
|
|
428
393
|
var WORD_SPLIT = /[-_]/u;
|
|
429
394
|
var isUnderPath = (route, base) => base === "/" || route === base || route.startsWith(`${base}/`);
|
|
430
395
|
var isRootTab = (tab, root) => isUnderPath(root, tab.path);
|
|
431
|
-
var
|
|
396
|
+
var sidebarIcon = (page) => page.meta.sidebar.icon ?? page.meta.icon;
|
|
397
|
+
var WORD_FORMS = new Map([
|
|
398
|
+
["ai", "AI"],
|
|
399
|
+
["api", "API"],
|
|
400
|
+
["apis", "APIs"],
|
|
401
|
+
["asyncapi", "AsyncAPI"],
|
|
402
|
+
["cli", "CLI"],
|
|
403
|
+
["css", "CSS"],
|
|
404
|
+
["faq", "FAQ"],
|
|
405
|
+
["faqs", "FAQs"],
|
|
406
|
+
["graphql", "GraphQL"],
|
|
407
|
+
["html", "HTML"],
|
|
408
|
+
["http", "HTTP"],
|
|
409
|
+
["https", "HTTPS"],
|
|
410
|
+
["id", "ID"],
|
|
411
|
+
["ids", "IDs"],
|
|
412
|
+
["ios", "iOS"],
|
|
413
|
+
["js", "JS"],
|
|
414
|
+
["json", "JSON"],
|
|
415
|
+
["jwt", "JWT"],
|
|
416
|
+
["llm", "LLM"],
|
|
417
|
+
["llms", "LLMs"],
|
|
418
|
+
["macos", "macOS"],
|
|
419
|
+
["mcp", "MCP"],
|
|
420
|
+
["oauth", "OAuth"],
|
|
421
|
+
["openapi", "OpenAPI"],
|
|
422
|
+
["rss", "RSS"],
|
|
423
|
+
["sdk", "SDK"],
|
|
424
|
+
["sdks", "SDKs"],
|
|
425
|
+
["seo", "SEO"],
|
|
426
|
+
["sql", "SQL"],
|
|
427
|
+
["sso", "SSO"],
|
|
428
|
+
["ts", "TS"],
|
|
429
|
+
["ui", "UI"],
|
|
430
|
+
["url", "URL"],
|
|
431
|
+
["urls", "URLs"],
|
|
432
|
+
["xml", "XML"],
|
|
433
|
+
["yaml", "YAML"]
|
|
434
|
+
]);
|
|
435
|
+
var humanize = (segment) => segment.replace(NUMERIC_PREFIX, "").split(WORD_SPLIT).filter(Boolean).map((word) => WORD_FORMS.get(word) ?? word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
432
436
|
var numericOrder = (segment) => {
|
|
433
437
|
const value = segment.match(NUMERIC_PREFIX)?.groups?.order;
|
|
434
438
|
return value ? Math.trunc(Number(value)) : Number.POSITIVE_INFINITY;
|
|
@@ -515,7 +519,7 @@ var applyFolderMeta = (group, folderMeta, sharedMeta, metaPrefix, sharedMetaPref
|
|
|
515
519
|
}
|
|
516
520
|
};
|
|
517
521
|
var indexTitleMismatchDiagnostic = (page, folderPath, folderMeta, sharedMeta, metaPrefix, sharedMetaPrefix) => {
|
|
518
|
-
if (!page.meta.title || page.fallback || folderPath === "") {
|
|
522
|
+
if (!(page.meta.title && page.meta.sidebar.hidden) || page.fallback || folderPath === "") {
|
|
519
523
|
return;
|
|
520
524
|
}
|
|
521
525
|
const meta = folderMeta.get(metaKey(folderPath, metaPrefix)) ?? sharedMeta.get(metaKey(folderPath, sharedMetaPrefix));
|
|
@@ -704,7 +708,7 @@ var buildFileSystemSidebar = (pages, folderMeta, sharedMeta, metaPrefix, sharedM
|
|
|
704
708
|
deprecated: page.meta.deprecated || undefined,
|
|
705
709
|
description: page.description,
|
|
706
710
|
file: page.sourcePath,
|
|
707
|
-
icon: page
|
|
711
|
+
icon: sidebarIcon(page),
|
|
708
712
|
key: segmentKey(stem),
|
|
709
713
|
kind: "page",
|
|
710
714
|
label: page.meta.sidebar.label ?? page.title,
|
|
@@ -747,7 +751,7 @@ var configItemToNode = (item, byRoute, basePath) => {
|
|
|
747
751
|
badge: page.meta.sidebar.badge,
|
|
748
752
|
deprecated: page.meta.deprecated || undefined,
|
|
749
753
|
description: page.description,
|
|
750
|
-
icon: page
|
|
754
|
+
icon: sidebarIcon(page),
|
|
751
755
|
kind: "page",
|
|
752
756
|
label: page.meta.sidebar.label ?? page.title,
|
|
753
757
|
pageId: page.id,
|
|
@@ -802,7 +806,10 @@ var buildConfigSidebar = (items, byRoute, display, basePath) => {
|
|
|
802
806
|
}
|
|
803
807
|
return nodes;
|
|
804
808
|
};
|
|
805
|
-
var resolveTabHref = (sidebar, path) => {
|
|
809
|
+
var resolveTabHref = (sidebar, path, extraRoutes, basePath) => {
|
|
810
|
+
if (extraRoutes.has(path)) {
|
|
811
|
+
return path;
|
|
812
|
+
}
|
|
806
813
|
let first;
|
|
807
814
|
const walk = (nodes) => {
|
|
808
815
|
for (const node of nodes) {
|
|
@@ -819,10 +826,14 @@ var resolveTabHref = (sidebar, path) => {
|
|
|
819
826
|
}
|
|
820
827
|
return false;
|
|
821
828
|
};
|
|
822
|
-
|
|
829
|
+
if (walk(sidebar)) {
|
|
830
|
+
return path;
|
|
831
|
+
}
|
|
832
|
+
const bare = stripBasePath(basePath, path);
|
|
833
|
+
return extraRoutes.has(bare) ? bare : first ?? path;
|
|
823
834
|
};
|
|
824
|
-
var withTabHrefs = (tabs, sidebar) => tabs.map((tab) => {
|
|
825
|
-
const href = tab.href ?? resolveTabHref(sidebar, tab.path);
|
|
835
|
+
var withTabHrefs = (tabs, sidebar, extraRoutes, basePath) => tabs.map((tab) => {
|
|
836
|
+
const href = tab.href ?? resolveTabHref(sidebar, tab.path, extraRoutes, basePath);
|
|
826
837
|
return href === tab.path ? tab : { ...tab, href };
|
|
827
838
|
});
|
|
828
839
|
var rebaseNavChrome = (basePath, options) => {
|
|
@@ -869,6 +880,7 @@ var buildNavigation = (pages, options) => {
|
|
|
869
880
|
const metaPrefix = options.metaPrefix ?? "";
|
|
870
881
|
const sharedMetaPrefix = options.sharedMetaPrefix ?? "";
|
|
871
882
|
const sharedFolderMeta = options.sharedFolderMeta ?? new Map;
|
|
883
|
+
const extraRoutes = options.extraRoutes ?? new Set;
|
|
872
884
|
const { actions, cta, featured, selectors, tabs } = rebaseNavChrome(basePath, options);
|
|
873
885
|
const byRoute = new Map(pages.map((page) => [
|
|
874
886
|
options.refByLogical ? page.translationKey : page.route,
|
|
@@ -894,7 +906,7 @@ var buildNavigation = (pages, options) => {
|
|
|
894
906
|
root: rootTabPath,
|
|
895
907
|
selectors,
|
|
896
908
|
sidebar,
|
|
897
|
-
tabs: withTabHrefs(tabs, sidebar)
|
|
909
|
+
tabs: withTabHrefs(tabs, sidebar, extraRoutes, basePath)
|
|
898
910
|
};
|
|
899
911
|
}
|
|
900
912
|
const sidebar = buildFileSystemSidebar(pages, options.folderMeta, sharedFolderMeta, metaPrefix, sharedMetaPrefix, display, new Set(tabs.flatMap((tab) => isRootTab(tab, rootTabPath) ? [] : [tab.path])), diagnostics);
|
|
@@ -905,48 +917,10 @@ var buildNavigation = (pages, options) => {
|
|
|
905
917
|
root: rootTabPath,
|
|
906
918
|
selectors,
|
|
907
919
|
sidebar,
|
|
908
|
-
tabs: withTabHrefs(tabs, sidebar)
|
|
920
|
+
tabs: withTabHrefs(tabs, sidebar, extraRoutes, basePath)
|
|
909
921
|
};
|
|
910
922
|
};
|
|
911
923
|
|
|
912
|
-
// src/core/versions.ts
|
|
913
|
-
var VERSION_LIKE = /^v\d/iu;
|
|
914
|
-
var detectVersion = (parts, versions) => {
|
|
915
|
-
const [first] = parts;
|
|
916
|
-
if (first && versions.archived.some((version) => version.id === first)) {
|
|
917
|
-
return { rest: parts.slice(1), version: first };
|
|
918
|
-
}
|
|
919
|
-
return { rest: parts, version: "" };
|
|
920
|
-
};
|
|
921
|
-
var detectVersionRef = (ref, versions) => {
|
|
922
|
-
const { version, rest } = detectVersion(ref.split("/"), versions);
|
|
923
|
-
return { rest: rest.join("/"), version };
|
|
924
|
-
};
|
|
925
|
-
var versionizeRoute = (logicalRoute, version) => {
|
|
926
|
-
if (!version) {
|
|
927
|
-
return logicalRoute;
|
|
928
|
-
}
|
|
929
|
-
return logicalRoute === "/" ? `/${version}` : `/${version}${logicalRoute}`;
|
|
930
|
-
};
|
|
931
|
-
var versionsDiagnostics = (pages, versions) => {
|
|
932
|
-
const configured = new Set(versions.archived.map((version) => version.id));
|
|
933
|
-
const seen = new Set;
|
|
934
|
-
const diagnostics = [];
|
|
935
|
-
for (const page of pages) {
|
|
936
|
-
const [first] = page.source.ref.split("/");
|
|
937
|
-
if (first && !seen.has(first) && VERSION_LIKE.test(first) && !configured.has(first)) {
|
|
938
|
-
seen.add(first);
|
|
939
|
-
diagnostics.push({
|
|
940
|
-
code: "BLUME_VERSIONS_UNCONFIGURED_VERSION",
|
|
941
|
-
message: `Folder "${first}/" looks like a version, but "${first}" is not in versions.archived — its pages are treated as current-version content at /${first}/….`,
|
|
942
|
-
severity: "warning",
|
|
943
|
-
suggestion: `Add { id: "${first}" } to versions.archived, or rename the folder if it isn't a snapshot.`
|
|
944
|
-
});
|
|
945
|
-
}
|
|
946
|
-
}
|
|
947
|
-
return diagnostics;
|
|
948
|
-
};
|
|
949
|
-
|
|
950
924
|
// src/core/graph.ts
|
|
951
925
|
var collectRoutes = (pages) => {
|
|
952
926
|
const routes = new Map;
|
|
@@ -1001,7 +975,26 @@ var resolveTabLabels = (tabs, locale, defaultLocale) => (tabs ?? []).map((tab) =
|
|
|
1001
975
|
label: resolveLabel(tab.label, locale, defaultLocale)
|
|
1002
976
|
}));
|
|
1003
977
|
var buildLocaleNavigation = (code, pages, fallback, fallbackByKey, options, i18n, diagnostics, version = "") => {
|
|
1004
|
-
const
|
|
978
|
+
const basePath = options.basePath ?? "";
|
|
979
|
+
const real = pages.filter((page) => page.locale === code);
|
|
980
|
+
const localePages = localePagesFor(code, real, fallback, fallbackByKey, i18n, basePath);
|
|
981
|
+
const pageRoutes = [
|
|
982
|
+
...new Set([...pages, ...localePages].map((page) => page.route))
|
|
983
|
+
];
|
|
984
|
+
const extraRoutes = options.extraRoutes ?? new Set;
|
|
985
|
+
const serves = (path, section) => {
|
|
986
|
+
if (extraRoutes.has(path)) {
|
|
987
|
+
return true;
|
|
988
|
+
}
|
|
989
|
+
const based = withBasePath(basePath, path);
|
|
990
|
+
const prefix = based === "/" ? "/" : `${based}/`;
|
|
991
|
+
return pageRoutes.some((route) => route === based || section && route.startsWith(prefix));
|
|
992
|
+
};
|
|
993
|
+
const localizeServed = (path, section) => {
|
|
994
|
+
const localized = localizeInternalPath(path, code, i18n);
|
|
995
|
+
return localized === path || serves(localized, section) || !serves(path, section) ? localized : path;
|
|
996
|
+
};
|
|
997
|
+
const localizePath = (path) => localizeServed(path, true);
|
|
1005
998
|
const tabs = resolveTabLabels(options.navigation.tabs, code, i18n.defaultLocale).map((tab) => {
|
|
1006
999
|
const localized = {
|
|
1007
1000
|
...tab,
|
|
@@ -1012,24 +1005,23 @@ var buildLocaleNavigation = (code, pages, fallback, fallbackByKey, options, i18n
|
|
|
1012
1005
|
path: localizePath(tab.path)
|
|
1013
1006
|
};
|
|
1014
1007
|
if (localized.href) {
|
|
1015
|
-
localized.href =
|
|
1008
|
+
localized.href = localizeServed(localized.href, false);
|
|
1016
1009
|
}
|
|
1017
1010
|
return localized;
|
|
1018
1011
|
});
|
|
1019
|
-
const real = pages.filter((page) => page.locale === code);
|
|
1020
|
-
const localePages = localePagesFor(code, real, fallback, fallbackByKey, i18n, options.basePath ?? "");
|
|
1021
1012
|
const localeDir = i18n.parser === "dir" && code !== i18n.defaultLocale ? code : "";
|
|
1022
1013
|
const localizeHref = (item) => ({
|
|
1023
1014
|
...item,
|
|
1024
|
-
href:
|
|
1015
|
+
href: localizeServed(item.href, false)
|
|
1025
1016
|
});
|
|
1026
1017
|
const { actions, cta, featured } = options.navigation;
|
|
1027
|
-
|
|
1018
|
+
const navigation = buildNavigation(localePages, {
|
|
1028
1019
|
actions: actions?.map(localizeHref),
|
|
1029
|
-
basePath
|
|
1020
|
+
basePath,
|
|
1030
1021
|
cta: cta ? localizeHref(cta) : null,
|
|
1031
1022
|
diagnostics,
|
|
1032
1023
|
display: options.navigation.sidebar.display,
|
|
1024
|
+
extraRoutes: options.extraRoutes,
|
|
1033
1025
|
featured: featured?.map(localizeHref),
|
|
1034
1026
|
folderMeta: options.folderMeta,
|
|
1035
1027
|
localizedRoot: localizeRoute(versionizeRoute("/", version), code, i18n),
|
|
@@ -1041,13 +1033,14 @@ var buildLocaleNavigation = (code, pages, fallback, fallbackByKey, options, i18n
|
|
|
1041
1033
|
sidebar: version ? undefined : options.navigation.sidebar.items,
|
|
1042
1034
|
tabs
|
|
1043
1035
|
});
|
|
1036
|
+
return options.brandHref === undefined ? navigation : { ...navigation, brandHref: localizeServed(options.brandHref, false) };
|
|
1044
1037
|
};
|
|
1045
1038
|
var buildI18nNavigation = (pages, options, i18n, diagnostics, version = "") => {
|
|
1046
1039
|
const fallback = resolveFallbackLocale(i18n);
|
|
1047
1040
|
const fallbackByKey = new Map;
|
|
1048
1041
|
if (fallback) {
|
|
1049
1042
|
for (const page of pages) {
|
|
1050
|
-
if (page.locale === fallback) {
|
|
1043
|
+
if (page.locale === fallback && !page.monolingual) {
|
|
1051
1044
|
fallbackByKey.set(page.translationKey, page);
|
|
1052
1045
|
}
|
|
1053
1046
|
}
|
|
@@ -1087,6 +1080,7 @@ var buildVersionNavigation = (id, versionPages, options, diagnostics) => {
|
|
|
1087
1080
|
cta: options.navigation.cta,
|
|
1088
1081
|
diagnostics,
|
|
1089
1082
|
display: options.navigation.sidebar.display,
|
|
1083
|
+
extraRoutes: options.extraRoutes,
|
|
1090
1084
|
featured: options.navigation.featured,
|
|
1091
1085
|
folderMeta: options.folderMeta,
|
|
1092
1086
|
localizedRoot: versionizeRoute("/", id),
|
|
@@ -1113,6 +1107,7 @@ var buildContentGraph = (pages, options) => {
|
|
|
1113
1107
|
cta: options.navigation.cta,
|
|
1114
1108
|
diagnostics,
|
|
1115
1109
|
display: options.navigation.sidebar.display,
|
|
1110
|
+
extraRoutes: options.extraRoutes,
|
|
1116
1111
|
featured: options.navigation.featured,
|
|
1117
1112
|
folderMeta: options.folderMeta,
|
|
1118
1113
|
selectors: options.navigation.selectors,
|
|
@@ -1136,980 +1131,116 @@ var buildContentGraph = (pages, options) => {
|
|
|
1136
1131
|
};
|
|
1137
1132
|
};
|
|
1138
1133
|
|
|
1139
|
-
// src/core/
|
|
1140
|
-
import {
|
|
1141
|
-
import {
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
// src/core/frontmatter.ts
|
|
1163
|
-
import baseMatter from "gray-matter";
|
|
1164
|
-
import { dump, load } from "js-yaml";
|
|
1165
|
-
|
|
1166
|
-
// src/core/yaml.ts
|
|
1167
|
-
import {
|
|
1168
|
-
binaryTag,
|
|
1169
|
-
CORE_SCHEMA,
|
|
1170
|
-
mergeTag,
|
|
1171
|
-
omapTag,
|
|
1172
|
-
pairsTag,
|
|
1173
|
-
setTag,
|
|
1174
|
-
timestampTag
|
|
1175
|
-
} from "js-yaml";
|
|
1176
|
-
var YAML_SCHEMA = CORE_SCHEMA.withTags(timestampTag, mergeTag, binaryTag, omapTag, pairsTag, setTag);
|
|
1177
|
-
|
|
1178
|
-
// src/core/frontmatter.ts
|
|
1179
|
-
var yamlEngine = {
|
|
1180
|
-
parse: (input) => load(input, { schema: YAML_SCHEMA }) ?? {},
|
|
1181
|
-
stringify: (data) => dump(data)
|
|
1182
|
-
};
|
|
1183
|
-
var withYamlEngine = (options) => ({
|
|
1184
|
-
...options,
|
|
1185
|
-
engines: {
|
|
1186
|
-
yaml: yamlEngine,
|
|
1187
|
-
...options?.engines
|
|
1188
|
-
}
|
|
1189
|
-
});
|
|
1190
|
-
var opensWithThematicBreak = (input) => {
|
|
1191
|
-
const [first = "", second] = input.split(/\r?\n/u, 2);
|
|
1192
|
-
if (!/^-{3}\s*$/u.test(first)) {
|
|
1193
|
-
return false;
|
|
1194
|
-
}
|
|
1195
|
-
if (second === undefined || second.trim() === "") {
|
|
1196
|
-
return true;
|
|
1197
|
-
}
|
|
1198
|
-
return !input.includes(`
|
|
1199
|
-
---`, 1);
|
|
1200
|
-
};
|
|
1201
|
-
var passthrough = (input) => {
|
|
1202
|
-
const file = {
|
|
1203
|
-
content: input,
|
|
1204
|
-
data: {},
|
|
1205
|
-
excerpt: "",
|
|
1206
|
-
isEmpty: false,
|
|
1207
|
-
language: "",
|
|
1208
|
-
matter: "",
|
|
1209
|
-
orig: input,
|
|
1210
|
-
stringify: () => input
|
|
1211
|
-
};
|
|
1212
|
-
return file;
|
|
1213
|
-
};
|
|
1214
|
-
var isStringInput = (input) => typeof input === "string";
|
|
1215
|
-
var matter = Object.assign((input, options) => isStringInput(input) && opensWithThematicBreak(input) ? passthrough(input) : baseMatter(input, withYamlEngine(options)), baseMatter, {
|
|
1216
|
-
read: (filepath, options) => baseMatter.read(filepath, withYamlEngine(options)),
|
|
1217
|
-
stringify: (file, data, options) => baseMatter.stringify(isStringInput(file) ? { content: file } : file, data, withYamlEngine(options))
|
|
1218
|
-
});
|
|
1219
|
-
var frontmatter_default = matter;
|
|
1220
|
-
|
|
1221
|
-
// src/core/sources/normalize.ts
|
|
1222
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
1223
|
-
import GithubSlugger from "github-slugger";
|
|
1224
|
-
import { extname as extname2 } from "pathe";
|
|
1225
|
-
|
|
1226
|
-
// src/core/heading-markers.ts
|
|
1227
|
-
var TOC_HIDDEN_KEY = "__blumeTocHidden";
|
|
1228
|
-
var occupySlug = (slugger, id) => {
|
|
1229
|
-
slugger.occurrences[id] ??= 0;
|
|
1230
|
-
};
|
|
1231
|
-
var MARKER = /\s*(?:\{#(?<curlyId>[^\s}]+)\}|\[(?:#(?<id>[^\s\]]+)|(?<hide>!)?toc)\])\s*$/u;
|
|
1232
|
-
var parseHeadingMarkers = (text, isRefDefined) => {
|
|
1233
|
-
let remaining = text;
|
|
1234
|
-
let id;
|
|
1235
|
-
let toc;
|
|
1236
|
-
for (let match = MARKER.exec(remaining);match?.groups; match = MARKER.exec(remaining)) {
|
|
1237
|
-
const explicitId = match.groups.curlyId ?? match.groups.id;
|
|
1238
|
-
const label = explicitId === undefined ? `${match.groups.hide ?? ""}toc` : `#${explicitId}`;
|
|
1239
|
-
if (match.groups.curlyId === undefined && isRefDefined?.(label)) {
|
|
1240
|
-
break;
|
|
1241
|
-
}
|
|
1242
|
-
remaining = remaining.slice(0, match.index);
|
|
1243
|
-
if (explicitId === undefined) {
|
|
1244
|
-
toc ??= match.groups.hide === undefined ? "only" : "hide";
|
|
1245
|
-
} else {
|
|
1246
|
-
id ??= explicitId;
|
|
1247
|
-
}
|
|
1248
|
-
}
|
|
1249
|
-
return { id, text: remaining, toc };
|
|
1250
|
-
};
|
|
1251
|
-
|
|
1252
|
-
// src/core/sources/normalize.ts
|
|
1253
|
-
var NUMERIC_PREFIX2 = /^\d+[-_.]/u;
|
|
1254
|
-
var GROUP_FOLDER2 = /^\((?<label>.+)\)$/u;
|
|
1255
|
-
var WORD_SPLIT2 = /[-_]/u;
|
|
1256
|
-
var stripNumericPrefix = (segment) => segment.replace(NUMERIC_PREFIX2, "");
|
|
1257
|
-
var groupLabel = (segment) => segment.match(GROUP_FOLDER2)?.groups?.label ?? null;
|
|
1258
|
-
var slugify2 = (text) => text.normalize("NFC").toLowerCase().trim().replaceAll(/[^\p{L}\p{M}\p{N}\s_-]/gu, "").replaceAll(/[\s_]+/gu, "-").replaceAll(/-+/gu, "-").replaceAll(/^-|-$/gu, "");
|
|
1259
|
-
var slugifyPath = (text) => text.split("/").map(slugify2).filter(Boolean).join("/");
|
|
1260
|
-
var titleCase = (value) => value.split(WORD_SPLIT2).filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
1261
|
-
var sanitizeSegment = (segment) => segment.replaceAll(/[:\p{Cc}]/gu, "");
|
|
1262
|
-
var addRouteSegment = (part, segments, groups) => {
|
|
1263
|
-
if (part === "") {
|
|
1264
|
-
return;
|
|
1265
|
-
}
|
|
1266
|
-
const group = groupLabel(part);
|
|
1267
|
-
if (group !== null) {
|
|
1268
|
-
groups.push(group);
|
|
1269
|
-
return;
|
|
1270
|
-
}
|
|
1271
|
-
const clean = stripNumericPrefix(part);
|
|
1272
|
-
if (clean === "index") {
|
|
1273
|
-
return;
|
|
1274
|
-
}
|
|
1275
|
-
const safe = sanitizeSegment(clean);
|
|
1276
|
-
if (safe === "") {
|
|
1277
|
-
return;
|
|
1278
|
-
}
|
|
1279
|
-
segments.push(safe);
|
|
1280
|
-
};
|
|
1281
|
-
var mapRoute = (relativePath) => {
|
|
1282
|
-
const withoutExt = relativePath.slice(0, relativePath.length - extname2(relativePath).length);
|
|
1283
|
-
const rawParts = withoutExt.split("/");
|
|
1284
|
-
const segments = [];
|
|
1285
|
-
const groups = [];
|
|
1286
|
-
for (const part of rawParts) {
|
|
1287
|
-
addRouteSegment(part, segments, groups);
|
|
1288
|
-
}
|
|
1289
|
-
const route = segments.length === 0 ? "/" : `/${segments.join("/")}`;
|
|
1290
|
-
return { groups, route, segments };
|
|
1291
|
-
};
|
|
1292
|
-
var ATX_HEADING = /^ {0,3}(?<hashes>#{1,6})\s+(?<text>.+?)(?:\s+#+)?\s*$/u;
|
|
1293
|
-
var SETEXT_UNDERLINE = /^ {0,3}(?<marker>=+|-+)\s*$/u;
|
|
1294
|
-
var PARAGRAPH_INTERRUPT = /^ {0,3}(?:[-+*][ \t]|\d{1,9}[.)][ \t]|>)/u;
|
|
1295
|
-
var THEMATIC_BREAK = /^ {0,3}(?:(?:-[ \t]*){3,}|(?:\*[ \t]*){3,}|(?:_[ \t]*){3,})$/u;
|
|
1296
|
-
var FRONT_MATTER_CLOSE = /^(?:-{3}|\.{3})\s*$/u;
|
|
1297
|
-
var PROMPT_OPEN = /^<Prompt(?![\w-])/u;
|
|
1298
|
-
var PROMPT_CLOSE = /<\/Prompt>/u;
|
|
1299
|
-
var linesWithoutFrontMatter = (body) => {
|
|
1300
|
-
const lines = body.split(`
|
|
1301
|
-
`);
|
|
1302
|
-
if (!/^-{3}\s*$/u.test(lines[0] ?? "")) {
|
|
1303
|
-
return { lines, offset: 0 };
|
|
1304
|
-
}
|
|
1305
|
-
if ((lines[1] ?? "").trim() === "") {
|
|
1306
|
-
return { lines, offset: 0 };
|
|
1307
|
-
}
|
|
1308
|
-
const close = lines.findIndex((line, index) => index > 0 && FRONT_MATTER_CLOSE.test(line));
|
|
1309
|
-
return close === -1 ? { lines, offset: 0 } : { lines: lines.slice(close + 1), offset: close + 1 };
|
|
1310
|
-
};
|
|
1311
|
-
var BARE_CURLY_MARKER = /(?<!\\)\{#(?<id>[^\s}]+)\}(?:\s*\[(?:#[^\s\]]+|!?toc)\])*\s*$/u;
|
|
1312
|
-
var HTML_ID = /<[a-z][a-z0-9-]*(?:\s[^<>]*?)?\sid=(?:(?<quote>["'])(?<quoted>[^"'<>]+)\k<quote>|\{(?<jsxQuote>["'])(?<jsx>[^"'<>]+)\k<jsxQuote>\}|(?<bare>[^\s"'=<>`{}]+))/gu;
|
|
1313
|
-
var HTML_COMMENT = /<!--[\s\S]*?-->/gu;
|
|
1314
|
-
var INLINE_CODE = /`[^`]*`/gu;
|
|
1315
|
-
var finishPromptTag = (line, start, state) => {
|
|
1316
|
-
const end = line.indexOf(">", start);
|
|
1317
|
-
if (end === -1) {
|
|
1318
|
-
state.promptTag = true;
|
|
1319
|
-
return;
|
|
1320
|
-
}
|
|
1321
|
-
state.promptTag = false;
|
|
1322
|
-
if (line[end - 1] === "/" || line.includes("</Prompt>", end)) {
|
|
1323
|
-
return;
|
|
1324
|
-
}
|
|
1325
|
-
state.promptDepth += 1;
|
|
1326
|
-
};
|
|
1327
|
-
var ESCAPED_PUNCTUATION = /\\(?<char>[!-/:-@[-`{-~])/gu;
|
|
1328
|
-
var REF_DEFINITION = /^(?: {0,3}|[ \t]*(?:(?:>|(?:[-*+]|\d{1,9}[.)])[ \t])[ \t]*)+)\[(?<label>[^\]]+)\]:[ \t]*(?<rest>.*)$/u;
|
|
1329
|
-
var refDefinitionLabels = (lines) => {
|
|
1330
|
-
const labels = new Set;
|
|
1331
|
-
let fence = null;
|
|
1332
|
-
for (const [index, line] of lines.entries()) {
|
|
1333
|
-
const next = nextFenceState(line, fence);
|
|
1334
|
-
if (fence !== null || next !== null) {
|
|
1335
|
-
fence = next;
|
|
1336
|
-
continue;
|
|
1337
|
-
}
|
|
1338
|
-
const groups = line.match(REF_DEFINITION)?.groups;
|
|
1339
|
-
if (groups?.label === undefined || groups.label.trim() === "") {
|
|
1340
|
-
continue;
|
|
1341
|
-
}
|
|
1342
|
-
const destination = groups.rest ?? "";
|
|
1343
|
-
if (destination === "" && (lines[index + 1] ?? "").trim() === "") {
|
|
1344
|
-
continue;
|
|
1134
|
+
// src/core/last-modified.ts
|
|
1135
|
+
import { execFileSync } from "node:child_process";
|
|
1136
|
+
import { relative } from "pathe";
|
|
1137
|
+
var GIT_LOCATION_VARS = new Set([
|
|
1138
|
+
"GIT_COMMON_DIR",
|
|
1139
|
+
"GIT_DIR",
|
|
1140
|
+
"GIT_INDEX_FILE",
|
|
1141
|
+
"GIT_OBJECT_DIRECTORY",
|
|
1142
|
+
"GIT_PREFIX",
|
|
1143
|
+
"GIT_WORK_TREE"
|
|
1144
|
+
]);
|
|
1145
|
+
var gitEnv = () => Object.fromEntries(Object.entries(process.env).filter(([key]) => !GIT_LOCATION_VARS.has(key)));
|
|
1146
|
+
var resolveLastModifiedConfig = (value) => value === false ? { enabled: false, source: "git" } : { enabled: true, source: value };
|
|
1147
|
+
var parseGitLog = (output) => {
|
|
1148
|
+
const times = new Map;
|
|
1149
|
+
let current = null;
|
|
1150
|
+
for (const line of output.split(`
|
|
1151
|
+
`)) {
|
|
1152
|
+
if (line.startsWith("\x00")) {
|
|
1153
|
+
current = line.slice(1);
|
|
1154
|
+
} else if (line && current && !times.has(line)) {
|
|
1155
|
+
times.set(line, current);
|
|
1345
1156
|
}
|
|
1346
|
-
labels.add(groups.label.trim().replaceAll(/\s+/gu, " ").toLowerCase());
|
|
1347
|
-
}
|
|
1348
|
-
return labels;
|
|
1349
|
-
};
|
|
1350
|
-
var toHeading = (depth, raw, slugger, isRefDefined) => {
|
|
1351
|
-
const unescaped = raw.replaceAll(ESCAPED_PUNCTUATION, "$<char>");
|
|
1352
|
-
const markers = parseHeadingMarkers(unescaped, isRefDefined);
|
|
1353
|
-
const text = markers.text.trim();
|
|
1354
|
-
if (text === "" && (markers.id !== undefined || markers.toc !== undefined)) {
|
|
1355
|
-
return {
|
|
1356
|
-
heading: { depth, slug: slugger.slug(unescaped), text: unescaped },
|
|
1357
|
-
pinned: false
|
|
1358
|
-
};
|
|
1359
|
-
}
|
|
1360
|
-
if (markers.id !== undefined) {
|
|
1361
|
-
occupySlug(slugger, markers.id);
|
|
1362
|
-
return { heading: { depth, slug: markers.id, text }, pinned: true };
|
|
1363
|
-
}
|
|
1364
|
-
return { heading: { depth, slug: slugger.slug(text), text }, pinned: false };
|
|
1365
|
-
};
|
|
1366
|
-
var pushHeading = (headings, state, scanned, line) => {
|
|
1367
|
-
headings.push(scanned.heading);
|
|
1368
|
-
state.sites.push({ line, pinned: scanned.pinned });
|
|
1369
|
-
};
|
|
1370
|
-
var noteCurlyMarker = (text, line, state) => {
|
|
1371
|
-
const id = text.match(BARE_CURLY_MARKER)?.groups?.id;
|
|
1372
|
-
if (id !== undefined) {
|
|
1373
|
-
state.curlyMarkers.push({ id, line });
|
|
1374
1157
|
}
|
|
1158
|
+
return times;
|
|
1375
1159
|
};
|
|
1376
|
-
var
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
const text = (atx.groups.text ?? "").trim();
|
|
1382
|
-
pushHeading(headings, state, toHeading(depth, text, slugger, isRefDefined), state.line);
|
|
1383
|
-
noteCurlyMarker(text, state.line, state);
|
|
1384
|
-
state.paragraph = [];
|
|
1385
|
-
return;
|
|
1386
|
-
}
|
|
1387
|
-
const setext = line.match(SETEXT_UNDERLINE);
|
|
1388
|
-
if (setext?.groups && state.paragraph.length > 0) {
|
|
1389
|
-
const depth = setext.groups.marker?.startsWith("=") ? 1 : 2;
|
|
1390
|
-
const text = state.paragraph.join(" ").trim();
|
|
1391
|
-
pushHeading(headings, state, toHeading(depth, text, slugger, isRefDefined), state.line - 1);
|
|
1392
|
-
noteCurlyMarker(text, state.paragraphStart, state);
|
|
1393
|
-
state.paragraph = [];
|
|
1394
|
-
return;
|
|
1395
|
-
}
|
|
1396
|
-
if (line.trim() === "" || THEMATIC_BREAK.test(line) || PARAGRAPH_INTERRUPT.test(line)) {
|
|
1397
|
-
state.paragraph = [];
|
|
1398
|
-
return;
|
|
1399
|
-
}
|
|
1400
|
-
if (state.paragraph.length === 0) {
|
|
1401
|
-
state.paragraphStart = state.line;
|
|
1160
|
+
var gitRepositoryRoot = (root) => {
|
|
1161
|
+
try {
|
|
1162
|
+
return execFileSync("git", ["-C", root, "rev-parse", "--show-toplevel"], { encoding: "utf-8", env: gitEnv(), stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
1163
|
+
} catch {
|
|
1164
|
+
return null;
|
|
1402
1165
|
}
|
|
1403
|
-
state.paragraph.push(line.trim());
|
|
1404
1166
|
};
|
|
1405
|
-
var
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
state.fence = next;
|
|
1409
|
-
state.paragraph = [];
|
|
1410
|
-
return;
|
|
1411
|
-
}
|
|
1412
|
-
const trimmed = line.trimStart();
|
|
1413
|
-
if (state.promptTag) {
|
|
1414
|
-
finishPromptTag(trimmed, 0, state);
|
|
1415
|
-
state.paragraph = [];
|
|
1416
|
-
return;
|
|
1417
|
-
}
|
|
1418
|
-
if (PROMPT_OPEN.test(trimmed)) {
|
|
1419
|
-
finishPromptTag(trimmed, "<Prompt".length, state);
|
|
1420
|
-
state.paragraph = [];
|
|
1421
|
-
return;
|
|
1422
|
-
}
|
|
1423
|
-
if (state.promptDepth > 0) {
|
|
1424
|
-
if (PROMPT_CLOSE.test(line)) {
|
|
1425
|
-
state.promptDepth -= 1;
|
|
1426
|
-
}
|
|
1427
|
-
state.paragraph = [];
|
|
1428
|
-
return;
|
|
1167
|
+
var gitLastModifiedTimes = (root, contentRoots, sourcePaths, repositoryRoot) => {
|
|
1168
|
+
if (sourcePaths.length === 0 || contentRoots.length === 0) {
|
|
1169
|
+
return new Map;
|
|
1429
1170
|
}
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
const headings = [];
|
|
1434
|
-
const slugger = new GithubSlugger;
|
|
1435
|
-
const state = {
|
|
1436
|
-
anchorLines: [],
|
|
1437
|
-
curlyMarkers: [],
|
|
1438
|
-
fence: null,
|
|
1439
|
-
line: 0,
|
|
1440
|
-
paragraph: [],
|
|
1441
|
-
paragraphStart: 0,
|
|
1442
|
-
promptDepth: 0,
|
|
1443
|
-
promptTag: false,
|
|
1444
|
-
sites: []
|
|
1445
|
-
};
|
|
1446
|
-
const { lines, offset } = linesWithoutFrontMatter(body);
|
|
1447
|
-
const definedLabels = refDefinitionLabels(lines);
|
|
1448
|
-
const isRefDefined = (label) => definedLabels.has(label.toLowerCase());
|
|
1449
|
-
for (const [index, line] of lines.entries()) {
|
|
1450
|
-
state.line = index + offset + 1;
|
|
1451
|
-
scanHeadingLine(line, state, slugger, headings, isRefDefined);
|
|
1452
|
-
}
|
|
1453
|
-
const anchors = new Set;
|
|
1454
|
-
const markup = state.anchorLines.join(`
|
|
1455
|
-
`).replaceAll(HTML_COMMENT, " ");
|
|
1456
|
-
for (const match of markup.matchAll(HTML_ID)) {
|
|
1457
|
-
const id = match.groups?.quoted ?? match.groups?.jsx ?? match.groups?.bare;
|
|
1458
|
-
if (id !== undefined) {
|
|
1459
|
-
anchors.add(id);
|
|
1460
|
-
}
|
|
1171
|
+
const gitRoot = repositoryRoot === undefined ? gitRepositoryRoot(root) : repositoryRoot;
|
|
1172
|
+
if (gitRoot === null) {
|
|
1173
|
+
return new Map;
|
|
1461
1174
|
}
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
const target = match.groups?.target;
|
|
1481
|
-
if (target === undefined || match.index === undefined) {
|
|
1482
|
-
continue;
|
|
1483
|
-
}
|
|
1484
|
-
const targetOffset = targetOffsetIn(match[0], target, match.groups?.title);
|
|
1485
|
-
const entry = {
|
|
1486
|
-
column: match.index + targetOffset + 1,
|
|
1487
|
-
line: lineNumber,
|
|
1488
|
-
target
|
|
1489
|
-
};
|
|
1490
|
-
if (masked[match.index - 1] === "!") {
|
|
1491
|
-
entry.image = true;
|
|
1492
|
-
}
|
|
1493
|
-
links.push(entry);
|
|
1494
|
-
const label = match[0].slice(0, targetOffset - "](".length);
|
|
1495
|
-
for (const image of label.matchAll(MD_IMAGE)) {
|
|
1496
|
-
const imageTarget = image.groups?.target;
|
|
1497
|
-
if (imageTarget === undefined || image.index === undefined) {
|
|
1498
|
-
continue;
|
|
1175
|
+
try {
|
|
1176
|
+
const output = execFileSync("git", [
|
|
1177
|
+
"-C",
|
|
1178
|
+
root,
|
|
1179
|
+
"-c",
|
|
1180
|
+
"core.quotePath=false",
|
|
1181
|
+
"log",
|
|
1182
|
+
"--format=%x00%cI",
|
|
1183
|
+
"--name-only",
|
|
1184
|
+
"--",
|
|
1185
|
+
...contentRoots
|
|
1186
|
+
], { encoding: "utf-8", env: gitEnv(), maxBuffer: 256 * 1024 * 1024 });
|
|
1187
|
+
const byRepoPath = parseGitLog(output);
|
|
1188
|
+
const result = new Map;
|
|
1189
|
+
for (const sourcePath of sourcePaths) {
|
|
1190
|
+
const iso = byRepoPath.get(relative(gitRoot, sourcePath));
|
|
1191
|
+
if (iso) {
|
|
1192
|
+
result.set(sourcePath, iso);
|
|
1499
1193
|
}
|
|
1500
|
-
links.push({
|
|
1501
|
-
column: match.index + image.index + targetOffsetIn(image[0], imageTarget, image.groups?.title) + 1,
|
|
1502
|
-
image: true,
|
|
1503
|
-
line: lineNumber,
|
|
1504
|
-
target: imageTarget
|
|
1505
|
-
});
|
|
1506
1194
|
}
|
|
1195
|
+
return result;
|
|
1196
|
+
} catch {
|
|
1197
|
+
return new Map;
|
|
1507
1198
|
}
|
|
1508
|
-
return next;
|
|
1509
1199
|
};
|
|
1510
|
-
var
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1200
|
+
var isShallowGitRepository = (root) => {
|
|
1201
|
+
try {
|
|
1202
|
+
return execFileSync("git", ["-C", root, "rev-parse", "--is-shallow-repository"], {
|
|
1203
|
+
encoding: "utf-8",
|
|
1204
|
+
env: gitEnv(),
|
|
1205
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
1206
|
+
}).trim() === "true";
|
|
1207
|
+
} catch {
|
|
1208
|
+
return false;
|
|
1518
1209
|
}
|
|
1519
|
-
return links;
|
|
1520
1210
|
};
|
|
1521
|
-
var
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
const next = nextFenceState(line, fence);
|
|
1525
|
-
if (fence !== null || next !== null) {
|
|
1526
|
-
return next;
|
|
1211
|
+
var lastModifiedShallowWarning = (root, undatedCount) => {
|
|
1212
|
+
if (undatedCount === 0 || !isShallowGitRepository(root)) {
|
|
1213
|
+
return [];
|
|
1527
1214
|
}
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1215
|
+
return [
|
|
1216
|
+
{
|
|
1217
|
+
code: "BLUME_SHALLOW_GIT_HISTORY",
|
|
1218
|
+
message: `lastModified is on, but this build runs in a shallow git clone, so ${undatedCount} page(s) have no git-derived date — their sitemap <lastmod> and "Last updated" stamps are omitted.`,
|
|
1219
|
+
severity: "warning",
|
|
1220
|
+
suggestion: "Fetch full history in CI: set the VERCEL_DEEP_CLONE=true environment variable on Vercel, or fetch-depth: 0 for actions/checkout."
|
|
1533
1221
|
}
|
|
1534
|
-
|
|
1535
|
-
return next;
|
|
1222
|
+
];
|
|
1536
1223
|
};
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1224
|
+
|
|
1225
|
+
// src/core/meta.ts
|
|
1226
|
+
import { basename, dirname, relative as relative2 } from "pathe";
|
|
1227
|
+
import { glob } from "tinyglobby";
|
|
1228
|
+
var META_FILES = [
|
|
1229
|
+
"**/meta.ts",
|
|
1230
|
+
"**/meta.js",
|
|
1231
|
+
"**/meta.mjs",
|
|
1232
|
+
"**/meta.$.ts",
|
|
1233
|
+
"**/meta.$.js",
|
|
1234
|
+
"**/meta.$.mjs"
|
|
1235
|
+
];
|
|
1236
|
+
var isMetaFactory = (mod) => typeof mod === "function";
|
|
1237
|
+
var resolveMeta = async (mod) => isMetaFactory(mod) ? await mod() : mod;
|
|
1238
|
+
var metaKeyFor = (prefix, dir) => {
|
|
1239
|
+
const clean = prefix ? trimChar(prefix, "/") : "";
|
|
1240
|
+
if (!clean) {
|
|
1241
|
+
return dir;
|
|
1543
1242
|
}
|
|
1544
|
-
return
|
|
1545
|
-
};
|
|
1546
|
-
var strippedLineOffset = (raw, body) => raw ? Math.max(0, raw.split(`
|
|
1547
|
-
`).length - body.split(`
|
|
1548
|
-
`).length) : 0;
|
|
1549
|
-
var remapExpandedLinks = (links, origins, sourcePath) => links.map((link) => {
|
|
1550
|
-
const origin = origins[link.line - 1];
|
|
1551
|
-
if (!origin) {
|
|
1552
|
-
return link;
|
|
1553
|
-
}
|
|
1554
|
-
const remapped = { ...link, line: origin.line };
|
|
1555
|
-
if (origin.file !== sourcePath) {
|
|
1556
|
-
remapped.file = origin.file;
|
|
1557
|
-
}
|
|
1558
|
-
return remapped;
|
|
1559
|
-
});
|
|
1560
|
-
var entryIncludes = (entry) => entry.expanded && entry.expanded.includes.length > 0 ? entry.expanded.includes : undefined;
|
|
1561
|
-
var entryLinks = (entry) => entry.expanded ? remapExpandedLinks(extractLinks(entry.expanded.text), entry.expanded.origins, entry.sourcePath) : extractLinks(entry.body.text, strippedLineOffset(entry.raw, entry.body.text));
|
|
1562
|
-
var curlyMarkerDiagnostics = (entry, markers, sourceName) => markers.map(({ id, line }) => {
|
|
1563
|
-
const origin = entry.expanded?.origins[line - 1];
|
|
1564
|
-
const page = entry.sourcePath ?? `${sourceName}:${entry.ref}`;
|
|
1565
|
-
const inPartial = origin !== undefined && origin.file !== entry.sourcePath;
|
|
1566
|
-
return {
|
|
1567
|
-
code: "BLUME_MDX_CURLY_ANCHOR",
|
|
1568
|
-
file: origin?.file ?? page,
|
|
1569
|
-
line: origin?.line ?? line + strippedLineOffset(entry.raw, entry.body.text),
|
|
1570
|
-
message: inPartial ? `\`{#${id}}\` is a JSX expression once this partial is included in ${page} (.mdx), so that page fails to compile.` : `\`{#${id}}\` is a JSX expression in .mdx, so this page fails to compile.`,
|
|
1571
|
-
severity: "error",
|
|
1572
|
-
suggestion: `Write \`[#${id}]\` or escape it as \`\\{#${id}\\}\` — both pin the same anchor in .md and .mdx.`
|
|
1573
|
-
};
|
|
1574
|
-
});
|
|
1575
|
-
var deriveTitle = (meta, headings, id) => {
|
|
1576
|
-
if (meta.title) {
|
|
1577
|
-
return meta.title;
|
|
1578
|
-
}
|
|
1579
|
-
const firstHeading = headings.find((h) => h.depth === 1) ?? headings[0];
|
|
1580
|
-
if (firstHeading) {
|
|
1581
|
-
return firstHeading.text;
|
|
1582
|
-
}
|
|
1583
|
-
const base = id.split("/").pop() ?? id;
|
|
1584
|
-
return titleCase(stripNumericPrefix(base.replace(extname2(base), "")));
|
|
1585
|
-
};
|
|
1586
|
-
var trimSlashes = (value) => trimChar(value, "/");
|
|
1587
|
-
var isStringValue = (value) => typeof value === "string";
|
|
1588
|
-
var withPrefix = (prefix, path) => {
|
|
1589
|
-
const clean = prefix ? trimSlashes(prefix) : "";
|
|
1590
|
-
return clean ? `${clean}/${path}` : path;
|
|
1591
|
-
};
|
|
1592
|
-
var placeEntryRef = (ref, ext, ctx) => {
|
|
1593
|
-
const { version, rest } = ctx.versions ? detectVersionRef(ref, ctx.versions) : { rest: ref, version: "" };
|
|
1594
|
-
const { navPath, locales } = ctx.i18n ? localePlacement(rest, ext, ctx.i18n) : { locales: [""], navPath: rest };
|
|
1595
|
-
return { locales, navPath, version };
|
|
1596
|
-
};
|
|
1597
|
-
var resolveEntryRoute = (entry, ext, frontmatterSlug, ctx) => {
|
|
1598
|
-
const { locales, navPath, version } = placeEntryRef(entry.ref, ext, ctx);
|
|
1599
|
-
const slugInput = frontmatterSlug ?? entry.slug;
|
|
1600
|
-
const slug = slugInput ? trimSlashes(slugInput) : "";
|
|
1601
|
-
const routeInput = withPrefix(ctx.prefix, slug ? `${slug}${ext}` : navPath);
|
|
1602
|
-
const { segments, groups, route: versionKey } = mapRoute(routeInput);
|
|
1603
|
-
return {
|
|
1604
|
-
groups,
|
|
1605
|
-
locales,
|
|
1606
|
-
logicalRoute: versionizeRoute(versionKey, version),
|
|
1607
|
-
navPath: withPrefix(ctx.prefix, navPath),
|
|
1608
|
-
segments,
|
|
1609
|
-
version,
|
|
1610
|
-
versionKey
|
|
1611
|
-
};
|
|
1612
|
-
};
|
|
1613
|
-
var localizedRoute = (logicalRoute, locale, i18n) => i18n ? localizeRoute(logicalRoute, locale, i18n) : logicalRoute;
|
|
1614
|
-
var isKeyCarrier = (segment) => typeof segment === "object" && segment !== null;
|
|
1615
|
-
var isSymbolKey = (key) => typeof key === "symbol";
|
|
1616
|
-
var segmentKey2 = (segment) => {
|
|
1617
|
-
const key = isKeyCarrier(segment) ? segment.key : segment;
|
|
1618
|
-
return isSymbolKey(key) ? String(key) : key;
|
|
1619
|
-
};
|
|
1620
|
-
var validateCustomKeys = (data, extend) => {
|
|
1621
|
-
const custom = {};
|
|
1622
|
-
const issues = [];
|
|
1623
|
-
for (const [key, schema] of Object.entries(extend)) {
|
|
1624
|
-
const outcome = schema["~standard"].validate(data[key]);
|
|
1625
|
-
if (outcome instanceof Promise) {
|
|
1626
|
-
issues.push({
|
|
1627
|
-
message: "Async schemas are not supported for custom frontmatter keys.",
|
|
1628
|
-
path: [key]
|
|
1629
|
-
});
|
|
1630
|
-
continue;
|
|
1631
|
-
}
|
|
1632
|
-
if (outcome.issues !== undefined) {
|
|
1633
|
-
issues.push(...outcome.issues.map((issue) => ({
|
|
1634
|
-
message: issue.message,
|
|
1635
|
-
path: [key, ...(issue.path ?? []).map(segmentKey2)]
|
|
1636
|
-
})));
|
|
1637
|
-
continue;
|
|
1638
|
-
}
|
|
1639
|
-
if (outcome.value !== undefined || Object.hasOwn(data, key)) {
|
|
1640
|
-
custom[key] = outcome.value;
|
|
1641
|
-
}
|
|
1642
|
-
}
|
|
1643
|
-
return {
|
|
1644
|
-
custom: Object.keys(custom).length > 0 ? custom : undefined,
|
|
1645
|
-
issues
|
|
1646
|
-
};
|
|
1647
|
-
};
|
|
1648
|
-
var parseEntryMeta = (entry, ctx) => {
|
|
1649
|
-
const entryType = isStringValue(entry.data.type) ? entry.data.type : ctx.defaultType;
|
|
1650
|
-
const typeExtend = ctx.typeFrontmatter?.[entryType];
|
|
1651
|
-
const extend = ctx.frontmatterExtend || typeExtend ? { ...ctx.frontmatterExtend, ...typeExtend } : undefined;
|
|
1652
|
-
const known = extend ? Object.fromEntries(Object.entries(entry.data).filter(([key]) => !Object.hasOwn(extend, key))) : entry.data;
|
|
1653
|
-
const result = pageMetaSchema.safeParse(known);
|
|
1654
|
-
const customResult = extend ? validateCustomKeys(entry.data, extend) : null;
|
|
1655
|
-
if (result.success && (customResult?.issues.length ?? 0) === 0) {
|
|
1656
|
-
return { custom: customResult?.custom, meta: result.data };
|
|
1657
|
-
}
|
|
1658
|
-
const source = entry.raw ?? (entry.sourcePath && existsSync(entry.sourcePath) ? readFileSync(entry.sourcePath, "utf-8") : undefined);
|
|
1659
|
-
const location = {
|
|
1660
|
-
code: "BLUME_FRONTMATTER_INVALID",
|
|
1661
|
-
file: entry.sourcePath ?? `${ctx.source.name}:${entry.ref}`,
|
|
1662
|
-
source
|
|
1663
|
-
};
|
|
1664
|
-
return {
|
|
1665
|
-
diagnostics: [
|
|
1666
|
-
...result.success ? [] : diagnosticsFromZod(result.error, location),
|
|
1667
|
-
...customResult ? diagnosticsFromIssues(customResult.issues, location) : []
|
|
1668
|
-
]
|
|
1669
|
-
};
|
|
1670
|
-
};
|
|
1671
|
-
var normalizeEntry = (entry, ctx) => {
|
|
1672
|
-
const { format } = entry.body;
|
|
1673
|
-
const ext = format === "mdx" ? ".mdx" : ".md";
|
|
1674
|
-
const parsed = parseEntryMeta(entry, ctx);
|
|
1675
|
-
if (parsed.diagnostics) {
|
|
1676
|
-
return { diagnostics: parsed.diagnostics, pages: [] };
|
|
1677
|
-
}
|
|
1678
|
-
const { meta } = parsed;
|
|
1679
|
-
if (meta.hidden) {
|
|
1680
|
-
meta.sidebar.hidden = true;
|
|
1681
|
-
}
|
|
1682
|
-
if (meta.noindex) {
|
|
1683
|
-
meta.seo.noindex = true;
|
|
1684
|
-
}
|
|
1685
|
-
const {
|
|
1686
|
-
groups,
|
|
1687
|
-
locales,
|
|
1688
|
-
logicalRoute,
|
|
1689
|
-
navPath,
|
|
1690
|
-
segments,
|
|
1691
|
-
version,
|
|
1692
|
-
versionKey
|
|
1693
|
-
} = resolveEntryRoute(entry, ext, meta.slug, {
|
|
1694
|
-
i18n: ctx.i18n,
|
|
1695
|
-
prefix: ctx.source.prefix,
|
|
1696
|
-
versions: ctx.versions
|
|
1697
|
-
});
|
|
1698
|
-
const bodyText = entry.expanded?.text ?? entry.body.text;
|
|
1699
|
-
const { anchors, curlyMarkers, headings } = scanBody(bodyText);
|
|
1700
|
-
const { staged } = ctx.source;
|
|
1701
|
-
const base = {
|
|
1702
|
-
anchors,
|
|
1703
|
-
body: staged ? { format, text: entry.raw ?? entry.body.text } : undefined,
|
|
1704
|
-
collection: staged ? "staged" : undefined,
|
|
1705
|
-
componentsUsed: format === "mdx" ? extractComponentTags(bodyText) : undefined,
|
|
1706
|
-
contentType: meta.type ?? ctx.defaultType,
|
|
1707
|
-
custom: parsed.custom,
|
|
1708
|
-
description: meta.description,
|
|
1709
|
-
editUrl: entry.editUrl,
|
|
1710
|
-
entryId: staged ? `${ctx.source.name}/${entry.ref}` : undefined,
|
|
1711
|
-
format,
|
|
1712
|
-
groups,
|
|
1713
|
-
headings,
|
|
1714
|
-
id: `${ctx.source.name}:${entry.ref}`,
|
|
1715
|
-
includes: entryIncludes(entry),
|
|
1716
|
-
lastModified: meta.lastModified ?? entry.lastModified,
|
|
1717
|
-
links: entryLinks(entry),
|
|
1718
|
-
meta,
|
|
1719
|
-
navPath,
|
|
1720
|
-
segments,
|
|
1721
|
-
source: { name: ctx.source.name, ref: entry.ref },
|
|
1722
|
-
sourcePath: entry.sourcePath,
|
|
1723
|
-
title: deriveTitle(meta, headings, navPath),
|
|
1724
|
-
translationKey: logicalRoute,
|
|
1725
|
-
version,
|
|
1726
|
-
versionKey
|
|
1727
|
-
};
|
|
1728
|
-
const pages = locales.map((locale) => ({
|
|
1729
|
-
...base,
|
|
1730
|
-
locale,
|
|
1731
|
-
route: withBasePath(ctx.basePath ?? "", localizedRoute(logicalRoute, locale, ctx.i18n))
|
|
1732
|
-
}));
|
|
1733
|
-
return {
|
|
1734
|
-
diagnostics: format === "mdx" ? curlyMarkerDiagnostics(entry, curlyMarkers, ctx.source.name) : [],
|
|
1735
|
-
pages
|
|
1736
|
-
};
|
|
1737
|
-
};
|
|
1738
|
-
|
|
1739
|
-
// src/core/includes.ts
|
|
1740
|
-
var CONTENT_EXTENSIONS = new Set([".md", ".mdx"]);
|
|
1741
|
-
var INCLUDE_STATEMENT = /^<include(?<attrs>(?:\s+[a-z][\w-]*(?:\s*=\s*(?:"[^"]*"|'[^']*'))?)*)\s*>\s*(?<target>[^<>\s](?:[^<>]*[^<>\s])?)\s*<\/include\s*>$/u;
|
|
1742
|
-
var INCLUDE_ATTRIBUTE = /(?<name>[a-z][\w-]*)(?:\s*=\s*(?:"(?<double>[^"]*)"|'(?<single>[^']*)'))?/gu;
|
|
1743
|
-
var hasIncludeStatements = (text) => text.includes("<include");
|
|
1744
|
-
var INDENTED_CODE = /^(?: {4}|\t)/u;
|
|
1745
|
-
var SETEXT_UNDERLINE2 = /^ {0,3}(?:=+|-+)\s*$/u;
|
|
1746
|
-
var COMMENT_DELIMITERS = {
|
|
1747
|
-
md: { close: "-->", open: "<!--" },
|
|
1748
|
-
mdx: { close: "*/}", open: "{/*" }
|
|
1749
|
-
};
|
|
1750
|
-
var advanceCommentState = (line, delimiters, inComment) => {
|
|
1751
|
-
let inside = inComment;
|
|
1752
|
-
let cursor = 0;
|
|
1753
|
-
for (;; ) {
|
|
1754
|
-
const marker = inside ? delimiters.close : delimiters.open;
|
|
1755
|
-
const index = line.indexOf(marker, cursor);
|
|
1756
|
-
if (index === -1) {
|
|
1757
|
-
return inside;
|
|
1758
|
-
}
|
|
1759
|
-
inside = !inside;
|
|
1760
|
-
cursor = index + marker.length;
|
|
1761
|
-
}
|
|
1762
|
-
};
|
|
1763
|
-
var parseIncludeStatement = (line) => {
|
|
1764
|
-
const match = INCLUDE_STATEMENT.exec(line);
|
|
1765
|
-
if (!match?.groups) {
|
|
1766
|
-
return null;
|
|
1767
|
-
}
|
|
1768
|
-
const attributes = {};
|
|
1769
|
-
for (const attr of (match.groups.attrs ?? "").matchAll(INCLUDE_ATTRIBUTE)) {
|
|
1770
|
-
const name = attr.groups?.name;
|
|
1771
|
-
const value = attr.groups?.double ?? attr.groups?.single;
|
|
1772
|
-
if (name === "lang" && value) {
|
|
1773
|
-
attributes.lang = value;
|
|
1774
|
-
}
|
|
1775
|
-
if (name === "meta" && value) {
|
|
1776
|
-
attributes.meta = value;
|
|
1777
|
-
}
|
|
1778
|
-
}
|
|
1779
|
-
return { attributes, target: match.groups.target ?? "" };
|
|
1780
|
-
};
|
|
1781
|
-
var parseIncludeLine = (line) => INDENTED_CODE.test(line) ? null : parseIncludeStatement(line.trim());
|
|
1782
|
-
var DOCS_SUGGESTION = "Include paths resolve relative to the including file; paths starting with / resolve from the content root.";
|
|
1783
|
-
var includeError = (code, message, file, line, suggestion) => ({ code, file, line, message, severity: "error", suggestion });
|
|
1784
|
-
var escapesRoot = (root, path) => {
|
|
1785
|
-
const rel = relative(root, path);
|
|
1786
|
-
return rel === ".." || rel.startsWith("../");
|
|
1787
|
-
};
|
|
1788
|
-
var resolveIncludePath = (target, filePath, ctx, line) => {
|
|
1789
|
-
if (target.startsWith("/")) {
|
|
1790
|
-
if (!ctx.contentRoot) {
|
|
1791
|
-
return {
|
|
1792
|
-
error: includeError("BLUME_INCLUDE_OUTSIDE_ROOT", `Include target ${target} is root-relative, but no content root is configured here.`, filePath, line, "Use a path relative to the including file instead.")
|
|
1793
|
-
};
|
|
1794
|
-
}
|
|
1795
|
-
const path = join(ctx.contentRoot, target);
|
|
1796
|
-
if (escapesRoot(ctx.contentRoot, path)) {
|
|
1797
|
-
return {
|
|
1798
|
-
error: includeError("BLUME_INCLUDE_OUTSIDE_ROOT", `Include target ${target} resolves outside the content root.`, filePath, line, "Root-relative include paths resolve from the content root and cannot climb above it.")
|
|
1799
|
-
};
|
|
1800
|
-
}
|
|
1801
|
-
return { path };
|
|
1802
|
-
}
|
|
1803
|
-
const path = resolve(dirname(filePath), target);
|
|
1804
|
-
if (ctx.contentRoot && escapesRoot(ctx.contentRoot, path)) {
|
|
1805
|
-
return {
|
|
1806
|
-
error: includeError("BLUME_INCLUDE_OUTSIDE_ROOT", `Include target ${target} resolves outside the content root.`, filePath, line, "Move the included file under the content root so builds, version snapshots, and ejects all see it.")
|
|
1807
|
-
};
|
|
1808
|
-
}
|
|
1809
|
-
return { path };
|
|
1810
|
-
};
|
|
1811
|
-
var rebaseImageLine = (line, fromDir, toDir) => {
|
|
1812
|
-
const masked = line.replaceAll(INLINE_CODE, (span) => " ".repeat(span.length));
|
|
1813
|
-
let out = "";
|
|
1814
|
-
let cursor = 0;
|
|
1815
|
-
for (const match of masked.matchAll(MD_IMAGE)) {
|
|
1816
|
-
const target = match.groups?.target ?? "";
|
|
1817
|
-
if (target.startsWith("/") || target.startsWith("#") || URL.canParse(target)) {
|
|
1818
|
-
continue;
|
|
1819
|
-
}
|
|
1820
|
-
const rebased = relative(toDir, resolve(fromDir, target));
|
|
1821
|
-
const url = rebased.startsWith(".") ? rebased : `./${rebased}`;
|
|
1822
|
-
const offset = (match.index ?? 0) + targetOffsetIn(match[0], target, match.groups?.title);
|
|
1823
|
-
out += line.slice(cursor, offset) + url;
|
|
1824
|
-
cursor = offset + target.length;
|
|
1825
|
-
}
|
|
1826
|
-
return out + line.slice(cursor);
|
|
1827
|
-
};
|
|
1828
|
-
var rebaseImages = (lines, fromDir, toDir) => {
|
|
1829
|
-
if (fromDir === toDir) {
|
|
1830
|
-
return lines;
|
|
1831
|
-
}
|
|
1832
|
-
let fence = null;
|
|
1833
|
-
return lines.map((line) => {
|
|
1834
|
-
const next = nextFenceState(line, fence);
|
|
1835
|
-
const inFence = fence !== null || next !== null;
|
|
1836
|
-
fence = next;
|
|
1837
|
-
return inFence ? line : rebaseImageLine(line, fromDir, toDir);
|
|
1838
|
-
});
|
|
1839
|
-
};
|
|
1840
|
-
var codeBlockLines = (content, path, attributes) => {
|
|
1841
|
-
const body = content.replace(/\n$/u, "");
|
|
1842
|
-
let longestRun = 0;
|
|
1843
|
-
for (const run of body.match(/`+/gu) ?? []) {
|
|
1844
|
-
longestRun = Math.max(longestRun, run.length);
|
|
1845
|
-
}
|
|
1846
|
-
const fence = "`".repeat(Math.max(3, longestRun + 1));
|
|
1847
|
-
const ext = extname3(path);
|
|
1848
|
-
const lang = attributes.lang ?? (ext ? ext.slice(1) : "text");
|
|
1849
|
-
const meta = attributes.meta ? ` ${attributes.meta}` : "";
|
|
1850
|
-
return [`${fence}${lang}${meta}`, ...body.split(`
|
|
1851
|
-
`), fence];
|
|
1852
|
-
};
|
|
1853
|
-
var expandStatement = async (statement, filePath, line, ctx, stack) => {
|
|
1854
|
-
const resolved = resolveIncludePath(statement.target, filePath, ctx, line);
|
|
1855
|
-
if ("error" in resolved) {
|
|
1856
|
-
return resolved;
|
|
1857
|
-
}
|
|
1858
|
-
const { path } = resolved;
|
|
1859
|
-
if (stack.includes(path)) {
|
|
1860
|
-
return {
|
|
1861
|
-
error: includeError("BLUME_INCLUDE_CYCLE", `Circular include: ${[...stack, path].map((entry) => relative(ctx.contentRoot ?? dirname(path), entry)).join(" -> ")}.`, filePath, line, "Remove the include statement that closes the loop.")
|
|
1862
|
-
};
|
|
1863
|
-
}
|
|
1864
|
-
let content;
|
|
1865
|
-
try {
|
|
1866
|
-
content = await readFile(path, "utf-8");
|
|
1867
|
-
} catch (error) {
|
|
1868
|
-
return {
|
|
1869
|
-
error: includeError("BLUME_INCLUDE_NOT_FOUND", `Include target ${statement.target} was not found (looked at ${path}): ${error instanceof Error ? error.message : String(error)}.`, filePath, line, DOCS_SUGGESTION)
|
|
1870
|
-
};
|
|
1871
|
-
}
|
|
1872
|
-
ctx.includes.add(path);
|
|
1873
|
-
const asContent = !statement.attributes.lang && CONTENT_EXTENSIONS.has(extname3(path).toLowerCase());
|
|
1874
|
-
if (!asContent) {
|
|
1875
|
-
const lines = codeBlockLines(content, path, statement.attributes);
|
|
1876
|
-
return {
|
|
1877
|
-
lines,
|
|
1878
|
-
origins: lines.map((_, i) => ({ file: path, line: Math.max(1, i) }))
|
|
1879
|
-
};
|
|
1880
|
-
}
|
|
1881
|
-
const parsed = frontmatter_default(content);
|
|
1882
|
-
const body = parsed.content;
|
|
1883
|
-
const strippedOffset = Math.max(0, content.split(`
|
|
1884
|
-
`).length - body.split(`
|
|
1885
|
-
`).length);
|
|
1886
|
-
const expanded = await expandLines(body, path, strippedOffset, ctx, [
|
|
1887
|
-
...stack,
|
|
1888
|
-
path
|
|
1889
|
-
]);
|
|
1890
|
-
const lines = [...expanded.lines];
|
|
1891
|
-
const origins = [...expanded.origins];
|
|
1892
|
-
while (lines.at(-1)?.trim() === "") {
|
|
1893
|
-
lines.pop();
|
|
1894
|
-
origins.pop();
|
|
1895
|
-
}
|
|
1896
|
-
while (lines[0]?.trim() === "") {
|
|
1897
|
-
lines.shift();
|
|
1898
|
-
origins.shift();
|
|
1899
|
-
}
|
|
1900
|
-
return {
|
|
1901
|
-
lines: rebaseImages(lines, dirname(path), dirname(filePath)),
|
|
1902
|
-
origins
|
|
1903
|
-
};
|
|
1904
|
-
};
|
|
1905
|
-
var expandLines = async (body, filePath, lineOffset, ctx, stack) => {
|
|
1906
|
-
const sourceLines = body.split(`
|
|
1907
|
-
`);
|
|
1908
|
-
const isMdx = extname3(filePath).toLowerCase() === ".mdx";
|
|
1909
|
-
const delimiters = COMMENT_DELIMITERS[isMdx ? "mdx" : "md"];
|
|
1910
|
-
let fence = null;
|
|
1911
|
-
let inComment = false;
|
|
1912
|
-
const statements = sourceLines.map((line, index) => {
|
|
1913
|
-
if (inComment) {
|
|
1914
|
-
inComment = advanceCommentState(line, delimiters, true);
|
|
1915
|
-
return null;
|
|
1916
|
-
}
|
|
1917
|
-
const next = nextFenceState(line, fence);
|
|
1918
|
-
const inFence = fence !== null || next !== null;
|
|
1919
|
-
fence = next;
|
|
1920
|
-
if (inFence) {
|
|
1921
|
-
return null;
|
|
1922
|
-
}
|
|
1923
|
-
inComment = advanceCommentState(line, delimiters, false);
|
|
1924
|
-
if (inComment || !hasIncludeStatements(line)) {
|
|
1925
|
-
return null;
|
|
1926
|
-
}
|
|
1927
|
-
const statement = isMdx ? parseIncludeStatement(line.trim()) : parseIncludeLine(line);
|
|
1928
|
-
if (statement && !isMdx && SETEXT_UNDERLINE2.test(sourceLines[index + 1] ?? "")) {
|
|
1929
|
-
return null;
|
|
1930
|
-
}
|
|
1931
|
-
return statement;
|
|
1932
|
-
});
|
|
1933
|
-
const expansions = await Promise.all(statements.map((statement, index) => statement ? expandStatement(statement, filePath, lineOffset + index + 1, ctx, stack) : null));
|
|
1934
|
-
const lines = [];
|
|
1935
|
-
const origins = [];
|
|
1936
|
-
for (const [index, line] of sourceLines.entries()) {
|
|
1937
|
-
const rawLine = lineOffset + index + 1;
|
|
1938
|
-
const expanded = expansions[index];
|
|
1939
|
-
if (!expanded || "error" in expanded) {
|
|
1940
|
-
if (expanded) {
|
|
1941
|
-
ctx.errors.push(expanded.error);
|
|
1942
|
-
}
|
|
1943
|
-
lines.push(line);
|
|
1944
|
-
origins.push({ file: filePath, line: rawLine });
|
|
1945
|
-
continue;
|
|
1946
|
-
}
|
|
1947
|
-
const pad = () => {
|
|
1948
|
-
lines.push("");
|
|
1949
|
-
origins.push({ file: filePath, line: rawLine });
|
|
1950
|
-
};
|
|
1951
|
-
if (lines.at(-1)?.trim()) {
|
|
1952
|
-
pad();
|
|
1953
|
-
}
|
|
1954
|
-
lines.push(...expanded.lines);
|
|
1955
|
-
origins.push(...expanded.origins);
|
|
1956
|
-
if (sourceLines[index + 1]?.trim()) {
|
|
1957
|
-
pad();
|
|
1958
|
-
}
|
|
1959
|
-
}
|
|
1960
|
-
return { lines, origins };
|
|
1961
|
-
};
|
|
1962
|
-
var expandIncludes = async (body, options) => {
|
|
1963
|
-
const ctx = {
|
|
1964
|
-
contentRoot: options.contentRoot,
|
|
1965
|
-
errors: [],
|
|
1966
|
-
includes: new Set
|
|
1967
|
-
};
|
|
1968
|
-
const { lines, origins } = await expandLines(body, options.sourcePath, options.lineOffset ?? 0, ctx, [options.sourcePath]);
|
|
1969
|
-
return {
|
|
1970
|
-
errors: ctx.errors,
|
|
1971
|
-
includes: [...ctx.includes],
|
|
1972
|
-
origins,
|
|
1973
|
-
text: lines.join(`
|
|
1974
|
-
`)
|
|
1975
|
-
};
|
|
1976
|
-
};
|
|
1977
|
-
var buildIncludeGraph = (pages) => {
|
|
1978
|
-
const graph = {};
|
|
1979
|
-
for (const page of pages) {
|
|
1980
|
-
const { sourcePath } = page;
|
|
1981
|
-
if (!sourcePath) {
|
|
1982
|
-
continue;
|
|
1983
|
-
}
|
|
1984
|
-
for (const partial of page.includes ?? []) {
|
|
1985
|
-
const includers = graph[partial] ?? [];
|
|
1986
|
-
graph[partial] = includers;
|
|
1987
|
-
if (!includers.includes(sourcePath)) {
|
|
1988
|
-
includers.push(sourcePath);
|
|
1989
|
-
}
|
|
1990
|
-
}
|
|
1991
|
-
}
|
|
1992
|
-
return graph;
|
|
1993
|
-
};
|
|
1994
|
-
|
|
1995
|
-
// src/core/last-modified.ts
|
|
1996
|
-
import { execFileSync } from "node:child_process";
|
|
1997
|
-
import { relative as relative2 } from "pathe";
|
|
1998
|
-
var GIT_LOCATION_VARS = new Set([
|
|
1999
|
-
"GIT_COMMON_DIR",
|
|
2000
|
-
"GIT_DIR",
|
|
2001
|
-
"GIT_INDEX_FILE",
|
|
2002
|
-
"GIT_OBJECT_DIRECTORY",
|
|
2003
|
-
"GIT_PREFIX",
|
|
2004
|
-
"GIT_WORK_TREE"
|
|
2005
|
-
]);
|
|
2006
|
-
var gitEnv = () => Object.fromEntries(Object.entries(process.env).filter(([key]) => !GIT_LOCATION_VARS.has(key)));
|
|
2007
|
-
var resolveLastModifiedConfig = (value) => {
|
|
2008
|
-
if (value === false) {
|
|
2009
|
-
return { enabled: false, source: "git" };
|
|
2010
|
-
}
|
|
2011
|
-
if (value === true) {
|
|
2012
|
-
return { enabled: true, source: "git" };
|
|
2013
|
-
}
|
|
2014
|
-
return { enabled: true, source: value.type };
|
|
2015
|
-
};
|
|
2016
|
-
var parseGitLog = (output) => {
|
|
2017
|
-
const times = new Map;
|
|
2018
|
-
let current = null;
|
|
2019
|
-
for (const line of output.split(`
|
|
2020
|
-
`)) {
|
|
2021
|
-
if (line.startsWith("\x00")) {
|
|
2022
|
-
current = line.slice(1);
|
|
2023
|
-
} else if (line && current && !times.has(line)) {
|
|
2024
|
-
times.set(line, current);
|
|
2025
|
-
}
|
|
2026
|
-
}
|
|
2027
|
-
return times;
|
|
2028
|
-
};
|
|
2029
|
-
var gitRepositoryRoot = (root) => {
|
|
2030
|
-
try {
|
|
2031
|
-
return execFileSync("git", ["-C", root, "rev-parse", "--show-toplevel"], { encoding: "utf-8", env: gitEnv(), stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
2032
|
-
} catch {
|
|
2033
|
-
return null;
|
|
2034
|
-
}
|
|
2035
|
-
};
|
|
2036
|
-
var gitLastModifiedTimes = (root, contentRoots, sourcePaths, repositoryRoot) => {
|
|
2037
|
-
if (sourcePaths.length === 0 || contentRoots.length === 0) {
|
|
2038
|
-
return new Map;
|
|
2039
|
-
}
|
|
2040
|
-
const gitRoot = repositoryRoot === undefined ? gitRepositoryRoot(root) : repositoryRoot;
|
|
2041
|
-
if (gitRoot === null) {
|
|
2042
|
-
return new Map;
|
|
2043
|
-
}
|
|
2044
|
-
try {
|
|
2045
|
-
const output = execFileSync("git", [
|
|
2046
|
-
"-C",
|
|
2047
|
-
root,
|
|
2048
|
-
"-c",
|
|
2049
|
-
"core.quotePath=false",
|
|
2050
|
-
"log",
|
|
2051
|
-
"--format=%x00%cI",
|
|
2052
|
-
"--name-only",
|
|
2053
|
-
"--",
|
|
2054
|
-
...contentRoots
|
|
2055
|
-
], { encoding: "utf-8", env: gitEnv(), maxBuffer: 256 * 1024 * 1024 });
|
|
2056
|
-
const byRepoPath = parseGitLog(output);
|
|
2057
|
-
const result = new Map;
|
|
2058
|
-
for (const sourcePath of sourcePaths) {
|
|
2059
|
-
const iso = byRepoPath.get(relative2(gitRoot, sourcePath));
|
|
2060
|
-
if (iso) {
|
|
2061
|
-
result.set(sourcePath, iso);
|
|
2062
|
-
}
|
|
2063
|
-
}
|
|
2064
|
-
return result;
|
|
2065
|
-
} catch {
|
|
2066
|
-
return new Map;
|
|
2067
|
-
}
|
|
2068
|
-
};
|
|
2069
|
-
var isShallowGitRepository = (root) => {
|
|
2070
|
-
try {
|
|
2071
|
-
return execFileSync("git", ["-C", root, "rev-parse", "--is-shallow-repository"], {
|
|
2072
|
-
encoding: "utf-8",
|
|
2073
|
-
env: gitEnv(),
|
|
2074
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
2075
|
-
}).trim() === "true";
|
|
2076
|
-
} catch {
|
|
2077
|
-
return false;
|
|
2078
|
-
}
|
|
2079
|
-
};
|
|
2080
|
-
var lastModifiedShallowWarning = (root, undatedCount) => {
|
|
2081
|
-
if (undatedCount === 0 || !isShallowGitRepository(root)) {
|
|
2082
|
-
return [];
|
|
2083
|
-
}
|
|
2084
|
-
return [
|
|
2085
|
-
{
|
|
2086
|
-
code: "BLUME_SHALLOW_GIT_HISTORY",
|
|
2087
|
-
message: `lastModified is on, but this build runs in a shallow git clone, so ${undatedCount} page(s) have no git-derived date — their sitemap <lastmod> and "Last updated" stamps are omitted.`,
|
|
2088
|
-
severity: "warning",
|
|
2089
|
-
suggestion: "Fetch full history in CI: set the VERCEL_DEEP_CLONE=true environment variable on Vercel, or fetch-depth: 0 for actions/checkout."
|
|
2090
|
-
}
|
|
2091
|
-
];
|
|
2092
|
-
};
|
|
2093
|
-
|
|
2094
|
-
// src/core/meta.ts
|
|
2095
|
-
import { basename, dirname as dirname2, relative as relative3 } from "pathe";
|
|
2096
|
-
import { glob } from "tinyglobby";
|
|
2097
|
-
var META_FILES = [
|
|
2098
|
-
"**/meta.ts",
|
|
2099
|
-
"**/meta.js",
|
|
2100
|
-
"**/meta.mjs",
|
|
2101
|
-
"**/meta.$.ts",
|
|
2102
|
-
"**/meta.$.js",
|
|
2103
|
-
"**/meta.$.mjs"
|
|
2104
|
-
];
|
|
2105
|
-
var isMetaFactory = (mod) => typeof mod === "function";
|
|
2106
|
-
var resolveMeta = async (mod) => isMetaFactory(mod) ? await mod() : mod;
|
|
2107
|
-
var metaKeyFor = (prefix, dir) => {
|
|
2108
|
-
const clean = prefix ? trimChar(prefix, "/") : "";
|
|
2109
|
-
if (!clean) {
|
|
2110
|
-
return dir;
|
|
2111
|
-
}
|
|
2112
|
-
return dir ? `${clean}/${dir}` : clean;
|
|
1243
|
+
return dir ? `${clean}/${dir}` : clean;
|
|
2113
1244
|
};
|
|
2114
1245
|
var discoverFolderMeta = async (sources, options = {}) => {
|
|
2115
1246
|
const list = Array.isArray(sources) ? sources : [{ root: sources }];
|
|
@@ -2141,7 +1272,7 @@ var discoverFolderMeta = async (sources, options = {}) => {
|
|
|
2141
1272
|
}));
|
|
2142
1273
|
for (const { loaded, source } of perSource) {
|
|
2143
1274
|
for (const entry of loaded) {
|
|
2144
|
-
const dir =
|
|
1275
|
+
const dir = relative2(source.root, dirname(entry.file));
|
|
2145
1276
|
const [head, ...tail] = dir.split("/");
|
|
2146
1277
|
const version = head && versionDirs.has(head) ? head : "";
|
|
2147
1278
|
const afterVersion = version ? tail : [head ?? "", ...tail];
|
|
@@ -2174,1287 +1305,345 @@ var discoverFolderMeta = async (sources, options = {}) => {
|
|
|
2174
1305
|
};
|
|
2175
1306
|
|
|
2176
1307
|
// src/core/sources/resolve.ts
|
|
2177
|
-
import {
|
|
1308
|
+
import { join as join7 } from "pathe";
|
|
2178
1309
|
|
|
2179
|
-
// src/core/sources/
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
const seedBaseline = async () => {
|
|
2189
|
-
try {
|
|
2190
|
-
const { entries } = await seed();
|
|
2191
|
-
last ||= entriesDigest(entries);
|
|
2192
|
-
} catch {}
|
|
2193
|
-
};
|
|
2194
|
-
seedBaseline();
|
|
2195
|
-
}
|
|
2196
|
-
const tick = async () => {
|
|
2197
|
-
try {
|
|
2198
|
-
const { entries } = await load();
|
|
2199
|
-
const next = entriesDigest(entries);
|
|
2200
|
-
if (last && next !== last) {
|
|
2201
|
-
onChange();
|
|
2202
|
-
}
|
|
2203
|
-
last = next;
|
|
2204
|
-
} catch {}
|
|
2205
|
-
};
|
|
2206
|
-
const timer = setInterval(() => {
|
|
2207
|
-
tick();
|
|
2208
|
-
}, intervalSeconds * 1000);
|
|
2209
|
-
return () => clearInterval(timer);
|
|
2210
|
-
};
|
|
2211
|
-
var snapshotCache = (cacheDir) => {
|
|
2212
|
-
const file = join2(cacheDir, "entries.json");
|
|
2213
|
-
return {
|
|
2214
|
-
read: async () => {
|
|
2215
|
-
try {
|
|
2216
|
-
return JSON.parse(await readFile2(file, "utf-8"));
|
|
2217
|
-
} catch {
|
|
2218
|
-
return [];
|
|
2219
|
-
}
|
|
2220
|
-
},
|
|
2221
|
-
write: async (entries) => {
|
|
2222
|
-
try {
|
|
2223
|
-
await mkdir(cacheDir, { recursive: true });
|
|
2224
|
-
await writeFile(file, `${JSON.stringify(entries)}
|
|
2225
|
-
`, "utf-8");
|
|
2226
|
-
} catch {}
|
|
2227
|
-
}
|
|
2228
|
-
};
|
|
2229
|
-
};
|
|
2230
|
-
var loadWithCache = async (name, cache, fetchEntries, refresh = true) => {
|
|
2231
|
-
if (!refresh) {
|
|
2232
|
-
const cached = await cache.read();
|
|
2233
|
-
if (cached.length > 0) {
|
|
2234
|
-
return { diagnostics: [], entries: cached };
|
|
2235
|
-
}
|
|
2236
|
-
}
|
|
2237
|
-
try {
|
|
2238
|
-
const entries = await fetchEntries();
|
|
2239
|
-
await cache.write(entries);
|
|
2240
|
-
return { diagnostics: [], entries };
|
|
2241
|
-
} catch (error) {
|
|
2242
|
-
const fallback = await cache.read();
|
|
2243
|
-
if (fallback.length > 0) {
|
|
2244
|
-
const diagnostic = {
|
|
2245
|
-
code: "BLUME_SOURCE_OFFLINE",
|
|
2246
|
-
message: `Source "${name}" could not be fetched (${error.message}); served ${fallback.length} cached entries.`,
|
|
2247
|
-
severity: "warning"
|
|
2248
|
-
};
|
|
2249
|
-
return { diagnostics: [diagnostic], entries: fallback };
|
|
1310
|
+
// src/core/sources/json.ts
|
|
1311
|
+
var isJsonObject = (value) => typeof value === "object" && value !== null;
|
|
1312
|
+
var getPath = (doc, path) => {
|
|
1313
|
+
let current = doc;
|
|
1314
|
+
for (const key of path.split(".")) {
|
|
1315
|
+
if (isJsonObject(current)) {
|
|
1316
|
+
current = current[key];
|
|
1317
|
+
} else {
|
|
1318
|
+
return;
|
|
2250
1319
|
}
|
|
2251
|
-
throw new BlumeError({
|
|
2252
|
-
code: "BLUME_SOURCE_FETCH_FAILED",
|
|
2253
|
-
message: `Source "${name}" failed to load and no cache is available: ${error.message}`,
|
|
2254
|
-
severity: "error"
|
|
2255
|
-
});
|
|
2256
1320
|
}
|
|
1321
|
+
return current;
|
|
2257
1322
|
};
|
|
1323
|
+
var isStringValue2 = (value) => typeof value === "string";
|
|
1324
|
+
var asString = (value) => isStringValue2(value) ? value : undefined;
|
|
1325
|
+
var asArray = (value) => Array.isArray(value) ? value : [];
|
|
1326
|
+
var asObject = (value) => isJsonObject(value) && !Array.isArray(value) ? value : undefined;
|
|
1327
|
+
var isNumberValue = (value) => typeof value === "number";
|
|
1328
|
+
var asNumber = (value) => isNumberValue(value) ? value : undefined;
|
|
1329
|
+
var objectsIn = (value) => asArray(value).flatMap((item) => {
|
|
1330
|
+
const object = asObject(item);
|
|
1331
|
+
return object ? [object] : [];
|
|
1332
|
+
});
|
|
2258
1333
|
|
|
2259
|
-
// src/
|
|
2260
|
-
var
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
"
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
"patch",
|
|
2268
|
-
"trace"
|
|
2269
|
-
];
|
|
2270
|
-
var UNTAGGED = "Operations";
|
|
2271
|
-
var CASE_BOUNDARY = /(?<before>[\p{Ll}\p{N}])(?<capital>\p{Lu})/gu;
|
|
2272
|
-
var ACRONYM_BOUNDARY = /(?<acronym>\p{Lu})(?<word>\p{Lu}\p{Ll})/gu;
|
|
2273
|
-
var splitIdentifier = (identifier) => identifier.replace(CASE_BOUNDARY, "$<before>-$<capital>").replace(ACRONYM_BOUNDARY, "$<acronym>-$<word>");
|
|
2274
|
-
var operationKey = (method, path, operationId) => {
|
|
2275
|
-
const fromId = operationId ? slugify(splitIdentifier(operationId)) : "";
|
|
2276
|
-
return fromId || slugify(`${method}-${path}`);
|
|
2277
|
-
};
|
|
2278
|
-
var specOf = (specs, source) => Object.hasOwn(specs, source) ? specs[source] : undefined;
|
|
2279
|
-
var operationOf = (spec, id) => Object.hasOwn(spec.operations, id) ? spec.operations[id] : undefined;
|
|
2280
|
-
var specAddresses = (spec) => {
|
|
2281
|
-
const addresses = [];
|
|
2282
|
-
if (spec.kind === "graphql") {
|
|
2283
|
-
if (spec.endpoint) {
|
|
2284
|
-
addresses.push(spec.endpoint);
|
|
2285
|
-
}
|
|
2286
|
-
return { addresses, label: "Endpoint" };
|
|
2287
|
-
}
|
|
2288
|
-
if (spec.kind === "asyncapi") {
|
|
2289
|
-
const servers = spec.document.servers ?? {};
|
|
2290
|
-
for (const server of Object.values(servers)) {
|
|
2291
|
-
if (server?.host) {
|
|
2292
|
-
addresses.push(`${server.protocol ? `${server.protocol}://` : ""}${server.host}${server.pathname ?? ""}`);
|
|
2293
|
-
}
|
|
2294
|
-
}
|
|
2295
|
-
return { addresses, label: "Servers" };
|
|
2296
|
-
}
|
|
2297
|
-
const declared = spec.document.servers;
|
|
2298
|
-
for (const server of Array.isArray(declared) ? declared : []) {
|
|
2299
|
-
if (server.url) {
|
|
2300
|
-
addresses.push(server.url);
|
|
2301
|
-
}
|
|
1334
|
+
// src/core/sources/contentful-rich-text.ts
|
|
1335
|
+
var HEADING = /^heading-(?<level>[1-6])$/u;
|
|
1336
|
+
var CELL_PIPE = /\|/gu;
|
|
1337
|
+
var CELL_BREAK = /\n+/gu;
|
|
1338
|
+
var assetFromEntry = (asset) => {
|
|
1339
|
+
const url = asString(getPath(asset, "fields.file.url"));
|
|
1340
|
+
if (!url) {
|
|
1341
|
+
return null;
|
|
2302
1342
|
}
|
|
2303
|
-
return {
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
for (let suffix = 2;taken.has(slug); suffix += 1) {
|
|
2318
|
-
slug = `${base}-${suffix}`;
|
|
2319
|
-
}
|
|
2320
|
-
taken.add(slug);
|
|
2321
|
-
assigned.set(name, slug);
|
|
2322
|
-
return slug;
|
|
2323
|
-
};
|
|
2324
|
-
};
|
|
2325
|
-
var operationCollector = (baseRoute, tagMeta) => {
|
|
2326
|
-
const operations = [];
|
|
2327
|
-
const tagOrder = [];
|
|
2328
|
-
const tagsSeen = new Set;
|
|
2329
|
-
const seen = new Set;
|
|
2330
|
-
const slugForTag = tagSlugger();
|
|
2331
|
-
const add = (entry) => {
|
|
2332
|
-
const tagSlug = slugForTag(entry.tag);
|
|
2333
|
-
if (!tagsSeen.has(entry.tag)) {
|
|
2334
|
-
tagsSeen.add(entry.tag);
|
|
2335
|
-
tagOrder.push(entry.tag);
|
|
2336
|
-
}
|
|
2337
|
-
let { key } = entry;
|
|
2338
|
-
while (seen.has(key)) {
|
|
2339
|
-
key = `${key}-${entry.method}`;
|
|
2340
|
-
}
|
|
2341
|
-
seen.add(key);
|
|
2342
|
-
operations.push({
|
|
2343
|
-
...entry,
|
|
2344
|
-
key,
|
|
2345
|
-
route: `${baseRoute === "/" ? "" : baseRoute}/${tagSlug}/${key}`,
|
|
2346
|
-
tagSlug
|
|
2347
|
-
});
|
|
2348
|
-
};
|
|
2349
|
-
const finish = () => ({
|
|
2350
|
-
operations,
|
|
2351
|
-
tags: tagOrder.map((name) => ({
|
|
2352
|
-
description: tagMeta.get(name) ?? "",
|
|
2353
|
-
name,
|
|
2354
|
-
slug: slugForTag(name)
|
|
2355
|
-
}))
|
|
2356
|
-
});
|
|
2357
|
-
return { add, finish };
|
|
2358
|
-
};
|
|
2359
|
-
var extractOperations = (document, baseRoute) => {
|
|
2360
|
-
const warnings = [];
|
|
2361
|
-
const tagMeta = new Map((document.tags ?? []).filter(hasTagName).map((tag) => [tag.name, tag.description ?? ""]));
|
|
2362
|
-
const collector = operationCollector(baseRoute, tagMeta);
|
|
2363
|
-
for (const [path, item] of Object.entries(document.paths ?? {})) {
|
|
2364
|
-
if (!item) {
|
|
2365
|
-
continue;
|
|
2366
|
-
}
|
|
2367
|
-
if ("$ref" in item) {
|
|
2368
|
-
warnings.push(`Path "${path}" is a $ref to a shared path item; referenced path items are not resolved, so its operations are missing from the reference. Inline the path item under "paths" to render it.`);
|
|
2369
|
-
continue;
|
|
2370
|
-
}
|
|
2371
|
-
for (const method of HTTP_METHODS) {
|
|
2372
|
-
const operation = item[method];
|
|
2373
|
-
if (!isOperation(operation)) {
|
|
2374
|
-
continue;
|
|
1343
|
+
return {
|
|
1344
|
+
description: asString(getPath(asset, "fields.description")),
|
|
1345
|
+
title: asString(getPath(asset, "fields.title")),
|
|
1346
|
+
url: absoluteUrl(url)
|
|
1347
|
+
};
|
|
1348
|
+
};
|
|
1349
|
+
var children = (node) => objectsIn(node.content);
|
|
1350
|
+
var marksOf = (node) => {
|
|
1351
|
+
const marks = {};
|
|
1352
|
+
for (const mark of objectsIn(node.marks)) {
|
|
1353
|
+
switch (asString(mark.type)) {
|
|
1354
|
+
case "bold": {
|
|
1355
|
+
marks.bold = true;
|
|
1356
|
+
break;
|
|
2375
1357
|
}
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
key: operationKey(method, path, operation.operationId),
|
|
2380
|
-
method,
|
|
2381
|
-
operationId: operation.operationId,
|
|
2382
|
-
path,
|
|
2383
|
-
summary: operation.summary ?? "",
|
|
2384
|
-
tag: operation.tags?.[0] ?? UNTAGGED
|
|
2385
|
-
});
|
|
2386
|
-
}
|
|
2387
|
-
}
|
|
2388
|
-
return { ...collector.finish(), warnings };
|
|
2389
|
-
};
|
|
2390
|
-
|
|
2391
|
-
// src/openapi/asyncapi.ts
|
|
2392
|
-
var ASYNCAPI_ACTIONS = ["send", "receive"];
|
|
2393
|
-
var unescapePointer = (token) => token.replaceAll("~1", "/").replaceAll("~0", "~");
|
|
2394
|
-
var CHANNEL_REF = /^#\/channels\/(?<id>.+)$/u;
|
|
2395
|
-
var isString = (value) => typeof value === "string";
|
|
2396
|
-
var channelIdOf = (channel) => {
|
|
2397
|
-
const id = CHANNEL_REF.exec(channel?.$ref ?? "")?.groups?.id;
|
|
2398
|
-
return id === undefined ? undefined : unescapePointer(id);
|
|
2399
|
-
};
|
|
2400
|
-
var channelAddress = (channelId, channel) => {
|
|
2401
|
-
const address = channel?.address;
|
|
2402
|
-
return isString(address) && address !== "" ? address : channelId;
|
|
2403
|
-
};
|
|
2404
|
-
var isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2405
|
-
var COMPONENT_SECTION_REF = /^#\/components\/(?<section>channels|operations)\/(?<name>[^/]+)$/u;
|
|
2406
|
-
var inlineComponentRefs = (document) => {
|
|
2407
|
-
const maps = [
|
|
2408
|
-
[document.channels, "channels"],
|
|
2409
|
-
[document.operations, "operations"]
|
|
2410
|
-
];
|
|
2411
|
-
for (const [map, section] of maps) {
|
|
2412
|
-
if (!isObject(map)) {
|
|
2413
|
-
continue;
|
|
2414
|
-
}
|
|
2415
|
-
const table = document.components?.[section];
|
|
2416
|
-
for (const [id, entry] of Object.entries(map)) {
|
|
2417
|
-
if (!isObject(entry) || !isString(entry.$ref)) {
|
|
2418
|
-
continue;
|
|
1358
|
+
case "italic": {
|
|
1359
|
+
marks.italic = true;
|
|
1360
|
+
break;
|
|
2419
1361
|
}
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
1362
|
+
case "code": {
|
|
1363
|
+
marks.code = true;
|
|
1364
|
+
break;
|
|
2423
1365
|
}
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
1366
|
+
case "strikethrough": {
|
|
1367
|
+
marks.strike = true;
|
|
1368
|
+
break;
|
|
2427
1369
|
}
|
|
1370
|
+
default:
|
|
2428
1371
|
}
|
|
2429
1372
|
}
|
|
1373
|
+
return marks;
|
|
2430
1374
|
};
|
|
2431
|
-
var
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
return;
|
|
2436
|
-
}
|
|
2437
|
-
if (!isString(trait.$ref)) {
|
|
2438
|
-
return trait;
|
|
2439
|
-
}
|
|
2440
|
-
const groups = TRAIT_REF.exec(trait.$ref)?.groups;
|
|
2441
|
-
const section = groups?.section ? document.components?.[groups.section] : undefined;
|
|
2442
|
-
const resolved = section?.[groups?.name ?? ""];
|
|
2443
|
-
return isObject(resolved) ? resolved : undefined;
|
|
2444
|
-
};
|
|
2445
|
-
const mergeTraits = (node) => {
|
|
2446
|
-
const { traits } = node;
|
|
2447
|
-
if (!Array.isArray(traits)) {
|
|
2448
|
-
return;
|
|
2449
|
-
}
|
|
2450
|
-
delete node.traits;
|
|
2451
|
-
const merged = {};
|
|
2452
|
-
for (const trait of traits) {
|
|
2453
|
-
Object.assign(merged, resolveTrait(trait));
|
|
2454
|
-
}
|
|
2455
|
-
for (const [key, value] of Object.entries(merged)) {
|
|
2456
|
-
if (!(key in node)) {
|
|
2457
|
-
node[key] = value;
|
|
2458
|
-
}
|
|
2459
|
-
}
|
|
2460
|
-
};
|
|
2461
|
-
for (const operation of Object.values(document.operations ?? {})) {
|
|
2462
|
-
if (isObject(operation)) {
|
|
2463
|
-
mergeTraits(operation);
|
|
2464
|
-
}
|
|
2465
|
-
}
|
|
2466
|
-
const channelMaps = [
|
|
2467
|
-
...Object.values(document.channels ?? {}),
|
|
2468
|
-
...Object.values(document.components?.channels ?? {})
|
|
2469
|
-
];
|
|
2470
|
-
const messageMaps = [
|
|
2471
|
-
...channelMaps.map((channel) => isObject(channel) ? channel.messages : undefined),
|
|
2472
|
-
document.components?.messages
|
|
2473
|
-
];
|
|
2474
|
-
for (const messages of messageMaps) {
|
|
2475
|
-
if (!isObject(messages)) {
|
|
2476
|
-
continue;
|
|
2477
|
-
}
|
|
2478
|
-
for (const message of Object.values(messages)) {
|
|
2479
|
-
if (isObject(message) && !isString(message.$ref)) {
|
|
2480
|
-
mergeTraits(message);
|
|
2481
|
-
}
|
|
2482
|
-
}
|
|
1375
|
+
var linkedTarget = (node, resolve) => {
|
|
1376
|
+
const target = getPath(node, "data.target");
|
|
1377
|
+
if (getPath(node, "data.target.fields") !== undefined) {
|
|
1378
|
+
return target;
|
|
2483
1379
|
}
|
|
2484
|
-
|
|
1380
|
+
const id = asString(getPath(node, "data.target.sys.id"));
|
|
1381
|
+
return id ? resolve?.(id) ?? null : null;
|
|
2485
1382
|
};
|
|
2486
|
-
var
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
var operationSite = (id, operation, channels) => {
|
|
2491
|
-
const action = ASYNCAPI_ACTIONS.find((a) => a === operation.action);
|
|
2492
|
-
if (!action) {
|
|
2493
|
-
return `Operation "${id}" declares no send/receive action; it is missing from the reference.`;
|
|
2494
|
-
}
|
|
2495
|
-
const channelId = channelIdOf(operation.channel);
|
|
2496
|
-
const channel = channelId === undefined ? undefined : channels[channelId];
|
|
2497
|
-
if (channelId === undefined || !isObject(channel) || isString(channel.$ref)) {
|
|
2498
|
-
return `Operation "${id}" references a channel that isn't declared under "channels"; it is missing from the reference.`;
|
|
1383
|
+
var linkedAsset = (node, options) => {
|
|
1384
|
+
if (getPath(node, "data.target.fields") !== undefined) {
|
|
1385
|
+
const inline = linkedTarget(node);
|
|
1386
|
+
return inline ? assetFromEntry(inline) : null;
|
|
2499
1387
|
}
|
|
2500
|
-
|
|
1388
|
+
const id = asString(getPath(node, "data.target.sys.id"));
|
|
1389
|
+
return id ? options.resolveAsset?.(id) ?? null : null;
|
|
2501
1390
|
};
|
|
2502
|
-
var
|
|
2503
|
-
const
|
|
2504
|
-
const
|
|
2505
|
-
const
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
if (!isObject(operation)) {
|
|
2509
|
-
continue;
|
|
2510
|
-
}
|
|
2511
|
-
if (isString(operation.$ref)) {
|
|
2512
|
-
warnings.push(`Operation "${id}" is a reference that doesn't resolve to a components operation; it is missing from the reference.`);
|
|
2513
|
-
continue;
|
|
2514
|
-
}
|
|
2515
|
-
const site = operationSite(id, operation, channels);
|
|
2516
|
-
if (isString(site)) {
|
|
2517
|
-
warnings.push(site);
|
|
2518
|
-
continue;
|
|
2519
|
-
}
|
|
2520
|
-
const { action, address, channelId } = site;
|
|
2521
|
-
const tag = operation.tags?.find((candidate) => typeof candidate?.name === "string")?.name;
|
|
2522
|
-
collector.add({
|
|
2523
|
-
channelId,
|
|
2524
|
-
deprecated: operation.deprecated === true,
|
|
2525
|
-
description: operation.description ?? "",
|
|
2526
|
-
key: operationKey(action, address, id),
|
|
2527
|
-
method: action,
|
|
2528
|
-
operationId: id,
|
|
2529
|
-
path: address,
|
|
2530
|
-
summary: operation.title ?? operation.summary ?? "",
|
|
2531
|
-
tag: tag ?? address
|
|
2532
|
-
});
|
|
1391
|
+
var embeddedEntry = (node, options) => {
|
|
1392
|
+
const entry = linkedTarget(node, options.resolveEntry);
|
|
1393
|
+
const contentType = entry ? asString(getPath(entry, "sys.contentType.sys.id")) : undefined;
|
|
1394
|
+
const serializer = contentType ? options.serializers?.[contentType] : undefined;
|
|
1395
|
+
if (entry && serializer) {
|
|
1396
|
+
return serializer(entry);
|
|
2533
1397
|
}
|
|
2534
|
-
return {
|
|
1398
|
+
return unsupported(`Contentful embedded entry${contentType ? `: ${contentType}` : ""}`, writesMdx(options.serializers));
|
|
2535
1399
|
};
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
"subscription"
|
|
2542
|
-
];
|
|
2543
|
-
var GRAPHQL_TYPE_KINDS = [
|
|
2544
|
-
"object",
|
|
2545
|
-
"input",
|
|
2546
|
-
"enum",
|
|
2547
|
-
"interface",
|
|
2548
|
-
"union",
|
|
2549
|
-
"scalar"
|
|
2550
|
-
];
|
|
2551
|
-
var GRAPHQL_GROUP_LABELS = {
|
|
2552
|
-
enum: "Enums",
|
|
2553
|
-
input: "Input Objects",
|
|
2554
|
-
interface: "Interfaces",
|
|
2555
|
-
mutation: "Mutations",
|
|
2556
|
-
object: "Objects",
|
|
2557
|
-
query: "Queries",
|
|
2558
|
-
scalar: "Scalars",
|
|
2559
|
-
subscription: "Subscriptions",
|
|
2560
|
-
union: "Unions"
|
|
2561
|
-
};
|
|
2562
|
-
var isGraphqlOperationKind = (method) => GRAPHQL_OPERATION_KINDS.some((kind) => kind === method);
|
|
2563
|
-
var GRAPHQL_TYPE_KEYWORDS = {
|
|
2564
|
-
enum: "enum",
|
|
2565
|
-
input: "input",
|
|
2566
|
-
interface: "interface",
|
|
2567
|
-
object: "type",
|
|
2568
|
-
scalar: "scalar",
|
|
2569
|
-
union: "union"
|
|
2570
|
-
};
|
|
2571
|
-
var graphqlSignature = (operation) => {
|
|
2572
|
-
const member = operation.method;
|
|
2573
|
-
const keyword = isGraphqlOperationKind(member) ? member : GRAPHQL_TYPE_KEYWORDS[member];
|
|
2574
|
-
return `${keyword} ${operation.path}`;
|
|
2575
|
-
};
|
|
2576
|
-
var byName = (a, b) => a.name < b.name ? -1 : 1;
|
|
2577
|
-
var extractGraphqlOperations = (document, baseRoute) => {
|
|
2578
|
-
const collector = operationCollector(baseRoute, new Map);
|
|
2579
|
-
const rootNames = new Set(Object.values(document.roots));
|
|
2580
|
-
for (const kind of GRAPHQL_OPERATION_KINDS) {
|
|
2581
|
-
const rootName = document.roots[kind];
|
|
2582
|
-
const root = rootName === undefined ? undefined : document.types[rootName];
|
|
2583
|
-
for (const field of root?.fields ?? []) {
|
|
2584
|
-
collector.add({
|
|
2585
|
-
deprecated: field.deprecationReason !== undefined,
|
|
2586
|
-
description: field.description,
|
|
2587
|
-
key: operationKey(kind, field.name, field.name),
|
|
2588
|
-
method: kind,
|
|
2589
|
-
operationId: field.name,
|
|
2590
|
-
path: field.name,
|
|
2591
|
-
summary: "",
|
|
2592
|
-
tag: GRAPHQL_GROUP_LABELS[kind]
|
|
2593
|
-
});
|
|
1400
|
+
var renderInlines = (nodes, options) => nodes.map((node) => renderInlineNode(node, options)).join("");
|
|
1401
|
+
var renderInlineNode = (node, options) => {
|
|
1402
|
+
switch (asString(node.nodeType)) {
|
|
1403
|
+
case "text": {
|
|
1404
|
+
return renderInline(asString(node.value) ?? "", marksOf(node));
|
|
2594
1405
|
}
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
const members = Object.values(document.types).filter((type) => type.kind === kind && !(type.builtIn || rootNames.has(type.name))).toSorted(byName);
|
|
2598
|
-
for (const type of members) {
|
|
2599
|
-
collector.add({
|
|
2600
|
-
deprecated: false,
|
|
2601
|
-
description: type.description,
|
|
2602
|
-
key: operationKey(kind, type.name, type.name),
|
|
2603
|
-
method: kind,
|
|
2604
|
-
operationId: type.name,
|
|
2605
|
-
path: type.name,
|
|
2606
|
-
summary: "",
|
|
2607
|
-
tag: GRAPHQL_GROUP_LABELS[kind]
|
|
2608
|
-
});
|
|
1406
|
+
case "hyperlink": {
|
|
1407
|
+
return renderLink(renderInlines(children(node), options), asString(getPath(node, "data.uri")));
|
|
2609
1408
|
}
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
};
|
|
2613
|
-
|
|
2614
|
-
// src/openapi/parse.ts
|
|
2615
|
-
import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile2 } from "node:fs/promises";
|
|
2616
|
-
import { setTimeout as sleep } from "node:timers/promises";
|
|
2617
|
-
import { convert } from "@asyncapi/converter";
|
|
2618
|
-
import { normalize as normalize2, upgrade } from "@scalar/openapi-parser";
|
|
2619
|
-
import pRetry, { AbortError } from "p-retry";
|
|
2620
|
-
import { isAbsolute, join as join3 } from "pathe";
|
|
2621
|
-
|
|
2622
|
-
// src/openapi/graphql-build.ts
|
|
2623
|
-
import {
|
|
2624
|
-
buildClientSchema,
|
|
2625
|
-
buildSchema,
|
|
2626
|
-
getNamedType,
|
|
2627
|
-
isEnumType,
|
|
2628
|
-
isInputObjectType,
|
|
2629
|
-
isInterfaceType,
|
|
2630
|
-
isObjectType,
|
|
2631
|
-
isSpecifiedScalarType,
|
|
2632
|
-
isUnionType,
|
|
2633
|
-
print
|
|
2634
|
-
} from "graphql";
|
|
2635
|
-
var typeRef = (type) => ({
|
|
2636
|
-
display: String(type),
|
|
2637
|
-
name: getNamedType(type).name
|
|
2638
|
-
});
|
|
2639
|
-
var defaultLiteral = (input) => {
|
|
2640
|
-
const literal = input.default?.literal;
|
|
2641
|
-
return literal ? print(literal) : undefined;
|
|
2642
|
-
};
|
|
2643
|
-
var inputValue = (input) => {
|
|
2644
|
-
const value = {
|
|
2645
|
-
description: input.description ?? "",
|
|
2646
|
-
name: input.name,
|
|
2647
|
-
type: typeRef(input.type)
|
|
2648
|
-
};
|
|
2649
|
-
const printed = defaultLiteral(input);
|
|
2650
|
-
if (printed !== undefined) {
|
|
2651
|
-
value.default = printed;
|
|
2652
|
-
}
|
|
2653
|
-
if (input.deprecationReason !== null && input.deprecationReason !== undefined) {
|
|
2654
|
-
value.deprecationReason = input.deprecationReason;
|
|
2655
|
-
}
|
|
2656
|
-
return value;
|
|
2657
|
-
};
|
|
2658
|
-
var outputField = (field) => {
|
|
2659
|
-
const value = {
|
|
2660
|
-
args: field.args.map(inputValue),
|
|
2661
|
-
description: field.description ?? "",
|
|
2662
|
-
name: field.name,
|
|
2663
|
-
type: typeRef(field.type)
|
|
2664
|
-
};
|
|
2665
|
-
if (field.deprecationReason !== null && field.deprecationReason !== undefined) {
|
|
2666
|
-
value.deprecationReason = field.deprecationReason;
|
|
2667
|
-
}
|
|
2668
|
-
return value;
|
|
2669
|
-
};
|
|
2670
|
-
var enumValues = (type) => type.getValues().map((value) => {
|
|
2671
|
-
const member = {
|
|
2672
|
-
description: value.description ?? "",
|
|
2673
|
-
name: value.name
|
|
2674
|
-
};
|
|
2675
|
-
if (value.deprecationReason !== null && value.deprecationReason !== undefined) {
|
|
2676
|
-
member.deprecationReason = value.deprecationReason;
|
|
2677
|
-
}
|
|
2678
|
-
return member;
|
|
2679
|
-
});
|
|
2680
|
-
var objectDef = (type, kind) => {
|
|
2681
|
-
const interfaces = type.getInterfaces().map((iface) => iface.name);
|
|
2682
|
-
const def = {
|
|
2683
|
-
description: type.description ?? "",
|
|
2684
|
-
fields: Object.values(type.getFields()).map(outputField),
|
|
2685
|
-
kind,
|
|
2686
|
-
name: type.name
|
|
2687
|
-
};
|
|
2688
|
-
if (interfaces.length > 0) {
|
|
2689
|
-
def.interfaces = interfaces;
|
|
2690
|
-
}
|
|
2691
|
-
return def;
|
|
2692
|
-
};
|
|
2693
|
-
var inputDef = (type) => ({
|
|
2694
|
-
description: type.description ?? "",
|
|
2695
|
-
inputFields: Object.values(type.getFields()).map(inputValue),
|
|
2696
|
-
kind: "input",
|
|
2697
|
-
name: type.name
|
|
2698
|
-
});
|
|
2699
|
-
var unionDef = (type) => ({
|
|
2700
|
-
description: type.description ?? "",
|
|
2701
|
-
kind: "union",
|
|
2702
|
-
name: type.name,
|
|
2703
|
-
possibleTypes: type.getTypes().map((member) => member.name)
|
|
2704
|
-
});
|
|
2705
|
-
var scalarDef = (type) => {
|
|
2706
|
-
const def = {
|
|
2707
|
-
description: type.description ?? "",
|
|
2708
|
-
kind: "scalar",
|
|
2709
|
-
name: type.name
|
|
2710
|
-
};
|
|
2711
|
-
if (type.specifiedByURL !== null && type.specifiedByURL !== undefined) {
|
|
2712
|
-
def.specifiedByUrl = type.specifiedByURL;
|
|
2713
|
-
}
|
|
2714
|
-
if (isSpecifiedScalarType(type)) {
|
|
2715
|
-
def.builtIn = true;
|
|
2716
|
-
}
|
|
2717
|
-
return def;
|
|
2718
|
-
};
|
|
2719
|
-
var typeDef = (type, schema) => {
|
|
2720
|
-
if (isObjectType(type)) {
|
|
2721
|
-
return objectDef(type, "object");
|
|
2722
|
-
}
|
|
2723
|
-
if (isInterfaceType(type)) {
|
|
2724
|
-
const def = objectDef(type, "interface");
|
|
2725
|
-
const implementers = schema.getImplementations(type).objects.map((object) => object.name);
|
|
2726
|
-
if (implementers.length > 0) {
|
|
2727
|
-
def.possibleTypes = implementers;
|
|
1409
|
+
case "asset-hyperlink": {
|
|
1410
|
+
return renderLink(renderInlines(children(node), options), linkedAsset(node, options)?.url);
|
|
2728
1411
|
}
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
if (isInputObjectType(type)) {
|
|
2732
|
-
return inputDef(type);
|
|
2733
|
-
}
|
|
2734
|
-
if (isEnumType(type)) {
|
|
2735
|
-
return {
|
|
2736
|
-
description: type.description ?? "",
|
|
2737
|
-
enumValues: enumValues(type),
|
|
2738
|
-
kind: "enum",
|
|
2739
|
-
name: type.name
|
|
2740
|
-
};
|
|
2741
|
-
}
|
|
2742
|
-
if (isUnionType(type)) {
|
|
2743
|
-
return unionDef(type);
|
|
2744
|
-
}
|
|
2745
|
-
return scalarDef(type);
|
|
2746
|
-
};
|
|
2747
|
-
var documentOf = (schema) => {
|
|
2748
|
-
const types = {};
|
|
2749
|
-
for (const [name, type] of Object.entries(schema.getTypeMap())) {
|
|
2750
|
-
if (name.startsWith("__")) {
|
|
2751
|
-
continue;
|
|
2752
|
-
}
|
|
2753
|
-
types[name] = typeDef(type, schema);
|
|
2754
|
-
}
|
|
2755
|
-
const roots = {};
|
|
2756
|
-
const query = schema.getQueryType();
|
|
2757
|
-
const mutation = schema.getMutationType();
|
|
2758
|
-
const subscription = schema.getSubscriptionType();
|
|
2759
|
-
if (query) {
|
|
2760
|
-
roots.query = query.name;
|
|
2761
|
-
}
|
|
2762
|
-
if (mutation) {
|
|
2763
|
-
roots.mutation = mutation.name;
|
|
2764
|
-
}
|
|
2765
|
-
if (subscription) {
|
|
2766
|
-
roots.subscription = subscription.name;
|
|
2767
|
-
}
|
|
2768
|
-
return {
|
|
2769
|
-
info: { description: schema.description ?? "" },
|
|
2770
|
-
roots,
|
|
2771
|
-
types
|
|
2772
|
-
};
|
|
2773
|
-
};
|
|
2774
|
-
var hasSchemaKey = (value) => typeof value === "object" && value !== null && ("__schema" in value);
|
|
2775
|
-
var hasDataEnvelope = (value) => typeof value === "object" && value !== null && ("data" in value);
|
|
2776
|
-
var introspectionOf = (parsed) => {
|
|
2777
|
-
if (hasSchemaKey(parsed)) {
|
|
2778
|
-
return parsed;
|
|
2779
|
-
}
|
|
2780
|
-
return hasDataEnvelope(parsed) && hasSchemaKey(parsed.data) ? parsed.data : undefined;
|
|
2781
|
-
};
|
|
2782
|
-
var buildGraphqlDocument = (text) => {
|
|
2783
|
-
let parsed;
|
|
2784
|
-
let isJson = true;
|
|
2785
|
-
try {
|
|
2786
|
-
parsed = JSON.parse(text);
|
|
2787
|
-
} catch {
|
|
2788
|
-
isJson = false;
|
|
2789
|
-
}
|
|
2790
|
-
if (isJson) {
|
|
2791
|
-
const introspection = introspectionOf(parsed);
|
|
2792
|
-
if (!introspection) {
|
|
2793
|
-
throw new Error("the JSON document is not a GraphQL introspection result (no `__schema` key).");
|
|
1412
|
+
case "embedded-entry-inline": {
|
|
1413
|
+
return embeddedEntry(node, options);
|
|
2794
1414
|
}
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
return documentOf(buildSchema(text));
|
|
2798
|
-
};
|
|
2799
|
-
|
|
2800
|
-
// src/openapi/parse.ts
|
|
2801
|
-
var URL_SPEC = /^https?:\/\//u;
|
|
2802
|
-
var FETCH_TIMEOUT_MS = 15000;
|
|
2803
|
-
var MAX_ATTEMPTS = 3;
|
|
2804
|
-
var BASE_BACKOFF_MS = 500;
|
|
2805
|
-
var MAX_RETRY_WAIT_MS = 1e4;
|
|
2806
|
-
var SECOND_MS = 1000;
|
|
2807
|
-
var RETRYABLE_STATUS = new Set([408, 425, 429, 500, 502, 503, 504]);
|
|
2808
|
-
var USER_AGENT = "blume (+https://github.com/haydenbleasel/blume)";
|
|
2809
|
-
var PROXY_ENV_VARS = [
|
|
2810
|
-
"HTTP_PROXY",
|
|
2811
|
-
"http_proxy",
|
|
2812
|
-
"HTTPS_PROXY",
|
|
2813
|
-
"https_proxy",
|
|
2814
|
-
"ALL_PROXY",
|
|
2815
|
-
"all_proxy"
|
|
2816
|
-
];
|
|
2817
|
-
|
|
2818
|
-
class InvalidSpecError extends Error {
|
|
2819
|
-
constructor(message) {
|
|
2820
|
-
super(message);
|
|
2821
|
-
this.name = "InvalidSpecError";
|
|
2822
|
-
}
|
|
2823
|
-
}
|
|
2824
|
-
var proxyInstalled = false;
|
|
2825
|
-
var ensureProxyDispatcher = async () => {
|
|
2826
|
-
if (proxyInstalled || !PROXY_ENV_VARS.some((name) => process.env[name])) {
|
|
2827
|
-
return;
|
|
2828
|
-
}
|
|
2829
|
-
try {
|
|
2830
|
-
const { EnvHttpProxyAgent, setGlobalDispatcher } = await import("undici");
|
|
2831
|
-
setGlobalDispatcher(new EnvHttpProxyAgent);
|
|
2832
|
-
proxyInstalled = true;
|
|
2833
|
-
} catch {}
|
|
2834
|
-
};
|
|
2835
|
-
var retryAfterMs = (response) => {
|
|
2836
|
-
const header = response.headers.get("retry-after");
|
|
2837
|
-
if (!header) {
|
|
2838
|
-
return;
|
|
2839
|
-
}
|
|
2840
|
-
const seconds = Number(header);
|
|
2841
|
-
if (Number.isFinite(seconds)) {
|
|
2842
|
-
return seconds > 0 ? seconds * SECOND_MS : undefined;
|
|
2843
|
-
}
|
|
2844
|
-
const delta = Date.parse(header) - Date.now();
|
|
2845
|
-
return Number.isFinite(delta) && delta > 0 ? delta : undefined;
|
|
2846
|
-
};
|
|
2847
|
-
var attemptFetch = async (spec) => {
|
|
2848
|
-
try {
|
|
2849
|
-
const response = await fetch(spec, {
|
|
2850
|
-
headers: {
|
|
2851
|
-
accept: "application/json, application/yaml, text/yaml, */*",
|
|
2852
|
-
"user-agent": USER_AGENT
|
|
2853
|
-
},
|
|
2854
|
-
redirect: "follow",
|
|
2855
|
-
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
|
|
2856
|
-
});
|
|
2857
|
-
if (response.ok) {
|
|
2858
|
-
return { text: await response.text() };
|
|
1415
|
+
default: {
|
|
1416
|
+
return renderInlines(children(node), options);
|
|
2859
1417
|
}
|
|
2860
|
-
return {
|
|
2861
|
-
error: new Error(`${spec} -> ${response.status} ${response.statusText}`),
|
|
2862
|
-
retryAfter: retryAfterMs(response),
|
|
2863
|
-
retryable: RETRYABLE_STATUS.has(response.status)
|
|
2864
|
-
};
|
|
2865
|
-
} catch (error) {
|
|
2866
|
-
return {
|
|
2867
|
-
error: error instanceof Error ? error : new Error(String(error)),
|
|
2868
|
-
retryable: true
|
|
2869
|
-
};
|
|
2870
1418
|
}
|
|
2871
1419
|
};
|
|
2872
|
-
var
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
return await pRetry(async () => {
|
|
2883
|
-
const attempt = await attemptFetch(spec);
|
|
2884
|
-
if ("text" in attempt) {
|
|
2885
|
-
return attempt.text;
|
|
2886
|
-
}
|
|
2887
|
-
if (!attempt.retryable) {
|
|
2888
|
-
throw new AbortError(attempt.error);
|
|
2889
|
-
}
|
|
2890
|
-
throw retryableFetchError(attempt.error, attempt.retryAfter);
|
|
2891
|
-
}, {
|
|
2892
|
-
factor: 2,
|
|
2893
|
-
maxTimeout: MAX_RETRY_WAIT_MS,
|
|
2894
|
-
minTimeout: BASE_BACKOFF_MS,
|
|
2895
|
-
onFailedAttempt: async (context) => {
|
|
2896
|
-
const { retryAfter } = context.error;
|
|
2897
|
-
if (retryAfter !== undefined && context.retriesLeft > 0) {
|
|
2898
|
-
await sleep(Math.max(0, Math.min(retryAfter, MAX_RETRY_WAIT_MS) - context.retryDelay));
|
|
2899
|
-
}
|
|
2900
|
-
},
|
|
2901
|
-
retries: MAX_ATTEMPTS - 1
|
|
2902
|
-
});
|
|
2903
|
-
};
|
|
2904
|
-
var cacheFileFor = (cacheDir, spec) => join3(cacheDir, `spec-${hashText(spec)}.cache`);
|
|
2905
|
-
var readCache = async (file) => {
|
|
2906
|
-
try {
|
|
2907
|
-
return await readFile3(file, "utf-8");
|
|
2908
|
-
} catch {
|
|
2909
|
-
return;
|
|
1420
|
+
var renderList = (items, marker, options) => items.map((item, index) => listItem(marker(index), children(item).map((child) => renderBlock(child, options)).filter((block) => block !== "").join(`
|
|
1421
|
+
`))).join(`
|
|
1422
|
+
`);
|
|
1423
|
+
var cellText = (cell, options) => children(cell).map((paragraph) => renderInlines(children(paragraph), options)).join(" ").replaceAll(CELL_BREAK, " ").replaceAll(CELL_PIPE, String.raw`\|`);
|
|
1424
|
+
var tableRow = (cells) => `| ${cells.join(" | ")} |`;
|
|
1425
|
+
var renderTable = (node, options) => {
|
|
1426
|
+
const rows = children(node).map((row) => children(row).map((cell) => cellText(cell, options)));
|
|
1427
|
+
const [head, ...body] = rows;
|
|
1428
|
+
if (!head) {
|
|
1429
|
+
return "";
|
|
2910
1430
|
}
|
|
1431
|
+
return [
|
|
1432
|
+
tableRow(head),
|
|
1433
|
+
tableRow(head.map(() => "---")),
|
|
1434
|
+
...body.map((cells) => tableRow(cells))
|
|
1435
|
+
].join(`
|
|
1436
|
+
`);
|
|
2911
1437
|
};
|
|
2912
|
-
var
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
};
|
|
2918
|
-
var readSpecText = async (spec, root, options) => {
|
|
2919
|
-
if (!URL_SPEC.test(spec)) {
|
|
2920
|
-
const absolute = isAbsolute(spec) ? spec : join3(root, spec);
|
|
2921
|
-
return { text: await readFile3(absolute, "utf-8"), warnings: [] };
|
|
1438
|
+
var renderBlock = (node, options) => {
|
|
1439
|
+
const type = asString(node.nodeType) ?? "";
|
|
1440
|
+
const heading = HEADING.exec(type)?.groups?.level;
|
|
1441
|
+
if (heading) {
|
|
1442
|
+
return `${headingPrefix(Number(heading))}${renderInlines(children(node), options)}`;
|
|
2922
1443
|
}
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
if (cached !== undefined) {
|
|
2927
|
-
return { text: cached, warnings: [] };
|
|
2928
|
-
}
|
|
2929
|
-
}
|
|
2930
|
-
try {
|
|
2931
|
-
const text = await fetchSpecText(spec);
|
|
2932
|
-
if (options.cacheDir && cacheFile) {
|
|
2933
|
-
await writeCache(options.cacheDir, cacheFile, text);
|
|
1444
|
+
switch (type) {
|
|
1445
|
+
case "paragraph": {
|
|
1446
|
+
return renderInlines(children(node), options);
|
|
2934
1447
|
}
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
if (cacheFile) {
|
|
2938
|
-
const cached = await readCache(cacheFile);
|
|
2939
|
-
if (cached !== undefined) {
|
|
2940
|
-
return {
|
|
2941
|
-
text: cached,
|
|
2942
|
-
warnings: [
|
|
2943
|
-
`Could not fetch ${spec} (${error.message}); using the last cached copy.`
|
|
2944
|
-
]
|
|
2945
|
-
};
|
|
2946
|
-
}
|
|
1448
|
+
case "blockquote": {
|
|
1449
|
+
return blockquote(joinBlocks(children(node).map((child) => renderBlock(child, options))));
|
|
2947
1450
|
}
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
};
|
|
2951
|
-
var isApiDocument = (value) => typeof value === "object" && value !== null;
|
|
2952
|
-
var parseSpec = async (spec, root, options = {}) => {
|
|
2953
|
-
const { text, warnings } = await readSpecText(spec, root, options);
|
|
2954
|
-
const normalized = normalize2(text);
|
|
2955
|
-
const { specification } = upgrade(normalized);
|
|
2956
|
-
if (!isApiDocument(specification)) {
|
|
2957
|
-
throw new InvalidSpecError(`${spec} is not a valid OpenAPI document (expected a YAML or JSON object).`);
|
|
2958
|
-
}
|
|
2959
|
-
return { document: specification, warnings };
|
|
2960
|
-
};
|
|
2961
|
-
var isAsyncApiDocument = (value) => typeof value === "object" && value !== null && ("asyncapi" in value) && typeof value.asyncapi === "string" && value.asyncapi !== "";
|
|
2962
|
-
var parseAsyncApiSpec = async (spec, root, options = {}) => {
|
|
2963
|
-
const { text, warnings } = await readSpecText(spec, root, options);
|
|
2964
|
-
const normalized = normalize2(text);
|
|
2965
|
-
if (!isAsyncApiDocument(normalized)) {
|
|
2966
|
-
throw new InvalidSpecError(`${spec} is not a valid AsyncAPI document (expected a YAML or JSON object with an \`asyncapi\` version field).`);
|
|
2967
|
-
}
|
|
2968
|
-
const version = normalized.asyncapi;
|
|
2969
|
-
let document = normalized;
|
|
2970
|
-
if (!version.startsWith("3.")) {
|
|
2971
|
-
const captured = [];
|
|
2972
|
-
const originalWarn = console.warn;
|
|
2973
|
-
console.warn = (...args) => {
|
|
2974
|
-
captured.push(args.map(String).join(" "));
|
|
2975
|
-
};
|
|
2976
|
-
try {
|
|
2977
|
-
document = convert(document, "3.0.0");
|
|
2978
|
-
} catch (error) {
|
|
2979
|
-
throw new InvalidSpecError(`${spec} could not be converted to AsyncAPI 3.0 (${error.message}).`);
|
|
2980
|
-
} finally {
|
|
2981
|
-
console.warn = originalWarn;
|
|
1451
|
+
case "unordered-list": {
|
|
1452
|
+
return renderList(children(node), () => "-", options);
|
|
2982
1453
|
}
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
return { document: normalizeAsyncApiDocument(document), warnings };
|
|
2986
|
-
};
|
|
2987
|
-
var parseGraphqlSpec = async (spec, root, options = {}) => {
|
|
2988
|
-
const { text, warnings } = await readSpecText(spec, root, options);
|
|
2989
|
-
try {
|
|
2990
|
-
return { document: buildGraphqlDocument(text), warnings };
|
|
2991
|
-
} catch (error) {
|
|
2992
|
-
throw new InvalidSpecError(`${spec} is not a valid GraphQL schema (${error.message.trim()})`);
|
|
2993
|
-
}
|
|
2994
|
-
};
|
|
2995
|
-
|
|
2996
|
-
// src/openapi/render-mdx.ts
|
|
2997
|
-
import { fromMarkdown } from "mdast-util-from-markdown";
|
|
2998
|
-
import { toString as mdastToString } from "mdast-util-to-string";
|
|
2999
|
-
import stringWidth2 from "string-width";
|
|
3000
|
-
|
|
3001
|
-
// src/core/api-name.ts
|
|
3002
|
-
var NAMES_AN_API = /\bAPIs?\b/iu;
|
|
3003
|
-
var apiNamePhrase = (name) => {
|
|
3004
|
-
const trimmed = name.trim();
|
|
3005
|
-
return NAMES_AN_API.test(trimmed) ? trimmed : `${trimmed} API`;
|
|
3006
|
-
};
|
|
3007
|
-
|
|
3008
|
-
// src/core/text-width.ts
|
|
3009
|
-
import stringWidth from "string-width";
|
|
3010
|
-
var columnsPrefix = (text, max) => {
|
|
3011
|
-
let end = 0;
|
|
3012
|
-
let used = 0;
|
|
3013
|
-
const graphemes = new Intl.Segmenter(undefined, { granularity: "grapheme" });
|
|
3014
|
-
for (const { index, segment } of graphemes.segment(text)) {
|
|
3015
|
-
const width = stringWidth(segment);
|
|
3016
|
-
if (used + width > max) {
|
|
3017
|
-
break;
|
|
1454
|
+
case "ordered-list": {
|
|
1455
|
+
return renderList(children(node), (index) => `${index + 1}.`, options);
|
|
3018
1456
|
}
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
}
|
|
3022
|
-
return text.slice(0, end);
|
|
3023
|
-
};
|
|
3024
|
-
|
|
3025
|
-
// src/openapi/signature.ts
|
|
3026
|
-
var operationSignature = (spec, operation) => spec.kind === "graphql" ? graphqlSignature(operation) : `${operation.method.toUpperCase()} ${operation.path}`;
|
|
3027
|
-
|
|
3028
|
-
// src/openapi/render-mdx.ts
|
|
3029
|
-
var MDX_UNSAFE = /[<{}]/gu;
|
|
3030
|
-
var ENTITIES = new Map([
|
|
3031
|
-
["<", "<"],
|
|
3032
|
-
["{", "{"],
|
|
3033
|
-
["}", "}"]
|
|
3034
|
-
]);
|
|
3035
|
-
var MDX_ESM_KEYWORD = /^(?<keyword>import|export)\b/gmu;
|
|
3036
|
-
var escapeProse = (text) => text.replace(MDX_UNSAFE, (char) => ENTITIES.get(char) ?? char).replace(MDX_ESM_KEYWORD, (keyword) => `&#${keyword.codePointAt(0)};${keyword.slice(1)}`);
|
|
3037
|
-
var codeSpans = (text) => {
|
|
3038
|
-
const spans = [];
|
|
3039
|
-
const collect = (node) => {
|
|
3040
|
-
if (node.type === "inlineCode" || node.type === "code") {
|
|
3041
|
-
const start = node.position?.start.offset ?? -1;
|
|
3042
|
-
const end = node.position?.end.offset ?? -1;
|
|
3043
|
-
const head = text.slice(Math.max(start, 0), Math.max(end, 0)).trimStart();
|
|
3044
|
-
if (start >= 0 && (node.type === "inlineCode" || head.startsWith("`") || head.startsWith("~"))) {
|
|
3045
|
-
spans.push([start, end]);
|
|
3046
|
-
}
|
|
3047
|
-
return;
|
|
1457
|
+
case "hr": {
|
|
1458
|
+
return "---";
|
|
3048
1459
|
}
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
}
|
|
1460
|
+
case "embedded-asset-block": {
|
|
1461
|
+
const asset = linkedAsset(node, options);
|
|
1462
|
+
return asset ? image(asset.description ?? asset.title ?? "", asset.url) : "";
|
|
3053
1463
|
}
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
return spans;
|
|
3057
|
-
};
|
|
3058
|
-
var mdxSafe = (text) => {
|
|
3059
|
-
let out = "";
|
|
3060
|
-
let cursor = 0;
|
|
3061
|
-
for (const [start, end] of codeSpans(text)) {
|
|
3062
|
-
out += escapeProse(text.slice(cursor, start));
|
|
3063
|
-
out += text.slice(start, end);
|
|
3064
|
-
cursor = end;
|
|
3065
|
-
}
|
|
3066
|
-
return out + escapeProse(text.slice(cursor));
|
|
3067
|
-
};
|
|
3068
|
-
var META_DESCRIPTION_MAX = 160;
|
|
3069
|
-
var WHITESPACE = /\s+/gu;
|
|
3070
|
-
var TRAILING_WORD = /\s+\S*$/u;
|
|
3071
|
-
var plainProse = (markdown) => {
|
|
3072
|
-
const tree = fromMarkdown(markdown);
|
|
3073
|
-
const first = tree.children.find((node) => node.type === "paragraph") ?? tree.children[0];
|
|
3074
|
-
return first ? mdastToString(first).replace(WHITESPACE, " ").trim() : "";
|
|
3075
|
-
};
|
|
3076
|
-
var clip = (text, max) => {
|
|
3077
|
-
if (max <= 0) {
|
|
3078
|
-
return "";
|
|
3079
|
-
}
|
|
3080
|
-
if (stringWidth2(text) <= max) {
|
|
3081
|
-
return text;
|
|
3082
|
-
}
|
|
3083
|
-
const head = columnsPrefix(text, max - 1);
|
|
3084
|
-
const onWordBoundary = head.replace(TRAILING_WORD, "");
|
|
3085
|
-
return `${stringWidth2(onWordBoundary) >= max / 2 ? onWordBoundary : head}…`;
|
|
3086
|
-
};
|
|
3087
|
-
var apiName = (spec) => spec.title || spec.label;
|
|
3088
|
-
var apiPhrase = (spec) => apiNamePhrase(apiName(spec));
|
|
3089
|
-
var GRAPHQL_MEMBER_PHRASES = {
|
|
3090
|
-
enum: "enum type",
|
|
3091
|
-
input: "input object type",
|
|
3092
|
-
interface: "interface type",
|
|
3093
|
-
mutation: "mutation",
|
|
3094
|
-
object: "object type",
|
|
3095
|
-
query: "query",
|
|
3096
|
-
scalar: "scalar type",
|
|
3097
|
-
subscription: "subscription",
|
|
3098
|
-
union: "union type"
|
|
3099
|
-
};
|
|
3100
|
-
var operationDescription = (spec, operation, options) => {
|
|
3101
|
-
if (!options.suffix) {
|
|
3102
|
-
return clip(plainProse(operation.description || operation.summary) || options.title, META_DESCRIPTION_MAX);
|
|
3103
|
-
}
|
|
3104
|
-
let subject;
|
|
3105
|
-
if (spec.kind === "asyncapi") {
|
|
3106
|
-
subject = `${operation.method} operation on ${operation.path}`;
|
|
3107
|
-
} else if (spec.kind === "graphql") {
|
|
3108
|
-
subject = `${operation.path} ${GRAPHQL_MEMBER_PHRASES[operation.method]}`;
|
|
3109
|
-
} else {
|
|
3110
|
-
subject = `${operation.method.toUpperCase()} ${operation.path} endpoint`;
|
|
3111
|
-
}
|
|
3112
|
-
const suffix = `Reference for the ${subject} in the ${apiPhrase(spec)}.`;
|
|
3113
|
-
const prose = clip(plainProse(operation.description || operation.summary), META_DESCRIPTION_MAX - stringWidth2(suffix) - 1);
|
|
3114
|
-
return clip([prose, suffix].filter(Boolean).join(" "), META_DESCRIPTION_MAX);
|
|
3115
|
-
};
|
|
3116
|
-
var withDescription = (description, component) => description.trim() ? `${mdxSafe(description.trim())}
|
|
3117
|
-
|
|
3118
|
-
${component}` : component;
|
|
3119
|
-
var operationMdx = (spec, operation, reference) => {
|
|
3120
|
-
const method = operation.method.toUpperCase();
|
|
3121
|
-
const graphql = spec.kind === "graphql";
|
|
3122
|
-
const fallbackTitle = graphql ? operation.path : operationSignature(spec, operation);
|
|
3123
|
-
const title = operation.summary || fallbackTitle;
|
|
3124
|
-
const description = operation.description.trim() === operation.summary.trim() ? "" : operation.description;
|
|
3125
|
-
const flags = {};
|
|
3126
|
-
if (reference?.includeInLlms === false) {
|
|
3127
|
-
flags.ai = { exclude: true };
|
|
3128
|
-
}
|
|
3129
|
-
if (operation.deprecated) {
|
|
3130
|
-
flags.deprecated = true;
|
|
3131
|
-
}
|
|
3132
|
-
const searchFlags = {};
|
|
3133
|
-
if (reference?.includeInSearch === false) {
|
|
3134
|
-
searchFlags.exclude = true;
|
|
3135
|
-
}
|
|
3136
|
-
const seo = {
|
|
3137
|
-
description: operationDescription(spec, operation, {
|
|
3138
|
-
suffix: reference?.seoDescriptionSuffix !== false,
|
|
3139
|
-
title
|
|
3140
|
-
})
|
|
3141
|
-
};
|
|
3142
|
-
if (reference?.noindex) {
|
|
3143
|
-
seo.noindex = true;
|
|
3144
|
-
}
|
|
3145
|
-
const sidebar = {
|
|
3146
|
-
label: operation.summary || operation.path
|
|
3147
|
-
};
|
|
3148
|
-
if (!graphql || isGraphqlOperationKind(operation.method)) {
|
|
3149
|
-
sidebar.badge = method;
|
|
3150
|
-
}
|
|
3151
|
-
const tags = graphql ? [operation.tag] : [operation.tag, method];
|
|
3152
|
-
return {
|
|
3153
|
-
body: withDescription(description, `<Operation source="${spec.slug}" id="${operation.key}" />`),
|
|
3154
|
-
data: {
|
|
3155
|
-
...flags,
|
|
3156
|
-
search: { ...searchFlags, tags },
|
|
3157
|
-
seo,
|
|
3158
|
-
sidebar,
|
|
3159
|
-
title,
|
|
3160
|
-
type: "openapi-operation"
|
|
3161
|
-
}
|
|
3162
|
-
};
|
|
3163
|
-
};
|
|
3164
|
-
var overviewMdx = (spec, reference) => {
|
|
3165
|
-
const operations = Object.values(spec.operations);
|
|
3166
|
-
const sections = [];
|
|
3167
|
-
const known = new Set;
|
|
3168
|
-
for (const tag of spec.tags) {
|
|
3169
|
-
if (!known.has(tag.slug)) {
|
|
3170
|
-
known.add(tag.slug);
|
|
3171
|
-
sections.push(tag);
|
|
3172
|
-
}
|
|
3173
|
-
}
|
|
3174
|
-
for (const operation of operations) {
|
|
3175
|
-
if (!known.has(operation.tagSlug)) {
|
|
3176
|
-
known.add(operation.tagSlug);
|
|
3177
|
-
sections.push({
|
|
3178
|
-
description: "",
|
|
3179
|
-
name: operation.tag,
|
|
3180
|
-
slug: operation.tagSlug
|
|
3181
|
-
});
|
|
1464
|
+
case "embedded-entry-block": {
|
|
1465
|
+
return embeddedEntry(node, options);
|
|
3182
1466
|
}
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
1467
|
+
case "table": {
|
|
1468
|
+
return renderTable(node, options);
|
|
1469
|
+
}
|
|
1470
|
+
default: {
|
|
1471
|
+
return unsupported(`Contentful node: ${type}`, writesMdx(options.serializers));
|
|
3188
1472
|
}
|
|
3189
|
-
const description = tag.description.trim() ? [mdxSafe(tag.description.trim())] : [];
|
|
3190
|
-
tagSections.push([
|
|
3191
|
-
`## ${mdxSafe(tag.name)}`,
|
|
3192
|
-
...description,
|
|
3193
|
-
`<ApiTagOperations source="${spec.slug}" tag="${tag.slug}" />`
|
|
3194
|
-
].join(`
|
|
3195
|
-
|
|
3196
|
-
`));
|
|
3197
|
-
}
|
|
3198
|
-
const flags = {};
|
|
3199
|
-
if (reference?.includeInLlms === false) {
|
|
3200
|
-
flags.ai = { exclude: true };
|
|
3201
|
-
}
|
|
3202
|
-
if (reference?.includeInSearch === false) {
|
|
3203
|
-
flags.search = { exclude: true };
|
|
3204
|
-
}
|
|
3205
|
-
const seo = {
|
|
3206
|
-
description: clip(plainProse(spec.description), META_DESCRIPTION_MAX) || `${apiPhrase(spec)} reference.`
|
|
3207
|
-
};
|
|
3208
|
-
if (reference?.noindex) {
|
|
3209
|
-
seo.noindex = true;
|
|
3210
1473
|
}
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
withDescription(spec.description, `<ApiOverview source="${spec.slug}" />`),
|
|
3214
|
-
...tagSections
|
|
3215
|
-
].join(`
|
|
1474
|
+
};
|
|
1475
|
+
var contentfulRichTextToMarkdown = (doc, options = {}) => markdownDocument(children(doc).map((node) => renderBlock(node, options)));
|
|
3216
1476
|
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
1477
|
+
// src/core/sources/remote.ts
|
|
1478
|
+
import { join } from "pathe";
|
|
1479
|
+
var remoteSource = (options, ctx) => {
|
|
1480
|
+
const cache = snapshotCache(ctx?.cacheDir ?? join(".blume", "cache", options.name));
|
|
1481
|
+
let snapshot = new Map;
|
|
1482
|
+
const load = async (refresh = ctx?.refresh ?? true) => {
|
|
1483
|
+
const result = await loadWithCache(options.name, cache, options.fetchEntries, refresh);
|
|
1484
|
+
snapshot = new Map(result.entries.map((entry) => [entry.ref, entry]));
|
|
1485
|
+
return result;
|
|
1486
|
+
};
|
|
1487
|
+
const read = async (ref) => {
|
|
1488
|
+
const cached = snapshot.get(ref);
|
|
1489
|
+
if (cached) {
|
|
1490
|
+
return cached.raw ?? cached.body.text;
|
|
3223
1491
|
}
|
|
1492
|
+
const all = await cache.read();
|
|
1493
|
+
return all.find((entry) => entry.ref === ref)?.raw ?? "";
|
|
1494
|
+
};
|
|
1495
|
+
return {
|
|
1496
|
+
load,
|
|
1497
|
+
name: options.name,
|
|
1498
|
+
prefix: options.prefix,
|
|
1499
|
+
read,
|
|
1500
|
+
staged: true,
|
|
1501
|
+
watch: options.pollInterval ? pollingWatch(() => load(true), options.pollInterval, () => load()) : undefined
|
|
3224
1502
|
};
|
|
3225
1503
|
};
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
var isOpenApiSource = (source) => ("kind" in source) && source.kind === "openapi-source";
|
|
3229
|
-
var routeToRef = (route) => route.replace(/^\/+/u, "");
|
|
3230
|
-
var KIND_LABELS = {
|
|
3231
|
-
asyncapi: "AsyncAPI",
|
|
3232
|
-
graphql: "GraphQL",
|
|
3233
|
-
openapi: "OpenAPI"
|
|
3234
|
-
};
|
|
3235
|
-
var CODE_PREFIXES = {
|
|
3236
|
-
asyncapi: "BLUME_ASYNCAPI",
|
|
3237
|
-
graphql: "BLUME_GRAPHQL",
|
|
3238
|
-
openapi: "BLUME_OPENAPI"
|
|
3239
|
-
};
|
|
3240
|
-
var SPEC_WARNING_CODES = {
|
|
3241
|
-
asyncapi: "BLUME_ASYNCAPI_SPEC_WARNING",
|
|
3242
|
-
graphql: "BLUME_GRAPHQL_SPEC_WARNING",
|
|
3243
|
-
openapi: "BLUME_OPENAPI_STALE"
|
|
3244
|
-
};
|
|
3245
|
-
var SKIPPED_CODES = {
|
|
3246
|
-
asyncapi: "BLUME_ASYNCAPI_SKIPPED_OPERATION",
|
|
3247
|
-
graphql: "BLUME_GRAPHQL_SKIPPED",
|
|
3248
|
-
openapi: "BLUME_OPENAPI_REF_PATH_ITEM"
|
|
3249
|
-
};
|
|
3250
|
-
var EMPTY_SUGGESTIONS = {
|
|
3251
|
-
asyncapi: "Check the spec points at an AsyncAPI document with `channels` and `operations`.",
|
|
3252
|
-
graphql: "Check the spec points at a GraphQL schema (SDL or introspection JSON) whose root types declare fields.",
|
|
3253
|
-
openapi: "Check the spec points at an OpenAPI document with operations under `paths`."
|
|
3254
|
-
};
|
|
3255
|
-
var INVALID_SUGGESTIONS = {
|
|
3256
|
-
asyncapi: "Point the spec at an AsyncAPI document (a YAML or JSON file with an object at the top level).",
|
|
3257
|
-
graphql: "Point the spec at a GraphQL schema — SDL text or an introspection JSON result.",
|
|
3258
|
-
openapi: "Point the spec at an OpenAPI document (a YAML or JSON file with an object at the top level)."
|
|
3259
|
-
};
|
|
3260
|
-
var toEntry = (rendered, ref) => {
|
|
3261
|
-
const raw = frontmatter_default.stringify(`${rendered.body}
|
|
3262
|
-
`, rendered.data);
|
|
1504
|
+
var stagedEntry = (slug, data, markdown, lastModified, format = "md") => {
|
|
1505
|
+
const raw = frontmatter_default.stringify(markdown, data);
|
|
3263
1506
|
return {
|
|
3264
|
-
body: { format
|
|
3265
|
-
data: { ...
|
|
1507
|
+
body: { format, text: markdown },
|
|
1508
|
+
data: { ...data },
|
|
3266
1509
|
hash: hashText(raw),
|
|
1510
|
+
lastModified,
|
|
3267
1511
|
raw,
|
|
3268
|
-
ref
|
|
1512
|
+
ref: `${slug}.${format}`
|
|
3269
1513
|
};
|
|
3270
1514
|
};
|
|
3271
|
-
var
|
|
3272
|
-
|
|
3273
|
-
const
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
]));
|
|
1515
|
+
var REMOTE_TIMEOUT_MS = 30000;
|
|
1516
|
+
var fetchJson = async (url, client) => {
|
|
1517
|
+
const doFetch = client.fetchImpl ?? globalThis.fetch;
|
|
1518
|
+
const res = await doFetch(url, {
|
|
1519
|
+
headers: { accept: "application/json", ...client.headers },
|
|
1520
|
+
signal: AbortSignal.timeout(REMOTE_TIMEOUT_MS)
|
|
1521
|
+
});
|
|
1522
|
+
if (!res.ok) {
|
|
1523
|
+
throw new Error(`${url} responded ${res.status} ${res.statusText}`.trim());
|
|
1524
|
+
}
|
|
1525
|
+
return await res.json();
|
|
3283
1526
|
};
|
|
3284
|
-
var
|
|
3285
|
-
const
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
document,
|
|
3291
|
-
extractWarnings: extracted.warnings,
|
|
3292
|
-
operations: extracted.operations,
|
|
3293
|
-
tags: extracted.tags,
|
|
3294
|
-
warnings
|
|
3295
|
-
};
|
|
1527
|
+
var queryString = (params) => {
|
|
1528
|
+
const search = new URLSearchParams;
|
|
1529
|
+
for (const [key, value] of Object.entries(params)) {
|
|
1530
|
+
if (value !== undefined) {
|
|
1531
|
+
search.set(key, value);
|
|
1532
|
+
}
|
|
3296
1533
|
}
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
1534
|
+
return search.toString();
|
|
1535
|
+
};
|
|
1536
|
+
var documentEntry = (doc, fields, id, lower, draft = false, lowersToMdx = false) => {
|
|
1537
|
+
const slugValue = asString(getPath(doc, fields.slug)) ?? id;
|
|
1538
|
+
const slug = slugifyPath(slugValue) || slugify(id) || "untitled";
|
|
1539
|
+
const data = {};
|
|
1540
|
+
const title = asString(getPath(doc, fields.title));
|
|
1541
|
+
const description = asString(getPath(doc, fields.description));
|
|
1542
|
+
if (title) {
|
|
1543
|
+
data.title = title;
|
|
3307
1544
|
}
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
1545
|
+
if (description) {
|
|
1546
|
+
data.description = description;
|
|
1547
|
+
}
|
|
1548
|
+
if (draft) {
|
|
1549
|
+
data.draft = true;
|
|
1550
|
+
}
|
|
1551
|
+
const body = getPath(doc, fields.body);
|
|
1552
|
+
let markdown = "";
|
|
1553
|
+
let format = "md";
|
|
1554
|
+
if (isStringValue2(body)) {
|
|
1555
|
+
markdown = `${body.trimEnd()}
|
|
1556
|
+
`;
|
|
1557
|
+
} else if (body !== undefined) {
|
|
1558
|
+
markdown = lower(body);
|
|
1559
|
+
format = lowersToMdx ? "mdx" : "md";
|
|
1560
|
+
}
|
|
1561
|
+
return stagedEntry(slug, data, markdown, asString(getPath(doc, fields.lastModified)), format);
|
|
3317
1562
|
};
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
}
|
|
3346
|
-
])),
|
|
3347
|
-
playground: { enabled: reference.display.playground.enabled, proxy },
|
|
3348
|
-
route: reference.route,
|
|
3349
|
-
slug: reference.slug,
|
|
3350
|
-
tags,
|
|
3351
|
-
title: info.title ?? reference.label,
|
|
3352
|
-
version: info.version ?? ""
|
|
3353
|
-
};
|
|
3354
|
-
if (reference.endpoint !== undefined) {
|
|
3355
|
-
spec.endpoint = reference.endpoint;
|
|
3356
|
-
}
|
|
3357
|
-
return {
|
|
3358
|
-
diagnostics: [
|
|
3359
|
-
...warnings.map((message) => ({
|
|
3360
|
-
code: SPEC_WARNING_CODES[reference.kind],
|
|
3361
|
-
message,
|
|
3362
|
-
severity: "warning"
|
|
3363
|
-
})),
|
|
3364
|
-
...extractWarnings.map((message) => ({
|
|
3365
|
-
code: SKIPPED_CODES[reference.kind],
|
|
3366
|
-
message: `In ${kindLabel} spec "${reference.spec}": ${message}`,
|
|
3367
|
-
severity: "warning"
|
|
3368
|
-
})),
|
|
3369
|
-
...operations.length === 0 ? [
|
|
3370
|
-
{
|
|
3371
|
-
code: `${codePrefix}_EMPTY`,
|
|
3372
|
-
message: `${kindLabel} spec "${reference.spec}" for ${reference.route} declares no operations; its API reference is empty.`,
|
|
3373
|
-
severity: "warning",
|
|
3374
|
-
suggestion: EMPTY_SUGGESTIONS[reference.kind]
|
|
3375
|
-
}
|
|
3376
|
-
] : []
|
|
3377
|
-
],
|
|
3378
|
-
entries: specEntries(spec, operations, reference),
|
|
3379
|
-
folderMeta: tagFolderMeta(spec, tags),
|
|
3380
|
-
slug: reference.slug,
|
|
3381
|
-
spec
|
|
3382
|
-
};
|
|
3383
|
-
} catch (error) {
|
|
3384
|
-
return {
|
|
3385
|
-
code: `${codePrefix}_UNAVAILABLE`,
|
|
3386
|
-
message: `Could not load ${kindLabel} spec "${reference.spec}" for ${reference.route} (${error.message}); its reference pages were skipped.`,
|
|
3387
|
-
severity: ctx.mode === "build" ? "error" : "warning",
|
|
3388
|
-
suggestion: error instanceof InvalidSpecError ? INVALID_SUGGESTIONS[reference.kind] : "Check the spec URL/path is reachable from the build environment; behind a proxy, set HTTP(S)_PROXY."
|
|
3389
|
-
};
|
|
3390
|
-
}
|
|
1563
|
+
|
|
1564
|
+
// src/core/sources/contentful.ts
|
|
1565
|
+
var DELIVERY_HOST = "https://cdn.contentful.com";
|
|
1566
|
+
var PREVIEW_HOST = "https://preview.contentful.com";
|
|
1567
|
+
var PAGE_SIZE = 100;
|
|
1568
|
+
var DEFAULT_FIELDS = {
|
|
1569
|
+
body: "body",
|
|
1570
|
+
description: "description",
|
|
1571
|
+
lastModified: "sys.updatedAt",
|
|
1572
|
+
slug: "slug",
|
|
1573
|
+
title: "title"
|
|
1574
|
+
};
|
|
1575
|
+
var byId = (objects) => new Map(objects.map((object) => [asString(getPath(object, "sys.id")) ?? "", object]));
|
|
1576
|
+
var contentfulSource = (options, ctx) => {
|
|
1577
|
+
const fields = { ...DEFAULT_FIELDS, ...options.fields };
|
|
1578
|
+
const toEntry = (item, assets, linked) => {
|
|
1579
|
+
const sys = asObject(item.sys) ?? {};
|
|
1580
|
+
const id = asString(sys.id) ?? "";
|
|
1581
|
+
const view = { ...asObject(item.fields), sys };
|
|
1582
|
+
return documentEntry(view, fields, id, (body) => isJsonObject(body) ? contentfulRichTextToMarkdown(body, {
|
|
1583
|
+
resolveAsset: (assetId) => {
|
|
1584
|
+
const asset = assets.get(assetId);
|
|
1585
|
+
return asset ? assetFromEntry(asset) : null;
|
|
1586
|
+
},
|
|
1587
|
+
resolveEntry: (entryId) => linked.get(entryId) ?? null,
|
|
1588
|
+
serializers: options.serializers
|
|
1589
|
+
}) : "", false, writesMdx(options.serializers));
|
|
3391
1590
|
};
|
|
3392
|
-
const
|
|
3393
|
-
const
|
|
1591
|
+
const fetchEntries = async () => {
|
|
1592
|
+
const preview = ctx?.preview ?? false;
|
|
1593
|
+
const deliveryToken = options.token ?? process.env.CONTENTFUL_ACCESS_TOKEN;
|
|
1594
|
+
const previewToken = options.previewToken ?? process.env.CONTENTFUL_PREVIEW_TOKEN;
|
|
1595
|
+
if (preview && !previewToken) {
|
|
1596
|
+
throw new Error("Contentful --preview needs a Preview API token: set previewToken or CONTENTFUL_PREVIEW_TOKEN.");
|
|
1597
|
+
}
|
|
1598
|
+
const token = preview ? previewToken : deliveryToken;
|
|
1599
|
+
const client = {
|
|
1600
|
+
fetchImpl: options.fetchImpl,
|
|
1601
|
+
headers: token ? { authorization: `Bearer ${token}` } : {}
|
|
1602
|
+
};
|
|
1603
|
+
const host = preview ? PREVIEW_HOST : DELIVERY_HOST;
|
|
1604
|
+
const base = `${host}/spaces/${options.space}/environments/${options.environment ?? "master"}/entries`;
|
|
3394
1605
|
const entries = [];
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
1606
|
+
let skip = 0;
|
|
1607
|
+
let more = true;
|
|
1608
|
+
while (more) {
|
|
1609
|
+
const query = queryString({
|
|
1610
|
+
...options.params,
|
|
1611
|
+
content_type: options.contentType,
|
|
1612
|
+
include: "2",
|
|
1613
|
+
limit: String(PAGE_SIZE),
|
|
1614
|
+
locale: options.locale,
|
|
1615
|
+
skip: String(skip)
|
|
1616
|
+
});
|
|
1617
|
+
const page = asObject(await fetchJson(`${base}?${query}`, client));
|
|
1618
|
+
if (!page) {
|
|
1619
|
+
throw new Error("Contentful returned a non-object response");
|
|
3406
1620
|
}
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
1621
|
+
const assets = byId(objectsIn(getPath(page, "includes.Asset")));
|
|
1622
|
+
const linked = byId(objectsIn(getPath(page, "includes.Entry")));
|
|
1623
|
+
const items = objectsIn(page.items);
|
|
1624
|
+
for (const item of items) {
|
|
1625
|
+
entries.push(toEntry(item, assets, linked));
|
|
1626
|
+
}
|
|
1627
|
+
skip += items.length;
|
|
1628
|
+
more = items.length > 0 && skip < (asNumber(page.total) ?? 0);
|
|
3411
1629
|
}
|
|
3412
|
-
|
|
3413
|
-
return { diagnostics, entries, folderMeta };
|
|
3414
|
-
};
|
|
3415
|
-
return {
|
|
3416
|
-
kind: "openapi-source",
|
|
3417
|
-
load,
|
|
3418
|
-
name: "openapi",
|
|
3419
|
-
openApiData: () => parsed,
|
|
3420
|
-
staged: true
|
|
1630
|
+
return entries;
|
|
3421
1631
|
};
|
|
1632
|
+
return remoteSource({
|
|
1633
|
+
fetchEntries,
|
|
1634
|
+
name: options.name,
|
|
1635
|
+
pollInterval: options.pollInterval,
|
|
1636
|
+
prefix: options.prefix
|
|
1637
|
+
}, ctx);
|
|
3422
1638
|
};
|
|
3423
1639
|
|
|
3424
1640
|
// src/core/sources/filesystem.ts
|
|
3425
|
-
import { existsSync
|
|
3426
|
-
import { readFile
|
|
3427
|
-
import { extname as
|
|
1641
|
+
import { existsSync, watch as fsWatch } from "node:fs";
|
|
1642
|
+
import { readFile } from "node:fs/promises";
|
|
1643
|
+
import { extname as extname2, isAbsolute, join as join2, relative as relative3, resolve } from "pathe";
|
|
3428
1644
|
import { glob as glob2 } from "tinyglobby";
|
|
3429
|
-
|
|
3430
|
-
// src/core/sources/watch.ts
|
|
3431
|
-
var BLUME_IGNORE_DIRS = [
|
|
3432
|
-
".blume",
|
|
3433
|
-
".blume-verify",
|
|
3434
|
-
".cache",
|
|
3435
|
-
".git",
|
|
3436
|
-
".next",
|
|
3437
|
-
".turbo",
|
|
3438
|
-
".vercel",
|
|
3439
|
-
"dist",
|
|
3440
|
-
"node_modules"
|
|
3441
|
-
];
|
|
3442
|
-
var baselineScanIgnore = () => BLUME_IGNORE_DIRS.map((dir) => `**/${dir}/**`);
|
|
3443
|
-
var BLUME_WATCH_IGNORE_DIRS = BLUME_IGNORE_DIRS;
|
|
3444
|
-
var excludeDirSegments = (patterns) => patterns.map((pattern) => /^(?<dir>[^*/]+)\/\*\*$/u.exec(pattern)?.groups?.dir).filter((dir) => dir !== undefined);
|
|
3445
|
-
var ignoringWatchListener = (onChange, ignoreDirs = BLUME_WATCH_IGNORE_DIRS, ignoreSegment = () => false) => {
|
|
3446
|
-
const ignore = new Set(ignoreDirs);
|
|
3447
|
-
return (_event, filename) => {
|
|
3448
|
-
if (filename !== null && filename.split(/[/\\]/u).some((segment) => ignore.has(segment) || ignoreSegment(segment))) {
|
|
3449
|
-
return;
|
|
3450
|
-
}
|
|
3451
|
-
onChange();
|
|
3452
|
-
};
|
|
3453
|
-
};
|
|
3454
|
-
|
|
3455
|
-
// src/core/sources/filesystem.ts
|
|
3456
1645
|
var filesystemSource = (options) => {
|
|
3457
|
-
const contentRoot =
|
|
1646
|
+
const contentRoot = isAbsolute(options.root) ? options.root : join2(resolve(options.projectRoot), options.root);
|
|
3458
1647
|
const load = async () => {
|
|
3459
1648
|
const files = await glob2(options.include, {
|
|
3460
1649
|
absolute: true,
|
|
@@ -3464,22 +1653,22 @@ var filesystemSource = (options) => {
|
|
|
3464
1653
|
});
|
|
3465
1654
|
files.sort();
|
|
3466
1655
|
const entries = await Promise.all(files.map(async (file) => {
|
|
3467
|
-
const source = await
|
|
3468
|
-
const ext =
|
|
1656
|
+
const source = await readFile(file, "utf-8");
|
|
1657
|
+
const ext = extname2(file).toLowerCase();
|
|
3469
1658
|
const format = ext === ".mdx" ? "mdx" : "md";
|
|
3470
1659
|
const parsed = frontmatter_default(source);
|
|
3471
1660
|
return {
|
|
3472
1661
|
body: { format, text: parsed.content },
|
|
3473
1662
|
data: parsed.data,
|
|
3474
1663
|
raw: source,
|
|
3475
|
-
ref:
|
|
1664
|
+
ref: relative3(contentRoot, file),
|
|
3476
1665
|
sourcePath: file
|
|
3477
1666
|
};
|
|
3478
1667
|
}));
|
|
3479
1668
|
return { diagnostics: [], entries };
|
|
3480
1669
|
};
|
|
3481
1670
|
const validate = () => {
|
|
3482
|
-
if (!
|
|
1671
|
+
if (!existsSync(contentRoot)) {
|
|
3483
1672
|
throw new BlumeError({
|
|
3484
1673
|
code: options.missingCode ?? "BLUME_CONTENT_ROOT_MISSING",
|
|
3485
1674
|
file: contentRoot,
|
|
@@ -3494,7 +1683,7 @@ var filesystemSource = (options) => {
|
|
|
3494
1683
|
...excludeDirSegments(options.exclude)
|
|
3495
1684
|
]);
|
|
3496
1685
|
const watch = (onChange) => {
|
|
3497
|
-
if (!
|
|
1686
|
+
if (!existsSync(contentRoot)) {
|
|
3498
1687
|
return () => {};
|
|
3499
1688
|
}
|
|
3500
1689
|
const watcher = fsWatch(contentRoot, { recursive: true }, ignoringWatchListener(onChange, watchIgnoreDirs));
|
|
@@ -3505,7 +1694,7 @@ var filesystemSource = (options) => {
|
|
|
3505
1694
|
load,
|
|
3506
1695
|
name: options.name,
|
|
3507
1696
|
prefix: options.prefix,
|
|
3508
|
-
read: (ref) =>
|
|
1697
|
+
read: (ref) => readFile(join2(contentRoot, ref), "utf-8"),
|
|
3509
1698
|
staged: false,
|
|
3510
1699
|
validate,
|
|
3511
1700
|
watch
|
|
@@ -3513,11 +1702,11 @@ var filesystemSource = (options) => {
|
|
|
3513
1702
|
};
|
|
3514
1703
|
|
|
3515
1704
|
// src/core/sources/github-releases.ts
|
|
3516
|
-
import { fromMarkdown
|
|
1705
|
+
import { fromMarkdown } from "mdast-util-from-markdown";
|
|
3517
1706
|
import { gfmFromMarkdown } from "mdast-util-gfm";
|
|
3518
|
-
import { toString as
|
|
1707
|
+
import { toString as mdastToString } from "mdast-util-to-string";
|
|
3519
1708
|
import { gfm } from "micromark-extension-gfm";
|
|
3520
|
-
import
|
|
1709
|
+
import stringWidth from "string-width";
|
|
3521
1710
|
var DEFAULT_LIMIT = 100;
|
|
3522
1711
|
var PER_PAGE = 100;
|
|
3523
1712
|
var LEADING_V = /^v/iu;
|
|
@@ -3526,26 +1715,54 @@ var EDGE_DASHES = /^-+|-+$/gu;
|
|
|
3526
1715
|
var DESCRIPTION_MAX = 160;
|
|
3527
1716
|
var DESCRIPTION_MIN = 110;
|
|
3528
1717
|
var CHANGESET_HASH = /^(?<mark>\s*(?:[-*+]|\d+[.)])\s+)[0-9a-f]{7,40}:\s+/gmu;
|
|
3529
|
-
var
|
|
1718
|
+
var WHITESPACE = /\s+/gu;
|
|
3530
1719
|
var TRAILING_FRAGMENT = /[\s,;:.—–-]+$/u;
|
|
3531
1720
|
var NON_PROSE = new Set(["code", "heading", "html", "thematicBreak"]);
|
|
3532
1721
|
var releaseDescription = (body) => {
|
|
3533
|
-
const tree =
|
|
1722
|
+
const tree = fromMarkdown(body.replaceAll(CHANGESET_HASH, "$<mark>"), {
|
|
3534
1723
|
extensions: [gfm()],
|
|
3535
1724
|
mdastExtensions: [gfmFromMarkdown()]
|
|
3536
1725
|
});
|
|
3537
|
-
const text = tree.children.filter((node) => !NON_PROSE.has(node.type)).map((node) =>
|
|
1726
|
+
const text = tree.children.filter((node) => !NON_PROSE.has(node.type)).map((node) => mdastToString(node, { includeHtml: false, includeImageAlt: false })).join(" ").replaceAll(WHITESPACE, " ").trim();
|
|
3538
1727
|
if (!text) {
|
|
3539
1728
|
return;
|
|
3540
1729
|
}
|
|
3541
|
-
if (
|
|
1730
|
+
if (stringWidth(text) <= DESCRIPTION_MAX) {
|
|
3542
1731
|
return text;
|
|
3543
1732
|
}
|
|
3544
1733
|
const slice = columnsPrefix(text, DESCRIPTION_MAX - 1);
|
|
3545
1734
|
const boundary = slice.lastIndexOf(" ");
|
|
3546
|
-
const head = (boundary !== -1 &&
|
|
1735
|
+
const head = (boundary !== -1 && stringWidth(slice.slice(0, boundary)) >= DESCRIPTION_MIN ? slice.slice(0, boundary) : slice).replace(TRAILING_FRAGMENT, "");
|
|
3547
1736
|
return `${head}…`;
|
|
3548
1737
|
};
|
|
1738
|
+
var headingsIn = (node) => {
|
|
1739
|
+
if (node.type === "heading") {
|
|
1740
|
+
return [node];
|
|
1741
|
+
}
|
|
1742
|
+
const found = [];
|
|
1743
|
+
if ("children" in node) {
|
|
1744
|
+
for (const child of node.children) {
|
|
1745
|
+
found.push(...headingsIn(child));
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
return found;
|
|
1749
|
+
};
|
|
1750
|
+
var liftHeadings = (body) => {
|
|
1751
|
+
const headings = headingsIn(fromMarkdown(body, {
|
|
1752
|
+
extensions: [gfm()],
|
|
1753
|
+
mdastExtensions: [gfmFromMarkdown()]
|
|
1754
|
+
}));
|
|
1755
|
+
const lift = Math.min(...headings.map((heading) => heading.depth)) - 2;
|
|
1756
|
+
if (headings.length === 0 || lift <= 0) {
|
|
1757
|
+
return body;
|
|
1758
|
+
}
|
|
1759
|
+
let lifted = body;
|
|
1760
|
+
for (const heading of headings.toReversed()) {
|
|
1761
|
+
const marker = lifted.indexOf("#", heading.position?.start.offset);
|
|
1762
|
+
lifted = lifted.slice(0, marker) + lifted.slice(marker + lift);
|
|
1763
|
+
}
|
|
1764
|
+
return lifted;
|
|
1765
|
+
};
|
|
3549
1766
|
var slugifyTag = (tag) => tag.toLowerCase().replaceAll(NON_SLUG, "-").replaceAll(EDGE_DASHES, "");
|
|
3550
1767
|
var githubHeaders = () => {
|
|
3551
1768
|
const headers = new Headers({ Accept: "application/vnd.github+json" });
|
|
@@ -3560,9 +1777,9 @@ var releaseToEntry = (release) => {
|
|
|
3560
1777
|
const title = release.name?.trim() || release.tag_name;
|
|
3561
1778
|
const date = release.published_at ?? release.created_at;
|
|
3562
1779
|
const category = release.prerelease ? "Prerelease" : "Release";
|
|
3563
|
-
const body = (release.body ?? "").replaceAll(`\r
|
|
1780
|
+
const body = liftHeadings(neutralizeUnsafeLinks((release.body ?? "").replaceAll(`\r
|
|
3564
1781
|
`, `
|
|
3565
|
-
`).trim();
|
|
1782
|
+
`)).trim());
|
|
3566
1783
|
const description = releaseDescription(body);
|
|
3567
1784
|
const data = {
|
|
3568
1785
|
changelog: { category, version },
|
|
@@ -3648,6 +1865,7 @@ var githubReleasesSource = (options, ctx) => {
|
|
|
3648
1865
|
};
|
|
3649
1866
|
return {
|
|
3650
1867
|
load,
|
|
1868
|
+
monolingual: true,
|
|
3651
1869
|
name: options.name,
|
|
3652
1870
|
prefix: options.prefix,
|
|
3653
1871
|
read,
|
|
@@ -3800,36 +2018,22 @@ var mdxRemoteSource = (options, ctx) => {
|
|
|
3800
2018
|
};
|
|
3801
2019
|
|
|
3802
2020
|
// src/core/sources/notion.ts
|
|
3803
|
-
import { setTimeout as
|
|
2021
|
+
import { setTimeout as sleep } from "node:timers/promises";
|
|
3804
2022
|
import pLimit from "p-limit";
|
|
3805
|
-
import { join as
|
|
3806
|
-
|
|
3807
|
-
// src/components/content/youtube.ts
|
|
3808
|
-
var BARE_ID = /^[\w-]{11}$/u;
|
|
3809
|
-
var URL_ID = /(?:youtu\.be\/|\/embed\/|\/shorts\/|\/live\/|[?&]v=)(?<id>[\w-]{11})/u;
|
|
3810
|
-
var parseYouTubeId = (input) => {
|
|
3811
|
-
const value = input.trim();
|
|
3812
|
-
if (!value) {
|
|
3813
|
-
return null;
|
|
3814
|
-
}
|
|
3815
|
-
if (BARE_ID.test(value)) {
|
|
3816
|
-
return value;
|
|
3817
|
-
}
|
|
3818
|
-
return URL_ID.exec(value)?.groups?.id ?? null;
|
|
3819
|
-
};
|
|
2023
|
+
import { join as join4 } from "pathe";
|
|
3820
2024
|
|
|
3821
2025
|
// src/core/sources/assets.ts
|
|
3822
2026
|
import { randomUUID } from "node:crypto";
|
|
3823
2027
|
import {
|
|
3824
2028
|
access,
|
|
3825
|
-
mkdir
|
|
2029
|
+
mkdir,
|
|
3826
2030
|
readdir,
|
|
3827
2031
|
rename,
|
|
3828
2032
|
rm,
|
|
3829
|
-
writeFile
|
|
2033
|
+
writeFile
|
|
3830
2034
|
} from "node:fs/promises";
|
|
3831
|
-
import { extname as
|
|
3832
|
-
var
|
|
2035
|
+
import { extname as extname3, join as join3 } from "pathe";
|
|
2036
|
+
var MD_IMAGE = /!\[(?<alt>[^\]]*)\]\((?<url>[^)\s]+)\)/gu;
|
|
3833
2037
|
var HTML_VIDEO_SRC = /(?<open><video\b[^>]*?\ssrc=")(?<url>[^"]+)(?<close>")/gu;
|
|
3834
2038
|
var REMOTE = /^https?:\/\//u;
|
|
3835
2039
|
var SAFE_EXT = /^\.[a-z0-9]+$/iu;
|
|
@@ -3853,7 +2057,7 @@ var PART_SUFFIX = ".part";
|
|
|
3853
2057
|
var DEFAULT_TIMEOUT_MS = 120000;
|
|
3854
2058
|
var extFromUrl = (url) => {
|
|
3855
2059
|
const clean = url.split("?")[0] ?? url;
|
|
3856
|
-
const ext =
|
|
2060
|
+
const ext = extname3(clean);
|
|
3857
2061
|
return SAFE_EXT.test(ext) ? ext.toLowerCase() : null;
|
|
3858
2062
|
};
|
|
3859
2063
|
var mediaType = (res) => res.headers.get("content-type")?.split(";")[0]?.trim().toLowerCase() ?? "";
|
|
@@ -3878,6 +2082,7 @@ var completedFor = async (dir, stem) => {
|
|
|
3878
2082
|
var materializeAssets = async (markdown, ctx) => {
|
|
3879
2083
|
const doFetch = ctx.fetchImpl ?? globalThis.fetch;
|
|
3880
2084
|
const limit = ctx.limit ?? ((task) => task());
|
|
2085
|
+
const inFlight = ctx.inFlight ?? new Map;
|
|
3881
2086
|
const timeoutMs = ctx.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
3882
2087
|
const diagnostics = [];
|
|
3883
2088
|
const fences = [];
|
|
@@ -3886,7 +2091,7 @@ var materializeAssets = async (markdown, ctx) => {
|
|
|
3886
2091
|
return `\x00blume-fence-${fences.length - 1}\x00`;
|
|
3887
2092
|
});
|
|
3888
2093
|
const urls = new Set;
|
|
3889
|
-
for (const pattern of [
|
|
2094
|
+
for (const pattern of [MD_IMAGE, HTML_VIDEO_SRC]) {
|
|
3890
2095
|
for (const match of masked.matchAll(pattern)) {
|
|
3891
2096
|
const url = match.groups?.url;
|
|
3892
2097
|
if (url && REMOTE.test(url)) {
|
|
@@ -3894,10 +2099,9 @@ var materializeAssets = async (markdown, ctx) => {
|
|
|
3894
2099
|
}
|
|
3895
2100
|
}
|
|
3896
2101
|
}
|
|
3897
|
-
const download = async (url) => {
|
|
3898
|
-
const stem = hashText(url.split("?")[0] ?? url);
|
|
2102
|
+
const download = async (url, stem) => {
|
|
3899
2103
|
const urlExt = extFromUrl(url);
|
|
3900
|
-
if (urlExt && await exists(
|
|
2104
|
+
if (urlExt && await exists(join3(ctx.assetsDir, `${stem}${urlExt}`))) {
|
|
3901
2105
|
return `${stem}${urlExt}`;
|
|
3902
2106
|
}
|
|
3903
2107
|
const completed = urlExt ? null : await completedFor(ctx.assetsDir, stem);
|
|
@@ -3916,11 +2120,11 @@ var materializeAssets = async (markdown, ctx) => {
|
|
|
3916
2120
|
throw new Error("empty response body");
|
|
3917
2121
|
}
|
|
3918
2122
|
const file = `${stem}${urlExt ?? EXT_BY_MIME.get(type) ?? UNKNOWN_EXT}`;
|
|
3919
|
-
const target =
|
|
3920
|
-
await
|
|
2123
|
+
const target = join3(ctx.assetsDir, file);
|
|
2124
|
+
await mkdir(ctx.assetsDir, { recursive: true });
|
|
3921
2125
|
const part = `${target}.${randomUUID()}${PART_SUFFIX}`;
|
|
3922
2126
|
try {
|
|
3923
|
-
await
|
|
2127
|
+
await writeFile(part, res.body);
|
|
3924
2128
|
} catch (error) {
|
|
3925
2129
|
await rm(part, { force: true });
|
|
3926
2130
|
throw error;
|
|
@@ -3928,10 +2132,30 @@ var materializeAssets = async (markdown, ctx) => {
|
|
|
3928
2132
|
await rename(part, target);
|
|
3929
2133
|
return file;
|
|
3930
2134
|
};
|
|
2135
|
+
const publish = async (url) => {
|
|
2136
|
+
const stem = hashText(url.split("?")[0] ?? url);
|
|
2137
|
+
const pending = inFlight.get(stem);
|
|
2138
|
+
if (pending) {
|
|
2139
|
+
try {
|
|
2140
|
+
return await pending;
|
|
2141
|
+
} catch {
|
|
2142
|
+
return await publish(url);
|
|
2143
|
+
}
|
|
2144
|
+
}
|
|
2145
|
+
const own = (async () => {
|
|
2146
|
+
try {
|
|
2147
|
+
return await limit(() => download(url, stem));
|
|
2148
|
+
} finally {
|
|
2149
|
+
inFlight.delete(stem);
|
|
2150
|
+
}
|
|
2151
|
+
})();
|
|
2152
|
+
inFlight.set(stem, own);
|
|
2153
|
+
return await own;
|
|
2154
|
+
};
|
|
3931
2155
|
const rewrites = new Map;
|
|
3932
2156
|
await Promise.all([...urls].map(async (url) => {
|
|
3933
2157
|
try {
|
|
3934
|
-
const file = await
|
|
2158
|
+
const file = await publish(url);
|
|
3935
2159
|
rewrites.set(url, `${ctx.assetsBaseUrl}/${file}`);
|
|
3936
2160
|
} catch (error) {
|
|
3937
2161
|
diagnostics.push({
|
|
@@ -3941,7 +2165,7 @@ var materializeAssets = async (markdown, ctx) => {
|
|
|
3941
2165
|
});
|
|
3942
2166
|
}
|
|
3943
2167
|
}));
|
|
3944
|
-
const rewritten = masked.replaceAll(
|
|
2168
|
+
const rewritten = masked.replaceAll(MD_IMAGE, (match, alt, url) => {
|
|
3945
2169
|
const local = rewrites.get(url);
|
|
3946
2170
|
return local ? `` : match;
|
|
3947
2171
|
}).replaceAll(HTML_VIDEO_SRC, (match, open, url, close) => {
|
|
@@ -3952,22 +2176,12 @@ var materializeAssets = async (markdown, ctx) => {
|
|
|
3952
2176
|
};
|
|
3953
2177
|
|
|
3954
2178
|
// src/core/sources/notion.ts
|
|
3955
|
-
var richToMarkdown = (rich = []) => rich.map((
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
text = `**${text}**`;
|
|
3962
|
-
}
|
|
3963
|
-
if (node.annotations?.italic) {
|
|
3964
|
-
text = `*${text}*`;
|
|
3965
|
-
}
|
|
3966
|
-
if (node.annotations?.strikethrough) {
|
|
3967
|
-
text = `~~${text}~~`;
|
|
3968
|
-
}
|
|
3969
|
-
return node.href ? `[${text}](${node.href})` : text;
|
|
3970
|
-
}).join("");
|
|
2179
|
+
var richToMarkdown = (rich = []) => rich.map(({ annotations = {}, href, plain_text: text }) => renderLink(renderInline(text, {
|
|
2180
|
+
bold: annotations.bold,
|
|
2181
|
+
code: annotations.code,
|
|
2182
|
+
italic: annotations.italic,
|
|
2183
|
+
strike: annotations.strikethrough
|
|
2184
|
+
}), href ?? undefined)).join("");
|
|
3971
2185
|
var isBlockPayload = (value) => typeof value === "object";
|
|
3972
2186
|
var payloadOf = (block) => {
|
|
3973
2187
|
const value = block[block.type];
|
|
@@ -3977,7 +2191,7 @@ var blockField = (block) => payloadOf(block)?.rich_text ?? [];
|
|
|
3977
2191
|
var RATE_LIMITED = 429;
|
|
3978
2192
|
var MAX_RETRIES = 4;
|
|
3979
2193
|
var BASE_DELAY_MS = 500;
|
|
3980
|
-
var
|
|
2194
|
+
var SECOND_MS = 1000;
|
|
3981
2195
|
var DEFAULT_CONCURRENCY = 3;
|
|
3982
2196
|
var ASSET_DOWNLOAD_CONCURRENCY = 4;
|
|
3983
2197
|
var withNotionRetry = async (call, attempt = 0) => {
|
|
@@ -3989,8 +2203,8 @@ var withNotionRetry = async (call, attempt = 0) => {
|
|
|
3989
2203
|
throw error;
|
|
3990
2204
|
}
|
|
3991
2205
|
const retryAfter = Number(error.headers?.["retry-after"]);
|
|
3992
|
-
const wait = retryAfter > 0 ? retryAfter *
|
|
3993
|
-
await
|
|
2206
|
+
const wait = retryAfter > 0 ? retryAfter * SECOND_MS : BASE_DELAY_MS * 2 ** attempt * (1 + Math.random());
|
|
2207
|
+
await sleep(wait);
|
|
3994
2208
|
return withNotionRetry(call, attempt + 1);
|
|
3995
2209
|
}
|
|
3996
2210
|
};
|
|
@@ -4056,13 +2270,11 @@ var renderLeaf = (block) => {
|
|
|
4056
2270
|
return "---";
|
|
4057
2271
|
}
|
|
4058
2272
|
case "code": {
|
|
4059
|
-
return
|
|
4060
|
-
${text}
|
|
4061
|
-
\`\`\``;
|
|
2273
|
+
return codeFence(richToPlain(blockField(block)), data.language ?? "");
|
|
4062
2274
|
}
|
|
4063
2275
|
case "image": {
|
|
4064
2276
|
const url = data.external?.url ?? data.file?.url;
|
|
4065
|
-
return url ?
|
|
2277
|
+
return url ? image(richToPlain(data.caption), url) : "";
|
|
4066
2278
|
}
|
|
4067
2279
|
case "video": {
|
|
4068
2280
|
return renderVideo(data);
|
|
@@ -4076,18 +2288,19 @@ var notionSource = (options, ctx) => {
|
|
|
4076
2288
|
const props = options.properties ?? {};
|
|
4077
2289
|
const limit = pLimit(Math.max(1, options.concurrency ?? DEFAULT_CONCURRENCY));
|
|
4078
2290
|
const downloads = pLimit(ASSET_DOWNLOAD_CONCURRENCY);
|
|
2291
|
+
const inFlight = new Map;
|
|
4079
2292
|
const notionCall = (call) => withNotionRetry(() => limit(call));
|
|
4080
|
-
const cache = snapshotCache(ctx?.cacheDir ??
|
|
4081
|
-
const assetsDir = ctx?.assetsDir ??
|
|
2293
|
+
const cache = snapshotCache(ctx?.cacheDir ?? join4(".blume", "cache", options.name));
|
|
2294
|
+
const assetsDir = ctx?.assetsDir ?? join4(".blume", "public", "blume-assets", options.name);
|
|
4082
2295
|
const assetsBaseUrl = ctx?.assetsBaseUrl ?? `/blume-assets/${options.name}`;
|
|
4083
2296
|
let snapshot = new Map;
|
|
4084
|
-
const resolveClient =
|
|
2297
|
+
const resolveClient = () => {
|
|
4085
2298
|
if (options.client) {
|
|
4086
2299
|
return options.client;
|
|
4087
2300
|
}
|
|
4088
2301
|
let Client;
|
|
4089
2302
|
try {
|
|
4090
|
-
const sdk =
|
|
2303
|
+
const sdk = nodeRequire("@notionhq/client");
|
|
4091
2304
|
({ Client } = sdk);
|
|
4092
2305
|
} catch {
|
|
4093
2306
|
throw new BlumeError({
|
|
@@ -4115,7 +2328,7 @@ ${body}
|
|
|
4115
2328
|
</Callout>`;
|
|
4116
2329
|
}
|
|
4117
2330
|
if (block.type === "toggle") {
|
|
4118
|
-
const title = jsxString(
|
|
2331
|
+
const title = jsxString(richToPlain(blockField(block)));
|
|
4119
2332
|
return `<Accordion>
|
|
4120
2333
|
<AccordionItem title=${title}>
|
|
4121
2334
|
${await children(block)}
|
|
@@ -4191,11 +2404,11 @@ ${nested}`;
|
|
|
4191
2404
|
};
|
|
4192
2405
|
const frontmatter = (page) => {
|
|
4193
2406
|
const data = {};
|
|
4194
|
-
const title =
|
|
2407
|
+
const title = richToPlain(titleProperty(page)?.title);
|
|
4195
2408
|
if (title) {
|
|
4196
2409
|
data.title = title;
|
|
4197
2410
|
}
|
|
4198
|
-
const description =
|
|
2411
|
+
const description = richToPlain(page.properties[props.description ?? "Description"]?.rich_text);
|
|
4199
2412
|
if (description) {
|
|
4200
2413
|
data.description = description;
|
|
4201
2414
|
}
|
|
@@ -4206,7 +2419,7 @@ ${nested}`;
|
|
|
4206
2419
|
if (order !== undefined) {
|
|
4207
2420
|
data.sidebar = { order };
|
|
4208
2421
|
}
|
|
4209
|
-
const slugProp =
|
|
2422
|
+
const slugProp = richToPlain(page.properties[props.slug ?? "Slug"]?.rich_text);
|
|
4210
2423
|
const slug = slugifyPath(slugProp || title) || page.id;
|
|
4211
2424
|
return { data, slug };
|
|
4212
2425
|
};
|
|
@@ -4217,6 +2430,7 @@ ${nested}`;
|
|
|
4217
2430
|
assetsBaseUrl,
|
|
4218
2431
|
assetsDir,
|
|
4219
2432
|
fetchImpl: options.fetchImpl,
|
|
2433
|
+
inFlight,
|
|
4220
2434
|
limit: downloads
|
|
4221
2435
|
});
|
|
4222
2436
|
const raw = frontmatter_default.stringify(assets.markdown, data);
|
|
@@ -4251,7 +2465,7 @@ ${nested}`;
|
|
|
4251
2465
|
const load = async (refresh = ctx?.refresh ?? true) => {
|
|
4252
2466
|
const assetDiagnostics = [];
|
|
4253
2467
|
const result = await loadWithCache(options.name, cache, async () => {
|
|
4254
|
-
const client =
|
|
2468
|
+
const client = resolveClient();
|
|
4255
2469
|
const dataSourceId = await resolveDataSource(client);
|
|
4256
2470
|
const pages = await collectAll((cursor) => queryDataSource(client, dataSourceId, cursor));
|
|
4257
2471
|
const built = await Promise.all(pages.map((page) => toEntry(client, page)));
|
|
@@ -4285,9 +2499,9 @@ ${nested}`;
|
|
|
4285
2499
|
};
|
|
4286
2500
|
|
|
4287
2501
|
// src/core/sources/obsidian.ts
|
|
4288
|
-
import { existsSync as
|
|
4289
|
-
import { readdir as readdir2, readFile as
|
|
4290
|
-
import { basename as basename2, isAbsolute as
|
|
2502
|
+
import { existsSync as existsSync2, watch as fsWatch2, statSync } from "node:fs";
|
|
2503
|
+
import { readdir as readdir2, readFile as readFile2, stat } from "node:fs/promises";
|
|
2504
|
+
import { basename as basename2, isAbsolute as isAbsolute2, join as join5, relative as relative4, resolve as resolve2 } from "pathe";
|
|
4291
2505
|
var MARKDOWN_FILE = /\.md$/iu;
|
|
4292
2506
|
var OBSIDIAN_COMMENT = /%%.*?%%/gu;
|
|
4293
2507
|
var WIKILINK = /(?<embed>!)?\[\[(?<target>(?:[^\][|#\n][^\]|#\n]*?)?)(?:#(?<heading>[^\]|\n]+?))?(?:\\?\|(?<alias>[^\]\n]+))?\]\]/gu;
|
|
@@ -4435,7 +2649,7 @@ var transformChunk = (chunk, index, self, unresolved) => chunk.replaceAll(OBSIDI
|
|
|
4435
2649
|
return `[${label}](${href}#${anchor})`;
|
|
4436
2650
|
});
|
|
4437
2651
|
var transformProse = (text, index, self, unresolved) => splitLiterals(text).map((chunk) => chunk.literal ? chunk.text : transformChunk(chunk.text, index, self, unresolved)).join("");
|
|
4438
|
-
var
|
|
2652
|
+
var INDENTED_CODE = /^(?: {4}|\t)/u;
|
|
4439
2653
|
var LIST_ITEM = /^ {0,3}(?:[-+*]|\d{1,9}[.)])(?: |$)/u;
|
|
4440
2654
|
var indentOf = (line) => line.length - line.trimStart().length;
|
|
4441
2655
|
var listAfter = (line, inList) => {
|
|
@@ -4448,7 +2662,7 @@ var listAfter = (line, inList) => {
|
|
|
4448
2662
|
return line.startsWith(" ") || line.startsWith("\t") ? inList : false;
|
|
4449
2663
|
};
|
|
4450
2664
|
var fenceAfter = (line, fence, fenceIndent, inList) => {
|
|
4451
|
-
const canDelimit = fence === null ? inList || !
|
|
2665
|
+
const canDelimit = fence === null ? inList || !INDENTED_CODE.test(line) : indentOf(line) <= fenceIndent + 3;
|
|
4452
2666
|
return canDelimit ? nextFenceState(line, fence) : fence;
|
|
4453
2667
|
};
|
|
4454
2668
|
var transformBody = (body, index, self, unresolved) => {
|
|
@@ -4470,7 +2684,7 @@ var transformBody = (body, index, self, unresolved) => {
|
|
|
4470
2684
|
`)) {
|
|
4471
2685
|
const blank = line.trim() === "";
|
|
4472
2686
|
if (fence === null && indentedCode) {
|
|
4473
|
-
if (blank ||
|
|
2687
|
+
if (blank || INDENTED_CODE.test(line)) {
|
|
4474
2688
|
out.push(line);
|
|
4475
2689
|
afterBlank = blank;
|
|
4476
2690
|
continue;
|
|
@@ -4478,7 +2692,7 @@ var transformBody = (body, index, self, unresolved) => {
|
|
|
4478
2692
|
indentedCode = false;
|
|
4479
2693
|
}
|
|
4480
2694
|
inList = listAfter(line, inList);
|
|
4481
|
-
if (fence === null && afterBlank && !(blank || inList) &&
|
|
2695
|
+
if (fence === null && afterBlank && !(blank || inList) && INDENTED_CODE.test(line)) {
|
|
4482
2696
|
flush();
|
|
4483
2697
|
indentedCode = true;
|
|
4484
2698
|
out.push(line);
|
|
@@ -4602,9 +2816,9 @@ var noteToEntry = (pair, index, options, unresolved) => {
|
|
|
4602
2816
|
};
|
|
4603
2817
|
};
|
|
4604
2818
|
var readNote = async (vaultDir, rel, options) => {
|
|
4605
|
-
const absPath =
|
|
2819
|
+
const absPath = join5(vaultDir, rel);
|
|
4606
2820
|
try {
|
|
4607
|
-
const { content, data } = frontmatter_default(await
|
|
2821
|
+
const { content, data } = frontmatter_default(await readFile2(absPath, "utf-8"));
|
|
4608
2822
|
return {
|
|
4609
2823
|
absPath,
|
|
4610
2824
|
content,
|
|
@@ -4629,7 +2843,7 @@ var classify = async (dir, entry) => {
|
|
|
4629
2843
|
};
|
|
4630
2844
|
}
|
|
4631
2845
|
try {
|
|
4632
|
-
const target = await stat(
|
|
2846
|
+
const target = await stat(join5(dir, entry.name));
|
|
4633
2847
|
return {
|
|
4634
2848
|
directory: target.isDirectory(),
|
|
4635
2849
|
file: target.isFile(),
|
|
@@ -4649,11 +2863,11 @@ var walkVault = async (dir, root, exclude) => {
|
|
|
4649
2863
|
const listed = await readdir2(dir, { withFileTypes: true });
|
|
4650
2864
|
const entries = await Promise.all(listed.filter((entry) => !(isHidden(entry.name) || exclude.has(entry.name))).map((entry) => classify(dir, entry)));
|
|
4651
2865
|
for (const entry of entries.toSorted(byVaultOrder)) {
|
|
4652
|
-
const full =
|
|
2866
|
+
const full = join5(dir, entry.name);
|
|
4653
2867
|
if (entry.directory) {
|
|
4654
2868
|
found.push(...await walkVault(full, root, exclude));
|
|
4655
2869
|
} else if (entry.file && MARKDOWN_FILE.test(entry.name)) {
|
|
4656
|
-
found.push(
|
|
2870
|
+
found.push(relative4(root, full));
|
|
4657
2871
|
}
|
|
4658
2872
|
}
|
|
4659
2873
|
return found;
|
|
@@ -4689,7 +2903,7 @@ var unresolvedDiagnostics = (name, unresolved) => {
|
|
|
4689
2903
|
return diagnostics;
|
|
4690
2904
|
};
|
|
4691
2905
|
var obsidianSource = (options, ctx) => {
|
|
4692
|
-
const vaultDir =
|
|
2906
|
+
const vaultDir = resolve2(ctx.projectRoot, options.vault);
|
|
4693
2907
|
const exclude = new Set([...BLUME_IGNORE_DIRS, ...options.exclude ?? []]);
|
|
4694
2908
|
const load = async () => {
|
|
4695
2909
|
const files = await walkVault(vaultDir, vaultDir, exclude);
|
|
@@ -4704,9 +2918,9 @@ var obsidianSource = (options, ctx) => {
|
|
|
4704
2918
|
};
|
|
4705
2919
|
};
|
|
4706
2920
|
const read = async (ref) => {
|
|
4707
|
-
const absPath =
|
|
4708
|
-
const rel =
|
|
4709
|
-
if (rel.startsWith("..") ||
|
|
2921
|
+
const absPath = resolve2(vaultDir, ref);
|
|
2922
|
+
const rel = relative4(vaultDir, absPath);
|
|
2923
|
+
if (rel.startsWith("..") || isAbsolute2(rel)) {
|
|
4710
2924
|
throw new BlumeError({
|
|
4711
2925
|
code: "BLUME_SOURCE_MISCONFIGURED",
|
|
4712
2926
|
file: absPath,
|
|
@@ -4715,7 +2929,7 @@ var obsidianSource = (options, ctx) => {
|
|
|
4715
2929
|
suggestion: "Reference notes by their vault-relative path."
|
|
4716
2930
|
});
|
|
4717
2931
|
}
|
|
4718
|
-
return await
|
|
2932
|
+
return await readFile2(absPath, "utf-8");
|
|
4719
2933
|
};
|
|
4720
2934
|
const validate = () => {
|
|
4721
2935
|
const stats = statSync(vaultDir, { throwIfNoEntry: false });
|
|
@@ -4732,7 +2946,7 @@ var obsidianSource = (options, ctx) => {
|
|
|
4732
2946
|
});
|
|
4733
2947
|
};
|
|
4734
2948
|
const watch = (onChange) => {
|
|
4735
|
-
if (!
|
|
2949
|
+
if (!existsSync2(vaultDir)) {
|
|
4736
2950
|
return () => {};
|
|
4737
2951
|
}
|
|
4738
2952
|
const watcher = fsWatch2(vaultDir, { recursive: true }, ignoringWatchListener(onChange, exclude, isHidden));
|
|
@@ -4750,8 +2964,193 @@ var obsidianSource = (options, ctx) => {
|
|
|
4750
2964
|
};
|
|
4751
2965
|
};
|
|
4752
2966
|
|
|
2967
|
+
// src/core/sources/lexical.ts
|
|
2968
|
+
var IS_BOLD = 1;
|
|
2969
|
+
var IS_ITALIC = 2;
|
|
2970
|
+
var IS_STRIKETHROUGH = 4;
|
|
2971
|
+
var IS_CODE = 16;
|
|
2972
|
+
var hasFlag = (format, flag) => Math.floor(format / flag) % 2 === 1;
|
|
2973
|
+
var marksOf2 = (node) => {
|
|
2974
|
+
const format = asNumber(node.format) ?? 0;
|
|
2975
|
+
return {
|
|
2976
|
+
bold: hasFlag(format, IS_BOLD),
|
|
2977
|
+
code: hasFlag(format, IS_CODE),
|
|
2978
|
+
italic: hasFlag(format, IS_ITALIC),
|
|
2979
|
+
strike: hasFlag(format, IS_STRIKETHROUGH)
|
|
2980
|
+
};
|
|
2981
|
+
};
|
|
2982
|
+
var children2 = (node) => objectsIn(node.children);
|
|
2983
|
+
var typeOf = (node) => asString(node.type) ?? "";
|
|
2984
|
+
var customBlock = (node, options) => {
|
|
2985
|
+
const fields = asObject(node.fields);
|
|
2986
|
+
const blockType = fields ? asString(fields.blockType) : undefined;
|
|
2987
|
+
const serializer = blockType ? options.serializers?.[blockType] : undefined;
|
|
2988
|
+
if (fields && serializer) {
|
|
2989
|
+
return serializer(fields);
|
|
2990
|
+
}
|
|
2991
|
+
return unsupported(`Lexical block${blockType ? `: ${blockType}` : ""}`, writesMdx(options.serializers));
|
|
2992
|
+
};
|
|
2993
|
+
var renderInlines2 = (nodes, options) => nodes.map((node) => renderInlineNode2(node, options)).join("");
|
|
2994
|
+
var renderInlineNode2 = (node, options) => {
|
|
2995
|
+
switch (typeOf(node)) {
|
|
2996
|
+
case "text": {
|
|
2997
|
+
return renderInline(asString(node.text) ?? "", marksOf2(node));
|
|
2998
|
+
}
|
|
2999
|
+
case "linebreak": {
|
|
3000
|
+
return `
|
|
3001
|
+
`;
|
|
3002
|
+
}
|
|
3003
|
+
case "tab": {
|
|
3004
|
+
return "\t";
|
|
3005
|
+
}
|
|
3006
|
+
case "link":
|
|
3007
|
+
case "autolink": {
|
|
3008
|
+
return renderLink(renderInlines2(children2(node), options), asString(getPath(node, "fields.url")) ?? asString(node.url));
|
|
3009
|
+
}
|
|
3010
|
+
case "inlineBlock": {
|
|
3011
|
+
return customBlock(node, options);
|
|
3012
|
+
}
|
|
3013
|
+
default: {
|
|
3014
|
+
return renderInlines2(children2(node), options);
|
|
3015
|
+
}
|
|
3016
|
+
}
|
|
3017
|
+
};
|
|
3018
|
+
var renderUpload = (node, options) => {
|
|
3019
|
+
const value = asObject(node.value);
|
|
3020
|
+
const url = value ? asString(value.url) : undefined;
|
|
3021
|
+
if (!(value && url)) {
|
|
3022
|
+
return unsupported("Lexical upload (fetch with depth 1 to populate it)", writesMdx(options.serializers));
|
|
3023
|
+
}
|
|
3024
|
+
const alt = asString(value.alt) ?? asString(value.filename) ?? "";
|
|
3025
|
+
return image(alt, absoluteUrl(url, options.baseUrl));
|
|
3026
|
+
};
|
|
3027
|
+
var renderList2 = (node, options) => {
|
|
3028
|
+
const listType = asString(node.listType) ?? "bullet";
|
|
3029
|
+
const start = asNumber(node.start) ?? 1;
|
|
3030
|
+
const items = [];
|
|
3031
|
+
let lastMarker = "-";
|
|
3032
|
+
let index = 0;
|
|
3033
|
+
for (const item of children2(node)) {
|
|
3034
|
+
const kids = children2(item);
|
|
3035
|
+
const nested = kids.filter((kid) => typeOf(kid) === "list");
|
|
3036
|
+
const inline = kids.filter((kid) => typeOf(kid) !== "list");
|
|
3037
|
+
const sub = nested.map((list) => renderList2(list, options)).join(`
|
|
3038
|
+
`);
|
|
3039
|
+
if (inline.length === 0 && nested.length > 0) {
|
|
3040
|
+
items.push(items.length > 0 ? indent(sub, lastMarker.length + 1) : sub);
|
|
3041
|
+
continue;
|
|
3042
|
+
}
|
|
3043
|
+
lastMarker = listType === "number" ? `${start + index}.` : "-";
|
|
3044
|
+
let check = "";
|
|
3045
|
+
if (listType === "check") {
|
|
3046
|
+
check = item.checked === true ? "[x] " : "[ ] ";
|
|
3047
|
+
}
|
|
3048
|
+
const line = `${check}${renderInlines2(inline, options)}`;
|
|
3049
|
+
items.push(listItem(lastMarker, sub ? `${line}
|
|
3050
|
+
${sub}` : line));
|
|
3051
|
+
index += 1;
|
|
3052
|
+
}
|
|
3053
|
+
return items.join(`
|
|
3054
|
+
`);
|
|
3055
|
+
};
|
|
3056
|
+
var renderBlock2 = (node, options) => {
|
|
3057
|
+
switch (typeOf(node)) {
|
|
3058
|
+
case "paragraph": {
|
|
3059
|
+
return renderInlines2(children2(node), options);
|
|
3060
|
+
}
|
|
3061
|
+
case "heading": {
|
|
3062
|
+
const level = Number((asString(node.tag) ?? "h1").slice(1));
|
|
3063
|
+
return `${headingPrefix(level)}${renderInlines2(children2(node), options)}`;
|
|
3064
|
+
}
|
|
3065
|
+
case "quote": {
|
|
3066
|
+
return blockquote(renderInlines2(children2(node), options));
|
|
3067
|
+
}
|
|
3068
|
+
case "list": {
|
|
3069
|
+
return renderList2(node, options);
|
|
3070
|
+
}
|
|
3071
|
+
case "horizontalrule": {
|
|
3072
|
+
return "---";
|
|
3073
|
+
}
|
|
3074
|
+
case "upload": {
|
|
3075
|
+
return renderUpload(node, options);
|
|
3076
|
+
}
|
|
3077
|
+
case "block": {
|
|
3078
|
+
return customBlock(node, options);
|
|
3079
|
+
}
|
|
3080
|
+
default: {
|
|
3081
|
+
return unsupported(`Lexical node: ${typeOf(node)}`, writesMdx(options.serializers));
|
|
3082
|
+
}
|
|
3083
|
+
}
|
|
3084
|
+
};
|
|
3085
|
+
var lexicalToMarkdown = (state, options = {}) => {
|
|
3086
|
+
const root = asObject(state.root) ?? state;
|
|
3087
|
+
return markdownDocument(children2(root).map((node) => renderBlock2(node, options)));
|
|
3088
|
+
};
|
|
3089
|
+
|
|
3090
|
+
// src/core/sources/payload.ts
|
|
3091
|
+
var PAGE_SIZE2 = 100;
|
|
3092
|
+
var DEFAULT_FIELDS2 = {
|
|
3093
|
+
body: "content",
|
|
3094
|
+
description: "description",
|
|
3095
|
+
lastModified: "updatedAt",
|
|
3096
|
+
slug: "slug",
|
|
3097
|
+
title: "title"
|
|
3098
|
+
};
|
|
3099
|
+
var payloadSource = (options, ctx) => {
|
|
3100
|
+
const fields = { ...DEFAULT_FIELDS2, ...options.fields };
|
|
3101
|
+
const origin = options.url.replace(/\/+$/u, "");
|
|
3102
|
+
const lower = (body) => lexicalToMarkdown(body, {
|
|
3103
|
+
baseUrl: origin,
|
|
3104
|
+
serializers: options.serializers
|
|
3105
|
+
});
|
|
3106
|
+
const fetchEntries = async () => {
|
|
3107
|
+
const preview = ctx?.preview ?? false;
|
|
3108
|
+
const token = options.token ?? process.env.PAYLOAD_API_KEY;
|
|
3109
|
+
const client = {
|
|
3110
|
+
fetchImpl: options.fetchImpl,
|
|
3111
|
+
headers: token ? {
|
|
3112
|
+
authorization: `${options.authCollection ?? "users"} API-Key ${token}`
|
|
3113
|
+
} : {}
|
|
3114
|
+
};
|
|
3115
|
+
const base = `${origin}/api/${options.collection}`;
|
|
3116
|
+
const entries = [];
|
|
3117
|
+
let page = 1;
|
|
3118
|
+
let more = true;
|
|
3119
|
+
while (more) {
|
|
3120
|
+
const query = queryString({
|
|
3121
|
+
...options.params,
|
|
3122
|
+
depth: String(options.depth ?? 1),
|
|
3123
|
+
draft: preview ? "true" : undefined,
|
|
3124
|
+
limit: String(PAGE_SIZE2),
|
|
3125
|
+
page: String(page)
|
|
3126
|
+
});
|
|
3127
|
+
const result = asObject(await fetchJson(`${base}?${query}`, client));
|
|
3128
|
+
if (!result) {
|
|
3129
|
+
throw new Error("Payload returned a non-object response");
|
|
3130
|
+
}
|
|
3131
|
+
for (const doc of objectsIn(result.docs)) {
|
|
3132
|
+
const draft = asString(doc._status) === "draft";
|
|
3133
|
+
if (draft && !preview) {
|
|
3134
|
+
continue;
|
|
3135
|
+
}
|
|
3136
|
+
const id = asString(doc.id) ?? String(doc.id ?? "");
|
|
3137
|
+
entries.push(documentEntry(doc, fields, id, (body) => isJsonObject(body) ? lower(body) : "", draft, writesMdx(options.serializers)));
|
|
3138
|
+
}
|
|
3139
|
+
more = result.hasNextPage === true;
|
|
3140
|
+
page += 1;
|
|
3141
|
+
}
|
|
3142
|
+
return entries;
|
|
3143
|
+
};
|
|
3144
|
+
return remoteSource({
|
|
3145
|
+
fetchEntries,
|
|
3146
|
+
name: options.name,
|
|
3147
|
+
pollInterval: options.pollInterval,
|
|
3148
|
+
prefix: options.prefix
|
|
3149
|
+
}, ctx);
|
|
3150
|
+
};
|
|
3151
|
+
|
|
4753
3152
|
// src/core/sources/sanity.ts
|
|
4754
|
-
import { join as
|
|
3153
|
+
import { join as join6 } from "pathe";
|
|
4755
3154
|
|
|
4756
3155
|
// src/core/sources/portable-text.ts
|
|
4757
3156
|
var HEADING_STYLES = new Map([
|
|
@@ -4762,11 +3161,9 @@ var HEADING_STYLES = new Map([
|
|
|
4762
3161
|
["h5", "##### "],
|
|
4763
3162
|
["h6", "###### "]
|
|
4764
3163
|
]);
|
|
4765
|
-
var MARKDOWN_SPECIALS = /[\\`*_[\]~<]/gu;
|
|
4766
|
-
var escapeText = (text) => text.replaceAll(MARKDOWN_SPECIALS, String.raw`\$&`);
|
|
4767
3164
|
var renderSpan = (span, defs) => {
|
|
4768
3165
|
const isCode = span.marks?.includes("code") ?? false;
|
|
4769
|
-
let text = isCode ? span.text ?? "" :
|
|
3166
|
+
let text = isCode ? span.text ?? "" : escapeMarkdownText(span.text ?? "");
|
|
4770
3167
|
if (!span.marks || span.marks.length === 0) {
|
|
4771
3168
|
return text;
|
|
4772
3169
|
}
|
|
@@ -4804,7 +3201,7 @@ var renderChildren = (block) => {
|
|
|
4804
3201
|
return (block.children ?? []).map((span) => renderSpan(span, defs)).join("");
|
|
4805
3202
|
};
|
|
4806
3203
|
var isAltText = (value) => typeof value === "string";
|
|
4807
|
-
var
|
|
3204
|
+
var renderBlock3 = (block, options) => {
|
|
4808
3205
|
const custom = options.serializers?.[block._type];
|
|
4809
3206
|
if (custom) {
|
|
4810
3207
|
return custom(block);
|
|
@@ -4812,10 +3209,10 @@ var renderBlock = (block, options) => {
|
|
|
4812
3209
|
if (block._type === "image") {
|
|
4813
3210
|
const url = options.imageUrl?.(block);
|
|
4814
3211
|
const alt = isAltText(block.alt) ? block.alt : "";
|
|
4815
|
-
return url ?
|
|
3212
|
+
return url ? image(alt, url) : "";
|
|
4816
3213
|
}
|
|
4817
3214
|
if (block._type !== "block") {
|
|
4818
|
-
return
|
|
3215
|
+
return unsupported(`Portable Text block: ${block._type}`, writesMdx(options.serializers));
|
|
4819
3216
|
}
|
|
4820
3217
|
const inline = renderChildren(block);
|
|
4821
3218
|
if (block.listItem) {
|
|
@@ -4829,7 +3226,7 @@ var renderBlock = (block, options) => {
|
|
|
4829
3226
|
return `${HEADING_STYLES.get(block.style ?? "normal") ?? ""}${inline}`;
|
|
4830
3227
|
};
|
|
4831
3228
|
var portableTextToMarkdown = (blocks, options = {}) => {
|
|
4832
|
-
const lines = blocks.map((block) =>
|
|
3229
|
+
const lines = blocks.map((block) => renderBlock3(block, options));
|
|
4833
3230
|
const out = [];
|
|
4834
3231
|
for (let i = 0;i < lines.length; i += 1) {
|
|
4835
3232
|
const line = lines[i] ?? "";
|
|
@@ -4849,20 +3246,6 @@ var portableTextToMarkdown = (blocks, options = {}) => {
|
|
|
4849
3246
|
|
|
4850
3247
|
// src/core/sources/sanity.ts
|
|
4851
3248
|
var IMAGE_REF = /^image-(?<id>[a-f0-9]+)-(?<dims>\d+x\d+)-(?<ext>\w+)$/u;
|
|
4852
|
-
var isTraversable = (value) => typeof value === "object" && value !== null;
|
|
4853
|
-
var getPath = (doc, path) => {
|
|
4854
|
-
let current = doc;
|
|
4855
|
-
for (const key of path.split(".")) {
|
|
4856
|
-
if (isTraversable(current)) {
|
|
4857
|
-
current = current[key];
|
|
4858
|
-
} else {
|
|
4859
|
-
return;
|
|
4860
|
-
}
|
|
4861
|
-
}
|
|
4862
|
-
return current;
|
|
4863
|
-
};
|
|
4864
|
-
var isStringValue2 = (value) => typeof value === "string";
|
|
4865
|
-
var asString = (value) => isStringValue2(value) ? value : undefined;
|
|
4866
3249
|
var imageUrlFromRef = (ref, projectId, dataset) => {
|
|
4867
3250
|
const match = ref.match(IMAGE_REF);
|
|
4868
3251
|
if (!match?.groups) {
|
|
@@ -4871,13 +3254,13 @@ var imageUrlFromRef = (ref, projectId, dataset) => {
|
|
|
4871
3254
|
const { id, dims, ext } = match.groups;
|
|
4872
3255
|
return `https://cdn.sanity.io/images/${projectId}/${dataset}/${id}-${dims}.${ext}`;
|
|
4873
3256
|
};
|
|
4874
|
-
var resolveClient =
|
|
3257
|
+
var resolveClient = (options, preview) => {
|
|
4875
3258
|
if (options.client) {
|
|
4876
3259
|
return options.client;
|
|
4877
3260
|
}
|
|
4878
3261
|
let createClient;
|
|
4879
3262
|
try {
|
|
4880
|
-
({ createClient } =
|
|
3263
|
+
({ createClient } = nodeRequire("@sanity/client"));
|
|
4881
3264
|
} catch {
|
|
4882
3265
|
throw new BlumeError({
|
|
4883
3266
|
code: "BLUME_SOURCE_SDK_MISSING",
|
|
@@ -4896,11 +3279,11 @@ var resolveClient = async (options, preview) => {
|
|
|
4896
3279
|
};
|
|
4897
3280
|
var sanitySource = (options, ctx) => {
|
|
4898
3281
|
const fields = options.fields ?? {};
|
|
4899
|
-
const cache = snapshotCache(ctx?.cacheDir ??
|
|
3282
|
+
const cache = snapshotCache(ctx?.cacheDir ?? join6(".blume", "cache", options.name));
|
|
4900
3283
|
let snapshot = new Map;
|
|
4901
3284
|
const toEntry = (doc) => {
|
|
4902
3285
|
const slugValue = asString(getPath(doc, fields.slug ?? "slug.current")) ?? asString(doc._id) ?? "untitled";
|
|
4903
|
-
const slug = slugifyPath(slugValue) ||
|
|
3286
|
+
const slug = slugifyPath(slugValue) || slugify(asString(doc._id) ?? "") || "untitled";
|
|
4904
3287
|
const data = {};
|
|
4905
3288
|
const title = asString(getPath(doc, fields.title ?? "title"));
|
|
4906
3289
|
const description = asString(getPath(doc, fields.description ?? "description"));
|
|
@@ -4918,19 +3301,20 @@ var sanitySource = (options, ctx) => {
|
|
|
4918
3301
|
},
|
|
4919
3302
|
serializers: options.serializers
|
|
4920
3303
|
}) : "";
|
|
3304
|
+
const format = writesMdx(options.serializers) ? "mdx" : "md";
|
|
4921
3305
|
const raw = frontmatter_default.stringify(markdown, data);
|
|
4922
3306
|
return {
|
|
4923
|
-
body: { format
|
|
3307
|
+
body: { format, text: markdown },
|
|
4924
3308
|
data: { ...data },
|
|
4925
3309
|
hash: hashText(raw),
|
|
4926
3310
|
lastModified: asString(getPath(doc, fields.lastModified ?? "_updatedAt")),
|
|
4927
3311
|
raw,
|
|
4928
|
-
ref: `${slug}
|
|
3312
|
+
ref: `${slug}.${format}`
|
|
4929
3313
|
};
|
|
4930
3314
|
};
|
|
4931
3315
|
const load = async (refresh = ctx?.refresh ?? true) => {
|
|
4932
3316
|
const result = await loadWithCache(options.name, cache, async () => {
|
|
4933
|
-
const client =
|
|
3317
|
+
const client = resolveClient(options, ctx?.preview ?? false);
|
|
4934
3318
|
const docs = await client.fetch(options.query);
|
|
4935
3319
|
return docs.map(toEntry);
|
|
4936
3320
|
}, refresh);
|
|
@@ -4955,6 +3339,162 @@ var sanitySource = (options, ctx) => {
|
|
|
4955
3339
|
};
|
|
4956
3340
|
};
|
|
4957
3341
|
|
|
3342
|
+
// src/core/sources/strapi-blocks.ts
|
|
3343
|
+
var children3 = (node) => objectsIn(node.children);
|
|
3344
|
+
var typeOf2 = (node) => asString(node.type) ?? "";
|
|
3345
|
+
var renderInlines3 = (nodes) => nodes.map((node) => renderInlineNode3(node)).join("");
|
|
3346
|
+
var renderInlineNode3 = (node) => {
|
|
3347
|
+
switch (typeOf2(node)) {
|
|
3348
|
+
case "text": {
|
|
3349
|
+
return renderInline(asString(node.text) ?? "", {
|
|
3350
|
+
bold: node.bold === true,
|
|
3351
|
+
code: node.code === true,
|
|
3352
|
+
italic: node.italic === true,
|
|
3353
|
+
strike: node.strikethrough === true
|
|
3354
|
+
});
|
|
3355
|
+
}
|
|
3356
|
+
case "link": {
|
|
3357
|
+
return renderLink(renderInlines3(children3(node)), asString(node.url));
|
|
3358
|
+
}
|
|
3359
|
+
default: {
|
|
3360
|
+
return renderInlines3(children3(node));
|
|
3361
|
+
}
|
|
3362
|
+
}
|
|
3363
|
+
};
|
|
3364
|
+
var renderList3 = (node) => {
|
|
3365
|
+
const ordered = asString(node.format) === "ordered";
|
|
3366
|
+
return children3(node).map((item, index) => {
|
|
3367
|
+
const kids = children3(item);
|
|
3368
|
+
const line = renderInlines3(kids.filter((kid) => typeOf2(kid) !== "list"));
|
|
3369
|
+
const sub = kids.filter((kid) => typeOf2(kid) === "list").map((list) => renderList3(list)).join(`
|
|
3370
|
+
`);
|
|
3371
|
+
const body = sub ? `${line}
|
|
3372
|
+
${sub}` : line;
|
|
3373
|
+
return listItem(ordered ? `${index + 1}.` : "-", body);
|
|
3374
|
+
}).join(`
|
|
3375
|
+
`);
|
|
3376
|
+
};
|
|
3377
|
+
var renderImage = (node, options) => {
|
|
3378
|
+
const file = asObject(node.image);
|
|
3379
|
+
const url = file ? asString(file.url) : undefined;
|
|
3380
|
+
if (!(file && url)) {
|
|
3381
|
+
return "";
|
|
3382
|
+
}
|
|
3383
|
+
return image(asString(file.alternativeText) ?? asString(file.name) ?? "", absoluteUrl(url, options.baseUrl));
|
|
3384
|
+
};
|
|
3385
|
+
var renderBlock4 = (node, options) => {
|
|
3386
|
+
switch (typeOf2(node)) {
|
|
3387
|
+
case "paragraph": {
|
|
3388
|
+
return renderInlines3(children3(node));
|
|
3389
|
+
}
|
|
3390
|
+
case "heading": {
|
|
3391
|
+
return `${headingPrefix(asNumber(node.level) ?? 1)}${renderInlines3(children3(node))}`;
|
|
3392
|
+
}
|
|
3393
|
+
case "quote": {
|
|
3394
|
+
return blockquote(renderInlines3(children3(node)));
|
|
3395
|
+
}
|
|
3396
|
+
case "list": {
|
|
3397
|
+
return renderList3(node);
|
|
3398
|
+
}
|
|
3399
|
+
case "code": {
|
|
3400
|
+
const code = children3(node).map((child) => asString(child.text) ?? "").join("");
|
|
3401
|
+
return codeFence(code, asString(node.language) ?? "");
|
|
3402
|
+
}
|
|
3403
|
+
case "image": {
|
|
3404
|
+
return renderImage(node, options);
|
|
3405
|
+
}
|
|
3406
|
+
default: {
|
|
3407
|
+
return unsupported(`Strapi block: ${typeOf2(node)}`);
|
|
3408
|
+
}
|
|
3409
|
+
}
|
|
3410
|
+
};
|
|
3411
|
+
var strapiBlocksToMarkdown = (blocks, options = {}) => markdownDocument(objectsIn(blocks).map((node) => renderBlock4(node, options)));
|
|
3412
|
+
|
|
3413
|
+
// src/core/sources/strapi.ts
|
|
3414
|
+
var PAGE_SIZE3 = 100;
|
|
3415
|
+
var DEFAULT_FIELDS3 = {
|
|
3416
|
+
body: "content",
|
|
3417
|
+
description: "description",
|
|
3418
|
+
lastModified: "updatedAt",
|
|
3419
|
+
slug: "slug",
|
|
3420
|
+
title: "title"
|
|
3421
|
+
};
|
|
3422
|
+
var flatten = (item) => {
|
|
3423
|
+
const attributes = asObject(item.attributes);
|
|
3424
|
+
return attributes ? { ...attributes, id: item.id ?? null } : item;
|
|
3425
|
+
};
|
|
3426
|
+
var idOf = (doc) => {
|
|
3427
|
+
const raw = doc.documentId ?? doc.id;
|
|
3428
|
+
return asString(raw) ?? String(asNumber(raw) ?? "");
|
|
3429
|
+
};
|
|
3430
|
+
var unpublished = (doc) => doc.publishedAt === null;
|
|
3431
|
+
var strapiSource = (options, ctx) => {
|
|
3432
|
+
const fields = { ...DEFAULT_FIELDS3, ...options.fields };
|
|
3433
|
+
const origin = options.url.replace(/\/+$/u, "");
|
|
3434
|
+
const fetchEntries = async () => {
|
|
3435
|
+
const token = options.token ?? process.env.STRAPI_API_TOKEN;
|
|
3436
|
+
const client = {
|
|
3437
|
+
fetchImpl: options.fetchImpl,
|
|
3438
|
+
headers: token ? { authorization: `Bearer ${token}` } : {}
|
|
3439
|
+
};
|
|
3440
|
+
const base = `${origin}/api/${options.contentType}`;
|
|
3441
|
+
const list = async (publication) => {
|
|
3442
|
+
const listing = { docs: [], v4: false };
|
|
3443
|
+
let page = 1;
|
|
3444
|
+
let more = true;
|
|
3445
|
+
while (more) {
|
|
3446
|
+
const query = queryString({
|
|
3447
|
+
...options.params,
|
|
3448
|
+
locale: options.locale,
|
|
3449
|
+
"pagination[pageSize]": String(PAGE_SIZE3),
|
|
3450
|
+
"pagination[page]": String(page),
|
|
3451
|
+
populate: options.populate ?? "*",
|
|
3452
|
+
...publication
|
|
3453
|
+
});
|
|
3454
|
+
const result = asObject(await fetchJson(`${base}?${query}`, client));
|
|
3455
|
+
if (!result) {
|
|
3456
|
+
throw new Error("Strapi returned a non-object response");
|
|
3457
|
+
}
|
|
3458
|
+
const items = objectsIn(result.data);
|
|
3459
|
+
for (const item of items) {
|
|
3460
|
+
listing.v4 ||= asObject(item.attributes) !== undefined;
|
|
3461
|
+
listing.docs.push(flatten(item));
|
|
3462
|
+
}
|
|
3463
|
+
const pageCount = asNumber(getPath(result, "meta.pagination.pageCount")) ?? 1;
|
|
3464
|
+
more = items.length > 0 && page < pageCount;
|
|
3465
|
+
page += 1;
|
|
3466
|
+
}
|
|
3467
|
+
return listing;
|
|
3468
|
+
};
|
|
3469
|
+
const toEntries = (docs, isDraft) => docs.map((doc) => documentEntry(doc, fields, idOf(doc), (body) => strapiBlocksToMarkdown(body, { baseUrl: origin }), isDraft(doc)));
|
|
3470
|
+
const published = await list({});
|
|
3471
|
+
if (!ctx?.preview) {
|
|
3472
|
+
return toEntries(published.docs, () => false);
|
|
3473
|
+
}
|
|
3474
|
+
if (published.v4) {
|
|
3475
|
+
const previewed = await list({ publicationState: "preview" });
|
|
3476
|
+
return toEntries(previewed.docs, unpublished);
|
|
3477
|
+
}
|
|
3478
|
+
const drafts = await list({ status: "draft" });
|
|
3479
|
+
if (drafts.docs.length === 0 && published.docs.length === 0) {
|
|
3480
|
+
const previewed = await list({ publicationState: "preview" }).catch(() => null);
|
|
3481
|
+
return previewed ? toEntries(previewed.docs, unpublished) : [];
|
|
3482
|
+
}
|
|
3483
|
+
const publishedIds = new Set(published.docs.map(idOf));
|
|
3484
|
+
const draftIds = new Set(drafts.docs.map(idOf));
|
|
3485
|
+
return [
|
|
3486
|
+
...toEntries(drafts.docs, (doc) => !publishedIds.has(idOf(doc))),
|
|
3487
|
+
...toEntries(published.docs.filter((doc) => !draftIds.has(idOf(doc))), () => false)
|
|
3488
|
+
];
|
|
3489
|
+
};
|
|
3490
|
+
return remoteSource({
|
|
3491
|
+
fetchEntries,
|
|
3492
|
+
name: options.name,
|
|
3493
|
+
pollInterval: options.pollInterval,
|
|
3494
|
+
prefix: options.prefix
|
|
3495
|
+
}, ctx);
|
|
3496
|
+
};
|
|
3497
|
+
|
|
4958
3498
|
// src/core/sources/resolve.ts
|
|
4959
3499
|
var uniqueNamer = () => {
|
|
4960
3500
|
const used = new Set;
|
|
@@ -4971,8 +3511,8 @@ var uniqueNamer = () => {
|
|
|
4971
3511
|
};
|
|
4972
3512
|
var sourceContext = (context, name, runtime) => ({
|
|
4973
3513
|
assetsBaseUrl: `/blume-assets/${name}`,
|
|
4974
|
-
assetsDir:
|
|
4975
|
-
cacheDir:
|
|
3514
|
+
assetsDir: join7(context.outDir, "public", "blume-assets", name),
|
|
3515
|
+
cacheDir: join7(context.outDir, "cache", name),
|
|
4976
3516
|
mode: runtime.mode,
|
|
4977
3517
|
preview: runtime.preview,
|
|
4978
3518
|
projectRoot: context.root,
|
|
@@ -4982,119 +3522,61 @@ var typeFrontmatterKeys = (config) => Object.fromEntries(Object.entries(config.c
|
|
|
4982
3522
|
type,
|
|
4983
3523
|
Object.keys(def.frontmatter)
|
|
4984
3524
|
]));
|
|
4985
|
-
var buildSource = (
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
|
|
4994
|
-
}
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
|
|
5001
|
-
|
|
5002
|
-
|
|
5003
|
-
|
|
5004
|
-
|
|
5005
|
-
|
|
5006
|
-
|
|
5007
|
-
|
|
5008
|
-
|
|
5009
|
-
}
|
|
5010
|
-
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
name,
|
|
5029
|
-
prefix: def.prefix,
|
|
5030
|
-
typeFrontmatterKeys: typeFrontmatterKeys(config),
|
|
5031
|
-
vault: def.vault,
|
|
5032
|
-
versions: config.versions
|
|
5033
|
-
}, sourceContext(context, name, runtime));
|
|
5034
|
-
}
|
|
5035
|
-
if (def.type === "github-releases") {
|
|
5036
|
-
return githubReleasesSource({
|
|
5037
|
-
drafts: def.drafts,
|
|
5038
|
-
limit: def.limit,
|
|
5039
|
-
name,
|
|
5040
|
-
owner: def.owner,
|
|
5041
|
-
pollInterval: def.pollInterval,
|
|
5042
|
-
prefix: def.prefix,
|
|
5043
|
-
prereleases: def.prereleases,
|
|
5044
|
-
repo: def.repo
|
|
5045
|
-
}, sourceContext(context, name, runtime));
|
|
5046
|
-
}
|
|
5047
|
-
return mdxRemoteSource({
|
|
5048
|
-
files: def.files,
|
|
5049
|
-
github: def.github,
|
|
5050
|
-
include: def.include,
|
|
5051
|
-
name,
|
|
5052
|
-
pollInterval: def.pollInterval,
|
|
5053
|
-
prefix: def.prefix,
|
|
5054
|
-
url: def.url
|
|
5055
|
-
}, sourceContext(context, name, runtime));
|
|
5056
|
-
};
|
|
5057
|
-
var resolveRoot = (projectRoot, root) => isAbsolute4(root) ? root : join9(resolve4(projectRoot), root);
|
|
5058
|
-
var resolveDocsCollection = (config, context) => {
|
|
5059
|
-
const filesystem = (config.content.sources ?? []).filter((def) => def.type === "filesystem");
|
|
5060
|
-
const only = filesystem.length === 1 ? filesystem[0] : undefined;
|
|
5061
|
-
if (only) {
|
|
5062
|
-
return {
|
|
5063
|
-
base: resolveRoot(context.root, only.root),
|
|
5064
|
-
exclude: only.exclude,
|
|
5065
|
-
include: only.include
|
|
5066
|
-
};
|
|
5067
|
-
}
|
|
5068
|
-
return {
|
|
5069
|
-
base: context.contentRoot,
|
|
5070
|
-
exclude: config.content.exclude,
|
|
5071
|
-
include: config.content.include
|
|
5072
|
-
};
|
|
5073
|
-
};
|
|
5074
|
-
var baseName = (def) => {
|
|
5075
|
-
if (def.type === "custom") {
|
|
5076
|
-
return def.source.name;
|
|
3525
|
+
var buildSource = (adapter, name, config, context, runtime) => {
|
|
3526
|
+
switch (adapter.kind) {
|
|
3527
|
+
case "filesystem": {
|
|
3528
|
+
const { pollInterval: _ignored, ...options } = adapter.options;
|
|
3529
|
+
return filesystemSource({ ...options, name, projectRoot: context.root });
|
|
3530
|
+
}
|
|
3531
|
+
case "custom": {
|
|
3532
|
+
const source = adapter.options;
|
|
3533
|
+
return source.name === name ? source : { ...source, name };
|
|
3534
|
+
}
|
|
3535
|
+
case "sanity": {
|
|
3536
|
+
return sanitySource({ ...adapter.options, name }, sourceContext(context, name, runtime));
|
|
3537
|
+
}
|
|
3538
|
+
case "notion": {
|
|
3539
|
+
return notionSource({ ...adapter.options, name }, sourceContext(context, name, runtime));
|
|
3540
|
+
}
|
|
3541
|
+
case "contentful": {
|
|
3542
|
+
return contentfulSource({ ...adapter.options, name }, sourceContext(context, name, runtime));
|
|
3543
|
+
}
|
|
3544
|
+
case "payload": {
|
|
3545
|
+
return payloadSource({ ...adapter.options, name }, sourceContext(context, name, runtime));
|
|
3546
|
+
}
|
|
3547
|
+
case "strapi": {
|
|
3548
|
+
return strapiSource({ ...adapter.options, name }, sourceContext(context, name, runtime));
|
|
3549
|
+
}
|
|
3550
|
+
case "obsidian": {
|
|
3551
|
+
const { pollInterval: _ignored, ...options } = adapter.options;
|
|
3552
|
+
return obsidianSource({
|
|
3553
|
+
...options,
|
|
3554
|
+
defaultType: config.content.defaultType,
|
|
3555
|
+
frontmatterKeys: Object.keys(config.frontmatter.extend),
|
|
3556
|
+
i18n: config.i18n,
|
|
3557
|
+
name,
|
|
3558
|
+
typeFrontmatterKeys: typeFrontmatterKeys(config),
|
|
3559
|
+
versions: config.versions
|
|
3560
|
+
}, sourceContext(context, name, runtime));
|
|
3561
|
+
}
|
|
3562
|
+
case "github-releases": {
|
|
3563
|
+
return githubReleasesSource({ ...adapter.options, name }, sourceContext(context, name, runtime));
|
|
3564
|
+
}
|
|
3565
|
+
default: {
|
|
3566
|
+
break;
|
|
3567
|
+
}
|
|
5077
3568
|
}
|
|
5078
|
-
return
|
|
3569
|
+
return mdxRemoteSource({ ...adapter.options, name }, sourceContext(context, name, runtime));
|
|
5079
3570
|
};
|
|
5080
|
-
var
|
|
5081
|
-
|
|
5082
|
-
|
|
5083
|
-
return [
|
|
5084
|
-
filesystemSource({
|
|
5085
|
-
exclude: config.content.exclude,
|
|
5086
|
-
include: config.content.include,
|
|
5087
|
-
name: "filesystem",
|
|
5088
|
-
projectRoot: context.root,
|
|
5089
|
-
root: config.content.root
|
|
5090
|
-
})
|
|
5091
|
-
];
|
|
3571
|
+
var baseName = (adapter) => {
|
|
3572
|
+
if (adapter.kind === "custom") {
|
|
3573
|
+
return adapter.options.name;
|
|
5092
3574
|
}
|
|
5093
|
-
|
|
5094
|
-
return defs.map((def) => buildSource(def, nameFor(baseName(def)), config, context, runtime));
|
|
3575
|
+
return adapter.options.prefix ?? adapter.kind;
|
|
5095
3576
|
};
|
|
5096
3577
|
var resolveSources = (config, context, runtime) => {
|
|
5097
|
-
const
|
|
3578
|
+
const nameFor = uniqueNamer();
|
|
3579
|
+
const sources = config.content.sources.map((adapter) => buildSource(adapter, nameFor(baseName(adapter)), config, context, runtime));
|
|
5098
3580
|
const references = blumeReferences(config);
|
|
5099
3581
|
if (references.length > 0) {
|
|
5100
3582
|
sources.push(openApiSource(references, sourceContext(context, "openapi", runtime)));
|
|
@@ -5104,25 +3586,18 @@ var resolveSources = (config, context, runtime) => {
|
|
|
5104
3586
|
|
|
5105
3587
|
// src/core/project-graph.ts
|
|
5106
3588
|
var isWithin = (dir, path) => {
|
|
5107
|
-
const rel =
|
|
5108
|
-
return !(rel.startsWith("..") ||
|
|
3589
|
+
const rel = relative5(dir, path);
|
|
3590
|
+
return !(rel.startsWith("..") || isAbsolute3(rel));
|
|
5109
3591
|
};
|
|
5110
3592
|
var applyConfigOverrides = (config, overrides) => {
|
|
5111
3593
|
if (!overrides) {
|
|
5112
3594
|
return config;
|
|
5113
3595
|
}
|
|
3596
|
+
const { contentRoot } = overrides;
|
|
3597
|
+
const sources = contentRoot ? config.content.sources.map((source) => source.kind === "filesystem" ? { ...source, options: { ...source.options, root: contentRoot } } : source) : config.content.sources;
|
|
5114
3598
|
return {
|
|
5115
3599
|
...config,
|
|
5116
|
-
content: {
|
|
5117
|
-
...config.content,
|
|
5118
|
-
root: overrides.contentRoot ?? config.content.root
|
|
5119
|
-
},
|
|
5120
|
-
deployment: {
|
|
5121
|
-
...config.deployment,
|
|
5122
|
-
adapter: overrides.adapter ?? config.deployment.adapter,
|
|
5123
|
-
base: overrides.base ?? config.deployment.base,
|
|
5124
|
-
output: overrides.output ?? config.deployment.output
|
|
5125
|
-
}
|
|
3600
|
+
content: { ...config.content, sources }
|
|
5126
3601
|
};
|
|
5127
3602
|
};
|
|
5128
3603
|
var entryIdDiagnostics = (pages, collectionBase) => {
|
|
@@ -5133,7 +3608,7 @@ var entryIdDiagnostics = (pages, collectionBase) => {
|
|
|
5133
3608
|
continue;
|
|
5134
3609
|
}
|
|
5135
3610
|
seen.add(page.sourcePath);
|
|
5136
|
-
const expected =
|
|
3611
|
+
const expected = relative5(collectionBase, page.sourcePath).split("\\").join("/");
|
|
5137
3612
|
const entryId = page.entryId ?? page.source.ref;
|
|
5138
3613
|
if (expected !== entryId) {
|
|
5139
3614
|
diagnostics.push({
|
|
@@ -5141,7 +3616,7 @@ var entryIdDiagnostics = (pages, collectionBase) => {
|
|
|
5141
3616
|
file: page.sourcePath,
|
|
5142
3617
|
message: `Content source "${page.source.name}" is rooted outside the docs collection base, so ${page.route} resolves entry id "${entryId}" but the collection would generate "${expected}" — the page would 404 at runtime.`,
|
|
5143
3618
|
severity: "error",
|
|
5144
|
-
suggestion: "Use a single filesystem source (the docs collection roots at it), or
|
|
3619
|
+
suggestion: "Use a single filesystem() source (the docs collection roots at it), or give every filesystem() source the same root and partition them with include globs — a root at a subdirectory of the first source's root still mismatches."
|
|
5145
3620
|
});
|
|
5146
3621
|
}
|
|
5147
3622
|
}
|
|
@@ -5163,6 +3638,7 @@ var normalizeLoadedEntries = (loaded, config) => {
|
|
|
5163
3638
|
frontmatterExtend,
|
|
5164
3639
|
i18n: config.i18n,
|
|
5165
3640
|
source: {
|
|
3641
|
+
monolingual: source.monolingual,
|
|
5166
3642
|
name: source.name,
|
|
5167
3643
|
prefix: source.prefix,
|
|
5168
3644
|
staged: source.staged
|
|
@@ -5179,13 +3655,15 @@ var normalizeLoadedEntries = (loaded, config) => {
|
|
|
5179
3655
|
}
|
|
5180
3656
|
return { diagnostics: allDiagnostics, droppedPages, pages };
|
|
5181
3657
|
};
|
|
3658
|
+
var isLogoShorthand = (logo) => typeof logo === "string";
|
|
3659
|
+
var logoHref = (logo) => logo === undefined || isLogoShorthand(logo) ? "/" : logo.href ?? "/";
|
|
5182
3660
|
var scanProject = async (root, options = {}) => {
|
|
5183
3661
|
const mode = options.mode ?? "dev";
|
|
5184
3662
|
const preview = options.preview ?? false;
|
|
5185
3663
|
const configResult = await loadConfig(root, {
|
|
5186
3664
|
devServerUrl: options.devServerUrl
|
|
5187
3665
|
});
|
|
5188
|
-
const config =
|
|
3666
|
+
const config = applyConfigOverrides(configResult.config, options.overrides);
|
|
5189
3667
|
const context = resolveProjectContext(root, config, {
|
|
5190
3668
|
runtimeDir: options.runtimeDir
|
|
5191
3669
|
});
|
|
@@ -5249,8 +3727,14 @@ var scanProject = async (root, options = {}) => {
|
|
|
5249
3727
|
const undated = pages.filter((page) => page.sourcePath && !page.lastModified && contentRoots.some((dir) => isWithin(dir, page.sourcePath ?? ""))).length;
|
|
5250
3728
|
lastModifiedWarnings.push(...lastModifiedShallowWarning(context.root, undated));
|
|
5251
3729
|
}
|
|
3730
|
+
const customPages = context.pagesRoot ? await discoverPages(context.pagesRoot) : [];
|
|
5252
3731
|
const graph = buildContentGraph(pages, {
|
|
5253
3732
|
basePath: config.basePath,
|
|
3733
|
+
brandHref: logoHref(config.logo),
|
|
3734
|
+
extraRoutes: new Set([
|
|
3735
|
+
...customStaticRoutes(customPages),
|
|
3736
|
+
...hasChangelogIndex(pages, config) ? [CHANGELOG_INDEX_ROUTE] : []
|
|
3737
|
+
]),
|
|
5254
3738
|
folderMeta: folderMeta.meta,
|
|
5255
3739
|
i18n: config.i18n,
|
|
5256
3740
|
navigation: config.navigation,
|
|
@@ -5267,7 +3751,7 @@ var scanProject = async (root, options = {}) => {
|
|
|
5267
3751
|
...contentDiagnostics,
|
|
5268
3752
|
...includeDiagnostics,
|
|
5269
3753
|
...folderMeta.diagnostics,
|
|
5270
|
-
...entryIdDiagnostics(pages, resolveDocsCollection(config, context).base),
|
|
3754
|
+
...entryIdDiagnostics(pages, resolveDocsCollection(config, context.root).base),
|
|
5271
3755
|
...graph.diagnostics,
|
|
5272
3756
|
...i18nWarnings,
|
|
5273
3757
|
...versionWarnings,
|
|
@@ -5282,7 +3766,7 @@ var scanProject = async (root, options = {}) => {
|
|
|
5282
3766
|
};
|
|
5283
3767
|
};
|
|
5284
3768
|
|
|
5285
|
-
export {
|
|
3769
|
+
export { validateSearchPopularIcons, validateNavTargets, contentIndexable, buildManifest, isWithin, scanProject };
|
|
5286
3770
|
|
|
5287
|
-
//# debugId=
|
|
5288
|
-
//# sourceMappingURL=chunk-
|
|
3771
|
+
//# debugId=EBFFBF92D39DE54464756E2164756E21
|
|
3772
|
+
//# sourceMappingURL=chunk-fs23ddbb.js.map
|