blume 1.7.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +19 -0
- package/CHANGELOG.md +227 -0
- package/README.md +34 -21
- package/dist/cli/chunk-11j0384y.js +148 -0
- package/dist/cli/chunk-11j0384y.js.map +10 -0
- package/dist/cli/{chunk-xhtpx3ff.js → chunk-1w8dp3qb.js} +17 -16
- package/dist/cli/{chunk-xhtpx3ff.js.map → chunk-1w8dp3qb.js.map} +3 -3
- package/dist/cli/chunk-2q1dwty4.js +75 -0
- package/dist/cli/chunk-2q1dwty4.js.map +11 -0
- package/dist/cli/chunk-41za066z.js +122 -0
- package/dist/cli/chunk-41za066z.js.map +11 -0
- package/dist/cli/chunk-5a2z0198.js +133 -0
- package/dist/cli/chunk-5a2z0198.js.map +10 -0
- package/dist/cli/{chunk-9he6crym.js → chunk-6k8vp3ta.js} +25 -13
- package/dist/cli/{chunk-9he6crym.js.map → chunk-6k8vp3ta.js.map} +4 -4
- package/dist/cli/{chunk-mt76t7dj.js → chunk-79njf86q.js} +133 -54
- package/dist/cli/chunk-79njf86q.js.map +11 -0
- package/dist/cli/{chunk-3w7b2vcx.js → chunk-7ez8ny0t.js} +2 -2
- package/dist/cli/{chunk-688e0dde.js → chunk-88cpgt6h.js} +1 -1
- package/dist/cli/chunk-a9kptbw5.js +361 -0
- package/dist/cli/chunk-a9kptbw5.js.map +14 -0
- package/dist/cli/chunk-abh8yjkn.js +31 -0
- package/dist/cli/chunk-abh8yjkn.js.map +10 -0
- package/dist/cli/chunk-b5aj94ah.js +91 -0
- package/dist/cli/chunk-b5aj94ah.js.map +10 -0
- package/dist/cli/{chunk-hs3gbh8p.js → chunk-bctazmbk.js} +9 -5
- package/dist/cli/chunk-bctazmbk.js.map +10 -0
- package/dist/cli/chunk-beat36xx.js +279 -0
- package/dist/cli/chunk-beat36xx.js.map +10 -0
- package/dist/cli/chunk-bnbmcwfb.js +145 -0
- package/dist/cli/chunk-bnbmcwfb.js.map +11 -0
- package/dist/cli/{chunk-9bkjd11x.js → chunk-bw22s759.js} +15 -5
- package/dist/cli/{chunk-9bkjd11x.js.map → chunk-bw22s759.js.map} +4 -4
- package/dist/cli/chunk-by2290sx.js +39 -0
- package/dist/cli/chunk-by2290sx.js.map +10 -0
- package/dist/cli/chunk-d1tadaw7.js +79 -0
- package/dist/cli/chunk-d1tadaw7.js.map +10 -0
- package/dist/cli/{chunk-t3tj0dgr.js → chunk-d80hr03s.js} +24 -19
- package/dist/cli/chunk-d80hr03s.js.map +15 -0
- package/dist/cli/chunk-ernrthtr.js +97 -0
- package/dist/cli/chunk-ernrthtr.js.map +10 -0
- package/dist/cli/chunk-f2972sbt.js +374 -0
- package/dist/cli/chunk-f2972sbt.js.map +10 -0
- package/dist/cli/{chunk-exeeb35e.js → chunk-f7t03s3g.js} +2 -2
- package/dist/cli/{chunk-2z47ypj8.js → chunk-fa25z98p.js} +16 -3
- package/dist/cli/chunk-fa25z98p.js.map +11 -0
- package/dist/cli/{chunk-12dxjqk7.js → chunk-fh5hj5jt.js} +44 -21
- package/dist/cli/chunk-fh5hj5jt.js.map +10 -0
- package/dist/cli/{chunk-8cd8tj54.js → chunk-j8mw0za6.js} +86 -57
- package/dist/cli/chunk-j8mw0za6.js.map +35 -0
- package/dist/cli/chunk-jts8mvcz.js +106 -0
- package/dist/cli/{chunk-2mzebbbz.js.map → chunk-jts8mvcz.js.map} +6 -4
- package/dist/cli/{chunk-ejjx8znq.js → chunk-mnqj32sj.js} +505 -536
- package/dist/cli/chunk-mnqj32sj.js.map +12 -0
- package/dist/cli/{chunk-196vjxp9.js → chunk-mwt1k8n7.js} +100 -372
- package/dist/cli/chunk-mwt1k8n7.js.map +10 -0
- package/dist/cli/chunk-nk3ts2xk.js +51 -0
- package/dist/cli/chunk-nk3ts2xk.js.map +10 -0
- package/dist/cli/{chunk-n9sra6sy.js → chunk-pat2zzwc.js} +10 -14
- package/dist/cli/{chunk-n9sra6sy.js.map → chunk-pat2zzwc.js.map} +2 -2
- package/dist/cli/chunk-pnnvybbk.js +176 -0
- package/dist/cli/chunk-pnnvybbk.js.map +11 -0
- package/dist/cli/{chunk-cvky9gb2.js → chunk-sqn5t4q0.js} +81 -87
- package/dist/cli/chunk-sqn5t4q0.js.map +10 -0
- package/dist/cli/{chunk-eevwt1sc.js → chunk-tzne8qfq.js} +15 -15
- package/dist/cli/{chunk-eevwt1sc.js.map → chunk-tzne8qfq.js.map} +1 -1
- package/dist/cli/chunk-xaz13gwg.js +12449 -0
- package/dist/cli/chunk-xaz13gwg.js.map +182 -0
- package/dist/cli/chunk-y3e45rc8.js +102 -0
- package/dist/cli/chunk-y3e45rc8.js.map +10 -0
- package/dist/cli/chunk-z01ze5c1.js +261 -0
- package/dist/cli/chunk-z01ze5c1.js.map +10 -0
- package/dist/cli/{chunk-5n7t497w.js → chunk-z1f5arsg.js} +247 -755
- package/dist/cli/chunk-z1f5arsg.js.map +36 -0
- package/dist/cli/{chunk-hdm2dkd2.js → chunk-zg2gtj10.js} +1086 -2596
- package/dist/cli/chunk-zg2gtj10.js.map +35 -0
- package/dist/cli/{chunk-ppfvdcd4.js → chunk-zxccj738.js} +1 -1
- package/dist/cli/index.js +214 -57
- package/dist/cli/index.js.map +8 -7
- package/dist/types/ai/agent-readability.d.ts +52 -0
- package/dist/types/ai/ai-catalog.d.ts +42 -0
- package/dist/types/ai/api/paths.d.ts +17 -0
- package/dist/types/ai/api-catalog.d.ts +18 -0
- package/dist/types/ai/ask.d.ts +368 -0
- package/dist/types/ai/changelog-markdown.d.ts +2 -0
- package/dist/types/ai/component-markdown.d.ts +2 -2
- package/dist/types/ai/index.d.ts +24 -0
- package/dist/types/ai/link-headers.d.ts +24 -0
- package/dist/types/ai/llms.d.ts +25 -0
- package/dist/types/ai/markdown.d.ts +45 -0
- package/dist/types/ai/mcp/discovery.d.ts +68 -0
- package/dist/types/ai/mcp/tools.d.ts +16 -0
- package/dist/types/ai/openapi-components.d.ts +43 -0
- package/dist/types/ai/relative-links.d.ts +26 -0
- package/dist/types/ai/serializers.d.ts +15 -0
- package/dist/types/ai/skills.d.ts +42 -0
- package/dist/types/ai/tar.d.ts +25 -0
- package/dist/types/ai/visibility.d.ts +17 -0
- package/dist/types/ai/web-bot-auth.d.ts +16 -0
- package/dist/types/analytics/adobe.d.ts +35 -0
- package/dist/types/analytics/amplitude.d.ts +50 -0
- package/dist/types/analytics/clarity.d.ts +31 -0
- package/dist/types/analytics/clearbit.d.ts +29 -0
- package/dist/types/analytics/cloudflare.d.ts +41 -0
- package/dist/types/analytics/fathom.d.ts +41 -0
- package/dist/types/analytics/google-analytics.d.ts +44 -0
- package/dist/types/analytics/google-tag-manager.d.ts +40 -0
- package/dist/types/analytics/head.d.ts +30 -0
- package/dist/types/analytics/heap.d.ts +40 -0
- package/dist/types/analytics/hightouch.d.ts +44 -0
- package/dist/types/analytics/hotjar.d.ts +33 -0
- package/dist/types/analytics/index.d.ts +61 -0
- package/dist/types/analytics/inline.d.ts +17 -0
- package/dist/types/analytics/logrocket.d.ts +44 -0
- package/dist/types/analytics/mixpanel.d.ts +67 -0
- package/dist/types/analytics/pirsch.d.ts +42 -0
- package/dist/types/analytics/plausible.d.ts +56 -0
- package/dist/types/analytics/posthog.d.ts +45 -0
- package/dist/types/analytics/schema.d.ts +320 -0
- package/dist/types/analytics/script.d.ts +46 -0
- package/dist/types/analytics/segment.d.ts +50 -0
- package/dist/types/analytics/vercel.d.ts +48 -0
- package/dist/types/astro/integration.d.ts +76 -0
- package/dist/types/astro/markdown-negotiation.d.ts +23 -0
- package/dist/types/astro/module-types.d.ts +14 -0
- package/dist/types/astro/pages.d.ts +44 -0
- package/dist/types/cli/env.d.ts +12 -0
- package/dist/types/cli/init/scaffold.d.ts +154 -0
- package/dist/types/components/layout/nav-utils.d.ts +11 -0
- package/dist/types/core/adapter.d.ts +47 -0
- package/dist/types/core/api-name.d.ts +7 -0
- package/dist/types/core/changelog-index.d.ts +13 -0
- package/dist/types/core/config-input.d.ts +209 -505
- package/dist/types/core/config.d.ts +60 -34
- package/dist/types/core/content-assets.d.ts +76 -0
- package/dist/types/core/custom-pages.d.ts +33 -0
- package/dist/types/core/data.d.ts +28 -11
- package/dist/types/core/define-components.d.ts +12 -9
- package/dist/types/core/deployment-env.d.ts +6 -11
- package/dist/types/core/frontmatter.d.ts +10 -0
- package/dist/types/core/graph.d.ts +18 -0
- package/dist/types/core/heading-markers.d.ts +54 -0
- package/dist/types/core/i18n-ui.d.ts +6 -2
- package/dist/types/core/i18n.d.ts +87 -0
- package/dist/types/core/includes.d.ts +138 -0
- package/dist/types/core/last-modified.d.ts +47 -0
- package/dist/types/core/links.d.ts +95 -0
- package/dist/types/core/locale-links.d.ts +60 -0
- package/dist/types/core/manifest.d.ts +17 -0
- package/dist/types/core/meta.d.ts +38 -0
- package/dist/types/core/nav-diagnostics.d.ts +26 -0
- package/dist/types/core/navigation.d.ts +6 -0
- package/dist/types/core/node-require.d.ts +19 -0
- package/dist/types/core/package-json.d.ts +13 -0
- package/dist/types/core/probe.d.ts +42 -0
- package/dist/types/core/project-graph.d.ts +51 -0
- package/dist/types/core/project.d.ts +2 -0
- package/dist/types/core/safe-href.d.ts +2 -0
- package/dist/types/core/safe-links.d.ts +26 -0
- package/dist/types/core/schema.d.ts +2291 -441
- 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 +20 -1
- package/dist/types/core/unrecognized-keys.d.ts +7 -0
- package/dist/types/core/versions.d.ts +72 -0
- package/dist/types/core/yaml.d.ts +9 -0
- package/dist/types/deploy/adapter-output.d.ts +45 -0
- package/dist/types/deploy/adapters/cloudflare.d.ts +40 -0
- package/dist/types/deploy/adapters/index.d.ts +29 -0
- package/dist/types/deploy/adapters/netlify.d.ts +37 -0
- package/dist/types/deploy/adapters/node.d.ts +37 -0
- package/dist/types/deploy/adapters/registry.d.ts +133 -0
- package/dist/types/deploy/adapters/types.d.ts +71 -0
- package/dist/types/deploy/adapters/vercel.d.ts +38 -0
- package/dist/types/deploy/artifacts.d.ts +65 -0
- package/dist/types/deploy/cloudflare-negotiation.d.ts +196 -0
- package/dist/types/deploy/function-bundle.d.ts +80 -0
- package/dist/types/deploy/headers.d.ts +50 -0
- package/dist/types/deploy/node-headers.d.ts +42 -0
- package/dist/types/deploy/platforms/cloudflare.d.ts +40 -0
- package/dist/types/deploy/platforms/index.d.ts +18 -0
- package/dist/types/deploy/platforms/netlify.d.ts +13 -0
- package/dist/types/deploy/platforms/node.d.ts +11 -0
- package/dist/types/deploy/platforms/paths.d.ts +27 -0
- package/dist/types/deploy/platforms/static.d.ts +10 -0
- package/dist/types/deploy/platforms/types.d.ts +104 -0
- package/dist/types/deploy/platforms/vercel.d.ts +32 -0
- package/dist/types/deploy/redirects.d.ts +53 -0
- package/dist/types/deploy/robots.d.ts +8 -0
- package/dist/types/deploy/rss.d.ts +31 -0
- package/dist/types/deploy/sitemap.d.ts +21 -0
- package/dist/types/deploy/vercel-negotiation.d.ts +109 -0
- package/dist/types/markdown/code-title.d.ts +32 -0
- package/dist/types/markdown/fence-meta.d.ts +23 -0
- package/dist/types/markdown/themes.d.ts +3 -3
- package/dist/types/openapi/asyncapi.d.ts +129 -0
- package/dist/types/openapi/graphql-build.d.ts +8 -0
- package/dist/types/openapi/graphql.d.ts +122 -0
- package/dist/types/openapi/model.d.ts +158 -0
- package/dist/types/openapi/parse.d.ts +57 -0
- package/dist/types/openapi/references.d.ts +37 -25
- package/dist/types/openapi/render-mdx.d.ts +33 -0
- package/dist/types/openapi/sentence.d.ts +7 -0
- package/dist/types/openapi/signature.d.ts +10 -0
- package/dist/types/openapi/source.d.ts +22 -0
- package/dist/types/openapi/spec-dependency-error.d.ts +10 -0
- package/dist/types/reference/asyncapi.d.ts +166 -0
- package/dist/types/reference/graphql.d.ts +181 -0
- package/dist/types/reference/index.d.ts +32 -0
- package/dist/types/reference/openapi.d.ts +165 -0
- package/dist/types/reference/options.d.ts +157 -0
- package/dist/types/reference/scalar.d.ts +136 -0
- package/dist/types/reference/schema.d.ts +630 -0
- package/dist/types/search/adapters/algolia.d.ts +32 -0
- package/dist/types/search/adapters/flexsearch.d.ts +12 -0
- package/dist/types/search/adapters/index.d.ts +31 -0
- package/dist/types/search/adapters/mixedbread.d.ts +22 -0
- package/dist/types/search/adapters/orama-cloud.d.ts +33 -0
- package/dist/types/search/adapters/orama.d.ts +13 -0
- package/dist/types/search/adapters/pagefind.d.ts +12 -0
- package/dist/types/search/adapters/registry.d.ts +228 -0
- package/dist/types/search/adapters/types.d.ts +34 -0
- package/dist/types/search/adapters/typesense.d.ts +42 -0
- package/dist/types/search/build.d.ts +23 -0
- package/dist/types/search/documents.d.ts +90 -0
- package/dist/types/search/facets.d.ts +3 -0
- package/dist/types/search/sync/algolia.d.ts +14 -0
- package/dist/types/search/sync/index.d.ts +14 -0
- package/dist/types/search/sync/orama-cloud.d.ts +10 -0
- package/dist/types/search/sync/typesense.d.ts +14 -0
- package/dist/types/sources/contentful.d.ts +68 -0
- package/dist/types/sources/custom.d.ts +20 -0
- package/dist/types/sources/filesystem.d.ts +42 -0
- package/dist/types/sources/github-releases.d.ts +46 -0
- package/dist/types/sources/index.d.ts +48 -0
- package/dist/types/sources/mdx-remote.d.ts +63 -0
- package/dist/types/sources/notion.d.ts +65 -0
- package/dist/types/sources/obsidian.d.ts +34 -0
- package/dist/types/sources/payload.d.ts +68 -0
- package/dist/types/sources/registry.d.ts +1414 -0
- package/dist/types/sources/sanity.d.ts +69 -0
- package/dist/types/sources/shared.d.ts +46 -0
- package/dist/types/sources/strapi.d.ts +66 -0
- package/dist/types/theme/icon-kind.d.ts +11 -0
- package/dist/types/theme/icons.d.ts +20 -0
- package/docs/01-quickstart.mdx +18 -18
- package/docs/02-deployment.mdx +50 -26
- package/docs/03-upgrading.mdx +351 -0
- package/docs/04-migrating.mdx +58 -0
- package/docs/08-faq.mdx +3 -3
- package/docs/advanced/blog.mdx +13 -6
- package/docs/advanced/changelog.mdx +23 -35
- package/docs/advanced/custom-pages.mdx +20 -8
- package/docs/advanced/meta.ts +1 -8
- package/docs/advanced/skills.mdx +8 -0
- package/docs/cli/audit.mdx +646 -0
- package/docs/cli/doctor.mdx +29 -0
- package/docs/{reference/eval.mdx → cli/evals.mdx} +9 -8
- package/docs/cli/index.mdx +105 -0
- package/docs/cli/meta.ts +7 -0
- package/docs/{reference → cli}/translate.mdx +1 -1
- package/docs/cli/validate.mdx +41 -0
- package/docs/cli/version.mdx +40 -0
- package/docs/configuration/analytics.mdx +350 -59
- package/docs/configuration/ask-ai.mdx +176 -61
- package/docs/configuration/customization.mdx +15 -9
- package/docs/configuration/index.mdx +52 -31
- package/docs/configuration/search.mdx +75 -54
- package/docs/configuration/theming.mdx +24 -15
- package/docs/content/components.mdx +21 -5
- package/docs/{reference → content}/frontmatter.mdx +37 -1
- package/docs/content/i18n.mdx +8 -6
- package/docs/content/includes.mdx +2 -4
- package/docs/content/index.mdx +1 -1
- package/docs/content/islands.mdx +10 -5
- package/docs/content/meta.mdx +1 -1
- package/docs/content/meta.ts +1 -0
- package/docs/content/navigation.mdx +12 -7
- package/docs/content/sources.mdx +145 -50
- package/docs/content/syntax.mdx +26 -12
- package/docs/content/versioning.mdx +3 -3
- package/docs/discoverability/agent-discovery.mdx +91 -10
- package/docs/discoverability/index.mdx +5 -5
- package/docs/discoverability/json-api.mdx +4 -4
- package/docs/discoverability/llms-txt.mdx +6 -6
- package/docs/discoverability/markdown.mdx +4 -4
- package/docs/discoverability/mcp.mdx +11 -11
- package/docs/discoverability/sitemap-and-robots.mdx +3 -3
- package/docs/index.mdx +2 -2
- package/docs/references/asyncapi.mdx +59 -0
- package/docs/{advanced → references}/graphql.mdx +45 -32
- package/docs/{reference → references}/meta.ts +2 -2
- package/docs/references/openapi.mdx +171 -0
- package/docs/references/scalar.mdx +64 -0
- package/package.json +42 -8
- package/skills/blume/SKILL.md +21 -8
- package/skills/blume-migrate/SKILL.md +22 -21
- package/skills/blume-migrate/assets/oxfmt@0.67.0.patch +49 -0
- package/skills/blume-migrate/references/docusaurus.md +5 -4
- package/skills/blume-migrate/references/fumadocs.md +4 -4
- package/skills/blume-migrate/references/mintlify.md +23 -8
- package/skills/blume-migrate/references/monorepo.md +6 -6
- package/skills/blume-migrate/references/starlight.md +4 -4
- package/src/ai/agent-readability.ts +26 -22
- package/src/ai/ai-catalog.ts +259 -0
- package/src/ai/api/handlers.ts +46 -11
- package/src/ai/api-catalog.ts +8 -8
- package/src/ai/ask-data.ts +1 -1
- package/src/ai/ask.ts +624 -100
- package/src/ai/changelog-markdown.ts +91 -0
- package/src/ai/component-markdown.ts +328 -12
- package/src/ai/index.ts +45 -0
- package/src/ai/link-headers.ts +19 -6
- package/src/ai/llms.ts +26 -15
- package/src/ai/markdown.ts +35 -5
- package/src/ai/mcp/data.ts +9 -5
- package/src/ai/mcp/discovery.ts +1 -1
- package/src/ai/openapi-components.ts +4 -1
- package/src/ai/relative-links.ts +170 -0
- package/src/ai/serializers.ts +2 -2
- package/src/ai/skills.ts +1 -1
- package/src/ai/web-bot-auth.ts +2 -2
- package/src/analytics/adobe.ts +46 -0
- package/src/analytics/amplitude.ts +79 -0
- package/src/analytics/clarity.ts +46 -0
- package/src/analytics/clearbit.ts +47 -0
- package/src/analytics/cloudflare.ts +67 -0
- package/src/analytics/fathom.ts +64 -0
- package/src/analytics/google-analytics.ts +84 -0
- package/src/analytics/google-tag-manager.ts +61 -0
- package/src/analytics/head.ts +130 -0
- package/src/analytics/heap.ts +65 -0
- package/src/analytics/hightouch.ts +77 -0
- package/src/analytics/hotjar.ts +47 -0
- package/src/analytics/index.ts +71 -0
- package/src/analytics/inline.ts +21 -0
- package/src/analytics/logrocket.ts +71 -0
- package/src/analytics/mixpanel.ts +92 -0
- package/src/analytics/pirsch.ts +66 -0
- package/src/analytics/plausible.ts +83 -0
- package/src/analytics/posthog.ts +78 -0
- package/src/analytics/schema.ts +60 -0
- package/src/analytics/script.ts +60 -0
- package/src/analytics/segment.ts +85 -0
- package/src/analytics/vercel.ts +50 -0
- package/src/astro/adapter-root.ts +7 -9
- package/src/astro/component-slots.ts +131 -91
- package/src/astro/generate.ts +114 -345
- package/src/astro/integration.ts +2 -6
- package/src/astro/pages.ts +13 -101
- package/src/astro/render-deps.ts +379 -0
- package/src/astro/runtime-deps.ts +201 -0
- package/src/astro/templates.ts +554 -541
- package/src/audit/agent.ts +24 -0
- package/src/audit/catalog.ts +2 -2
- package/src/audit/checks/assets.ts +2 -2
- package/src/audit/checks/dns-aid.ts +1 -1
- package/src/audit/checks/duplicates.ts +3 -1
- package/src/audit/checks/i18n.ts +1 -1
- package/src/audit/checks/indexability.ts +7 -7
- package/src/audit/checks/links.ts +2 -2
- package/src/audit/checks/llms.ts +6 -6
- package/src/audit/checks/network.ts +3 -3
- package/src/audit/checks/og-image.ts +2 -2
- package/src/audit/checks/robots.ts +1 -1
- package/src/audit/checks/sitemap.ts +2 -2
- package/src/audit/checks/social.ts +1 -1
- package/src/audit/run.ts +4 -3
- package/src/audit/terms.ts +31 -0
- package/src/audit/url.ts +13 -13
- package/src/cli/command-meta.ts +10 -0
- package/src/cli/commands/audit.ts +39 -20
- package/src/cli/commands/build.ts +71 -314
- package/src/cli/commands/check.ts +1 -0
- package/src/cli/commands/dev.ts +40 -1
- package/src/cli/commands/doctor.ts +90 -14
- package/src/cli/commands/eject.ts +44 -7
- package/src/cli/commands/eval.ts +2 -2
- package/src/cli/commands/init.ts +161 -41
- package/src/cli/commands/migrate.ts +121 -0
- package/src/cli/commands/preview.ts +7 -1
- package/src/cli/commands/translate.ts +2 -2
- package/src/cli/commands/upgrade.ts +141 -0
- package/src/cli/commands/version.ts +57 -44
- package/src/cli/eject-scripts.ts +121 -6
- package/src/cli/index.ts +11 -1
- package/src/cli/init/install.ts +70 -0
- package/src/cli/init/questions.ts +7 -0
- package/src/cli/init/scaffold.ts +459 -75
- package/src/cli/lazy-command.ts +37 -1
- package/src/cli/prepare.ts +40 -6
- package/src/cli/required-secrets.ts +38 -11
- package/src/cli/unknown-flags.ts +266 -0
- package/src/cli/yarn-pnp.ts +52 -0
- package/src/components/content/AccordionItem.astro +7 -1
- package/src/components/content/Card.astro +4 -3
- package/src/components/content/ColorItem.astro +22 -4
- package/src/components/content/GithubInfo.astro +2 -2
- package/src/components/content/Prompt.astro +25 -25
- package/src/components/content/Tabs.astro +3 -1
- package/src/components/content/Tile.astro +2 -3
- package/src/components/content/Tooltip.astro +57 -9
- package/src/components/content/content-strings.ts +34 -0
- package/src/components/content/diff.ts +1 -1
- package/src/components/content/mermaid-element.ts +13 -2
- package/src/components/content/prompt-markdown.ts +292 -0
- package/src/components/content/tooltip-id.ts +41 -0
- package/src/components/islands/hooks.ts +75 -3
- package/src/components/layout/Analytics.astro +21 -79
- package/src/components/layout/Banner.astro +3 -1
- package/src/components/layout/DiscoveryLinks.astro +69 -0
- package/src/components/layout/Header.astro +83 -20
- package/src/components/layout/LanguageSwitcher.astro +4 -1
- package/src/components/layout/Logo.astro +23 -2
- package/src/components/layout/NavSelector.astro +13 -2
- package/src/components/layout/NavTree.astro +12 -3
- package/src/components/layout/NavTreeScript.astro +17 -3
- package/src/components/layout/PageActions.astro +3 -3
- package/src/components/layout/PageFeedback.astro +11 -1
- package/src/components/layout/PageLayout.astro +52 -5
- package/src/components/layout/ReferenceLayout.astro +21 -12
- package/src/components/layout/RootLayout.astro +69 -43
- package/src/components/layout/Search.astro +30 -6
- package/src/components/layout/WebMcp.astro +1 -1
- package/src/components/layout/analytics-client.ts +101 -15
- package/src/components/layout/drawer-inert.ts +113 -15
- package/src/components/layout/dropdown-clamp.ts +105 -0
- package/src/components/layout/head-scripts.ts +15 -6
- package/src/components/layout/nav-utils.ts +17 -0
- package/src/components/layout/search/algolia.ts +8 -8
- package/src/components/layout/search/orama-cloud.ts +9 -7
- package/src/components/layout/search/typesense.ts +11 -17
- package/src/components/openapi/MessageComposer.astro +2 -2
- package/src/components/openapi/Playground.astro +2 -2
- package/src/components/openapi/playground-client.ts +79 -10
- package/src/core/changelog-index.ts +24 -0
- package/src/core/component-overrides.ts +399 -154
- package/src/core/config-input.ts +212 -543
- package/src/core/config.ts +130 -41
- package/src/core/custom-pages.ts +105 -0
- package/src/core/data.ts +32 -11
- package/src/core/define-components.ts +12 -9
- package/src/core/deployment-env.ts +18 -74
- package/src/core/diagnostics.ts +14 -7
- package/src/core/graph.ts +69 -25
- package/src/core/i18n-ui.ts +6 -2
- package/src/core/i18n.ts +17 -0
- package/src/core/includes.ts +156 -38
- package/src/core/last-modified.ts +6 -11
- package/src/core/links.ts +166 -2
- package/src/core/manifest.ts +10 -3
- package/src/core/navigation.ts +137 -19
- 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 +531 -721
- package/src/core/server-features.ts +8 -9
- package/src/core/sources/assets.ts +47 -11
- package/src/core/sources/collection.ts +67 -0
- package/src/core/sources/contentful-rich-text.ts +285 -0
- package/src/core/sources/contentful.ts +173 -0
- package/src/core/sources/github-releases.ts +51 -1
- package/src/core/sources/json.ts +71 -0
- package/src/core/sources/lexical.ts +195 -0
- package/src/core/sources/lower.ts +226 -0
- package/src/core/sources/normalize.ts +52 -2
- package/src/core/sources/notion.ts +39 -28
- package/src/core/sources/payload.ts +135 -0
- package/src/core/sources/portable-text.ts +11 -16
- package/src/core/sources/remote.ts +226 -0
- package/src/core/sources/resolve.ts +104 -166
- package/src/core/sources/sanity.ts +16 -49
- package/src/core/sources/strapi-blocks.ts +124 -0
- package/src/core/sources/strapi.ts +191 -0
- package/src/core/sources/types.ts +12 -1
- package/src/core/types.ts +20 -1
- package/src/core/ui-packs/ar.ts +6 -2
- package/src/core/ui-packs/bg.ts +6 -2
- package/src/core/ui-packs/bn.ts +6 -2
- package/src/core/ui-packs/ca.ts +3 -1
- package/src/core/ui-packs/cs.ts +6 -2
- package/src/core/ui-packs/da.ts +6 -2
- package/src/core/ui-packs/de.ts +6 -2
- package/src/core/ui-packs/el.ts +3 -1
- package/src/core/ui-packs/es.ts +3 -1
- package/src/core/ui-packs/fa.ts +6 -2
- package/src/core/ui-packs/fi.ts +6 -2
- package/src/core/ui-packs/fr.ts +3 -1
- package/src/core/ui-packs/he.ts +6 -2
- package/src/core/ui-packs/hi.ts +6 -2
- package/src/core/ui-packs/hr.ts +6 -2
- package/src/core/ui-packs/hu.ts +6 -2
- package/src/core/ui-packs/id.ts +6 -2
- package/src/core/ui-packs/it.ts +3 -1
- package/src/core/ui-packs/ja.ts +3 -1
- package/src/core/ui-packs/ko.ts +3 -1
- package/src/core/ui-packs/nl.ts +6 -2
- package/src/core/ui-packs/no.ts +6 -2
- package/src/core/ui-packs/pl.ts +6 -2
- package/src/core/ui-packs/pt-br.ts +3 -1
- package/src/core/ui-packs/pt.ts +3 -1
- package/src/core/ui-packs/ro.ts +6 -2
- package/src/core/ui-packs/ru.ts +6 -2
- package/src/core/ui-packs/sk.ts +6 -2
- package/src/core/ui-packs/sr.ts +6 -2
- package/src/core/ui-packs/sv.ts +6 -2
- package/src/core/ui-packs/th.ts +3 -1
- package/src/core/ui-packs/tr.ts +6 -2
- package/src/core/ui-packs/uk.ts +6 -2
- package/src/core/ui-packs/vi.ts +3 -1
- package/src/core/ui-packs/zh-tw.ts +3 -1
- package/src/core/ui-packs/zh.ts +3 -1
- package/src/core/unrecognized-keys.ts +10 -0
- package/src/core/version-cut.ts +116 -8
- package/src/deploy/adapter-output.ts +57 -97
- package/src/deploy/adapters/cloudflare.ts +39 -0
- package/src/deploy/adapters/index.ts +41 -0
- package/src/deploy/adapters/netlify.ts +34 -0
- package/src/deploy/adapters/node.ts +34 -0
- package/src/deploy/adapters/registry.ts +127 -0
- package/src/deploy/adapters/types.ts +92 -0
- package/src/deploy/adapters/vercel.ts +35 -0
- package/src/deploy/artifacts.ts +67 -28
- package/src/deploy/cloudflare-negotiation.ts +179 -100
- package/src/deploy/function-bundle.ts +18 -3
- package/src/deploy/headers.ts +129 -22
- 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 +27 -4
- package/src/eval/agents.ts +32 -1
- package/src/eval/findings.ts +19 -11
- package/src/eval/report.ts +10 -2
- package/src/markdown/external-links.ts +65 -0
- package/src/markdown/include.ts +45 -27
- package/src/markdown/index.ts +34 -9
- package/src/markdown/inline-code.ts +12 -6
- package/src/markdown/relative-links.ts +324 -0
- package/src/markdown/themes.ts +3 -3
- package/src/migrate/migrate.ts +149 -0
- package/src/openapi/parse.ts +64 -16
- package/src/openapi/proxy.ts +62 -10
- package/src/openapi/references.ts +147 -147
- package/src/openapi/render-mdx.ts +32 -10
- package/src/openapi/scalar.ts +15 -13
- package/src/openapi/sentence.ts +14 -0
- package/src/openapi/source.ts +37 -21
- package/src/openapi/spec-dependency-error.ts +15 -0
- package/src/reference/asyncapi.ts +83 -0
- package/src/reference/graphql.ts +89 -0
- package/src/reference/index.ts +40 -0
- package/src/reference/openapi.ts +83 -0
- package/src/reference/options.ts +201 -0
- package/src/reference/scalar.ts +136 -0
- package/src/reference/schema.ts +88 -0
- package/src/registry/eject.ts +97 -42
- package/src/search/adapters/algolia.ts +46 -0
- package/src/search/adapters/flexsearch.ts +29 -0
- package/src/search/adapters/index.ts +39 -0
- package/src/search/adapters/mixedbread.ts +39 -0
- package/src/search/adapters/orama-cloud.ts +51 -0
- package/src/search/adapters/orama.ts +24 -0
- package/src/search/adapters/pagefind.ts +27 -0
- package/src/search/adapters/registry.ts +131 -0
- package/src/search/adapters/types.ts +46 -0
- package/src/search/adapters/typesense.ts +57 -0
- package/src/search/build.ts +33 -7
- package/src/search/documents.ts +6 -0
- package/src/search/sync/algolia.ts +12 -11
- package/src/search/sync/index.ts +35 -20
- package/src/search/sync/orama-cloud.ts +12 -9
- package/src/search/sync/typesense.ts +15 -13
- package/src/sources/contentful.ts +63 -0
- package/src/sources/custom.ts +38 -0
- package/src/sources/filesystem.ts +51 -0
- package/src/sources/github-releases.ts +52 -0
- package/src/sources/index.ts +60 -0
- package/src/sources/mdx-remote.ts +76 -0
- package/src/sources/notion.ts +63 -0
- package/src/sources/obsidian.ts +38 -0
- package/src/sources/payload.ts +60 -0
- package/src/sources/registry.ts +182 -0
- package/src/sources/sanity.ts +66 -0
- package/src/sources/shared.ts +52 -0
- package/src/sources/strapi.ts +58 -0
- package/src/theme/entry.ts +47 -2
- package/src/translate/report.ts +40 -7
- package/src/upgrade/upgrade.ts +499 -0
- package/dist/cli/chunk-12dxjqk7.js.map +0 -10
- package/dist/cli/chunk-196vjxp9.js.map +0 -13
- package/dist/cli/chunk-2mzebbbz.js +0 -69
- package/dist/cli/chunk-2z47ypj8.js.map +0 -11
- package/dist/cli/chunk-30e87n55.js +0 -108
- package/dist/cli/chunk-30e87n55.js.map +0 -10
- package/dist/cli/chunk-450a7rcr.js +0 -185
- package/dist/cli/chunk-450a7rcr.js.map +0 -11
- package/dist/cli/chunk-5n7t497w.js.map +0 -40
- package/dist/cli/chunk-61j18dwk.js +0 -5342
- package/dist/cli/chunk-61j18dwk.js.map +0 -58
- package/dist/cli/chunk-88by27n5.js +0 -17
- package/dist/cli/chunk-88by27n5.js.map +0 -10
- package/dist/cli/chunk-8cd8tj54.js.map +0 -34
- package/dist/cli/chunk-aztttvb3.js +0 -381
- package/dist/cli/chunk-aztttvb3.js.map +0 -12
- package/dist/cli/chunk-cvky9gb2.js.map +0 -11
- package/dist/cli/chunk-ejjx8znq.js.map +0 -15
- package/dist/cli/chunk-fmceyezb.js +0 -1007
- package/dist/cli/chunk-fmceyezb.js.map +0 -13
- package/dist/cli/chunk-hdm2dkd2.js.map +0 -48
- package/dist/cli/chunk-hs3gbh8p.js.map +0 -10
- package/dist/cli/chunk-jbj4qhfw.js +0 -30
- package/dist/cli/chunk-jbj4qhfw.js.map +0 -10
- package/dist/cli/chunk-mqb2ka8m.js +0 -68
- package/dist/cli/chunk-mqb2ka8m.js.map +0 -10
- package/dist/cli/chunk-mt76t7dj.js.map +0 -11
- package/dist/cli/chunk-q4rae3bg.js +0 -60
- package/dist/cli/chunk-q4rae3bg.js.map +0 -10
- package/dist/cli/chunk-ra1v2nc2.js +0 -35
- package/dist/cli/chunk-ra1v2nc2.js.map +0 -10
- package/dist/cli/chunk-t3tj0dgr.js.map +0 -15
- package/dist/cli/chunk-tqa1s0k8.js +0 -69
- package/dist/cli/chunk-tqa1s0k8.js.map +0 -11
- package/dist/cli/chunk-vh9w1sgp.js +0 -73
- package/dist/cli/chunk-vh9w1sgp.js.map +0 -10
- package/dist/cli/chunk-vkrsvbr5.js +0 -107
- package/dist/cli/chunk-vkrsvbr5.js.map +0 -11
- package/dist/cli/chunk-vrfp10qk.js +0 -81
- package/dist/cli/chunk-vrfp10qk.js.map +0 -10
- package/dist/cli/chunk-wjt80jps.js +0 -1049
- package/dist/cli/chunk-wjt80jps.js.map +0 -24
- package/docs/advanced/api-reference.mdx +0 -240
- package/docs/reference/cli.mdx +0 -197
- package/skills/blume-migrate/assets/oxfmt@0.55.0.patch +0 -20
- package/src/components/content/changelog-element.ts +0 -69
- package/src/search/providers.ts +0 -91
- /package/dist/cli/{chunk-3w7b2vcx.js.map → chunk-7ez8ny0t.js.map} +0 -0
- /package/dist/cli/{chunk-688e0dde.js.map → chunk-88cpgt6h.js.map} +0 -0
- /package/dist/cli/{chunk-exeeb35e.js.map → chunk-f7t03s3g.js.map} +0 -0
- /package/dist/cli/{chunk-ppfvdcd4.js.map → chunk-zxccj738.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-xaz13gwg.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;
|
|
@@ -486,7 +490,8 @@ var metaKey = (path, metaPrefix) => {
|
|
|
486
490
|
}
|
|
487
491
|
return path ? `${metaPrefix}/${path}` : metaPrefix;
|
|
488
492
|
};
|
|
489
|
-
var applyFolderMeta = (group, folderMeta, sharedMeta, metaPrefix, sharedMetaPrefix, indexDisplay) => {
|
|
493
|
+
var applyFolderMeta = (group, folderMeta, sharedMeta, metaPrefix, sharedMetaPrefix, indexDisplay, indexRoute) => {
|
|
494
|
+
group.route = indexRoute.get(group.path);
|
|
490
495
|
const meta = folderMeta.get(metaKey(group.path, metaPrefix)) ?? sharedMeta.get(metaKey(group.path, sharedMetaPrefix));
|
|
491
496
|
group.display = indexDisplay.get(group.path) ?? meta?.display;
|
|
492
497
|
if (meta) {
|
|
@@ -509,12 +514,12 @@ var applyFolderMeta = (group, folderMeta, sharedMeta, metaPrefix, sharedMetaPref
|
|
|
509
514
|
}
|
|
510
515
|
for (const child of group.children) {
|
|
511
516
|
if (child.kind === "group") {
|
|
512
|
-
applyFolderMeta(child, folderMeta, sharedMeta, metaPrefix, sharedMetaPrefix, indexDisplay);
|
|
517
|
+
applyFolderMeta(child, folderMeta, sharedMeta, metaPrefix, sharedMetaPrefix, indexDisplay, indexRoute);
|
|
513
518
|
}
|
|
514
519
|
}
|
|
515
520
|
};
|
|
516
521
|
var indexTitleMismatchDiagnostic = (page, folderPath, folderMeta, sharedMeta, metaPrefix, sharedMetaPrefix) => {
|
|
517
|
-
if (!page.meta.title || page.fallback || folderPath === "") {
|
|
522
|
+
if (!(page.meta.title && page.meta.sidebar.hidden) || page.fallback || folderPath === "") {
|
|
518
523
|
return;
|
|
519
524
|
}
|
|
520
525
|
const meta = folderMeta.get(metaKey(folderPath, metaPrefix)) ?? sharedMeta.get(metaKey(folderPath, sharedMetaPrefix));
|
|
@@ -656,12 +661,14 @@ var toNavNode = (node, display) => {
|
|
|
656
661
|
icon: node.icon,
|
|
657
662
|
kind: "group",
|
|
658
663
|
label: node.label,
|
|
659
|
-
path: node.routePath
|
|
664
|
+
path: node.routePath,
|
|
665
|
+
route: node.route
|
|
660
666
|
};
|
|
661
667
|
};
|
|
662
668
|
var buildFileSystemSidebar = (pages, folderMeta, sharedMeta, metaPrefix, sharedMetaPrefix, display, tabPaths, diagnostics = []) => {
|
|
663
669
|
const root = createGroup("", "", "", 0);
|
|
664
670
|
const indexDisplay = new Map;
|
|
671
|
+
const indexRoute = new Map;
|
|
665
672
|
for (const page of pages) {
|
|
666
673
|
const parts = page.navPath.split("/");
|
|
667
674
|
const filename = parts.at(-1) ?? page.navPath;
|
|
@@ -675,6 +682,9 @@ var buildFileSystemSidebar = (pages, folderMeta, sharedMeta, metaPrefix, sharedM
|
|
|
675
682
|
if (page.meta.sidebar.display && !page.fallback) {
|
|
676
683
|
indexDisplay.set(dirs.join("/"), page.meta.sidebar.display);
|
|
677
684
|
}
|
|
685
|
+
if (dirs.length > 0) {
|
|
686
|
+
indexRoute.set(dirs.join("/"), page.route);
|
|
687
|
+
}
|
|
678
688
|
}
|
|
679
689
|
if (page.meta.sidebar.hidden) {
|
|
680
690
|
continue;
|
|
@@ -698,7 +708,7 @@ var buildFileSystemSidebar = (pages, folderMeta, sharedMeta, metaPrefix, sharedM
|
|
|
698
708
|
deprecated: page.meta.deprecated || undefined,
|
|
699
709
|
description: page.description,
|
|
700
710
|
file: page.sourcePath,
|
|
701
|
-
icon: page
|
|
711
|
+
icon: sidebarIcon(page),
|
|
702
712
|
key: segmentKey(stem),
|
|
703
713
|
kind: "page",
|
|
704
714
|
label: page.meta.sidebar.label ?? page.title,
|
|
@@ -708,7 +718,7 @@ var buildFileSystemSidebar = (pages, folderMeta, sharedMeta, metaPrefix, sharedM
|
|
|
708
718
|
route: page.route
|
|
709
719
|
});
|
|
710
720
|
}
|
|
711
|
-
applyFolderMeta(root, folderMeta, sharedMeta, metaPrefix, sharedMetaPrefix, indexDisplay);
|
|
721
|
+
applyFolderMeta(root, folderMeta, sharedMeta, metaPrefix, sharedMetaPrefix, indexDisplay, indexRoute);
|
|
712
722
|
sortNodes(root.children, diagnostics);
|
|
713
723
|
hoistPages(root.children, display, true);
|
|
714
724
|
hoistTabSections(root.children, tabPaths, display);
|
|
@@ -741,7 +751,7 @@ var configItemToNode = (item, byRoute, basePath) => {
|
|
|
741
751
|
badge: page.meta.sidebar.badge,
|
|
742
752
|
deprecated: page.meta.deprecated || undefined,
|
|
743
753
|
description: page.description,
|
|
744
|
-
icon: page
|
|
754
|
+
icon: sidebarIcon(page),
|
|
745
755
|
kind: "page",
|
|
746
756
|
label: page.meta.sidebar.label ?? page.title,
|
|
747
757
|
pageId: page.id,
|
|
@@ -796,7 +806,10 @@ var buildConfigSidebar = (items, byRoute, display, basePath) => {
|
|
|
796
806
|
}
|
|
797
807
|
return nodes;
|
|
798
808
|
};
|
|
799
|
-
var resolveTabHref = (sidebar, path) => {
|
|
809
|
+
var resolveTabHref = (sidebar, path, extraRoutes, basePath) => {
|
|
810
|
+
if (extraRoutes.has(path)) {
|
|
811
|
+
return path;
|
|
812
|
+
}
|
|
800
813
|
let first;
|
|
801
814
|
const walk = (nodes) => {
|
|
802
815
|
for (const node of nodes) {
|
|
@@ -813,10 +826,14 @@ var resolveTabHref = (sidebar, path) => {
|
|
|
813
826
|
}
|
|
814
827
|
return false;
|
|
815
828
|
};
|
|
816
|
-
|
|
829
|
+
if (walk(sidebar)) {
|
|
830
|
+
return path;
|
|
831
|
+
}
|
|
832
|
+
const bare = stripBasePath(basePath, path);
|
|
833
|
+
return extraRoutes.has(bare) ? bare : first ?? path;
|
|
817
834
|
};
|
|
818
|
-
var withTabHrefs = (tabs, sidebar) => tabs.map((tab) => {
|
|
819
|
-
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);
|
|
820
837
|
return href === tab.path ? tab : { ...tab, href };
|
|
821
838
|
});
|
|
822
839
|
var rebaseNavChrome = (basePath, options) => {
|
|
@@ -863,6 +880,7 @@ var buildNavigation = (pages, options) => {
|
|
|
863
880
|
const metaPrefix = options.metaPrefix ?? "";
|
|
864
881
|
const sharedMetaPrefix = options.sharedMetaPrefix ?? "";
|
|
865
882
|
const sharedFolderMeta = options.sharedFolderMeta ?? new Map;
|
|
883
|
+
const extraRoutes = options.extraRoutes ?? new Set;
|
|
866
884
|
const { actions, cta, featured, selectors, tabs } = rebaseNavChrome(basePath, options);
|
|
867
885
|
const byRoute = new Map(pages.map((page) => [
|
|
868
886
|
options.refByLogical ? page.translationKey : page.route,
|
|
@@ -888,7 +906,7 @@ var buildNavigation = (pages, options) => {
|
|
|
888
906
|
root: rootTabPath,
|
|
889
907
|
selectors,
|
|
890
908
|
sidebar,
|
|
891
|
-
tabs: withTabHrefs(tabs, sidebar)
|
|
909
|
+
tabs: withTabHrefs(tabs, sidebar, extraRoutes, basePath)
|
|
892
910
|
};
|
|
893
911
|
}
|
|
894
912
|
const sidebar = buildFileSystemSidebar(pages, options.folderMeta, sharedFolderMeta, metaPrefix, sharedMetaPrefix, display, new Set(tabs.flatMap((tab) => isRootTab(tab, rootTabPath) ? [] : [tab.path])), diagnostics);
|
|
@@ -899,48 +917,10 @@ var buildNavigation = (pages, options) => {
|
|
|
899
917
|
root: rootTabPath,
|
|
900
918
|
selectors,
|
|
901
919
|
sidebar,
|
|
902
|
-
tabs: withTabHrefs(tabs, sidebar)
|
|
920
|
+
tabs: withTabHrefs(tabs, sidebar, extraRoutes, basePath)
|
|
903
921
|
};
|
|
904
922
|
};
|
|
905
923
|
|
|
906
|
-
// src/core/versions.ts
|
|
907
|
-
var VERSION_LIKE = /^v\d/iu;
|
|
908
|
-
var detectVersion = (parts, versions) => {
|
|
909
|
-
const [first] = parts;
|
|
910
|
-
if (first && versions.archived.some((version) => version.id === first)) {
|
|
911
|
-
return { rest: parts.slice(1), version: first };
|
|
912
|
-
}
|
|
913
|
-
return { rest: parts, version: "" };
|
|
914
|
-
};
|
|
915
|
-
var detectVersionRef = (ref, versions) => {
|
|
916
|
-
const { version, rest } = detectVersion(ref.split("/"), versions);
|
|
917
|
-
return { rest: rest.join("/"), version };
|
|
918
|
-
};
|
|
919
|
-
var versionizeRoute = (logicalRoute, version) => {
|
|
920
|
-
if (!version) {
|
|
921
|
-
return logicalRoute;
|
|
922
|
-
}
|
|
923
|
-
return logicalRoute === "/" ? `/${version}` : `/${version}${logicalRoute}`;
|
|
924
|
-
};
|
|
925
|
-
var versionsDiagnostics = (pages, versions) => {
|
|
926
|
-
const configured = new Set(versions.archived.map((version) => version.id));
|
|
927
|
-
const seen = new Set;
|
|
928
|
-
const diagnostics = [];
|
|
929
|
-
for (const page of pages) {
|
|
930
|
-
const [first] = page.source.ref.split("/");
|
|
931
|
-
if (first && !seen.has(first) && VERSION_LIKE.test(first) && !configured.has(first)) {
|
|
932
|
-
seen.add(first);
|
|
933
|
-
diagnostics.push({
|
|
934
|
-
code: "BLUME_VERSIONS_UNCONFIGURED_VERSION",
|
|
935
|
-
message: `Folder "${first}/" looks like a version, but "${first}" is not in versions.archived — its pages are treated as current-version content at /${first}/….`,
|
|
936
|
-
severity: "warning",
|
|
937
|
-
suggestion: `Add { id: "${first}" } to versions.archived, or rename the folder if it isn't a snapshot.`
|
|
938
|
-
});
|
|
939
|
-
}
|
|
940
|
-
}
|
|
941
|
-
return diagnostics;
|
|
942
|
-
};
|
|
943
|
-
|
|
944
924
|
// src/core/graph.ts
|
|
945
925
|
var collectRoutes = (pages) => {
|
|
946
926
|
const routes = new Map;
|
|
@@ -995,7 +975,26 @@ var resolveTabLabels = (tabs, locale, defaultLocale) => (tabs ?? []).map((tab) =
|
|
|
995
975
|
label: resolveLabel(tab.label, locale, defaultLocale)
|
|
996
976
|
}));
|
|
997
977
|
var buildLocaleNavigation = (code, pages, fallback, fallbackByKey, options, i18n, diagnostics, version = "") => {
|
|
998
|
-
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);
|
|
999
998
|
const tabs = resolveTabLabels(options.navigation.tabs, code, i18n.defaultLocale).map((tab) => {
|
|
1000
999
|
const localized = {
|
|
1001
1000
|
...tab,
|
|
@@ -1006,24 +1005,23 @@ var buildLocaleNavigation = (code, pages, fallback, fallbackByKey, options, i18n
|
|
|
1006
1005
|
path: localizePath(tab.path)
|
|
1007
1006
|
};
|
|
1008
1007
|
if (localized.href) {
|
|
1009
|
-
localized.href =
|
|
1008
|
+
localized.href = localizeServed(localized.href, false);
|
|
1010
1009
|
}
|
|
1011
1010
|
return localized;
|
|
1012
1011
|
});
|
|
1013
|
-
const real = pages.filter((page) => page.locale === code);
|
|
1014
|
-
const localePages = localePagesFor(code, real, fallback, fallbackByKey, i18n, options.basePath ?? "");
|
|
1015
1012
|
const localeDir = i18n.parser === "dir" && code !== i18n.defaultLocale ? code : "";
|
|
1016
1013
|
const localizeHref = (item) => ({
|
|
1017
1014
|
...item,
|
|
1018
|
-
href:
|
|
1015
|
+
href: localizeServed(item.href, false)
|
|
1019
1016
|
});
|
|
1020
1017
|
const { actions, cta, featured } = options.navigation;
|
|
1021
|
-
|
|
1018
|
+
const navigation = buildNavigation(localePages, {
|
|
1022
1019
|
actions: actions?.map(localizeHref),
|
|
1023
|
-
basePath
|
|
1020
|
+
basePath,
|
|
1024
1021
|
cta: cta ? localizeHref(cta) : null,
|
|
1025
1022
|
diagnostics,
|
|
1026
1023
|
display: options.navigation.sidebar.display,
|
|
1024
|
+
extraRoutes: options.extraRoutes,
|
|
1027
1025
|
featured: featured?.map(localizeHref),
|
|
1028
1026
|
folderMeta: options.folderMeta,
|
|
1029
1027
|
localizedRoot: localizeRoute(versionizeRoute("/", version), code, i18n),
|
|
@@ -1035,13 +1033,14 @@ var buildLocaleNavigation = (code, pages, fallback, fallbackByKey, options, i18n
|
|
|
1035
1033
|
sidebar: version ? undefined : options.navigation.sidebar.items,
|
|
1036
1034
|
tabs
|
|
1037
1035
|
});
|
|
1036
|
+
return options.brandHref === undefined ? navigation : { ...navigation, brandHref: localizeServed(options.brandHref, false) };
|
|
1038
1037
|
};
|
|
1039
1038
|
var buildI18nNavigation = (pages, options, i18n, diagnostics, version = "") => {
|
|
1040
1039
|
const fallback = resolveFallbackLocale(i18n);
|
|
1041
1040
|
const fallbackByKey = new Map;
|
|
1042
1041
|
if (fallback) {
|
|
1043
1042
|
for (const page of pages) {
|
|
1044
|
-
if (page.locale === fallback) {
|
|
1043
|
+
if (page.locale === fallback && !page.monolingual) {
|
|
1045
1044
|
fallbackByKey.set(page.translationKey, page);
|
|
1046
1045
|
}
|
|
1047
1046
|
}
|
|
@@ -1081,6 +1080,7 @@ var buildVersionNavigation = (id, versionPages, options, diagnostics) => {
|
|
|
1081
1080
|
cta: options.navigation.cta,
|
|
1082
1081
|
diagnostics,
|
|
1083
1082
|
display: options.navigation.sidebar.display,
|
|
1083
|
+
extraRoutes: options.extraRoutes,
|
|
1084
1084
|
featured: options.navigation.featured,
|
|
1085
1085
|
folderMeta: options.folderMeta,
|
|
1086
1086
|
localizedRoot: versionizeRoute("/", id),
|
|
@@ -1107,6 +1107,7 @@ var buildContentGraph = (pages, options) => {
|
|
|
1107
1107
|
cta: options.navigation.cta,
|
|
1108
1108
|
diagnostics,
|
|
1109
1109
|
display: options.navigation.sidebar.display,
|
|
1110
|
+
extraRoutes: options.extraRoutes,
|
|
1110
1111
|
featured: options.navigation.featured,
|
|
1111
1112
|
folderMeta: options.folderMeta,
|
|
1112
1113
|
selectors: options.navigation.selectors,
|
|
@@ -1130,980 +1131,116 @@ var buildContentGraph = (pages, options) => {
|
|
|
1130
1131
|
};
|
|
1131
1132
|
};
|
|
1132
1133
|
|
|
1133
|
-
// src/core/
|
|
1134
|
-
import {
|
|
1135
|
-
import {
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
// src/core/frontmatter.ts
|
|
1157
|
-
import baseMatter from "gray-matter";
|
|
1158
|
-
import { dump, load } from "js-yaml";
|
|
1159
|
-
|
|
1160
|
-
// src/core/yaml.ts
|
|
1161
|
-
import {
|
|
1162
|
-
binaryTag,
|
|
1163
|
-
CORE_SCHEMA,
|
|
1164
|
-
mergeTag,
|
|
1165
|
-
omapTag,
|
|
1166
|
-
pairsTag,
|
|
1167
|
-
setTag,
|
|
1168
|
-
timestampTag
|
|
1169
|
-
} from "js-yaml";
|
|
1170
|
-
var YAML_SCHEMA = CORE_SCHEMA.withTags(timestampTag, mergeTag, binaryTag, omapTag, pairsTag, setTag);
|
|
1171
|
-
|
|
1172
|
-
// src/core/frontmatter.ts
|
|
1173
|
-
var yamlEngine = {
|
|
1174
|
-
parse: (input) => load(input, { schema: YAML_SCHEMA }) ?? {},
|
|
1175
|
-
stringify: (data) => dump(data)
|
|
1176
|
-
};
|
|
1177
|
-
var withYamlEngine = (options) => ({
|
|
1178
|
-
...options,
|
|
1179
|
-
engines: {
|
|
1180
|
-
yaml: yamlEngine,
|
|
1181
|
-
...options?.engines
|
|
1182
|
-
}
|
|
1183
|
-
});
|
|
1184
|
-
var opensWithThematicBreak = (input) => {
|
|
1185
|
-
const [first = "", second] = input.split(/\r?\n/u, 2);
|
|
1186
|
-
if (!/^-{3}\s*$/u.test(first)) {
|
|
1187
|
-
return false;
|
|
1188
|
-
}
|
|
1189
|
-
if (second === undefined || second.trim() === "") {
|
|
1190
|
-
return true;
|
|
1191
|
-
}
|
|
1192
|
-
return !input.includes(`
|
|
1193
|
-
---`, 1);
|
|
1194
|
-
};
|
|
1195
|
-
var passthrough = (input) => {
|
|
1196
|
-
const file = {
|
|
1197
|
-
content: input,
|
|
1198
|
-
data: {},
|
|
1199
|
-
excerpt: "",
|
|
1200
|
-
isEmpty: false,
|
|
1201
|
-
language: "",
|
|
1202
|
-
matter: "",
|
|
1203
|
-
orig: input,
|
|
1204
|
-
stringify: () => input
|
|
1205
|
-
};
|
|
1206
|
-
return file;
|
|
1207
|
-
};
|
|
1208
|
-
var isStringInput = (input) => typeof input === "string";
|
|
1209
|
-
var matter = Object.assign((input, options) => isStringInput(input) && opensWithThematicBreak(input) ? passthrough(input) : baseMatter(input, withYamlEngine(options)), baseMatter, {
|
|
1210
|
-
read: (filepath, options) => baseMatter.read(filepath, withYamlEngine(options)),
|
|
1211
|
-
stringify: (file, data, options) => baseMatter.stringify(isStringInput(file) ? { content: file } : file, data, withYamlEngine(options))
|
|
1212
|
-
});
|
|
1213
|
-
var frontmatter_default = matter;
|
|
1214
|
-
|
|
1215
|
-
// src/core/sources/normalize.ts
|
|
1216
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
1217
|
-
import GithubSlugger from "github-slugger";
|
|
1218
|
-
import { extname as extname2 } from "pathe";
|
|
1219
|
-
|
|
1220
|
-
// src/core/heading-markers.ts
|
|
1221
|
-
var TOC_HIDDEN_KEY = "__blumeTocHidden";
|
|
1222
|
-
var occupySlug = (slugger, id) => {
|
|
1223
|
-
slugger.occurrences[id] ??= 0;
|
|
1224
|
-
};
|
|
1225
|
-
var MARKER = /\s*(?:\{#(?<curlyId>[^\s}]+)\}|\[(?:#(?<id>[^\s\]]+)|(?<hide>!)?toc)\])\s*$/u;
|
|
1226
|
-
var parseHeadingMarkers = (text, isRefDefined) => {
|
|
1227
|
-
let remaining = text;
|
|
1228
|
-
let id;
|
|
1229
|
-
let toc;
|
|
1230
|
-
for (let match = MARKER.exec(remaining);match?.groups; match = MARKER.exec(remaining)) {
|
|
1231
|
-
const explicitId = match.groups.curlyId ?? match.groups.id;
|
|
1232
|
-
const label = explicitId === undefined ? `${match.groups.hide ?? ""}toc` : `#${explicitId}`;
|
|
1233
|
-
if (match.groups.curlyId === undefined && isRefDefined?.(label)) {
|
|
1234
|
-
break;
|
|
1235
|
-
}
|
|
1236
|
-
remaining = remaining.slice(0, match.index);
|
|
1237
|
-
if (explicitId === undefined) {
|
|
1238
|
-
toc ??= match.groups.hide === undefined ? "only" : "hide";
|
|
1239
|
-
} else {
|
|
1240
|
-
id ??= explicitId;
|
|
1241
|
-
}
|
|
1242
|
-
}
|
|
1243
|
-
return { id, text: remaining, toc };
|
|
1244
|
-
};
|
|
1245
|
-
|
|
1246
|
-
// src/core/sources/normalize.ts
|
|
1247
|
-
var NUMERIC_PREFIX2 = /^\d+[-_.]/u;
|
|
1248
|
-
var GROUP_FOLDER2 = /^\((?<label>.+)\)$/u;
|
|
1249
|
-
var WORD_SPLIT2 = /[-_]/u;
|
|
1250
|
-
var stripNumericPrefix = (segment) => segment.replace(NUMERIC_PREFIX2, "");
|
|
1251
|
-
var groupLabel = (segment) => segment.match(GROUP_FOLDER2)?.groups?.label ?? null;
|
|
1252
|
-
var slugify2 = (text) => text.normalize("NFC").toLowerCase().trim().replaceAll(/[^\p{L}\p{M}\p{N}\s_-]/gu, "").replaceAll(/[\s_]+/gu, "-").replaceAll(/-+/gu, "-").replaceAll(/^-|-$/gu, "");
|
|
1253
|
-
var slugifyPath = (text) => text.split("/").map(slugify2).filter(Boolean).join("/");
|
|
1254
|
-
var titleCase = (value) => value.split(WORD_SPLIT2).filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
1255
|
-
var sanitizeSegment = (segment) => segment.replaceAll(/[:\p{Cc}]/gu, "");
|
|
1256
|
-
var addRouteSegment = (part, segments, groups) => {
|
|
1257
|
-
if (part === "") {
|
|
1258
|
-
return;
|
|
1259
|
-
}
|
|
1260
|
-
const group = groupLabel(part);
|
|
1261
|
-
if (group !== null) {
|
|
1262
|
-
groups.push(group);
|
|
1263
|
-
return;
|
|
1264
|
-
}
|
|
1265
|
-
const clean = stripNumericPrefix(part);
|
|
1266
|
-
if (clean === "index") {
|
|
1267
|
-
return;
|
|
1268
|
-
}
|
|
1269
|
-
const safe = sanitizeSegment(clean);
|
|
1270
|
-
if (safe === "") {
|
|
1271
|
-
return;
|
|
1272
|
-
}
|
|
1273
|
-
segments.push(safe);
|
|
1274
|
-
};
|
|
1275
|
-
var mapRoute = (relativePath) => {
|
|
1276
|
-
const withoutExt = relativePath.slice(0, relativePath.length - extname2(relativePath).length);
|
|
1277
|
-
const rawParts = withoutExt.split("/");
|
|
1278
|
-
const segments = [];
|
|
1279
|
-
const groups = [];
|
|
1280
|
-
for (const part of rawParts) {
|
|
1281
|
-
addRouteSegment(part, segments, groups);
|
|
1282
|
-
}
|
|
1283
|
-
const route = segments.length === 0 ? "/" : `/${segments.join("/")}`;
|
|
1284
|
-
return { groups, route, segments };
|
|
1285
|
-
};
|
|
1286
|
-
var ATX_HEADING = /^ {0,3}(?<hashes>#{1,6})\s+(?<text>.+?)(?:\s+#+)?\s*$/u;
|
|
1287
|
-
var SETEXT_UNDERLINE = /^ {0,3}(?<marker>=+|-+)\s*$/u;
|
|
1288
|
-
var PARAGRAPH_INTERRUPT = /^ {0,3}(?:[-+*][ \t]|\d{1,9}[.)][ \t]|>)/u;
|
|
1289
|
-
var THEMATIC_BREAK = /^ {0,3}(?:(?:-[ \t]*){3,}|(?:\*[ \t]*){3,}|(?:_[ \t]*){3,})$/u;
|
|
1290
|
-
var FRONT_MATTER_CLOSE = /^(?:-{3}|\.{3})\s*$/u;
|
|
1291
|
-
var PROMPT_OPEN = /^<Prompt(?![\w-])/u;
|
|
1292
|
-
var PROMPT_CLOSE = /<\/Prompt>/u;
|
|
1293
|
-
var linesWithoutFrontMatter = (body) => {
|
|
1294
|
-
const lines = body.split(`
|
|
1295
|
-
`);
|
|
1296
|
-
if (!/^-{3}\s*$/u.test(lines[0] ?? "")) {
|
|
1297
|
-
return { lines, offset: 0 };
|
|
1298
|
-
}
|
|
1299
|
-
if ((lines[1] ?? "").trim() === "") {
|
|
1300
|
-
return { lines, offset: 0 };
|
|
1301
|
-
}
|
|
1302
|
-
const close = lines.findIndex((line, index) => index > 0 && FRONT_MATTER_CLOSE.test(line));
|
|
1303
|
-
return close === -1 ? { lines, offset: 0 } : { lines: lines.slice(close + 1), offset: close + 1 };
|
|
1304
|
-
};
|
|
1305
|
-
var BARE_CURLY_MARKER = /(?<!\\)\{#(?<id>[^\s}]+)\}(?:\s*\[(?:#[^\s\]]+|!?toc)\])*\s*$/u;
|
|
1306
|
-
var HTML_ID = /<[a-z][a-z0-9-]*(?:\s[^<>]*?)?\sid=(?:(?<quote>["'])(?<quoted>[^"'<>]+)\k<quote>|\{(?<jsxQuote>["'])(?<jsx>[^"'<>]+)\k<jsxQuote>\}|(?<bare>[^\s"'=<>`{}]+))/gu;
|
|
1307
|
-
var HTML_COMMENT = /<!--[\s\S]*?-->/gu;
|
|
1308
|
-
var INLINE_CODE = /`[^`]*`/gu;
|
|
1309
|
-
var finishPromptTag = (line, start, state) => {
|
|
1310
|
-
const end = line.indexOf(">", start);
|
|
1311
|
-
if (end === -1) {
|
|
1312
|
-
state.promptTag = true;
|
|
1313
|
-
return;
|
|
1314
|
-
}
|
|
1315
|
-
state.promptTag = false;
|
|
1316
|
-
if (line[end - 1] === "/" || line.includes("</Prompt>", end)) {
|
|
1317
|
-
return;
|
|
1318
|
-
}
|
|
1319
|
-
state.promptDepth += 1;
|
|
1320
|
-
};
|
|
1321
|
-
var ESCAPED_PUNCTUATION = /\\(?<char>[!-/:-@[-`{-~])/gu;
|
|
1322
|
-
var REF_DEFINITION = /^(?: {0,3}|[ \t]*(?:(?:>|(?:[-*+]|\d{1,9}[.)])[ \t])[ \t]*)+)\[(?<label>[^\]]+)\]:[ \t]*(?<rest>.*)$/u;
|
|
1323
|
-
var refDefinitionLabels = (lines) => {
|
|
1324
|
-
const labels = new Set;
|
|
1325
|
-
let fence = null;
|
|
1326
|
-
for (const [index, line] of lines.entries()) {
|
|
1327
|
-
const next = nextFenceState(line, fence);
|
|
1328
|
-
if (fence !== null || next !== null) {
|
|
1329
|
-
fence = next;
|
|
1330
|
-
continue;
|
|
1331
|
-
}
|
|
1332
|
-
const groups = line.match(REF_DEFINITION)?.groups;
|
|
1333
|
-
if (groups?.label === undefined || groups.label.trim() === "") {
|
|
1334
|
-
continue;
|
|
1335
|
-
}
|
|
1336
|
-
const destination = groups.rest ?? "";
|
|
1337
|
-
if (destination === "" && (lines[index + 1] ?? "").trim() === "") {
|
|
1338
|
-
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);
|
|
1339
1156
|
}
|
|
1340
|
-
labels.add(groups.label.trim().replaceAll(/\s+/gu, " ").toLowerCase());
|
|
1341
|
-
}
|
|
1342
|
-
return labels;
|
|
1343
|
-
};
|
|
1344
|
-
var toHeading = (depth, raw, slugger, isRefDefined) => {
|
|
1345
|
-
const unescaped = raw.replaceAll(ESCAPED_PUNCTUATION, "$<char>");
|
|
1346
|
-
const markers = parseHeadingMarkers(unescaped, isRefDefined);
|
|
1347
|
-
const text = markers.text.trim();
|
|
1348
|
-
if (text === "" && (markers.id !== undefined || markers.toc !== undefined)) {
|
|
1349
|
-
return {
|
|
1350
|
-
heading: { depth, slug: slugger.slug(unescaped), text: unescaped },
|
|
1351
|
-
pinned: false
|
|
1352
|
-
};
|
|
1353
|
-
}
|
|
1354
|
-
if (markers.id !== undefined) {
|
|
1355
|
-
occupySlug(slugger, markers.id);
|
|
1356
|
-
return { heading: { depth, slug: markers.id, text }, pinned: true };
|
|
1357
|
-
}
|
|
1358
|
-
return { heading: { depth, slug: slugger.slug(text), text }, pinned: false };
|
|
1359
|
-
};
|
|
1360
|
-
var pushHeading = (headings, state, scanned, line) => {
|
|
1361
|
-
headings.push(scanned.heading);
|
|
1362
|
-
state.sites.push({ line, pinned: scanned.pinned });
|
|
1363
|
-
};
|
|
1364
|
-
var noteCurlyMarker = (text, line, state) => {
|
|
1365
|
-
const id = text.match(BARE_CURLY_MARKER)?.groups?.id;
|
|
1366
|
-
if (id !== undefined) {
|
|
1367
|
-
state.curlyMarkers.push({ id, line });
|
|
1368
1157
|
}
|
|
1158
|
+
return times;
|
|
1369
1159
|
};
|
|
1370
|
-
var
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
const text = (atx.groups.text ?? "").trim();
|
|
1376
|
-
pushHeading(headings, state, toHeading(depth, text, slugger, isRefDefined), state.line);
|
|
1377
|
-
noteCurlyMarker(text, state.line, state);
|
|
1378
|
-
state.paragraph = [];
|
|
1379
|
-
return;
|
|
1380
|
-
}
|
|
1381
|
-
const setext = line.match(SETEXT_UNDERLINE);
|
|
1382
|
-
if (setext?.groups && state.paragraph.length > 0) {
|
|
1383
|
-
const depth = setext.groups.marker?.startsWith("=") ? 1 : 2;
|
|
1384
|
-
const text = state.paragraph.join(" ").trim();
|
|
1385
|
-
pushHeading(headings, state, toHeading(depth, text, slugger, isRefDefined), state.line - 1);
|
|
1386
|
-
noteCurlyMarker(text, state.paragraphStart, state);
|
|
1387
|
-
state.paragraph = [];
|
|
1388
|
-
return;
|
|
1389
|
-
}
|
|
1390
|
-
if (line.trim() === "" || THEMATIC_BREAK.test(line) || PARAGRAPH_INTERRUPT.test(line)) {
|
|
1391
|
-
state.paragraph = [];
|
|
1392
|
-
return;
|
|
1393
|
-
}
|
|
1394
|
-
if (state.paragraph.length === 0) {
|
|
1395
|
-
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;
|
|
1396
1165
|
}
|
|
1397
|
-
state.paragraph.push(line.trim());
|
|
1398
1166
|
};
|
|
1399
|
-
var
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
state.fence = next;
|
|
1403
|
-
state.paragraph = [];
|
|
1404
|
-
return;
|
|
1405
|
-
}
|
|
1406
|
-
const trimmed = line.trimStart();
|
|
1407
|
-
if (state.promptTag) {
|
|
1408
|
-
finishPromptTag(trimmed, 0, state);
|
|
1409
|
-
state.paragraph = [];
|
|
1410
|
-
return;
|
|
1411
|
-
}
|
|
1412
|
-
if (PROMPT_OPEN.test(trimmed)) {
|
|
1413
|
-
finishPromptTag(trimmed, "<Prompt".length, state);
|
|
1414
|
-
state.paragraph = [];
|
|
1415
|
-
return;
|
|
1416
|
-
}
|
|
1417
|
-
if (state.promptDepth > 0) {
|
|
1418
|
-
if (PROMPT_CLOSE.test(line)) {
|
|
1419
|
-
state.promptDepth -= 1;
|
|
1420
|
-
}
|
|
1421
|
-
state.paragraph = [];
|
|
1422
|
-
return;
|
|
1167
|
+
var gitLastModifiedTimes = (root, contentRoots, sourcePaths, repositoryRoot) => {
|
|
1168
|
+
if (sourcePaths.length === 0 || contentRoots.length === 0) {
|
|
1169
|
+
return new Map;
|
|
1423
1170
|
}
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
const headings = [];
|
|
1428
|
-
const slugger = new GithubSlugger;
|
|
1429
|
-
const state = {
|
|
1430
|
-
anchorLines: [],
|
|
1431
|
-
curlyMarkers: [],
|
|
1432
|
-
fence: null,
|
|
1433
|
-
line: 0,
|
|
1434
|
-
paragraph: [],
|
|
1435
|
-
paragraphStart: 0,
|
|
1436
|
-
promptDepth: 0,
|
|
1437
|
-
promptTag: false,
|
|
1438
|
-
sites: []
|
|
1439
|
-
};
|
|
1440
|
-
const { lines, offset } = linesWithoutFrontMatter(body);
|
|
1441
|
-
const definedLabels = refDefinitionLabels(lines);
|
|
1442
|
-
const isRefDefined = (label) => definedLabels.has(label.toLowerCase());
|
|
1443
|
-
for (const [index, line] of lines.entries()) {
|
|
1444
|
-
state.line = index + offset + 1;
|
|
1445
|
-
scanHeadingLine(line, state, slugger, headings, isRefDefined);
|
|
1446
|
-
}
|
|
1447
|
-
const anchors = new Set;
|
|
1448
|
-
const markup = state.anchorLines.join(`
|
|
1449
|
-
`).replaceAll(HTML_COMMENT, " ");
|
|
1450
|
-
for (const match of markup.matchAll(HTML_ID)) {
|
|
1451
|
-
const id = match.groups?.quoted ?? match.groups?.jsx ?? match.groups?.bare;
|
|
1452
|
-
if (id !== undefined) {
|
|
1453
|
-
anchors.add(id);
|
|
1454
|
-
}
|
|
1171
|
+
const gitRoot = repositoryRoot === undefined ? gitRepositoryRoot(root) : repositoryRoot;
|
|
1172
|
+
if (gitRoot === null) {
|
|
1173
|
+
return new Map;
|
|
1455
1174
|
}
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
const target = match.groups?.target;
|
|
1475
|
-
if (target === undefined || match.index === undefined) {
|
|
1476
|
-
continue;
|
|
1477
|
-
}
|
|
1478
|
-
const targetOffset = targetOffsetIn(match[0], target, match.groups?.title);
|
|
1479
|
-
const entry = {
|
|
1480
|
-
column: match.index + targetOffset + 1,
|
|
1481
|
-
line: lineNumber,
|
|
1482
|
-
target
|
|
1483
|
-
};
|
|
1484
|
-
if (masked[match.index - 1] === "!") {
|
|
1485
|
-
entry.image = true;
|
|
1486
|
-
}
|
|
1487
|
-
links.push(entry);
|
|
1488
|
-
const label = match[0].slice(0, targetOffset - "](".length);
|
|
1489
|
-
for (const image of label.matchAll(MD_IMAGE)) {
|
|
1490
|
-
const imageTarget = image.groups?.target;
|
|
1491
|
-
if (imageTarget === undefined || image.index === undefined) {
|
|
1492
|
-
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);
|
|
1493
1193
|
}
|
|
1494
|
-
links.push({
|
|
1495
|
-
column: match.index + image.index + targetOffsetIn(image[0], imageTarget, image.groups?.title) + 1,
|
|
1496
|
-
image: true,
|
|
1497
|
-
line: lineNumber,
|
|
1498
|
-
target: imageTarget
|
|
1499
|
-
});
|
|
1500
1194
|
}
|
|
1195
|
+
return result;
|
|
1196
|
+
} catch {
|
|
1197
|
+
return new Map;
|
|
1501
1198
|
}
|
|
1502
|
-
return next;
|
|
1503
1199
|
};
|
|
1504
|
-
var
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
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;
|
|
1512
1209
|
}
|
|
1513
|
-
return links;
|
|
1514
1210
|
};
|
|
1515
|
-
var
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
const next = nextFenceState(line, fence);
|
|
1519
|
-
if (fence !== null || next !== null) {
|
|
1520
|
-
return next;
|
|
1211
|
+
var lastModifiedShallowWarning = (root, undatedCount) => {
|
|
1212
|
+
if (undatedCount === 0 || !isShallowGitRepository(root)) {
|
|
1213
|
+
return [];
|
|
1521
1214
|
}
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
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."
|
|
1527
1221
|
}
|
|
1528
|
-
|
|
1529
|
-
return next;
|
|
1222
|
+
];
|
|
1530
1223
|
};
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
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;
|
|
1537
1242
|
}
|
|
1538
|
-
return
|
|
1539
|
-
};
|
|
1540
|
-
var strippedLineOffset = (raw, body) => raw ? Math.max(0, raw.split(`
|
|
1541
|
-
`).length - body.split(`
|
|
1542
|
-
`).length) : 0;
|
|
1543
|
-
var remapExpandedLinks = (links, origins, sourcePath) => links.map((link) => {
|
|
1544
|
-
const origin = origins[link.line - 1];
|
|
1545
|
-
if (!origin) {
|
|
1546
|
-
return link;
|
|
1547
|
-
}
|
|
1548
|
-
const remapped = { ...link, line: origin.line };
|
|
1549
|
-
if (origin.file !== sourcePath) {
|
|
1550
|
-
remapped.file = origin.file;
|
|
1551
|
-
}
|
|
1552
|
-
return remapped;
|
|
1553
|
-
});
|
|
1554
|
-
var entryIncludes = (entry) => entry.expanded && entry.expanded.includes.length > 0 ? entry.expanded.includes : undefined;
|
|
1555
|
-
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));
|
|
1556
|
-
var curlyMarkerDiagnostics = (entry, markers, sourceName) => markers.map(({ id, line }) => {
|
|
1557
|
-
const origin = entry.expanded?.origins[line - 1];
|
|
1558
|
-
const page = entry.sourcePath ?? `${sourceName}:${entry.ref}`;
|
|
1559
|
-
const inPartial = origin !== undefined && origin.file !== entry.sourcePath;
|
|
1560
|
-
return {
|
|
1561
|
-
code: "BLUME_MDX_CURLY_ANCHOR",
|
|
1562
|
-
file: origin?.file ?? page,
|
|
1563
|
-
line: origin?.line ?? line + strippedLineOffset(entry.raw, entry.body.text),
|
|
1564
|
-
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.`,
|
|
1565
|
-
severity: "error",
|
|
1566
|
-
suggestion: `Write \`[#${id}]\` or escape it as \`\\{#${id}\\}\` — both pin the same anchor in .md and .mdx.`
|
|
1567
|
-
};
|
|
1568
|
-
});
|
|
1569
|
-
var deriveTitle = (meta, headings, id) => {
|
|
1570
|
-
if (meta.title) {
|
|
1571
|
-
return meta.title;
|
|
1572
|
-
}
|
|
1573
|
-
const firstHeading = headings.find((h) => h.depth === 1) ?? headings[0];
|
|
1574
|
-
if (firstHeading) {
|
|
1575
|
-
return firstHeading.text;
|
|
1576
|
-
}
|
|
1577
|
-
const base = id.split("/").pop() ?? id;
|
|
1578
|
-
return titleCase(stripNumericPrefix(base.replace(extname2(base), "")));
|
|
1579
|
-
};
|
|
1580
|
-
var trimSlashes = (value) => trimChar(value, "/");
|
|
1581
|
-
var isStringValue = (value) => typeof value === "string";
|
|
1582
|
-
var withPrefix = (prefix, path) => {
|
|
1583
|
-
const clean = prefix ? trimSlashes(prefix) : "";
|
|
1584
|
-
return clean ? `${clean}/${path}` : path;
|
|
1585
|
-
};
|
|
1586
|
-
var placeEntryRef = (ref, ext, ctx) => {
|
|
1587
|
-
const { version, rest } = ctx.versions ? detectVersionRef(ref, ctx.versions) : { rest: ref, version: "" };
|
|
1588
|
-
const { navPath, locales } = ctx.i18n ? localePlacement(rest, ext, ctx.i18n) : { locales: [""], navPath: rest };
|
|
1589
|
-
return { locales, navPath, version };
|
|
1590
|
-
};
|
|
1591
|
-
var resolveEntryRoute = (entry, ext, frontmatterSlug, ctx) => {
|
|
1592
|
-
const { locales, navPath, version } = placeEntryRef(entry.ref, ext, ctx);
|
|
1593
|
-
const slugInput = frontmatterSlug ?? entry.slug;
|
|
1594
|
-
const slug = slugInput ? trimSlashes(slugInput) : "";
|
|
1595
|
-
const routeInput = withPrefix(ctx.prefix, slug ? `${slug}${ext}` : navPath);
|
|
1596
|
-
const { segments, groups, route: versionKey } = mapRoute(routeInput);
|
|
1597
|
-
return {
|
|
1598
|
-
groups,
|
|
1599
|
-
locales,
|
|
1600
|
-
logicalRoute: versionizeRoute(versionKey, version),
|
|
1601
|
-
navPath: withPrefix(ctx.prefix, navPath),
|
|
1602
|
-
segments,
|
|
1603
|
-
version,
|
|
1604
|
-
versionKey
|
|
1605
|
-
};
|
|
1606
|
-
};
|
|
1607
|
-
var localizedRoute = (logicalRoute, locale, i18n) => i18n ? localizeRoute(logicalRoute, locale, i18n) : logicalRoute;
|
|
1608
|
-
var isKeyCarrier = (segment) => typeof segment === "object" && segment !== null;
|
|
1609
|
-
var isSymbolKey = (key) => typeof key === "symbol";
|
|
1610
|
-
var segmentKey2 = (segment) => {
|
|
1611
|
-
const key = isKeyCarrier(segment) ? segment.key : segment;
|
|
1612
|
-
return isSymbolKey(key) ? String(key) : key;
|
|
1613
|
-
};
|
|
1614
|
-
var validateCustomKeys = (data, extend) => {
|
|
1615
|
-
const custom = {};
|
|
1616
|
-
const issues = [];
|
|
1617
|
-
for (const [key, schema] of Object.entries(extend)) {
|
|
1618
|
-
const outcome = schema["~standard"].validate(data[key]);
|
|
1619
|
-
if (outcome instanceof Promise) {
|
|
1620
|
-
issues.push({
|
|
1621
|
-
message: "Async schemas are not supported for custom frontmatter keys.",
|
|
1622
|
-
path: [key]
|
|
1623
|
-
});
|
|
1624
|
-
continue;
|
|
1625
|
-
}
|
|
1626
|
-
if (outcome.issues !== undefined) {
|
|
1627
|
-
issues.push(...outcome.issues.map((issue) => ({
|
|
1628
|
-
message: issue.message,
|
|
1629
|
-
path: [key, ...(issue.path ?? []).map(segmentKey2)]
|
|
1630
|
-
})));
|
|
1631
|
-
continue;
|
|
1632
|
-
}
|
|
1633
|
-
if (outcome.value !== undefined || Object.hasOwn(data, key)) {
|
|
1634
|
-
custom[key] = outcome.value;
|
|
1635
|
-
}
|
|
1636
|
-
}
|
|
1637
|
-
return {
|
|
1638
|
-
custom: Object.keys(custom).length > 0 ? custom : undefined,
|
|
1639
|
-
issues
|
|
1640
|
-
};
|
|
1641
|
-
};
|
|
1642
|
-
var parseEntryMeta = (entry, ctx) => {
|
|
1643
|
-
const entryType = isStringValue(entry.data.type) ? entry.data.type : ctx.defaultType;
|
|
1644
|
-
const typeExtend = ctx.typeFrontmatter?.[entryType];
|
|
1645
|
-
const extend = ctx.frontmatterExtend || typeExtend ? { ...ctx.frontmatterExtend, ...typeExtend } : undefined;
|
|
1646
|
-
const known = extend ? Object.fromEntries(Object.entries(entry.data).filter(([key]) => !Object.hasOwn(extend, key))) : entry.data;
|
|
1647
|
-
const result = pageMetaSchema.safeParse(known);
|
|
1648
|
-
const customResult = extend ? validateCustomKeys(entry.data, extend) : null;
|
|
1649
|
-
if (result.success && (customResult?.issues.length ?? 0) === 0) {
|
|
1650
|
-
return { custom: customResult?.custom, meta: result.data };
|
|
1651
|
-
}
|
|
1652
|
-
const source = entry.raw ?? (entry.sourcePath && existsSync(entry.sourcePath) ? readFileSync(entry.sourcePath, "utf-8") : undefined);
|
|
1653
|
-
const location = {
|
|
1654
|
-
code: "BLUME_FRONTMATTER_INVALID",
|
|
1655
|
-
file: entry.sourcePath ?? `${ctx.source.name}:${entry.ref}`,
|
|
1656
|
-
source
|
|
1657
|
-
};
|
|
1658
|
-
return {
|
|
1659
|
-
diagnostics: [
|
|
1660
|
-
...result.success ? [] : diagnosticsFromZod(result.error, location),
|
|
1661
|
-
...customResult ? diagnosticsFromIssues(customResult.issues, location) : []
|
|
1662
|
-
]
|
|
1663
|
-
};
|
|
1664
|
-
};
|
|
1665
|
-
var normalizeEntry = (entry, ctx) => {
|
|
1666
|
-
const { format } = entry.body;
|
|
1667
|
-
const ext = format === "mdx" ? ".mdx" : ".md";
|
|
1668
|
-
const parsed = parseEntryMeta(entry, ctx);
|
|
1669
|
-
if (parsed.diagnostics) {
|
|
1670
|
-
return { diagnostics: parsed.diagnostics, pages: [] };
|
|
1671
|
-
}
|
|
1672
|
-
const { meta } = parsed;
|
|
1673
|
-
if (meta.hidden) {
|
|
1674
|
-
meta.sidebar.hidden = true;
|
|
1675
|
-
}
|
|
1676
|
-
if (meta.noindex) {
|
|
1677
|
-
meta.seo.noindex = true;
|
|
1678
|
-
}
|
|
1679
|
-
const {
|
|
1680
|
-
groups,
|
|
1681
|
-
locales,
|
|
1682
|
-
logicalRoute,
|
|
1683
|
-
navPath,
|
|
1684
|
-
segments,
|
|
1685
|
-
version,
|
|
1686
|
-
versionKey
|
|
1687
|
-
} = resolveEntryRoute(entry, ext, meta.slug, {
|
|
1688
|
-
i18n: ctx.i18n,
|
|
1689
|
-
prefix: ctx.source.prefix,
|
|
1690
|
-
versions: ctx.versions
|
|
1691
|
-
});
|
|
1692
|
-
const bodyText = entry.expanded?.text ?? entry.body.text;
|
|
1693
|
-
const { anchors, curlyMarkers, headings } = scanBody(bodyText);
|
|
1694
|
-
const { staged } = ctx.source;
|
|
1695
|
-
const base = {
|
|
1696
|
-
anchors,
|
|
1697
|
-
body: staged ? { format, text: entry.raw ?? entry.body.text } : undefined,
|
|
1698
|
-
collection: staged ? "staged" : undefined,
|
|
1699
|
-
componentsUsed: format === "mdx" ? extractComponentTags(bodyText) : undefined,
|
|
1700
|
-
contentType: meta.type ?? ctx.defaultType,
|
|
1701
|
-
custom: parsed.custom,
|
|
1702
|
-
description: meta.description,
|
|
1703
|
-
editUrl: entry.editUrl,
|
|
1704
|
-
entryId: staged ? `${ctx.source.name}/${entry.ref}` : undefined,
|
|
1705
|
-
format,
|
|
1706
|
-
groups,
|
|
1707
|
-
headings,
|
|
1708
|
-
id: `${ctx.source.name}:${entry.ref}`,
|
|
1709
|
-
includes: entryIncludes(entry),
|
|
1710
|
-
lastModified: meta.lastModified ?? entry.lastModified,
|
|
1711
|
-
links: entryLinks(entry),
|
|
1712
|
-
meta,
|
|
1713
|
-
navPath,
|
|
1714
|
-
segments,
|
|
1715
|
-
source: { name: ctx.source.name, ref: entry.ref },
|
|
1716
|
-
sourcePath: entry.sourcePath,
|
|
1717
|
-
title: deriveTitle(meta, headings, navPath),
|
|
1718
|
-
translationKey: logicalRoute,
|
|
1719
|
-
version,
|
|
1720
|
-
versionKey
|
|
1721
|
-
};
|
|
1722
|
-
const pages = locales.map((locale) => ({
|
|
1723
|
-
...base,
|
|
1724
|
-
locale,
|
|
1725
|
-
route: withBasePath(ctx.basePath ?? "", localizedRoute(logicalRoute, locale, ctx.i18n))
|
|
1726
|
-
}));
|
|
1727
|
-
return {
|
|
1728
|
-
diagnostics: format === "mdx" ? curlyMarkerDiagnostics(entry, curlyMarkers, ctx.source.name) : [],
|
|
1729
|
-
pages
|
|
1730
|
-
};
|
|
1731
|
-
};
|
|
1732
|
-
|
|
1733
|
-
// src/core/includes.ts
|
|
1734
|
-
var CONTENT_EXTENSIONS = new Set([".md", ".mdx"]);
|
|
1735
|
-
var INCLUDE_STATEMENT = /^<include(?<attrs>(?:\s+[a-z][\w-]*(?:\s*=\s*(?:"[^"]*"|'[^']*'))?)*)\s*>\s*(?<target>[^<>\s](?:[^<>]*[^<>\s])?)\s*<\/include\s*>$/u;
|
|
1736
|
-
var INCLUDE_ATTRIBUTE = /(?<name>[a-z][\w-]*)(?:\s*=\s*(?:"(?<double>[^"]*)"|'(?<single>[^']*)'))?/gu;
|
|
1737
|
-
var hasIncludeStatements = (text) => text.includes("<include");
|
|
1738
|
-
var INDENTED_CODE = /^(?: {4}|\t)/u;
|
|
1739
|
-
var SETEXT_UNDERLINE2 = /^ {0,3}(?:=+|-+)\s*$/u;
|
|
1740
|
-
var COMMENT_DELIMITERS = {
|
|
1741
|
-
md: { close: "-->", open: "<!--" },
|
|
1742
|
-
mdx: { close: "*/}", open: "{/*" }
|
|
1743
|
-
};
|
|
1744
|
-
var advanceCommentState = (line, delimiters, inComment) => {
|
|
1745
|
-
let inside = inComment;
|
|
1746
|
-
let cursor = 0;
|
|
1747
|
-
for (;; ) {
|
|
1748
|
-
const marker = inside ? delimiters.close : delimiters.open;
|
|
1749
|
-
const index = line.indexOf(marker, cursor);
|
|
1750
|
-
if (index === -1) {
|
|
1751
|
-
return inside;
|
|
1752
|
-
}
|
|
1753
|
-
inside = !inside;
|
|
1754
|
-
cursor = index + marker.length;
|
|
1755
|
-
}
|
|
1756
|
-
};
|
|
1757
|
-
var parseIncludeStatement = (line) => {
|
|
1758
|
-
const match = INCLUDE_STATEMENT.exec(line);
|
|
1759
|
-
if (!match?.groups) {
|
|
1760
|
-
return null;
|
|
1761
|
-
}
|
|
1762
|
-
const attributes = {};
|
|
1763
|
-
for (const attr of (match.groups.attrs ?? "").matchAll(INCLUDE_ATTRIBUTE)) {
|
|
1764
|
-
const name = attr.groups?.name;
|
|
1765
|
-
const value = attr.groups?.double ?? attr.groups?.single;
|
|
1766
|
-
if (name === "lang" && value) {
|
|
1767
|
-
attributes.lang = value;
|
|
1768
|
-
}
|
|
1769
|
-
if (name === "meta" && value) {
|
|
1770
|
-
attributes.meta = value;
|
|
1771
|
-
}
|
|
1772
|
-
}
|
|
1773
|
-
return { attributes, target: match.groups.target ?? "" };
|
|
1774
|
-
};
|
|
1775
|
-
var parseIncludeLine = (line) => INDENTED_CODE.test(line) ? null : parseIncludeStatement(line.trim());
|
|
1776
|
-
var DOCS_SUGGESTION = "Include paths resolve relative to the including file; paths starting with / resolve from the content root.";
|
|
1777
|
-
var includeError = (code, message, file, line, suggestion) => ({ code, file, line, message, severity: "error", suggestion });
|
|
1778
|
-
var escapesRoot = (root, path) => {
|
|
1779
|
-
const rel = relative(root, path);
|
|
1780
|
-
return rel === ".." || rel.startsWith("../");
|
|
1781
|
-
};
|
|
1782
|
-
var resolveIncludePath = (target, filePath, ctx, line) => {
|
|
1783
|
-
if (target.startsWith("/")) {
|
|
1784
|
-
if (!ctx.contentRoot) {
|
|
1785
|
-
return {
|
|
1786
|
-
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.")
|
|
1787
|
-
};
|
|
1788
|
-
}
|
|
1789
|
-
const path = join(ctx.contentRoot, target);
|
|
1790
|
-
if (escapesRoot(ctx.contentRoot, path)) {
|
|
1791
|
-
return {
|
|
1792
|
-
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.")
|
|
1793
|
-
};
|
|
1794
|
-
}
|
|
1795
|
-
return { path };
|
|
1796
|
-
}
|
|
1797
|
-
const path = resolve(dirname(filePath), target);
|
|
1798
|
-
if (ctx.contentRoot && escapesRoot(ctx.contentRoot, path)) {
|
|
1799
|
-
return {
|
|
1800
|
-
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.")
|
|
1801
|
-
};
|
|
1802
|
-
}
|
|
1803
|
-
return { path };
|
|
1804
|
-
};
|
|
1805
|
-
var rebaseImageLine = (line, fromDir, toDir) => {
|
|
1806
|
-
const masked = line.replaceAll(INLINE_CODE, (span) => " ".repeat(span.length));
|
|
1807
|
-
let out = "";
|
|
1808
|
-
let cursor = 0;
|
|
1809
|
-
for (const match of masked.matchAll(MD_IMAGE)) {
|
|
1810
|
-
const target = match.groups?.target ?? "";
|
|
1811
|
-
if (target.startsWith("/") || target.startsWith("#") || URL.canParse(target)) {
|
|
1812
|
-
continue;
|
|
1813
|
-
}
|
|
1814
|
-
const rebased = relative(toDir, resolve(fromDir, target));
|
|
1815
|
-
const url = rebased.startsWith(".") ? rebased : `./${rebased}`;
|
|
1816
|
-
const offset = (match.index ?? 0) + targetOffsetIn(match[0], target, match.groups?.title);
|
|
1817
|
-
out += line.slice(cursor, offset) + url;
|
|
1818
|
-
cursor = offset + target.length;
|
|
1819
|
-
}
|
|
1820
|
-
return out + line.slice(cursor);
|
|
1821
|
-
};
|
|
1822
|
-
var rebaseImages = (lines, fromDir, toDir) => {
|
|
1823
|
-
if (fromDir === toDir) {
|
|
1824
|
-
return lines;
|
|
1825
|
-
}
|
|
1826
|
-
let fence = null;
|
|
1827
|
-
return lines.map((line) => {
|
|
1828
|
-
const next = nextFenceState(line, fence);
|
|
1829
|
-
const inFence = fence !== null || next !== null;
|
|
1830
|
-
fence = next;
|
|
1831
|
-
return inFence ? line : rebaseImageLine(line, fromDir, toDir);
|
|
1832
|
-
});
|
|
1833
|
-
};
|
|
1834
|
-
var codeBlockLines = (content, path, attributes) => {
|
|
1835
|
-
const body = content.replace(/\n$/u, "");
|
|
1836
|
-
let longestRun = 0;
|
|
1837
|
-
for (const run of body.match(/`+/gu) ?? []) {
|
|
1838
|
-
longestRun = Math.max(longestRun, run.length);
|
|
1839
|
-
}
|
|
1840
|
-
const fence = "`".repeat(Math.max(3, longestRun + 1));
|
|
1841
|
-
const ext = extname3(path);
|
|
1842
|
-
const lang = attributes.lang ?? (ext ? ext.slice(1) : "text");
|
|
1843
|
-
const meta = attributes.meta ? ` ${attributes.meta}` : "";
|
|
1844
|
-
return [`${fence}${lang}${meta}`, ...body.split(`
|
|
1845
|
-
`), fence];
|
|
1846
|
-
};
|
|
1847
|
-
var expandStatement = async (statement, filePath, line, ctx, stack) => {
|
|
1848
|
-
const resolved = resolveIncludePath(statement.target, filePath, ctx, line);
|
|
1849
|
-
if ("error" in resolved) {
|
|
1850
|
-
return resolved;
|
|
1851
|
-
}
|
|
1852
|
-
const { path } = resolved;
|
|
1853
|
-
if (stack.includes(path)) {
|
|
1854
|
-
return {
|
|
1855
|
-
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.")
|
|
1856
|
-
};
|
|
1857
|
-
}
|
|
1858
|
-
let content;
|
|
1859
|
-
try {
|
|
1860
|
-
content = await readFile(path, "utf-8");
|
|
1861
|
-
} catch (error) {
|
|
1862
|
-
return {
|
|
1863
|
-
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)
|
|
1864
|
-
};
|
|
1865
|
-
}
|
|
1866
|
-
ctx.includes.add(path);
|
|
1867
|
-
const asContent = !statement.attributes.lang && CONTENT_EXTENSIONS.has(extname3(path).toLowerCase());
|
|
1868
|
-
if (!asContent) {
|
|
1869
|
-
const lines = codeBlockLines(content, path, statement.attributes);
|
|
1870
|
-
return {
|
|
1871
|
-
lines,
|
|
1872
|
-
origins: lines.map((_, i) => ({ file: path, line: Math.max(1, i) }))
|
|
1873
|
-
};
|
|
1874
|
-
}
|
|
1875
|
-
const parsed = frontmatter_default(content);
|
|
1876
|
-
const body = parsed.content;
|
|
1877
|
-
const strippedOffset = Math.max(0, content.split(`
|
|
1878
|
-
`).length - body.split(`
|
|
1879
|
-
`).length);
|
|
1880
|
-
const expanded = await expandLines(body, path, strippedOffset, ctx, [
|
|
1881
|
-
...stack,
|
|
1882
|
-
path
|
|
1883
|
-
]);
|
|
1884
|
-
const lines = [...expanded.lines];
|
|
1885
|
-
const origins = [...expanded.origins];
|
|
1886
|
-
while (lines.at(-1)?.trim() === "") {
|
|
1887
|
-
lines.pop();
|
|
1888
|
-
origins.pop();
|
|
1889
|
-
}
|
|
1890
|
-
while (lines[0]?.trim() === "") {
|
|
1891
|
-
lines.shift();
|
|
1892
|
-
origins.shift();
|
|
1893
|
-
}
|
|
1894
|
-
return {
|
|
1895
|
-
lines: rebaseImages(lines, dirname(path), dirname(filePath)),
|
|
1896
|
-
origins
|
|
1897
|
-
};
|
|
1898
|
-
};
|
|
1899
|
-
var expandLines = async (body, filePath, lineOffset, ctx, stack) => {
|
|
1900
|
-
const sourceLines = body.split(`
|
|
1901
|
-
`);
|
|
1902
|
-
const isMdx = extname3(filePath).toLowerCase() === ".mdx";
|
|
1903
|
-
const delimiters = COMMENT_DELIMITERS[isMdx ? "mdx" : "md"];
|
|
1904
|
-
let fence = null;
|
|
1905
|
-
let inComment = false;
|
|
1906
|
-
const statements = sourceLines.map((line, index) => {
|
|
1907
|
-
if (inComment) {
|
|
1908
|
-
inComment = advanceCommentState(line, delimiters, true);
|
|
1909
|
-
return null;
|
|
1910
|
-
}
|
|
1911
|
-
const next = nextFenceState(line, fence);
|
|
1912
|
-
const inFence = fence !== null || next !== null;
|
|
1913
|
-
fence = next;
|
|
1914
|
-
if (inFence) {
|
|
1915
|
-
return null;
|
|
1916
|
-
}
|
|
1917
|
-
inComment = advanceCommentState(line, delimiters, false);
|
|
1918
|
-
if (inComment || !hasIncludeStatements(line)) {
|
|
1919
|
-
return null;
|
|
1920
|
-
}
|
|
1921
|
-
const statement = isMdx ? parseIncludeStatement(line.trim()) : parseIncludeLine(line);
|
|
1922
|
-
if (statement && !isMdx && SETEXT_UNDERLINE2.test(sourceLines[index + 1] ?? "")) {
|
|
1923
|
-
return null;
|
|
1924
|
-
}
|
|
1925
|
-
return statement;
|
|
1926
|
-
});
|
|
1927
|
-
const expansions = await Promise.all(statements.map((statement, index) => statement ? expandStatement(statement, filePath, lineOffset + index + 1, ctx, stack) : null));
|
|
1928
|
-
const lines = [];
|
|
1929
|
-
const origins = [];
|
|
1930
|
-
for (const [index, line] of sourceLines.entries()) {
|
|
1931
|
-
const rawLine = lineOffset + index + 1;
|
|
1932
|
-
const expanded = expansions[index];
|
|
1933
|
-
if (!expanded || "error" in expanded) {
|
|
1934
|
-
if (expanded) {
|
|
1935
|
-
ctx.errors.push(expanded.error);
|
|
1936
|
-
}
|
|
1937
|
-
lines.push(line);
|
|
1938
|
-
origins.push({ file: filePath, line: rawLine });
|
|
1939
|
-
continue;
|
|
1940
|
-
}
|
|
1941
|
-
const pad = () => {
|
|
1942
|
-
lines.push("");
|
|
1943
|
-
origins.push({ file: filePath, line: rawLine });
|
|
1944
|
-
};
|
|
1945
|
-
if (lines.at(-1)?.trim()) {
|
|
1946
|
-
pad();
|
|
1947
|
-
}
|
|
1948
|
-
lines.push(...expanded.lines);
|
|
1949
|
-
origins.push(...expanded.origins);
|
|
1950
|
-
if (sourceLines[index + 1]?.trim()) {
|
|
1951
|
-
pad();
|
|
1952
|
-
}
|
|
1953
|
-
}
|
|
1954
|
-
return { lines, origins };
|
|
1955
|
-
};
|
|
1956
|
-
var expandIncludes = async (body, options) => {
|
|
1957
|
-
const ctx = {
|
|
1958
|
-
contentRoot: options.contentRoot,
|
|
1959
|
-
errors: [],
|
|
1960
|
-
includes: new Set
|
|
1961
|
-
};
|
|
1962
|
-
const { lines, origins } = await expandLines(body, options.sourcePath, options.lineOffset ?? 0, ctx, [options.sourcePath]);
|
|
1963
|
-
return {
|
|
1964
|
-
errors: ctx.errors,
|
|
1965
|
-
includes: [...ctx.includes],
|
|
1966
|
-
origins,
|
|
1967
|
-
text: lines.join(`
|
|
1968
|
-
`)
|
|
1969
|
-
};
|
|
1970
|
-
};
|
|
1971
|
-
var buildIncludeGraph = (pages) => {
|
|
1972
|
-
const graph = {};
|
|
1973
|
-
for (const page of pages) {
|
|
1974
|
-
const { sourcePath } = page;
|
|
1975
|
-
if (!sourcePath) {
|
|
1976
|
-
continue;
|
|
1977
|
-
}
|
|
1978
|
-
for (const partial of page.includes ?? []) {
|
|
1979
|
-
const includers = graph[partial] ?? [];
|
|
1980
|
-
graph[partial] = includers;
|
|
1981
|
-
if (!includers.includes(sourcePath)) {
|
|
1982
|
-
includers.push(sourcePath);
|
|
1983
|
-
}
|
|
1984
|
-
}
|
|
1985
|
-
}
|
|
1986
|
-
return graph;
|
|
1987
|
-
};
|
|
1988
|
-
|
|
1989
|
-
// src/core/last-modified.ts
|
|
1990
|
-
import { execFileSync } from "node:child_process";
|
|
1991
|
-
import { relative as relative2 } from "pathe";
|
|
1992
|
-
var GIT_LOCATION_VARS = new Set([
|
|
1993
|
-
"GIT_COMMON_DIR",
|
|
1994
|
-
"GIT_DIR",
|
|
1995
|
-
"GIT_INDEX_FILE",
|
|
1996
|
-
"GIT_OBJECT_DIRECTORY",
|
|
1997
|
-
"GIT_PREFIX",
|
|
1998
|
-
"GIT_WORK_TREE"
|
|
1999
|
-
]);
|
|
2000
|
-
var gitEnv = () => Object.fromEntries(Object.entries(process.env).filter(([key]) => !GIT_LOCATION_VARS.has(key)));
|
|
2001
|
-
var resolveLastModifiedConfig = (value) => {
|
|
2002
|
-
if (value === false) {
|
|
2003
|
-
return { enabled: false, source: "git" };
|
|
2004
|
-
}
|
|
2005
|
-
if (value === true) {
|
|
2006
|
-
return { enabled: true, source: "git" };
|
|
2007
|
-
}
|
|
2008
|
-
return { enabled: true, source: value.type };
|
|
2009
|
-
};
|
|
2010
|
-
var parseGitLog = (output) => {
|
|
2011
|
-
const times = new Map;
|
|
2012
|
-
let current = null;
|
|
2013
|
-
for (const line of output.split(`
|
|
2014
|
-
`)) {
|
|
2015
|
-
if (line.startsWith("\x00")) {
|
|
2016
|
-
current = line.slice(1);
|
|
2017
|
-
} else if (line && current && !times.has(line)) {
|
|
2018
|
-
times.set(line, current);
|
|
2019
|
-
}
|
|
2020
|
-
}
|
|
2021
|
-
return times;
|
|
2022
|
-
};
|
|
2023
|
-
var gitRepositoryRoot = (root) => {
|
|
2024
|
-
try {
|
|
2025
|
-
return execFileSync("git", ["-C", root, "rev-parse", "--show-toplevel"], { encoding: "utf-8", env: gitEnv(), stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
2026
|
-
} catch {
|
|
2027
|
-
return null;
|
|
2028
|
-
}
|
|
2029
|
-
};
|
|
2030
|
-
var gitLastModifiedTimes = (root, contentRoots, sourcePaths, repositoryRoot) => {
|
|
2031
|
-
if (sourcePaths.length === 0 || contentRoots.length === 0) {
|
|
2032
|
-
return new Map;
|
|
2033
|
-
}
|
|
2034
|
-
const gitRoot = repositoryRoot === undefined ? gitRepositoryRoot(root) : repositoryRoot;
|
|
2035
|
-
if (gitRoot === null) {
|
|
2036
|
-
return new Map;
|
|
2037
|
-
}
|
|
2038
|
-
try {
|
|
2039
|
-
const output = execFileSync("git", [
|
|
2040
|
-
"-C",
|
|
2041
|
-
root,
|
|
2042
|
-
"-c",
|
|
2043
|
-
"core.quotePath=false",
|
|
2044
|
-
"log",
|
|
2045
|
-
"--format=%x00%cI",
|
|
2046
|
-
"--name-only",
|
|
2047
|
-
"--",
|
|
2048
|
-
...contentRoots
|
|
2049
|
-
], { encoding: "utf-8", env: gitEnv(), maxBuffer: 256 * 1024 * 1024 });
|
|
2050
|
-
const byRepoPath = parseGitLog(output);
|
|
2051
|
-
const result = new Map;
|
|
2052
|
-
for (const sourcePath of sourcePaths) {
|
|
2053
|
-
const iso = byRepoPath.get(relative2(gitRoot, sourcePath));
|
|
2054
|
-
if (iso) {
|
|
2055
|
-
result.set(sourcePath, iso);
|
|
2056
|
-
}
|
|
2057
|
-
}
|
|
2058
|
-
return result;
|
|
2059
|
-
} catch {
|
|
2060
|
-
return new Map;
|
|
2061
|
-
}
|
|
2062
|
-
};
|
|
2063
|
-
var isShallowGitRepository = (root) => {
|
|
2064
|
-
try {
|
|
2065
|
-
return execFileSync("git", ["-C", root, "rev-parse", "--is-shallow-repository"], {
|
|
2066
|
-
encoding: "utf-8",
|
|
2067
|
-
env: gitEnv(),
|
|
2068
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
2069
|
-
}).trim() === "true";
|
|
2070
|
-
} catch {
|
|
2071
|
-
return false;
|
|
2072
|
-
}
|
|
2073
|
-
};
|
|
2074
|
-
var lastModifiedShallowWarning = (root, undatedCount) => {
|
|
2075
|
-
if (undatedCount === 0 || !isShallowGitRepository(root)) {
|
|
2076
|
-
return [];
|
|
2077
|
-
}
|
|
2078
|
-
return [
|
|
2079
|
-
{
|
|
2080
|
-
code: "BLUME_SHALLOW_GIT_HISTORY",
|
|
2081
|
-
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.`,
|
|
2082
|
-
severity: "warning",
|
|
2083
|
-
suggestion: "Fetch full history in CI: set the VERCEL_DEEP_CLONE=true environment variable on Vercel, or fetch-depth: 0 for actions/checkout."
|
|
2084
|
-
}
|
|
2085
|
-
];
|
|
2086
|
-
};
|
|
2087
|
-
|
|
2088
|
-
// src/core/meta.ts
|
|
2089
|
-
import { basename, dirname as dirname2, relative as relative3 } from "pathe";
|
|
2090
|
-
import { glob } from "tinyglobby";
|
|
2091
|
-
var META_FILES = [
|
|
2092
|
-
"**/meta.ts",
|
|
2093
|
-
"**/meta.js",
|
|
2094
|
-
"**/meta.mjs",
|
|
2095
|
-
"**/meta.$.ts",
|
|
2096
|
-
"**/meta.$.js",
|
|
2097
|
-
"**/meta.$.mjs"
|
|
2098
|
-
];
|
|
2099
|
-
var isMetaFactory = (mod) => typeof mod === "function";
|
|
2100
|
-
var resolveMeta = async (mod) => isMetaFactory(mod) ? await mod() : mod;
|
|
2101
|
-
var metaKeyFor = (prefix, dir) => {
|
|
2102
|
-
const clean = prefix ? trimChar(prefix, "/") : "";
|
|
2103
|
-
if (!clean) {
|
|
2104
|
-
return dir;
|
|
2105
|
-
}
|
|
2106
|
-
return dir ? `${clean}/${dir}` : clean;
|
|
1243
|
+
return dir ? `${clean}/${dir}` : clean;
|
|
2107
1244
|
};
|
|
2108
1245
|
var discoverFolderMeta = async (sources, options = {}) => {
|
|
2109
1246
|
const list = Array.isArray(sources) ? sources : [{ root: sources }];
|
|
@@ -2135,7 +1272,7 @@ var discoverFolderMeta = async (sources, options = {}) => {
|
|
|
2135
1272
|
}));
|
|
2136
1273
|
for (const { loaded, source } of perSource) {
|
|
2137
1274
|
for (const entry of loaded) {
|
|
2138
|
-
const dir =
|
|
1275
|
+
const dir = relative2(source.root, dirname(entry.file));
|
|
2139
1276
|
const [head, ...tail] = dir.split("/");
|
|
2140
1277
|
const version = head && versionDirs.has(head) ? head : "";
|
|
2141
1278
|
const afterVersion = version ? tail : [head ?? "", ...tail];
|
|
@@ -2168,1287 +1305,345 @@ var discoverFolderMeta = async (sources, options = {}) => {
|
|
|
2168
1305
|
};
|
|
2169
1306
|
|
|
2170
1307
|
// src/core/sources/resolve.ts
|
|
2171
|
-
import {
|
|
1308
|
+
import { join as join7 } from "pathe";
|
|
2172
1309
|
|
|
2173
|
-
// src/core/sources/
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
const seedBaseline = async () => {
|
|
2183
|
-
try {
|
|
2184
|
-
const { entries } = await seed();
|
|
2185
|
-
last ||= entriesDigest(entries);
|
|
2186
|
-
} catch {}
|
|
2187
|
-
};
|
|
2188
|
-
seedBaseline();
|
|
2189
|
-
}
|
|
2190
|
-
const tick = async () => {
|
|
2191
|
-
try {
|
|
2192
|
-
const { entries } = await load();
|
|
2193
|
-
const next = entriesDigest(entries);
|
|
2194
|
-
if (last && next !== last) {
|
|
2195
|
-
onChange();
|
|
2196
|
-
}
|
|
2197
|
-
last = next;
|
|
2198
|
-
} catch {}
|
|
2199
|
-
};
|
|
2200
|
-
const timer = setInterval(() => {
|
|
2201
|
-
tick();
|
|
2202
|
-
}, intervalSeconds * 1000);
|
|
2203
|
-
return () => clearInterval(timer);
|
|
2204
|
-
};
|
|
2205
|
-
var snapshotCache = (cacheDir) => {
|
|
2206
|
-
const file = join2(cacheDir, "entries.json");
|
|
2207
|
-
return {
|
|
2208
|
-
read: async () => {
|
|
2209
|
-
try {
|
|
2210
|
-
return JSON.parse(await readFile2(file, "utf-8"));
|
|
2211
|
-
} catch {
|
|
2212
|
-
return [];
|
|
2213
|
-
}
|
|
2214
|
-
},
|
|
2215
|
-
write: async (entries) => {
|
|
2216
|
-
try {
|
|
2217
|
-
await mkdir(cacheDir, { recursive: true });
|
|
2218
|
-
await writeFile(file, `${JSON.stringify(entries)}
|
|
2219
|
-
`, "utf-8");
|
|
2220
|
-
} catch {}
|
|
2221
|
-
}
|
|
2222
|
-
};
|
|
2223
|
-
};
|
|
2224
|
-
var loadWithCache = async (name, cache, fetchEntries, refresh = true) => {
|
|
2225
|
-
if (!refresh) {
|
|
2226
|
-
const cached = await cache.read();
|
|
2227
|
-
if (cached.length > 0) {
|
|
2228
|
-
return { diagnostics: [], entries: cached };
|
|
2229
|
-
}
|
|
2230
|
-
}
|
|
2231
|
-
try {
|
|
2232
|
-
const entries = await fetchEntries();
|
|
2233
|
-
await cache.write(entries);
|
|
2234
|
-
return { diagnostics: [], entries };
|
|
2235
|
-
} catch (error) {
|
|
2236
|
-
const fallback = await cache.read();
|
|
2237
|
-
if (fallback.length > 0) {
|
|
2238
|
-
const diagnostic = {
|
|
2239
|
-
code: "BLUME_SOURCE_OFFLINE",
|
|
2240
|
-
message: `Source "${name}" could not be fetched (${error.message}); served ${fallback.length} cached entries.`,
|
|
2241
|
-
severity: "warning"
|
|
2242
|
-
};
|
|
2243
|
-
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;
|
|
2244
1319
|
}
|
|
2245
|
-
throw new BlumeError({
|
|
2246
|
-
code: "BLUME_SOURCE_FETCH_FAILED",
|
|
2247
|
-
message: `Source "${name}" failed to load and no cache is available: ${error.message}`,
|
|
2248
|
-
severity: "error"
|
|
2249
|
-
});
|
|
2250
1320
|
}
|
|
1321
|
+
return current;
|
|
2251
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
|
+
});
|
|
2252
1333
|
|
|
2253
|
-
// src/
|
|
2254
|
-
var
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
"
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
"patch",
|
|
2262
|
-
"trace"
|
|
2263
|
-
];
|
|
2264
|
-
var UNTAGGED = "Operations";
|
|
2265
|
-
var CASE_BOUNDARY = /(?<before>[\p{Ll}\p{N}])(?<capital>\p{Lu})/gu;
|
|
2266
|
-
var ACRONYM_BOUNDARY = /(?<acronym>\p{Lu})(?<word>\p{Lu}\p{Ll})/gu;
|
|
2267
|
-
var splitIdentifier = (identifier) => identifier.replace(CASE_BOUNDARY, "$<before>-$<capital>").replace(ACRONYM_BOUNDARY, "$<acronym>-$<word>");
|
|
2268
|
-
var operationKey = (method, path, operationId) => {
|
|
2269
|
-
const fromId = operationId ? slugify(splitIdentifier(operationId)) : "";
|
|
2270
|
-
return fromId || slugify(`${method}-${path}`);
|
|
2271
|
-
};
|
|
2272
|
-
var specOf = (specs, source) => Object.hasOwn(specs, source) ? specs[source] : undefined;
|
|
2273
|
-
var operationOf = (spec, id) => Object.hasOwn(spec.operations, id) ? spec.operations[id] : undefined;
|
|
2274
|
-
var specAddresses = (spec) => {
|
|
2275
|
-
const addresses = [];
|
|
2276
|
-
if (spec.kind === "graphql") {
|
|
2277
|
-
if (spec.endpoint) {
|
|
2278
|
-
addresses.push(spec.endpoint);
|
|
2279
|
-
}
|
|
2280
|
-
return { addresses, label: "Endpoint" };
|
|
2281
|
-
}
|
|
2282
|
-
if (spec.kind === "asyncapi") {
|
|
2283
|
-
const servers = spec.document.servers ?? {};
|
|
2284
|
-
for (const server of Object.values(servers)) {
|
|
2285
|
-
if (server?.host) {
|
|
2286
|
-
addresses.push(`${server.protocol ? `${server.protocol}://` : ""}${server.host}${server.pathname ?? ""}`);
|
|
2287
|
-
}
|
|
2288
|
-
}
|
|
2289
|
-
return { addresses, label: "Servers" };
|
|
2290
|
-
}
|
|
2291
|
-
const declared = spec.document.servers;
|
|
2292
|
-
for (const server of Array.isArray(declared) ? declared : []) {
|
|
2293
|
-
if (server.url) {
|
|
2294
|
-
addresses.push(server.url);
|
|
2295
|
-
}
|
|
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;
|
|
2296
1342
|
}
|
|
2297
|
-
return {
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
for (let suffix = 2;taken.has(slug); suffix += 1) {
|
|
2312
|
-
slug = `${base}-${suffix}`;
|
|
2313
|
-
}
|
|
2314
|
-
taken.add(slug);
|
|
2315
|
-
assigned.set(name, slug);
|
|
2316
|
-
return slug;
|
|
2317
|
-
};
|
|
2318
|
-
};
|
|
2319
|
-
var operationCollector = (baseRoute, tagMeta) => {
|
|
2320
|
-
const operations = [];
|
|
2321
|
-
const tagOrder = [];
|
|
2322
|
-
const tagsSeen = new Set;
|
|
2323
|
-
const seen = new Set;
|
|
2324
|
-
const slugForTag = tagSlugger();
|
|
2325
|
-
const add = (entry) => {
|
|
2326
|
-
const tagSlug = slugForTag(entry.tag);
|
|
2327
|
-
if (!tagsSeen.has(entry.tag)) {
|
|
2328
|
-
tagsSeen.add(entry.tag);
|
|
2329
|
-
tagOrder.push(entry.tag);
|
|
2330
|
-
}
|
|
2331
|
-
let { key } = entry;
|
|
2332
|
-
while (seen.has(key)) {
|
|
2333
|
-
key = `${key}-${entry.method}`;
|
|
2334
|
-
}
|
|
2335
|
-
seen.add(key);
|
|
2336
|
-
operations.push({
|
|
2337
|
-
...entry,
|
|
2338
|
-
key,
|
|
2339
|
-
route: `${baseRoute === "/" ? "" : baseRoute}/${tagSlug}/${key}`,
|
|
2340
|
-
tagSlug
|
|
2341
|
-
});
|
|
2342
|
-
};
|
|
2343
|
-
const finish = () => ({
|
|
2344
|
-
operations,
|
|
2345
|
-
tags: tagOrder.map((name) => ({
|
|
2346
|
-
description: tagMeta.get(name) ?? "",
|
|
2347
|
-
name,
|
|
2348
|
-
slug: slugForTag(name)
|
|
2349
|
-
}))
|
|
2350
|
-
});
|
|
2351
|
-
return { add, finish };
|
|
2352
|
-
};
|
|
2353
|
-
var extractOperations = (document, baseRoute) => {
|
|
2354
|
-
const warnings = [];
|
|
2355
|
-
const tagMeta = new Map((document.tags ?? []).filter(hasTagName).map((tag) => [tag.name, tag.description ?? ""]));
|
|
2356
|
-
const collector = operationCollector(baseRoute, tagMeta);
|
|
2357
|
-
for (const [path, item] of Object.entries(document.paths ?? {})) {
|
|
2358
|
-
if (!item) {
|
|
2359
|
-
continue;
|
|
2360
|
-
}
|
|
2361
|
-
if ("$ref" in item) {
|
|
2362
|
-
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.`);
|
|
2363
|
-
continue;
|
|
2364
|
-
}
|
|
2365
|
-
for (const method of HTTP_METHODS) {
|
|
2366
|
-
const operation = item[method];
|
|
2367
|
-
if (!isOperation(operation)) {
|
|
2368
|
-
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;
|
|
2369
1357
|
}
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
key: operationKey(method, path, operation.operationId),
|
|
2374
|
-
method,
|
|
2375
|
-
operationId: operation.operationId,
|
|
2376
|
-
path,
|
|
2377
|
-
summary: operation.summary ?? "",
|
|
2378
|
-
tag: operation.tags?.[0] ?? UNTAGGED
|
|
2379
|
-
});
|
|
2380
|
-
}
|
|
2381
|
-
}
|
|
2382
|
-
return { ...collector.finish(), warnings };
|
|
2383
|
-
};
|
|
2384
|
-
|
|
2385
|
-
// src/openapi/asyncapi.ts
|
|
2386
|
-
var ASYNCAPI_ACTIONS = ["send", "receive"];
|
|
2387
|
-
var unescapePointer = (token) => token.replaceAll("~1", "/").replaceAll("~0", "~");
|
|
2388
|
-
var CHANNEL_REF = /^#\/channels\/(?<id>.+)$/u;
|
|
2389
|
-
var isString = (value) => typeof value === "string";
|
|
2390
|
-
var channelIdOf = (channel) => {
|
|
2391
|
-
const id = CHANNEL_REF.exec(channel?.$ref ?? "")?.groups?.id;
|
|
2392
|
-
return id === undefined ? undefined : unescapePointer(id);
|
|
2393
|
-
};
|
|
2394
|
-
var channelAddress = (channelId, channel) => {
|
|
2395
|
-
const address = channel?.address;
|
|
2396
|
-
return isString(address) && address !== "" ? address : channelId;
|
|
2397
|
-
};
|
|
2398
|
-
var isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2399
|
-
var COMPONENT_SECTION_REF = /^#\/components\/(?<section>channels|operations)\/(?<name>[^/]+)$/u;
|
|
2400
|
-
var inlineComponentRefs = (document) => {
|
|
2401
|
-
const maps = [
|
|
2402
|
-
[document.channels, "channels"],
|
|
2403
|
-
[document.operations, "operations"]
|
|
2404
|
-
];
|
|
2405
|
-
for (const [map, section] of maps) {
|
|
2406
|
-
if (!isObject(map)) {
|
|
2407
|
-
continue;
|
|
2408
|
-
}
|
|
2409
|
-
const table = document.components?.[section];
|
|
2410
|
-
for (const [id, entry] of Object.entries(map)) {
|
|
2411
|
-
if (!isObject(entry) || !isString(entry.$ref)) {
|
|
2412
|
-
continue;
|
|
1358
|
+
case "italic": {
|
|
1359
|
+
marks.italic = true;
|
|
1360
|
+
break;
|
|
2413
1361
|
}
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
1362
|
+
case "code": {
|
|
1363
|
+
marks.code = true;
|
|
1364
|
+
break;
|
|
2417
1365
|
}
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
1366
|
+
case "strikethrough": {
|
|
1367
|
+
marks.strike = true;
|
|
1368
|
+
break;
|
|
2421
1369
|
}
|
|
1370
|
+
default:
|
|
2422
1371
|
}
|
|
2423
1372
|
}
|
|
1373
|
+
return marks;
|
|
2424
1374
|
};
|
|
2425
|
-
var
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
return;
|
|
2430
|
-
}
|
|
2431
|
-
if (!isString(trait.$ref)) {
|
|
2432
|
-
return trait;
|
|
2433
|
-
}
|
|
2434
|
-
const groups = TRAIT_REF.exec(trait.$ref)?.groups;
|
|
2435
|
-
const section = groups?.section ? document.components?.[groups.section] : undefined;
|
|
2436
|
-
const resolved = section?.[groups?.name ?? ""];
|
|
2437
|
-
return isObject(resolved) ? resolved : undefined;
|
|
2438
|
-
};
|
|
2439
|
-
const mergeTraits = (node) => {
|
|
2440
|
-
const { traits } = node;
|
|
2441
|
-
if (!Array.isArray(traits)) {
|
|
2442
|
-
return;
|
|
2443
|
-
}
|
|
2444
|
-
delete node.traits;
|
|
2445
|
-
const merged = {};
|
|
2446
|
-
for (const trait of traits) {
|
|
2447
|
-
Object.assign(merged, resolveTrait(trait));
|
|
2448
|
-
}
|
|
2449
|
-
for (const [key, value] of Object.entries(merged)) {
|
|
2450
|
-
if (!(key in node)) {
|
|
2451
|
-
node[key] = value;
|
|
2452
|
-
}
|
|
2453
|
-
}
|
|
2454
|
-
};
|
|
2455
|
-
for (const operation of Object.values(document.operations ?? {})) {
|
|
2456
|
-
if (isObject(operation)) {
|
|
2457
|
-
mergeTraits(operation);
|
|
2458
|
-
}
|
|
2459
|
-
}
|
|
2460
|
-
const channelMaps = [
|
|
2461
|
-
...Object.values(document.channels ?? {}),
|
|
2462
|
-
...Object.values(document.components?.channels ?? {})
|
|
2463
|
-
];
|
|
2464
|
-
const messageMaps = [
|
|
2465
|
-
...channelMaps.map((channel) => isObject(channel) ? channel.messages : undefined),
|
|
2466
|
-
document.components?.messages
|
|
2467
|
-
];
|
|
2468
|
-
for (const messages of messageMaps) {
|
|
2469
|
-
if (!isObject(messages)) {
|
|
2470
|
-
continue;
|
|
2471
|
-
}
|
|
2472
|
-
for (const message of Object.values(messages)) {
|
|
2473
|
-
if (isObject(message) && !isString(message.$ref)) {
|
|
2474
|
-
mergeTraits(message);
|
|
2475
|
-
}
|
|
2476
|
-
}
|
|
1375
|
+
var linkedTarget = (node, resolve) => {
|
|
1376
|
+
const target = getPath(node, "data.target");
|
|
1377
|
+
if (getPath(node, "data.target.fields") !== undefined) {
|
|
1378
|
+
return target;
|
|
2477
1379
|
}
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
var normalizeAsyncApiDocument = (document) => {
|
|
2481
|
-
inlineComponentRefs(document);
|
|
2482
|
-
return applyAsyncApiTraits(document);
|
|
1380
|
+
const id = asString(getPath(node, "data.target.sys.id"));
|
|
1381
|
+
return id ? resolve?.(id) ?? null : null;
|
|
2483
1382
|
};
|
|
2484
|
-
var
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
return
|
|
1383
|
+
var linkedAsset = (node, options) => {
|
|
1384
|
+
if (getPath(node, "data.target.fields") !== undefined) {
|
|
1385
|
+
const inline = linkedTarget(node);
|
|
1386
|
+
return inline ? assetFromEntry(inline) : null;
|
|
2488
1387
|
}
|
|
2489
|
-
const
|
|
2490
|
-
|
|
2491
|
-
if (channelId === undefined || !isObject(channel) || isString(channel.$ref)) {
|
|
2492
|
-
return `Operation "${id}" references a channel that isn't declared under "channels"; it is missing from the reference.`;
|
|
2493
|
-
}
|
|
2494
|
-
return { action, address: channelAddress(channelId, channel), channelId };
|
|
1388
|
+
const id = asString(getPath(node, "data.target.sys.id"));
|
|
1389
|
+
return id ? options.resolveAsset?.(id) ?? null : null;
|
|
2495
1390
|
};
|
|
2496
|
-
var
|
|
2497
|
-
const
|
|
2498
|
-
const
|
|
2499
|
-
const
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
if (!isObject(operation)) {
|
|
2503
|
-
continue;
|
|
2504
|
-
}
|
|
2505
|
-
if (isString(operation.$ref)) {
|
|
2506
|
-
warnings.push(`Operation "${id}" is a reference that doesn't resolve to a components operation; it is missing from the reference.`);
|
|
2507
|
-
continue;
|
|
2508
|
-
}
|
|
2509
|
-
const site = operationSite(id, operation, channels);
|
|
2510
|
-
if (isString(site)) {
|
|
2511
|
-
warnings.push(site);
|
|
2512
|
-
continue;
|
|
2513
|
-
}
|
|
2514
|
-
const { action, address, channelId } = site;
|
|
2515
|
-
const tag = operation.tags?.find((candidate) => typeof candidate?.name === "string")?.name;
|
|
2516
|
-
collector.add({
|
|
2517
|
-
channelId,
|
|
2518
|
-
deprecated: operation.deprecated === true,
|
|
2519
|
-
description: operation.description ?? "",
|
|
2520
|
-
key: operationKey(action, address, id),
|
|
2521
|
-
method: action,
|
|
2522
|
-
operationId: id,
|
|
2523
|
-
path: address,
|
|
2524
|
-
summary: operation.title ?? operation.summary ?? "",
|
|
2525
|
-
tag: tag ?? address
|
|
2526
|
-
});
|
|
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);
|
|
2527
1397
|
}
|
|
2528
|
-
return {
|
|
1398
|
+
return unsupported(`Contentful embedded entry${contentType ? `: ${contentType}` : ""}`, writesMdx(options.serializers));
|
|
2529
1399
|
};
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
"subscription"
|
|
2536
|
-
];
|
|
2537
|
-
var GRAPHQL_TYPE_KINDS = [
|
|
2538
|
-
"object",
|
|
2539
|
-
"input",
|
|
2540
|
-
"enum",
|
|
2541
|
-
"interface",
|
|
2542
|
-
"union",
|
|
2543
|
-
"scalar"
|
|
2544
|
-
];
|
|
2545
|
-
var GRAPHQL_GROUP_LABELS = {
|
|
2546
|
-
enum: "Enums",
|
|
2547
|
-
input: "Input Objects",
|
|
2548
|
-
interface: "Interfaces",
|
|
2549
|
-
mutation: "Mutations",
|
|
2550
|
-
object: "Objects",
|
|
2551
|
-
query: "Queries",
|
|
2552
|
-
scalar: "Scalars",
|
|
2553
|
-
subscription: "Subscriptions",
|
|
2554
|
-
union: "Unions"
|
|
2555
|
-
};
|
|
2556
|
-
var isGraphqlOperationKind = (method) => GRAPHQL_OPERATION_KINDS.some((kind) => kind === method);
|
|
2557
|
-
var GRAPHQL_TYPE_KEYWORDS = {
|
|
2558
|
-
enum: "enum",
|
|
2559
|
-
input: "input",
|
|
2560
|
-
interface: "interface",
|
|
2561
|
-
object: "type",
|
|
2562
|
-
scalar: "scalar",
|
|
2563
|
-
union: "union"
|
|
2564
|
-
};
|
|
2565
|
-
var graphqlSignature = (operation) => {
|
|
2566
|
-
const member = operation.method;
|
|
2567
|
-
const keyword = isGraphqlOperationKind(member) ? member : GRAPHQL_TYPE_KEYWORDS[member];
|
|
2568
|
-
return `${keyword} ${operation.path}`;
|
|
2569
|
-
};
|
|
2570
|
-
var byName = (a, b) => a.name < b.name ? -1 : 1;
|
|
2571
|
-
var extractGraphqlOperations = (document, baseRoute) => {
|
|
2572
|
-
const collector = operationCollector(baseRoute, new Map);
|
|
2573
|
-
const rootNames = new Set(Object.values(document.roots));
|
|
2574
|
-
for (const kind of GRAPHQL_OPERATION_KINDS) {
|
|
2575
|
-
const rootName = document.roots[kind];
|
|
2576
|
-
const root = rootName === undefined ? undefined : document.types[rootName];
|
|
2577
|
-
for (const field of root?.fields ?? []) {
|
|
2578
|
-
collector.add({
|
|
2579
|
-
deprecated: field.deprecationReason !== undefined,
|
|
2580
|
-
description: field.description,
|
|
2581
|
-
key: operationKey(kind, field.name, field.name),
|
|
2582
|
-
method: kind,
|
|
2583
|
-
operationId: field.name,
|
|
2584
|
-
path: field.name,
|
|
2585
|
-
summary: "",
|
|
2586
|
-
tag: GRAPHQL_GROUP_LABELS[kind]
|
|
2587
|
-
});
|
|
2588
|
-
}
|
|
2589
|
-
}
|
|
2590
|
-
for (const kind of GRAPHQL_TYPE_KINDS) {
|
|
2591
|
-
const members = Object.values(document.types).filter((type) => type.kind === kind && !(type.builtIn || rootNames.has(type.name))).toSorted(byName);
|
|
2592
|
-
for (const type of members) {
|
|
2593
|
-
collector.add({
|
|
2594
|
-
deprecated: false,
|
|
2595
|
-
description: type.description,
|
|
2596
|
-
key: operationKey(kind, type.name, type.name),
|
|
2597
|
-
method: kind,
|
|
2598
|
-
operationId: type.name,
|
|
2599
|
-
path: type.name,
|
|
2600
|
-
summary: "",
|
|
2601
|
-
tag: GRAPHQL_GROUP_LABELS[kind]
|
|
2602
|
-
});
|
|
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));
|
|
2603
1405
|
}
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
};
|
|
2607
|
-
|
|
2608
|
-
// src/openapi/parse.ts
|
|
2609
|
-
import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile2 } from "node:fs/promises";
|
|
2610
|
-
import { setTimeout as sleep } from "node:timers/promises";
|
|
2611
|
-
import { convert } from "@asyncapi/converter";
|
|
2612
|
-
import { normalize as normalize2, upgrade } from "@scalar/openapi-parser";
|
|
2613
|
-
import pRetry, { AbortError } from "p-retry";
|
|
2614
|
-
import { isAbsolute, join as join3 } from "pathe";
|
|
2615
|
-
|
|
2616
|
-
// src/openapi/graphql-build.ts
|
|
2617
|
-
import {
|
|
2618
|
-
buildClientSchema,
|
|
2619
|
-
buildSchema,
|
|
2620
|
-
getNamedType,
|
|
2621
|
-
isEnumType,
|
|
2622
|
-
isInputObjectType,
|
|
2623
|
-
isInterfaceType,
|
|
2624
|
-
isObjectType,
|
|
2625
|
-
isSpecifiedScalarType,
|
|
2626
|
-
isUnionType,
|
|
2627
|
-
print
|
|
2628
|
-
} from "graphql";
|
|
2629
|
-
var typeRef = (type) => ({
|
|
2630
|
-
display: String(type),
|
|
2631
|
-
name: getNamedType(type).name
|
|
2632
|
-
});
|
|
2633
|
-
var defaultLiteral = (input) => {
|
|
2634
|
-
const literal = input.default?.literal;
|
|
2635
|
-
return literal ? print(literal) : undefined;
|
|
2636
|
-
};
|
|
2637
|
-
var inputValue = (input) => {
|
|
2638
|
-
const value = {
|
|
2639
|
-
description: input.description ?? "",
|
|
2640
|
-
name: input.name,
|
|
2641
|
-
type: typeRef(input.type)
|
|
2642
|
-
};
|
|
2643
|
-
const printed = defaultLiteral(input);
|
|
2644
|
-
if (printed !== undefined) {
|
|
2645
|
-
value.default = printed;
|
|
2646
|
-
}
|
|
2647
|
-
if (input.deprecationReason !== null && input.deprecationReason !== undefined) {
|
|
2648
|
-
value.deprecationReason = input.deprecationReason;
|
|
2649
|
-
}
|
|
2650
|
-
return value;
|
|
2651
|
-
};
|
|
2652
|
-
var outputField = (field) => {
|
|
2653
|
-
const value = {
|
|
2654
|
-
args: field.args.map(inputValue),
|
|
2655
|
-
description: field.description ?? "",
|
|
2656
|
-
name: field.name,
|
|
2657
|
-
type: typeRef(field.type)
|
|
2658
|
-
};
|
|
2659
|
-
if (field.deprecationReason !== null && field.deprecationReason !== undefined) {
|
|
2660
|
-
value.deprecationReason = field.deprecationReason;
|
|
2661
|
-
}
|
|
2662
|
-
return value;
|
|
2663
|
-
};
|
|
2664
|
-
var enumValues = (type) => type.getValues().map((value) => {
|
|
2665
|
-
const member = {
|
|
2666
|
-
description: value.description ?? "",
|
|
2667
|
-
name: value.name
|
|
2668
|
-
};
|
|
2669
|
-
if (value.deprecationReason !== null && value.deprecationReason !== undefined) {
|
|
2670
|
-
member.deprecationReason = value.deprecationReason;
|
|
2671
|
-
}
|
|
2672
|
-
return member;
|
|
2673
|
-
});
|
|
2674
|
-
var objectDef = (type, kind) => {
|
|
2675
|
-
const interfaces = type.getInterfaces().map((iface) => iface.name);
|
|
2676
|
-
const def = {
|
|
2677
|
-
description: type.description ?? "",
|
|
2678
|
-
fields: Object.values(type.getFields()).map(outputField),
|
|
2679
|
-
kind,
|
|
2680
|
-
name: type.name
|
|
2681
|
-
};
|
|
2682
|
-
if (interfaces.length > 0) {
|
|
2683
|
-
def.interfaces = interfaces;
|
|
2684
|
-
}
|
|
2685
|
-
return def;
|
|
2686
|
-
};
|
|
2687
|
-
var inputDef = (type) => ({
|
|
2688
|
-
description: type.description ?? "",
|
|
2689
|
-
inputFields: Object.values(type.getFields()).map(inputValue),
|
|
2690
|
-
kind: "input",
|
|
2691
|
-
name: type.name
|
|
2692
|
-
});
|
|
2693
|
-
var unionDef = (type) => ({
|
|
2694
|
-
description: type.description ?? "",
|
|
2695
|
-
kind: "union",
|
|
2696
|
-
name: type.name,
|
|
2697
|
-
possibleTypes: type.getTypes().map((member) => member.name)
|
|
2698
|
-
});
|
|
2699
|
-
var scalarDef = (type) => {
|
|
2700
|
-
const def = {
|
|
2701
|
-
description: type.description ?? "",
|
|
2702
|
-
kind: "scalar",
|
|
2703
|
-
name: type.name
|
|
2704
|
-
};
|
|
2705
|
-
if (type.specifiedByURL !== null && type.specifiedByURL !== undefined) {
|
|
2706
|
-
def.specifiedByUrl = type.specifiedByURL;
|
|
2707
|
-
}
|
|
2708
|
-
if (isSpecifiedScalarType(type)) {
|
|
2709
|
-
def.builtIn = true;
|
|
2710
|
-
}
|
|
2711
|
-
return def;
|
|
2712
|
-
};
|
|
2713
|
-
var typeDef = (type, schema) => {
|
|
2714
|
-
if (isObjectType(type)) {
|
|
2715
|
-
return objectDef(type, "object");
|
|
2716
|
-
}
|
|
2717
|
-
if (isInterfaceType(type)) {
|
|
2718
|
-
const def = objectDef(type, "interface");
|
|
2719
|
-
const implementers = schema.getImplementations(type).objects.map((object) => object.name);
|
|
2720
|
-
if (implementers.length > 0) {
|
|
2721
|
-
def.possibleTypes = implementers;
|
|
1406
|
+
case "hyperlink": {
|
|
1407
|
+
return renderLink(renderInlines(children(node), options), asString(getPath(node, "data.uri")));
|
|
2722
1408
|
}
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
if (isInputObjectType(type)) {
|
|
2726
|
-
return inputDef(type);
|
|
2727
|
-
}
|
|
2728
|
-
if (isEnumType(type)) {
|
|
2729
|
-
return {
|
|
2730
|
-
description: type.description ?? "",
|
|
2731
|
-
enumValues: enumValues(type),
|
|
2732
|
-
kind: "enum",
|
|
2733
|
-
name: type.name
|
|
2734
|
-
};
|
|
2735
|
-
}
|
|
2736
|
-
if (isUnionType(type)) {
|
|
2737
|
-
return unionDef(type);
|
|
2738
|
-
}
|
|
2739
|
-
return scalarDef(type);
|
|
2740
|
-
};
|
|
2741
|
-
var documentOf = (schema) => {
|
|
2742
|
-
const types = {};
|
|
2743
|
-
for (const [name, type] of Object.entries(schema.getTypeMap())) {
|
|
2744
|
-
if (name.startsWith("__")) {
|
|
2745
|
-
continue;
|
|
1409
|
+
case "asset-hyperlink": {
|
|
1410
|
+
return renderLink(renderInlines(children(node), options), linkedAsset(node, options)?.url);
|
|
2746
1411
|
}
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
const roots = {};
|
|
2750
|
-
const query = schema.getQueryType();
|
|
2751
|
-
const mutation = schema.getMutationType();
|
|
2752
|
-
const subscription = schema.getSubscriptionType();
|
|
2753
|
-
if (query) {
|
|
2754
|
-
roots.query = query.name;
|
|
2755
|
-
}
|
|
2756
|
-
if (mutation) {
|
|
2757
|
-
roots.mutation = mutation.name;
|
|
2758
|
-
}
|
|
2759
|
-
if (subscription) {
|
|
2760
|
-
roots.subscription = subscription.name;
|
|
2761
|
-
}
|
|
2762
|
-
return {
|
|
2763
|
-
info: { description: schema.description ?? "" },
|
|
2764
|
-
roots,
|
|
2765
|
-
types
|
|
2766
|
-
};
|
|
2767
|
-
};
|
|
2768
|
-
var hasSchemaKey = (value) => typeof value === "object" && value !== null && ("__schema" in value);
|
|
2769
|
-
var hasDataEnvelope = (value) => typeof value === "object" && value !== null && ("data" in value);
|
|
2770
|
-
var introspectionOf = (parsed) => {
|
|
2771
|
-
if (hasSchemaKey(parsed)) {
|
|
2772
|
-
return parsed;
|
|
2773
|
-
}
|
|
2774
|
-
return hasDataEnvelope(parsed) && hasSchemaKey(parsed.data) ? parsed.data : undefined;
|
|
2775
|
-
};
|
|
2776
|
-
var buildGraphqlDocument = (text) => {
|
|
2777
|
-
let parsed;
|
|
2778
|
-
let isJson = true;
|
|
2779
|
-
try {
|
|
2780
|
-
parsed = JSON.parse(text);
|
|
2781
|
-
} catch {
|
|
2782
|
-
isJson = false;
|
|
2783
|
-
}
|
|
2784
|
-
if (isJson) {
|
|
2785
|
-
const introspection = introspectionOf(parsed);
|
|
2786
|
-
if (!introspection) {
|
|
2787
|
-
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);
|
|
2788
1414
|
}
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
return documentOf(buildSchema(text));
|
|
2792
|
-
};
|
|
2793
|
-
|
|
2794
|
-
// src/openapi/parse.ts
|
|
2795
|
-
var URL_SPEC = /^https?:\/\//u;
|
|
2796
|
-
var FETCH_TIMEOUT_MS = 15000;
|
|
2797
|
-
var MAX_ATTEMPTS = 3;
|
|
2798
|
-
var BASE_BACKOFF_MS = 500;
|
|
2799
|
-
var MAX_RETRY_WAIT_MS = 1e4;
|
|
2800
|
-
var SECOND_MS = 1000;
|
|
2801
|
-
var RETRYABLE_STATUS = new Set([408, 425, 429, 500, 502, 503, 504]);
|
|
2802
|
-
var USER_AGENT = "blume (+https://github.com/haydenbleasel/blume)";
|
|
2803
|
-
var PROXY_ENV_VARS = [
|
|
2804
|
-
"HTTP_PROXY",
|
|
2805
|
-
"http_proxy",
|
|
2806
|
-
"HTTPS_PROXY",
|
|
2807
|
-
"https_proxy",
|
|
2808
|
-
"ALL_PROXY",
|
|
2809
|
-
"all_proxy"
|
|
2810
|
-
];
|
|
2811
|
-
|
|
2812
|
-
class InvalidSpecError extends Error {
|
|
2813
|
-
constructor(message) {
|
|
2814
|
-
super(message);
|
|
2815
|
-
this.name = "InvalidSpecError";
|
|
2816
|
-
}
|
|
2817
|
-
}
|
|
2818
|
-
var proxyInstalled = false;
|
|
2819
|
-
var ensureProxyDispatcher = async () => {
|
|
2820
|
-
if (proxyInstalled || !PROXY_ENV_VARS.some((name) => process.env[name])) {
|
|
2821
|
-
return;
|
|
2822
|
-
}
|
|
2823
|
-
try {
|
|
2824
|
-
const { EnvHttpProxyAgent, setGlobalDispatcher } = await import("undici");
|
|
2825
|
-
setGlobalDispatcher(new EnvHttpProxyAgent);
|
|
2826
|
-
proxyInstalled = true;
|
|
2827
|
-
} catch {}
|
|
2828
|
-
};
|
|
2829
|
-
var retryAfterMs = (response) => {
|
|
2830
|
-
const header = response.headers.get("retry-after");
|
|
2831
|
-
if (!header) {
|
|
2832
|
-
return;
|
|
2833
|
-
}
|
|
2834
|
-
const seconds = Number(header);
|
|
2835
|
-
if (Number.isFinite(seconds)) {
|
|
2836
|
-
return seconds > 0 ? seconds * SECOND_MS : undefined;
|
|
2837
|
-
}
|
|
2838
|
-
const delta = Date.parse(header) - Date.now();
|
|
2839
|
-
return Number.isFinite(delta) && delta > 0 ? delta : undefined;
|
|
2840
|
-
};
|
|
2841
|
-
var attemptFetch = async (spec) => {
|
|
2842
|
-
try {
|
|
2843
|
-
const response = await fetch(spec, {
|
|
2844
|
-
headers: {
|
|
2845
|
-
accept: "application/json, application/yaml, text/yaml, */*",
|
|
2846
|
-
"user-agent": USER_AGENT
|
|
2847
|
-
},
|
|
2848
|
-
redirect: "follow",
|
|
2849
|
-
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
|
|
2850
|
-
});
|
|
2851
|
-
if (response.ok) {
|
|
2852
|
-
return { text: await response.text() };
|
|
1415
|
+
default: {
|
|
1416
|
+
return renderInlines(children(node), options);
|
|
2853
1417
|
}
|
|
2854
|
-
return {
|
|
2855
|
-
error: new Error(`${spec} -> ${response.status} ${response.statusText}`),
|
|
2856
|
-
retryAfter: retryAfterMs(response),
|
|
2857
|
-
retryable: RETRYABLE_STATUS.has(response.status)
|
|
2858
|
-
};
|
|
2859
|
-
} catch (error) {
|
|
2860
|
-
return {
|
|
2861
|
-
error: error instanceof Error ? error : new Error(String(error)),
|
|
2862
|
-
retryable: true
|
|
2863
|
-
};
|
|
2864
1418
|
}
|
|
2865
1419
|
};
|
|
2866
|
-
var
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
return await pRetry(async () => {
|
|
2877
|
-
const attempt = await attemptFetch(spec);
|
|
2878
|
-
if ("text" in attempt) {
|
|
2879
|
-
return attempt.text;
|
|
2880
|
-
}
|
|
2881
|
-
if (!attempt.retryable) {
|
|
2882
|
-
throw new AbortError(attempt.error);
|
|
2883
|
-
}
|
|
2884
|
-
throw retryableFetchError(attempt.error, attempt.retryAfter);
|
|
2885
|
-
}, {
|
|
2886
|
-
factor: 2,
|
|
2887
|
-
maxTimeout: MAX_RETRY_WAIT_MS,
|
|
2888
|
-
minTimeout: BASE_BACKOFF_MS,
|
|
2889
|
-
onFailedAttempt: async (context) => {
|
|
2890
|
-
const { retryAfter } = context.error;
|
|
2891
|
-
if (retryAfter !== undefined && context.retriesLeft > 0) {
|
|
2892
|
-
await sleep(Math.max(0, Math.min(retryAfter, MAX_RETRY_WAIT_MS) - context.retryDelay));
|
|
2893
|
-
}
|
|
2894
|
-
},
|
|
2895
|
-
retries: MAX_ATTEMPTS - 1
|
|
2896
|
-
});
|
|
2897
|
-
};
|
|
2898
|
-
var cacheFileFor = (cacheDir, spec) => join3(cacheDir, `spec-${hashText(spec)}.cache`);
|
|
2899
|
-
var readCache = async (file) => {
|
|
2900
|
-
try {
|
|
2901
|
-
return await readFile3(file, "utf-8");
|
|
2902
|
-
} catch {
|
|
2903
|
-
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 "";
|
|
2904
1430
|
}
|
|
1431
|
+
return [
|
|
1432
|
+
tableRow(head),
|
|
1433
|
+
tableRow(head.map(() => "---")),
|
|
1434
|
+
...body.map((cells) => tableRow(cells))
|
|
1435
|
+
].join(`
|
|
1436
|
+
`);
|
|
2905
1437
|
};
|
|
2906
|
-
var
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
};
|
|
2912
|
-
var readSpecText = async (spec, root, options) => {
|
|
2913
|
-
if (!URL_SPEC.test(spec)) {
|
|
2914
|
-
const absolute = isAbsolute(spec) ? spec : join3(root, spec);
|
|
2915
|
-
return { text: await readFile3(absolute, "utf-8"), warnings: [] };
|
|
2916
|
-
}
|
|
2917
|
-
const cacheFile = options.cacheDir ? cacheFileFor(options.cacheDir, spec) : undefined;
|
|
2918
|
-
if (cacheFile && options.refresh === false) {
|
|
2919
|
-
const cached = await readCache(cacheFile);
|
|
2920
|
-
if (cached !== undefined) {
|
|
2921
|
-
return { text: cached, warnings: [] };
|
|
2922
|
-
}
|
|
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)}`;
|
|
2923
1443
|
}
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
await writeCache(options.cacheDir, cacheFile, text);
|
|
1444
|
+
switch (type) {
|
|
1445
|
+
case "paragraph": {
|
|
1446
|
+
return renderInlines(children(node), options);
|
|
2928
1447
|
}
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
if (cacheFile) {
|
|
2932
|
-
const cached = await readCache(cacheFile);
|
|
2933
|
-
if (cached !== undefined) {
|
|
2934
|
-
return {
|
|
2935
|
-
text: cached,
|
|
2936
|
-
warnings: [
|
|
2937
|
-
`Could not fetch ${spec} (${error.message}); using the last cached copy.`
|
|
2938
|
-
]
|
|
2939
|
-
};
|
|
2940
|
-
}
|
|
1448
|
+
case "blockquote": {
|
|
1449
|
+
return blockquote(joinBlocks(children(node).map((child) => renderBlock(child, options))));
|
|
2941
1450
|
}
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
};
|
|
2945
|
-
var isApiDocument = (value) => typeof value === "object" && value !== null;
|
|
2946
|
-
var parseSpec = async (spec, root, options = {}) => {
|
|
2947
|
-
const { text, warnings } = await readSpecText(spec, root, options);
|
|
2948
|
-
const normalized = normalize2(text);
|
|
2949
|
-
const { specification } = upgrade(normalized);
|
|
2950
|
-
if (!isApiDocument(specification)) {
|
|
2951
|
-
throw new InvalidSpecError(`${spec} is not a valid OpenAPI document (expected a YAML or JSON object).`);
|
|
2952
|
-
}
|
|
2953
|
-
return { document: specification, warnings };
|
|
2954
|
-
};
|
|
2955
|
-
var isAsyncApiDocument = (value) => typeof value === "object" && value !== null && ("asyncapi" in value) && typeof value.asyncapi === "string" && value.asyncapi !== "";
|
|
2956
|
-
var parseAsyncApiSpec = async (spec, root, options = {}) => {
|
|
2957
|
-
const { text, warnings } = await readSpecText(spec, root, options);
|
|
2958
|
-
const normalized = normalize2(text);
|
|
2959
|
-
if (!isAsyncApiDocument(normalized)) {
|
|
2960
|
-
throw new InvalidSpecError(`${spec} is not a valid AsyncAPI document (expected a YAML or JSON object with an \`asyncapi\` version field).`);
|
|
2961
|
-
}
|
|
2962
|
-
const version = normalized.asyncapi;
|
|
2963
|
-
let document = normalized;
|
|
2964
|
-
if (!version.startsWith("3.")) {
|
|
2965
|
-
const captured = [];
|
|
2966
|
-
const originalWarn = console.warn;
|
|
2967
|
-
console.warn = (...args) => {
|
|
2968
|
-
captured.push(args.map(String).join(" "));
|
|
2969
|
-
};
|
|
2970
|
-
try {
|
|
2971
|
-
document = convert(document, "3.0.0");
|
|
2972
|
-
} catch (error) {
|
|
2973
|
-
throw new InvalidSpecError(`${spec} could not be converted to AsyncAPI 3.0 (${error.message}).`);
|
|
2974
|
-
} finally {
|
|
2975
|
-
console.warn = originalWarn;
|
|
2976
|
-
}
|
|
2977
|
-
warnings.push(...captured.map((message) => `Converting ${spec} to AsyncAPI 3.0: ${message}`));
|
|
2978
|
-
}
|
|
2979
|
-
return { document: normalizeAsyncApiDocument(document), warnings };
|
|
2980
|
-
};
|
|
2981
|
-
var parseGraphqlSpec = async (spec, root, options = {}) => {
|
|
2982
|
-
const { text, warnings } = await readSpecText(spec, root, options);
|
|
2983
|
-
try {
|
|
2984
|
-
return { document: buildGraphqlDocument(text), warnings };
|
|
2985
|
-
} catch (error) {
|
|
2986
|
-
throw new InvalidSpecError(`${spec} is not a valid GraphQL schema (${error.message.trim()})`);
|
|
2987
|
-
}
|
|
2988
|
-
};
|
|
2989
|
-
|
|
2990
|
-
// src/openapi/render-mdx.ts
|
|
2991
|
-
import { fromMarkdown } from "mdast-util-from-markdown";
|
|
2992
|
-
import { toString as mdastToString } from "mdast-util-to-string";
|
|
2993
|
-
import stringWidth2 from "string-width";
|
|
2994
|
-
|
|
2995
|
-
// src/core/api-name.ts
|
|
2996
|
-
var NAMES_AN_API = /\bAPIs?\b/iu;
|
|
2997
|
-
var apiNamePhrase = (name) => {
|
|
2998
|
-
const trimmed = name.trim();
|
|
2999
|
-
return NAMES_AN_API.test(trimmed) ? trimmed : `${trimmed} API`;
|
|
3000
|
-
};
|
|
3001
|
-
|
|
3002
|
-
// src/core/text-width.ts
|
|
3003
|
-
import stringWidth from "string-width";
|
|
3004
|
-
var columnsPrefix = (text, max) => {
|
|
3005
|
-
let end = 0;
|
|
3006
|
-
let used = 0;
|
|
3007
|
-
const graphemes = new Intl.Segmenter(undefined, { granularity: "grapheme" });
|
|
3008
|
-
for (const { index, segment } of graphemes.segment(text)) {
|
|
3009
|
-
const width = stringWidth(segment);
|
|
3010
|
-
if (used + width > max) {
|
|
3011
|
-
break;
|
|
1451
|
+
case "unordered-list": {
|
|
1452
|
+
return renderList(children(node), () => "-", options);
|
|
3012
1453
|
}
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
}
|
|
3016
|
-
return text.slice(0, end);
|
|
3017
|
-
};
|
|
3018
|
-
|
|
3019
|
-
// src/openapi/signature.ts
|
|
3020
|
-
var operationSignature = (spec, operation) => spec.kind === "graphql" ? graphqlSignature(operation) : `${operation.method.toUpperCase()} ${operation.path}`;
|
|
3021
|
-
|
|
3022
|
-
// src/openapi/render-mdx.ts
|
|
3023
|
-
var MDX_UNSAFE = /[<{}]/gu;
|
|
3024
|
-
var ENTITIES = new Map([
|
|
3025
|
-
["<", "<"],
|
|
3026
|
-
["{", "{"],
|
|
3027
|
-
["}", "}"]
|
|
3028
|
-
]);
|
|
3029
|
-
var MDX_ESM_KEYWORD = /^(?<keyword>import|export)\b/gmu;
|
|
3030
|
-
var escapeProse = (text) => text.replace(MDX_UNSAFE, (char) => ENTITIES.get(char) ?? char).replace(MDX_ESM_KEYWORD, (keyword) => `&#${keyword.codePointAt(0)};${keyword.slice(1)}`);
|
|
3031
|
-
var codeSpans = (text) => {
|
|
3032
|
-
const spans = [];
|
|
3033
|
-
const collect = (node) => {
|
|
3034
|
-
if (node.type === "inlineCode" || node.type === "code") {
|
|
3035
|
-
const start = node.position?.start.offset ?? -1;
|
|
3036
|
-
const end = node.position?.end.offset ?? -1;
|
|
3037
|
-
const head = text.slice(Math.max(start, 0), Math.max(end, 0)).trimStart();
|
|
3038
|
-
if (start >= 0 && (node.type === "inlineCode" || head.startsWith("`") || head.startsWith("~"))) {
|
|
3039
|
-
spans.push([start, end]);
|
|
3040
|
-
}
|
|
3041
|
-
return;
|
|
1454
|
+
case "ordered-list": {
|
|
1455
|
+
return renderList(children(node), (index) => `${index + 1}.`, options);
|
|
3042
1456
|
}
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
collect(child);
|
|
3046
|
-
}
|
|
1457
|
+
case "hr": {
|
|
1458
|
+
return "---";
|
|
3047
1459
|
}
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
};
|
|
3052
|
-
var mdxSafe = (text) => {
|
|
3053
|
-
let out = "";
|
|
3054
|
-
let cursor = 0;
|
|
3055
|
-
for (const [start, end] of codeSpans(text)) {
|
|
3056
|
-
out += escapeProse(text.slice(cursor, start));
|
|
3057
|
-
out += text.slice(start, end);
|
|
3058
|
-
cursor = end;
|
|
3059
|
-
}
|
|
3060
|
-
return out + escapeProse(text.slice(cursor));
|
|
3061
|
-
};
|
|
3062
|
-
var META_DESCRIPTION_MAX = 160;
|
|
3063
|
-
var WHITESPACE = /\s+/gu;
|
|
3064
|
-
var TRAILING_WORD = /\s+\S*$/u;
|
|
3065
|
-
var plainProse = (markdown) => {
|
|
3066
|
-
const tree = fromMarkdown(markdown);
|
|
3067
|
-
const first = tree.children.find((node) => node.type === "paragraph") ?? tree.children[0];
|
|
3068
|
-
return first ? mdastToString(first).replace(WHITESPACE, " ").trim() : "";
|
|
3069
|
-
};
|
|
3070
|
-
var clip = (text, max) => {
|
|
3071
|
-
if (max <= 0) {
|
|
3072
|
-
return "";
|
|
3073
|
-
}
|
|
3074
|
-
if (stringWidth2(text) <= max) {
|
|
3075
|
-
return text;
|
|
3076
|
-
}
|
|
3077
|
-
const head = columnsPrefix(text, max - 1);
|
|
3078
|
-
const onWordBoundary = head.replace(TRAILING_WORD, "");
|
|
3079
|
-
return `${stringWidth2(onWordBoundary) >= max / 2 ? onWordBoundary : head}…`;
|
|
3080
|
-
};
|
|
3081
|
-
var apiName = (spec) => spec.title || spec.label;
|
|
3082
|
-
var apiPhrase = (spec) => apiNamePhrase(apiName(spec));
|
|
3083
|
-
var GRAPHQL_MEMBER_PHRASES = {
|
|
3084
|
-
enum: "enum type",
|
|
3085
|
-
input: "input object type",
|
|
3086
|
-
interface: "interface type",
|
|
3087
|
-
mutation: "mutation",
|
|
3088
|
-
object: "object type",
|
|
3089
|
-
query: "query",
|
|
3090
|
-
scalar: "scalar type",
|
|
3091
|
-
subscription: "subscription",
|
|
3092
|
-
union: "union type"
|
|
3093
|
-
};
|
|
3094
|
-
var operationDescription = (spec, operation, options) => {
|
|
3095
|
-
if (!options.suffix) {
|
|
3096
|
-
return clip(plainProse(operation.description || operation.summary) || options.title, META_DESCRIPTION_MAX);
|
|
3097
|
-
}
|
|
3098
|
-
let subject;
|
|
3099
|
-
if (spec.kind === "asyncapi") {
|
|
3100
|
-
subject = `${operation.method} operation on ${operation.path}`;
|
|
3101
|
-
} else if (spec.kind === "graphql") {
|
|
3102
|
-
subject = `${operation.path} ${GRAPHQL_MEMBER_PHRASES[operation.method]}`;
|
|
3103
|
-
} else {
|
|
3104
|
-
subject = `${operation.method.toUpperCase()} ${operation.path} endpoint`;
|
|
3105
|
-
}
|
|
3106
|
-
const suffix = `Reference for the ${subject} in the ${apiPhrase(spec)}.`;
|
|
3107
|
-
const prose = clip(plainProse(operation.description || operation.summary), META_DESCRIPTION_MAX - stringWidth2(suffix) - 1);
|
|
3108
|
-
return clip([prose, suffix].filter(Boolean).join(" "), META_DESCRIPTION_MAX);
|
|
3109
|
-
};
|
|
3110
|
-
var withDescription = (description, component) => description.trim() ? `${mdxSafe(description.trim())}
|
|
3111
|
-
|
|
3112
|
-
${component}` : component;
|
|
3113
|
-
var operationMdx = (spec, operation, reference) => {
|
|
3114
|
-
const method = operation.method.toUpperCase();
|
|
3115
|
-
const graphql = spec.kind === "graphql";
|
|
3116
|
-
const fallbackTitle = graphql ? operation.path : operationSignature(spec, operation);
|
|
3117
|
-
const title = operation.summary || fallbackTitle;
|
|
3118
|
-
const description = operation.description.trim() === operation.summary.trim() ? "" : operation.description;
|
|
3119
|
-
const flags = {};
|
|
3120
|
-
if (reference?.includeInLlms === false) {
|
|
3121
|
-
flags.ai = { exclude: true };
|
|
3122
|
-
}
|
|
3123
|
-
if (operation.deprecated) {
|
|
3124
|
-
flags.deprecated = true;
|
|
3125
|
-
}
|
|
3126
|
-
const searchFlags = {};
|
|
3127
|
-
if (reference?.includeInSearch === false) {
|
|
3128
|
-
searchFlags.exclude = true;
|
|
3129
|
-
}
|
|
3130
|
-
const seo = {
|
|
3131
|
-
description: operationDescription(spec, operation, {
|
|
3132
|
-
suffix: reference?.seoDescriptionSuffix !== false,
|
|
3133
|
-
title
|
|
3134
|
-
})
|
|
3135
|
-
};
|
|
3136
|
-
if (reference?.noindex) {
|
|
3137
|
-
seo.noindex = true;
|
|
3138
|
-
}
|
|
3139
|
-
const sidebar = {
|
|
3140
|
-
label: operation.summary || operation.path
|
|
3141
|
-
};
|
|
3142
|
-
if (!graphql || isGraphqlOperationKind(operation.method)) {
|
|
3143
|
-
sidebar.badge = method;
|
|
3144
|
-
}
|
|
3145
|
-
const tags = graphql ? [operation.tag] : [operation.tag, method];
|
|
3146
|
-
return {
|
|
3147
|
-
body: withDescription(description, `<Operation source="${spec.slug}" id="${operation.key}" />`),
|
|
3148
|
-
data: {
|
|
3149
|
-
...flags,
|
|
3150
|
-
search: { ...searchFlags, tags },
|
|
3151
|
-
seo,
|
|
3152
|
-
sidebar,
|
|
3153
|
-
title,
|
|
3154
|
-
type: "openapi-operation"
|
|
1460
|
+
case "embedded-asset-block": {
|
|
1461
|
+
const asset = linkedAsset(node, options);
|
|
1462
|
+
return asset ? image(asset.description ?? asset.title ?? "", asset.url) : "";
|
|
3155
1463
|
}
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
var overviewMdx = (spec, reference) => {
|
|
3159
|
-
const operations = Object.values(spec.operations);
|
|
3160
|
-
const sections = [];
|
|
3161
|
-
const known = new Set;
|
|
3162
|
-
for (const tag of spec.tags) {
|
|
3163
|
-
if (!known.has(tag.slug)) {
|
|
3164
|
-
known.add(tag.slug);
|
|
3165
|
-
sections.push(tag);
|
|
3166
|
-
}
|
|
3167
|
-
}
|
|
3168
|
-
for (const operation of operations) {
|
|
3169
|
-
if (!known.has(operation.tagSlug)) {
|
|
3170
|
-
known.add(operation.tagSlug);
|
|
3171
|
-
sections.push({
|
|
3172
|
-
description: "",
|
|
3173
|
-
name: operation.tag,
|
|
3174
|
-
slug: operation.tagSlug
|
|
3175
|
-
});
|
|
1464
|
+
case "embedded-entry-block": {
|
|
1465
|
+
return embeddedEntry(node, options);
|
|
3176
1466
|
}
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
1467
|
+
case "table": {
|
|
1468
|
+
return renderTable(node, options);
|
|
1469
|
+
}
|
|
1470
|
+
default: {
|
|
1471
|
+
return unsupported(`Contentful node: ${type}`, writesMdx(options.serializers));
|
|
3182
1472
|
}
|
|
3183
|
-
const description = tag.description.trim() ? [mdxSafe(tag.description.trim())] : [];
|
|
3184
|
-
tagSections.push([
|
|
3185
|
-
`## ${mdxSafe(tag.name)}`,
|
|
3186
|
-
...description,
|
|
3187
|
-
`<ApiTagOperations source="${spec.slug}" tag="${tag.slug}" />`
|
|
3188
|
-
].join(`
|
|
3189
|
-
|
|
3190
|
-
`));
|
|
3191
|
-
}
|
|
3192
|
-
const flags = {};
|
|
3193
|
-
if (reference?.includeInLlms === false) {
|
|
3194
|
-
flags.ai = { exclude: true };
|
|
3195
|
-
}
|
|
3196
|
-
if (reference?.includeInSearch === false) {
|
|
3197
|
-
flags.search = { exclude: true };
|
|
3198
|
-
}
|
|
3199
|
-
const seo = {
|
|
3200
|
-
description: clip(plainProse(spec.description), META_DESCRIPTION_MAX) || `${apiPhrase(spec)} reference.`
|
|
3201
|
-
};
|
|
3202
|
-
if (reference?.noindex) {
|
|
3203
|
-
seo.noindex = true;
|
|
3204
1473
|
}
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
withDescription(spec.description, `<ApiOverview source="${spec.slug}" />`),
|
|
3208
|
-
...tagSections
|
|
3209
|
-
].join(`
|
|
1474
|
+
};
|
|
1475
|
+
var contentfulRichTextToMarkdown = (doc, options = {}) => markdownDocument(children(doc).map((node) => renderBlock(node, options)));
|
|
3210
1476
|
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
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;
|
|
3217
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
|
|
3218
1502
|
};
|
|
3219
1503
|
};
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
var isOpenApiSource = (source) => ("kind" in source) && source.kind === "openapi-source";
|
|
3223
|
-
var routeToRef = (route) => route.replace(/^\/+/u, "");
|
|
3224
|
-
var KIND_LABELS = {
|
|
3225
|
-
asyncapi: "AsyncAPI",
|
|
3226
|
-
graphql: "GraphQL",
|
|
3227
|
-
openapi: "OpenAPI"
|
|
3228
|
-
};
|
|
3229
|
-
var CODE_PREFIXES = {
|
|
3230
|
-
asyncapi: "BLUME_ASYNCAPI",
|
|
3231
|
-
graphql: "BLUME_GRAPHQL",
|
|
3232
|
-
openapi: "BLUME_OPENAPI"
|
|
3233
|
-
};
|
|
3234
|
-
var SPEC_WARNING_CODES = {
|
|
3235
|
-
asyncapi: "BLUME_ASYNCAPI_SPEC_WARNING",
|
|
3236
|
-
graphql: "BLUME_GRAPHQL_SPEC_WARNING",
|
|
3237
|
-
openapi: "BLUME_OPENAPI_STALE"
|
|
3238
|
-
};
|
|
3239
|
-
var SKIPPED_CODES = {
|
|
3240
|
-
asyncapi: "BLUME_ASYNCAPI_SKIPPED_OPERATION",
|
|
3241
|
-
graphql: "BLUME_GRAPHQL_SKIPPED",
|
|
3242
|
-
openapi: "BLUME_OPENAPI_REF_PATH_ITEM"
|
|
3243
|
-
};
|
|
3244
|
-
var EMPTY_SUGGESTIONS = {
|
|
3245
|
-
asyncapi: "Check the spec points at an AsyncAPI document with `channels` and `operations`.",
|
|
3246
|
-
graphql: "Check the spec points at a GraphQL schema (SDL or introspection JSON) whose root types declare fields.",
|
|
3247
|
-
openapi: "Check the spec points at an OpenAPI document with operations under `paths`."
|
|
3248
|
-
};
|
|
3249
|
-
var INVALID_SUGGESTIONS = {
|
|
3250
|
-
asyncapi: "Point the spec at an AsyncAPI document (a YAML or JSON file with an object at the top level).",
|
|
3251
|
-
graphql: "Point the spec at a GraphQL schema — SDL text or an introspection JSON result.",
|
|
3252
|
-
openapi: "Point the spec at an OpenAPI document (a YAML or JSON file with an object at the top level)."
|
|
3253
|
-
};
|
|
3254
|
-
var toEntry = (rendered, ref) => {
|
|
3255
|
-
const raw = frontmatter_default.stringify(`${rendered.body}
|
|
3256
|
-
`, rendered.data);
|
|
1504
|
+
var stagedEntry = (slug, data, markdown, lastModified, format = "md") => {
|
|
1505
|
+
const raw = frontmatter_default.stringify(markdown, data);
|
|
3257
1506
|
return {
|
|
3258
|
-
body: { format
|
|
3259
|
-
data: { ...
|
|
1507
|
+
body: { format, text: markdown },
|
|
1508
|
+
data: { ...data },
|
|
3260
1509
|
hash: hashText(raw),
|
|
1510
|
+
lastModified,
|
|
3261
1511
|
raw,
|
|
3262
|
-
ref
|
|
1512
|
+
ref: `${slug}.${format}`
|
|
3263
1513
|
};
|
|
3264
1514
|
};
|
|
3265
|
-
var
|
|
3266
|
-
|
|
3267
|
-
const
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
]));
|
|
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();
|
|
3277
1526
|
};
|
|
3278
|
-
var
|
|
3279
|
-
const
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
document,
|
|
3285
|
-
extractWarnings: extracted.warnings,
|
|
3286
|
-
operations: extracted.operations,
|
|
3287
|
-
tags: extracted.tags,
|
|
3288
|
-
warnings
|
|
3289
|
-
};
|
|
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
|
+
}
|
|
3290
1533
|
}
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
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;
|
|
3301
1544
|
}
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
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);
|
|
3311
1562
|
};
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
}
|
|
3340
|
-
])),
|
|
3341
|
-
playground: { enabled: reference.display.playground.enabled, proxy },
|
|
3342
|
-
route: reference.route,
|
|
3343
|
-
slug: reference.slug,
|
|
3344
|
-
tags,
|
|
3345
|
-
title: info.title ?? reference.label,
|
|
3346
|
-
version: info.version ?? ""
|
|
3347
|
-
};
|
|
3348
|
-
if (reference.endpoint !== undefined) {
|
|
3349
|
-
spec.endpoint = reference.endpoint;
|
|
3350
|
-
}
|
|
3351
|
-
return {
|
|
3352
|
-
diagnostics: [
|
|
3353
|
-
...warnings.map((message) => ({
|
|
3354
|
-
code: SPEC_WARNING_CODES[reference.kind],
|
|
3355
|
-
message,
|
|
3356
|
-
severity: "warning"
|
|
3357
|
-
})),
|
|
3358
|
-
...extractWarnings.map((message) => ({
|
|
3359
|
-
code: SKIPPED_CODES[reference.kind],
|
|
3360
|
-
message: `In ${kindLabel} spec "${reference.spec}": ${message}`,
|
|
3361
|
-
severity: "warning"
|
|
3362
|
-
})),
|
|
3363
|
-
...operations.length === 0 ? [
|
|
3364
|
-
{
|
|
3365
|
-
code: `${codePrefix}_EMPTY`,
|
|
3366
|
-
message: `${kindLabel} spec "${reference.spec}" for ${reference.route} declares no operations; its API reference is empty.`,
|
|
3367
|
-
severity: "warning",
|
|
3368
|
-
suggestion: EMPTY_SUGGESTIONS[reference.kind]
|
|
3369
|
-
}
|
|
3370
|
-
] : []
|
|
3371
|
-
],
|
|
3372
|
-
entries: specEntries(spec, operations, reference),
|
|
3373
|
-
folderMeta: tagFolderMeta(spec, tags),
|
|
3374
|
-
slug: reference.slug,
|
|
3375
|
-
spec
|
|
3376
|
-
};
|
|
3377
|
-
} catch (error) {
|
|
3378
|
-
return {
|
|
3379
|
-
code: `${codePrefix}_UNAVAILABLE`,
|
|
3380
|
-
message: `Could not load ${kindLabel} spec "${reference.spec}" for ${reference.route} (${error.message}); its reference pages were skipped.`,
|
|
3381
|
-
severity: ctx.mode === "build" ? "error" : "warning",
|
|
3382
|
-
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."
|
|
3383
|
-
};
|
|
3384
|
-
}
|
|
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));
|
|
3385
1590
|
};
|
|
3386
|
-
const
|
|
3387
|
-
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`;
|
|
3388
1605
|
const entries = [];
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
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");
|
|
3400
1620
|
}
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
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);
|
|
3405
1629
|
}
|
|
3406
|
-
|
|
3407
|
-
return { diagnostics, entries, folderMeta };
|
|
3408
|
-
};
|
|
3409
|
-
return {
|
|
3410
|
-
kind: "openapi-source",
|
|
3411
|
-
load,
|
|
3412
|
-
name: "openapi",
|
|
3413
|
-
openApiData: () => parsed,
|
|
3414
|
-
staged: true
|
|
1630
|
+
return entries;
|
|
3415
1631
|
};
|
|
1632
|
+
return remoteSource({
|
|
1633
|
+
fetchEntries,
|
|
1634
|
+
name: options.name,
|
|
1635
|
+
pollInterval: options.pollInterval,
|
|
1636
|
+
prefix: options.prefix
|
|
1637
|
+
}, ctx);
|
|
3416
1638
|
};
|
|
3417
1639
|
|
|
3418
1640
|
// src/core/sources/filesystem.ts
|
|
3419
|
-
import { existsSync
|
|
3420
|
-
import { readFile
|
|
3421
|
-
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";
|
|
3422
1644
|
import { glob as glob2 } from "tinyglobby";
|
|
3423
|
-
|
|
3424
|
-
// src/core/sources/watch.ts
|
|
3425
|
-
var BLUME_IGNORE_DIRS = [
|
|
3426
|
-
".blume",
|
|
3427
|
-
".blume-verify",
|
|
3428
|
-
".cache",
|
|
3429
|
-
".git",
|
|
3430
|
-
".next",
|
|
3431
|
-
".turbo",
|
|
3432
|
-
".vercel",
|
|
3433
|
-
"dist",
|
|
3434
|
-
"node_modules"
|
|
3435
|
-
];
|
|
3436
|
-
var baselineScanIgnore = () => BLUME_IGNORE_DIRS.map((dir) => `**/${dir}/**`);
|
|
3437
|
-
var BLUME_WATCH_IGNORE_DIRS = BLUME_IGNORE_DIRS;
|
|
3438
|
-
var excludeDirSegments = (patterns) => patterns.map((pattern) => /^(?<dir>[^*/]+)\/\*\*$/u.exec(pattern)?.groups?.dir).filter((dir) => dir !== undefined);
|
|
3439
|
-
var ignoringWatchListener = (onChange, ignoreDirs = BLUME_WATCH_IGNORE_DIRS, ignoreSegment = () => false) => {
|
|
3440
|
-
const ignore = new Set(ignoreDirs);
|
|
3441
|
-
return (_event, filename) => {
|
|
3442
|
-
if (filename !== null && filename.split(/[/\\]/u).some((segment) => ignore.has(segment) || ignoreSegment(segment))) {
|
|
3443
|
-
return;
|
|
3444
|
-
}
|
|
3445
|
-
onChange();
|
|
3446
|
-
};
|
|
3447
|
-
};
|
|
3448
|
-
|
|
3449
|
-
// src/core/sources/filesystem.ts
|
|
3450
1645
|
var filesystemSource = (options) => {
|
|
3451
|
-
const contentRoot =
|
|
1646
|
+
const contentRoot = isAbsolute(options.root) ? options.root : join2(resolve(options.projectRoot), options.root);
|
|
3452
1647
|
const load = async () => {
|
|
3453
1648
|
const files = await glob2(options.include, {
|
|
3454
1649
|
absolute: true,
|
|
@@ -3458,22 +1653,22 @@ var filesystemSource = (options) => {
|
|
|
3458
1653
|
});
|
|
3459
1654
|
files.sort();
|
|
3460
1655
|
const entries = await Promise.all(files.map(async (file) => {
|
|
3461
|
-
const source = await
|
|
3462
|
-
const ext =
|
|
1656
|
+
const source = await readFile(file, "utf-8");
|
|
1657
|
+
const ext = extname2(file).toLowerCase();
|
|
3463
1658
|
const format = ext === ".mdx" ? "mdx" : "md";
|
|
3464
1659
|
const parsed = frontmatter_default(source);
|
|
3465
1660
|
return {
|
|
3466
1661
|
body: { format, text: parsed.content },
|
|
3467
1662
|
data: parsed.data,
|
|
3468
1663
|
raw: source,
|
|
3469
|
-
ref:
|
|
1664
|
+
ref: relative3(contentRoot, file),
|
|
3470
1665
|
sourcePath: file
|
|
3471
1666
|
};
|
|
3472
1667
|
}));
|
|
3473
1668
|
return { diagnostics: [], entries };
|
|
3474
1669
|
};
|
|
3475
1670
|
const validate = () => {
|
|
3476
|
-
if (!
|
|
1671
|
+
if (!existsSync(contentRoot)) {
|
|
3477
1672
|
throw new BlumeError({
|
|
3478
1673
|
code: options.missingCode ?? "BLUME_CONTENT_ROOT_MISSING",
|
|
3479
1674
|
file: contentRoot,
|
|
@@ -3488,7 +1683,7 @@ var filesystemSource = (options) => {
|
|
|
3488
1683
|
...excludeDirSegments(options.exclude)
|
|
3489
1684
|
]);
|
|
3490
1685
|
const watch = (onChange) => {
|
|
3491
|
-
if (!
|
|
1686
|
+
if (!existsSync(contentRoot)) {
|
|
3492
1687
|
return () => {};
|
|
3493
1688
|
}
|
|
3494
1689
|
const watcher = fsWatch(contentRoot, { recursive: true }, ignoringWatchListener(onChange, watchIgnoreDirs));
|
|
@@ -3499,7 +1694,7 @@ var filesystemSource = (options) => {
|
|
|
3499
1694
|
load,
|
|
3500
1695
|
name: options.name,
|
|
3501
1696
|
prefix: options.prefix,
|
|
3502
|
-
read: (ref) =>
|
|
1697
|
+
read: (ref) => readFile(join2(contentRoot, ref), "utf-8"),
|
|
3503
1698
|
staged: false,
|
|
3504
1699
|
validate,
|
|
3505
1700
|
watch
|
|
@@ -3507,11 +1702,11 @@ var filesystemSource = (options) => {
|
|
|
3507
1702
|
};
|
|
3508
1703
|
|
|
3509
1704
|
// src/core/sources/github-releases.ts
|
|
3510
|
-
import { fromMarkdown
|
|
1705
|
+
import { fromMarkdown } from "mdast-util-from-markdown";
|
|
3511
1706
|
import { gfmFromMarkdown } from "mdast-util-gfm";
|
|
3512
|
-
import { toString as
|
|
1707
|
+
import { toString as mdastToString } from "mdast-util-to-string";
|
|
3513
1708
|
import { gfm } from "micromark-extension-gfm";
|
|
3514
|
-
import
|
|
1709
|
+
import stringWidth from "string-width";
|
|
3515
1710
|
var DEFAULT_LIMIT = 100;
|
|
3516
1711
|
var PER_PAGE = 100;
|
|
3517
1712
|
var LEADING_V = /^v/iu;
|
|
@@ -3520,26 +1715,54 @@ var EDGE_DASHES = /^-+|-+$/gu;
|
|
|
3520
1715
|
var DESCRIPTION_MAX = 160;
|
|
3521
1716
|
var DESCRIPTION_MIN = 110;
|
|
3522
1717
|
var CHANGESET_HASH = /^(?<mark>\s*(?:[-*+]|\d+[.)])\s+)[0-9a-f]{7,40}:\s+/gmu;
|
|
3523
|
-
var
|
|
1718
|
+
var WHITESPACE = /\s+/gu;
|
|
3524
1719
|
var TRAILING_FRAGMENT = /[\s,;:.—–-]+$/u;
|
|
3525
1720
|
var NON_PROSE = new Set(["code", "heading", "html", "thematicBreak"]);
|
|
3526
1721
|
var releaseDescription = (body) => {
|
|
3527
|
-
const tree =
|
|
1722
|
+
const tree = fromMarkdown(body.replaceAll(CHANGESET_HASH, "$<mark>"), {
|
|
3528
1723
|
extensions: [gfm()],
|
|
3529
1724
|
mdastExtensions: [gfmFromMarkdown()]
|
|
3530
1725
|
});
|
|
3531
|
-
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();
|
|
3532
1727
|
if (!text) {
|
|
3533
1728
|
return;
|
|
3534
1729
|
}
|
|
3535
|
-
if (
|
|
1730
|
+
if (stringWidth(text) <= DESCRIPTION_MAX) {
|
|
3536
1731
|
return text;
|
|
3537
1732
|
}
|
|
3538
1733
|
const slice = columnsPrefix(text, DESCRIPTION_MAX - 1);
|
|
3539
1734
|
const boundary = slice.lastIndexOf(" ");
|
|
3540
|
-
const head = (boundary !== -1 &&
|
|
1735
|
+
const head = (boundary !== -1 && stringWidth(slice.slice(0, boundary)) >= DESCRIPTION_MIN ? slice.slice(0, boundary) : slice).replace(TRAILING_FRAGMENT, "");
|
|
3541
1736
|
return `${head}…`;
|
|
3542
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
|
+
};
|
|
3543
1766
|
var slugifyTag = (tag) => tag.toLowerCase().replaceAll(NON_SLUG, "-").replaceAll(EDGE_DASHES, "");
|
|
3544
1767
|
var githubHeaders = () => {
|
|
3545
1768
|
const headers = new Headers({ Accept: "application/vnd.github+json" });
|
|
@@ -3554,9 +1777,9 @@ var releaseToEntry = (release) => {
|
|
|
3554
1777
|
const title = release.name?.trim() || release.tag_name;
|
|
3555
1778
|
const date = release.published_at ?? release.created_at;
|
|
3556
1779
|
const category = release.prerelease ? "Prerelease" : "Release";
|
|
3557
|
-
const body = (release.body ?? "").replaceAll(`\r
|
|
1780
|
+
const body = liftHeadings(neutralizeUnsafeLinks((release.body ?? "").replaceAll(`\r
|
|
3558
1781
|
`, `
|
|
3559
|
-
`).trim();
|
|
1782
|
+
`)).trim());
|
|
3560
1783
|
const description = releaseDescription(body);
|
|
3561
1784
|
const data = {
|
|
3562
1785
|
changelog: { category, version },
|
|
@@ -3642,6 +1865,7 @@ var githubReleasesSource = (options, ctx) => {
|
|
|
3642
1865
|
};
|
|
3643
1866
|
return {
|
|
3644
1867
|
load,
|
|
1868
|
+
monolingual: true,
|
|
3645
1869
|
name: options.name,
|
|
3646
1870
|
prefix: options.prefix,
|
|
3647
1871
|
read,
|
|
@@ -3794,36 +2018,22 @@ var mdxRemoteSource = (options, ctx) => {
|
|
|
3794
2018
|
};
|
|
3795
2019
|
|
|
3796
2020
|
// src/core/sources/notion.ts
|
|
3797
|
-
import { setTimeout as
|
|
2021
|
+
import { setTimeout as sleep } from "node:timers/promises";
|
|
3798
2022
|
import pLimit from "p-limit";
|
|
3799
|
-
import { join as
|
|
3800
|
-
|
|
3801
|
-
// src/components/content/youtube.ts
|
|
3802
|
-
var BARE_ID = /^[\w-]{11}$/u;
|
|
3803
|
-
var URL_ID = /(?:youtu\.be\/|\/embed\/|\/shorts\/|\/live\/|[?&]v=)(?<id>[\w-]{11})/u;
|
|
3804
|
-
var parseYouTubeId = (input) => {
|
|
3805
|
-
const value = input.trim();
|
|
3806
|
-
if (!value) {
|
|
3807
|
-
return null;
|
|
3808
|
-
}
|
|
3809
|
-
if (BARE_ID.test(value)) {
|
|
3810
|
-
return value;
|
|
3811
|
-
}
|
|
3812
|
-
return URL_ID.exec(value)?.groups?.id ?? null;
|
|
3813
|
-
};
|
|
2023
|
+
import { join as join4 } from "pathe";
|
|
3814
2024
|
|
|
3815
2025
|
// src/core/sources/assets.ts
|
|
3816
2026
|
import { randomUUID } from "node:crypto";
|
|
3817
2027
|
import {
|
|
3818
2028
|
access,
|
|
3819
|
-
mkdir
|
|
2029
|
+
mkdir,
|
|
3820
2030
|
readdir,
|
|
3821
2031
|
rename,
|
|
3822
2032
|
rm,
|
|
3823
|
-
writeFile
|
|
2033
|
+
writeFile
|
|
3824
2034
|
} from "node:fs/promises";
|
|
3825
|
-
import { extname as
|
|
3826
|
-
var
|
|
2035
|
+
import { extname as extname3, join as join3 } from "pathe";
|
|
2036
|
+
var MD_IMAGE = /!\[(?<alt>[^\]]*)\]\((?<url>[^)\s]+)\)/gu;
|
|
3827
2037
|
var HTML_VIDEO_SRC = /(?<open><video\b[^>]*?\ssrc=")(?<url>[^"]+)(?<close>")/gu;
|
|
3828
2038
|
var REMOTE = /^https?:\/\//u;
|
|
3829
2039
|
var SAFE_EXT = /^\.[a-z0-9]+$/iu;
|
|
@@ -3847,7 +2057,7 @@ var PART_SUFFIX = ".part";
|
|
|
3847
2057
|
var DEFAULT_TIMEOUT_MS = 120000;
|
|
3848
2058
|
var extFromUrl = (url) => {
|
|
3849
2059
|
const clean = url.split("?")[0] ?? url;
|
|
3850
|
-
const ext =
|
|
2060
|
+
const ext = extname3(clean);
|
|
3851
2061
|
return SAFE_EXT.test(ext) ? ext.toLowerCase() : null;
|
|
3852
2062
|
};
|
|
3853
2063
|
var mediaType = (res) => res.headers.get("content-type")?.split(";")[0]?.trim().toLowerCase() ?? "";
|
|
@@ -3872,6 +2082,7 @@ var completedFor = async (dir, stem) => {
|
|
|
3872
2082
|
var materializeAssets = async (markdown, ctx) => {
|
|
3873
2083
|
const doFetch = ctx.fetchImpl ?? globalThis.fetch;
|
|
3874
2084
|
const limit = ctx.limit ?? ((task) => task());
|
|
2085
|
+
const inFlight = ctx.inFlight ?? new Map;
|
|
3875
2086
|
const timeoutMs = ctx.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
3876
2087
|
const diagnostics = [];
|
|
3877
2088
|
const fences = [];
|
|
@@ -3880,7 +2091,7 @@ var materializeAssets = async (markdown, ctx) => {
|
|
|
3880
2091
|
return `\x00blume-fence-${fences.length - 1}\x00`;
|
|
3881
2092
|
});
|
|
3882
2093
|
const urls = new Set;
|
|
3883
|
-
for (const pattern of [
|
|
2094
|
+
for (const pattern of [MD_IMAGE, HTML_VIDEO_SRC]) {
|
|
3884
2095
|
for (const match of masked.matchAll(pattern)) {
|
|
3885
2096
|
const url = match.groups?.url;
|
|
3886
2097
|
if (url && REMOTE.test(url)) {
|
|
@@ -3888,10 +2099,9 @@ var materializeAssets = async (markdown, ctx) => {
|
|
|
3888
2099
|
}
|
|
3889
2100
|
}
|
|
3890
2101
|
}
|
|
3891
|
-
const download = async (url) => {
|
|
3892
|
-
const stem = hashText(url.split("?")[0] ?? url);
|
|
2102
|
+
const download = async (url, stem) => {
|
|
3893
2103
|
const urlExt = extFromUrl(url);
|
|
3894
|
-
if (urlExt && await exists(
|
|
2104
|
+
if (urlExt && await exists(join3(ctx.assetsDir, `${stem}${urlExt}`))) {
|
|
3895
2105
|
return `${stem}${urlExt}`;
|
|
3896
2106
|
}
|
|
3897
2107
|
const completed = urlExt ? null : await completedFor(ctx.assetsDir, stem);
|
|
@@ -3910,11 +2120,11 @@ var materializeAssets = async (markdown, ctx) => {
|
|
|
3910
2120
|
throw new Error("empty response body");
|
|
3911
2121
|
}
|
|
3912
2122
|
const file = `${stem}${urlExt ?? EXT_BY_MIME.get(type) ?? UNKNOWN_EXT}`;
|
|
3913
|
-
const target =
|
|
3914
|
-
await
|
|
2123
|
+
const target = join3(ctx.assetsDir, file);
|
|
2124
|
+
await mkdir(ctx.assetsDir, { recursive: true });
|
|
3915
2125
|
const part = `${target}.${randomUUID()}${PART_SUFFIX}`;
|
|
3916
2126
|
try {
|
|
3917
|
-
await
|
|
2127
|
+
await writeFile(part, res.body);
|
|
3918
2128
|
} catch (error) {
|
|
3919
2129
|
await rm(part, { force: true });
|
|
3920
2130
|
throw error;
|
|
@@ -3922,10 +2132,30 @@ var materializeAssets = async (markdown, ctx) => {
|
|
|
3922
2132
|
await rename(part, target);
|
|
3923
2133
|
return file;
|
|
3924
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
|
+
};
|
|
3925
2155
|
const rewrites = new Map;
|
|
3926
2156
|
await Promise.all([...urls].map(async (url) => {
|
|
3927
2157
|
try {
|
|
3928
|
-
const file = await
|
|
2158
|
+
const file = await publish(url);
|
|
3929
2159
|
rewrites.set(url, `${ctx.assetsBaseUrl}/${file}`);
|
|
3930
2160
|
} catch (error) {
|
|
3931
2161
|
diagnostics.push({
|
|
@@ -3935,7 +2165,7 @@ var materializeAssets = async (markdown, ctx) => {
|
|
|
3935
2165
|
});
|
|
3936
2166
|
}
|
|
3937
2167
|
}));
|
|
3938
|
-
const rewritten = masked.replaceAll(
|
|
2168
|
+
const rewritten = masked.replaceAll(MD_IMAGE, (match, alt, url) => {
|
|
3939
2169
|
const local = rewrites.get(url);
|
|
3940
2170
|
return local ? `` : match;
|
|
3941
2171
|
}).replaceAll(HTML_VIDEO_SRC, (match, open, url, close) => {
|
|
@@ -3946,22 +2176,12 @@ var materializeAssets = async (markdown, ctx) => {
|
|
|
3946
2176
|
};
|
|
3947
2177
|
|
|
3948
2178
|
// src/core/sources/notion.ts
|
|
3949
|
-
var richToMarkdown = (rich = []) => rich.map((
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
text = `**${text}**`;
|
|
3956
|
-
}
|
|
3957
|
-
if (node.annotations?.italic) {
|
|
3958
|
-
text = `*${text}*`;
|
|
3959
|
-
}
|
|
3960
|
-
if (node.annotations?.strikethrough) {
|
|
3961
|
-
text = `~~${text}~~`;
|
|
3962
|
-
}
|
|
3963
|
-
return node.href ? `[${text}](${node.href})` : text;
|
|
3964
|
-
}).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("");
|
|
3965
2185
|
var isBlockPayload = (value) => typeof value === "object";
|
|
3966
2186
|
var payloadOf = (block) => {
|
|
3967
2187
|
const value = block[block.type];
|
|
@@ -3971,7 +2191,7 @@ var blockField = (block) => payloadOf(block)?.rich_text ?? [];
|
|
|
3971
2191
|
var RATE_LIMITED = 429;
|
|
3972
2192
|
var MAX_RETRIES = 4;
|
|
3973
2193
|
var BASE_DELAY_MS = 500;
|
|
3974
|
-
var
|
|
2194
|
+
var SECOND_MS = 1000;
|
|
3975
2195
|
var DEFAULT_CONCURRENCY = 3;
|
|
3976
2196
|
var ASSET_DOWNLOAD_CONCURRENCY = 4;
|
|
3977
2197
|
var withNotionRetry = async (call, attempt = 0) => {
|
|
@@ -3983,8 +2203,8 @@ var withNotionRetry = async (call, attempt = 0) => {
|
|
|
3983
2203
|
throw error;
|
|
3984
2204
|
}
|
|
3985
2205
|
const retryAfter = Number(error.headers?.["retry-after"]);
|
|
3986
|
-
const wait = retryAfter > 0 ? retryAfter *
|
|
3987
|
-
await
|
|
2206
|
+
const wait = retryAfter > 0 ? retryAfter * SECOND_MS : BASE_DELAY_MS * 2 ** attempt * (1 + Math.random());
|
|
2207
|
+
await sleep(wait);
|
|
3988
2208
|
return withNotionRetry(call, attempt + 1);
|
|
3989
2209
|
}
|
|
3990
2210
|
};
|
|
@@ -4050,13 +2270,11 @@ var renderLeaf = (block) => {
|
|
|
4050
2270
|
return "---";
|
|
4051
2271
|
}
|
|
4052
2272
|
case "code": {
|
|
4053
|
-
return
|
|
4054
|
-
${text}
|
|
4055
|
-
\`\`\``;
|
|
2273
|
+
return codeFence(richToPlain(blockField(block)), data.language ?? "");
|
|
4056
2274
|
}
|
|
4057
2275
|
case "image": {
|
|
4058
2276
|
const url = data.external?.url ?? data.file?.url;
|
|
4059
|
-
return url ?
|
|
2277
|
+
return url ? image(richToPlain(data.caption), url) : "";
|
|
4060
2278
|
}
|
|
4061
2279
|
case "video": {
|
|
4062
2280
|
return renderVideo(data);
|
|
@@ -4070,18 +2288,19 @@ var notionSource = (options, ctx) => {
|
|
|
4070
2288
|
const props = options.properties ?? {};
|
|
4071
2289
|
const limit = pLimit(Math.max(1, options.concurrency ?? DEFAULT_CONCURRENCY));
|
|
4072
2290
|
const downloads = pLimit(ASSET_DOWNLOAD_CONCURRENCY);
|
|
2291
|
+
const inFlight = new Map;
|
|
4073
2292
|
const notionCall = (call) => withNotionRetry(() => limit(call));
|
|
4074
|
-
const cache = snapshotCache(ctx?.cacheDir ??
|
|
4075
|
-
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);
|
|
4076
2295
|
const assetsBaseUrl = ctx?.assetsBaseUrl ?? `/blume-assets/${options.name}`;
|
|
4077
2296
|
let snapshot = new Map;
|
|
4078
|
-
const resolveClient =
|
|
2297
|
+
const resolveClient = () => {
|
|
4079
2298
|
if (options.client) {
|
|
4080
2299
|
return options.client;
|
|
4081
2300
|
}
|
|
4082
2301
|
let Client;
|
|
4083
2302
|
try {
|
|
4084
|
-
const sdk =
|
|
2303
|
+
const sdk = nodeRequire("@notionhq/client");
|
|
4085
2304
|
({ Client } = sdk);
|
|
4086
2305
|
} catch {
|
|
4087
2306
|
throw new BlumeError({
|
|
@@ -4109,7 +2328,7 @@ ${body}
|
|
|
4109
2328
|
</Callout>`;
|
|
4110
2329
|
}
|
|
4111
2330
|
if (block.type === "toggle") {
|
|
4112
|
-
const title = jsxString(
|
|
2331
|
+
const title = jsxString(richToPlain(blockField(block)));
|
|
4113
2332
|
return `<Accordion>
|
|
4114
2333
|
<AccordionItem title=${title}>
|
|
4115
2334
|
${await children(block)}
|
|
@@ -4185,11 +2404,11 @@ ${nested}`;
|
|
|
4185
2404
|
};
|
|
4186
2405
|
const frontmatter = (page) => {
|
|
4187
2406
|
const data = {};
|
|
4188
|
-
const title =
|
|
2407
|
+
const title = richToPlain(titleProperty(page)?.title);
|
|
4189
2408
|
if (title) {
|
|
4190
2409
|
data.title = title;
|
|
4191
2410
|
}
|
|
4192
|
-
const description =
|
|
2411
|
+
const description = richToPlain(page.properties[props.description ?? "Description"]?.rich_text);
|
|
4193
2412
|
if (description) {
|
|
4194
2413
|
data.description = description;
|
|
4195
2414
|
}
|
|
@@ -4200,7 +2419,7 @@ ${nested}`;
|
|
|
4200
2419
|
if (order !== undefined) {
|
|
4201
2420
|
data.sidebar = { order };
|
|
4202
2421
|
}
|
|
4203
|
-
const slugProp =
|
|
2422
|
+
const slugProp = richToPlain(page.properties[props.slug ?? "Slug"]?.rich_text);
|
|
4204
2423
|
const slug = slugifyPath(slugProp || title) || page.id;
|
|
4205
2424
|
return { data, slug };
|
|
4206
2425
|
};
|
|
@@ -4211,6 +2430,7 @@ ${nested}`;
|
|
|
4211
2430
|
assetsBaseUrl,
|
|
4212
2431
|
assetsDir,
|
|
4213
2432
|
fetchImpl: options.fetchImpl,
|
|
2433
|
+
inFlight,
|
|
4214
2434
|
limit: downloads
|
|
4215
2435
|
});
|
|
4216
2436
|
const raw = frontmatter_default.stringify(assets.markdown, data);
|
|
@@ -4245,7 +2465,7 @@ ${nested}`;
|
|
|
4245
2465
|
const load = async (refresh = ctx?.refresh ?? true) => {
|
|
4246
2466
|
const assetDiagnostics = [];
|
|
4247
2467
|
const result = await loadWithCache(options.name, cache, async () => {
|
|
4248
|
-
const client =
|
|
2468
|
+
const client = resolveClient();
|
|
4249
2469
|
const dataSourceId = await resolveDataSource(client);
|
|
4250
2470
|
const pages = await collectAll((cursor) => queryDataSource(client, dataSourceId, cursor));
|
|
4251
2471
|
const built = await Promise.all(pages.map((page) => toEntry(client, page)));
|
|
@@ -4279,9 +2499,9 @@ ${nested}`;
|
|
|
4279
2499
|
};
|
|
4280
2500
|
|
|
4281
2501
|
// src/core/sources/obsidian.ts
|
|
4282
|
-
import { existsSync as
|
|
4283
|
-
import { readdir as readdir2, readFile as
|
|
4284
|
-
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";
|
|
4285
2505
|
var MARKDOWN_FILE = /\.md$/iu;
|
|
4286
2506
|
var OBSIDIAN_COMMENT = /%%.*?%%/gu;
|
|
4287
2507
|
var WIKILINK = /(?<embed>!)?\[\[(?<target>(?:[^\][|#\n][^\]|#\n]*?)?)(?:#(?<heading>[^\]|\n]+?))?(?:\\?\|(?<alias>[^\]\n]+))?\]\]/gu;
|
|
@@ -4429,7 +2649,7 @@ var transformChunk = (chunk, index, self, unresolved) => chunk.replaceAll(OBSIDI
|
|
|
4429
2649
|
return `[${label}](${href}#${anchor})`;
|
|
4430
2650
|
});
|
|
4431
2651
|
var transformProse = (text, index, self, unresolved) => splitLiterals(text).map((chunk) => chunk.literal ? chunk.text : transformChunk(chunk.text, index, self, unresolved)).join("");
|
|
4432
|
-
var
|
|
2652
|
+
var INDENTED_CODE = /^(?: {4}|\t)/u;
|
|
4433
2653
|
var LIST_ITEM = /^ {0,3}(?:[-+*]|\d{1,9}[.)])(?: |$)/u;
|
|
4434
2654
|
var indentOf = (line) => line.length - line.trimStart().length;
|
|
4435
2655
|
var listAfter = (line, inList) => {
|
|
@@ -4442,7 +2662,7 @@ var listAfter = (line, inList) => {
|
|
|
4442
2662
|
return line.startsWith(" ") || line.startsWith("\t") ? inList : false;
|
|
4443
2663
|
};
|
|
4444
2664
|
var fenceAfter = (line, fence, fenceIndent, inList) => {
|
|
4445
|
-
const canDelimit = fence === null ? inList || !
|
|
2665
|
+
const canDelimit = fence === null ? inList || !INDENTED_CODE.test(line) : indentOf(line) <= fenceIndent + 3;
|
|
4446
2666
|
return canDelimit ? nextFenceState(line, fence) : fence;
|
|
4447
2667
|
};
|
|
4448
2668
|
var transformBody = (body, index, self, unresolved) => {
|
|
@@ -4464,7 +2684,7 @@ var transformBody = (body, index, self, unresolved) => {
|
|
|
4464
2684
|
`)) {
|
|
4465
2685
|
const blank = line.trim() === "";
|
|
4466
2686
|
if (fence === null && indentedCode) {
|
|
4467
|
-
if (blank ||
|
|
2687
|
+
if (blank || INDENTED_CODE.test(line)) {
|
|
4468
2688
|
out.push(line);
|
|
4469
2689
|
afterBlank = blank;
|
|
4470
2690
|
continue;
|
|
@@ -4472,7 +2692,7 @@ var transformBody = (body, index, self, unresolved) => {
|
|
|
4472
2692
|
indentedCode = false;
|
|
4473
2693
|
}
|
|
4474
2694
|
inList = listAfter(line, inList);
|
|
4475
|
-
if (fence === null && afterBlank && !(blank || inList) &&
|
|
2695
|
+
if (fence === null && afterBlank && !(blank || inList) && INDENTED_CODE.test(line)) {
|
|
4476
2696
|
flush();
|
|
4477
2697
|
indentedCode = true;
|
|
4478
2698
|
out.push(line);
|
|
@@ -4596,9 +2816,9 @@ var noteToEntry = (pair, index, options, unresolved) => {
|
|
|
4596
2816
|
};
|
|
4597
2817
|
};
|
|
4598
2818
|
var readNote = async (vaultDir, rel, options) => {
|
|
4599
|
-
const absPath =
|
|
2819
|
+
const absPath = join5(vaultDir, rel);
|
|
4600
2820
|
try {
|
|
4601
|
-
const { content, data } = frontmatter_default(await
|
|
2821
|
+
const { content, data } = frontmatter_default(await readFile2(absPath, "utf-8"));
|
|
4602
2822
|
return {
|
|
4603
2823
|
absPath,
|
|
4604
2824
|
content,
|
|
@@ -4623,7 +2843,7 @@ var classify = async (dir, entry) => {
|
|
|
4623
2843
|
};
|
|
4624
2844
|
}
|
|
4625
2845
|
try {
|
|
4626
|
-
const target = await stat(
|
|
2846
|
+
const target = await stat(join5(dir, entry.name));
|
|
4627
2847
|
return {
|
|
4628
2848
|
directory: target.isDirectory(),
|
|
4629
2849
|
file: target.isFile(),
|
|
@@ -4643,11 +2863,11 @@ var walkVault = async (dir, root, exclude) => {
|
|
|
4643
2863
|
const listed = await readdir2(dir, { withFileTypes: true });
|
|
4644
2864
|
const entries = await Promise.all(listed.filter((entry) => !(isHidden(entry.name) || exclude.has(entry.name))).map((entry) => classify(dir, entry)));
|
|
4645
2865
|
for (const entry of entries.toSorted(byVaultOrder)) {
|
|
4646
|
-
const full =
|
|
2866
|
+
const full = join5(dir, entry.name);
|
|
4647
2867
|
if (entry.directory) {
|
|
4648
2868
|
found.push(...await walkVault(full, root, exclude));
|
|
4649
2869
|
} else if (entry.file && MARKDOWN_FILE.test(entry.name)) {
|
|
4650
|
-
found.push(
|
|
2870
|
+
found.push(relative4(root, full));
|
|
4651
2871
|
}
|
|
4652
2872
|
}
|
|
4653
2873
|
return found;
|
|
@@ -4683,7 +2903,7 @@ var unresolvedDiagnostics = (name, unresolved) => {
|
|
|
4683
2903
|
return diagnostics;
|
|
4684
2904
|
};
|
|
4685
2905
|
var obsidianSource = (options, ctx) => {
|
|
4686
|
-
const vaultDir =
|
|
2906
|
+
const vaultDir = resolve2(ctx.projectRoot, options.vault);
|
|
4687
2907
|
const exclude = new Set([...BLUME_IGNORE_DIRS, ...options.exclude ?? []]);
|
|
4688
2908
|
const load = async () => {
|
|
4689
2909
|
const files = await walkVault(vaultDir, vaultDir, exclude);
|
|
@@ -4698,9 +2918,9 @@ var obsidianSource = (options, ctx) => {
|
|
|
4698
2918
|
};
|
|
4699
2919
|
};
|
|
4700
2920
|
const read = async (ref) => {
|
|
4701
|
-
const absPath =
|
|
4702
|
-
const rel =
|
|
4703
|
-
if (rel.startsWith("..") ||
|
|
2921
|
+
const absPath = resolve2(vaultDir, ref);
|
|
2922
|
+
const rel = relative4(vaultDir, absPath);
|
|
2923
|
+
if (rel.startsWith("..") || isAbsolute2(rel)) {
|
|
4704
2924
|
throw new BlumeError({
|
|
4705
2925
|
code: "BLUME_SOURCE_MISCONFIGURED",
|
|
4706
2926
|
file: absPath,
|
|
@@ -4709,7 +2929,7 @@ var obsidianSource = (options, ctx) => {
|
|
|
4709
2929
|
suggestion: "Reference notes by their vault-relative path."
|
|
4710
2930
|
});
|
|
4711
2931
|
}
|
|
4712
|
-
return await
|
|
2932
|
+
return await readFile2(absPath, "utf-8");
|
|
4713
2933
|
};
|
|
4714
2934
|
const validate = () => {
|
|
4715
2935
|
const stats = statSync(vaultDir, { throwIfNoEntry: false });
|
|
@@ -4726,7 +2946,7 @@ var obsidianSource = (options, ctx) => {
|
|
|
4726
2946
|
});
|
|
4727
2947
|
};
|
|
4728
2948
|
const watch = (onChange) => {
|
|
4729
|
-
if (!
|
|
2949
|
+
if (!existsSync2(vaultDir)) {
|
|
4730
2950
|
return () => {};
|
|
4731
2951
|
}
|
|
4732
2952
|
const watcher = fsWatch2(vaultDir, { recursive: true }, ignoringWatchListener(onChange, exclude, isHidden));
|
|
@@ -4744,8 +2964,193 @@ var obsidianSource = (options, ctx) => {
|
|
|
4744
2964
|
};
|
|
4745
2965
|
};
|
|
4746
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
|
+
|
|
4747
3152
|
// src/core/sources/sanity.ts
|
|
4748
|
-
import { join as
|
|
3153
|
+
import { join as join6 } from "pathe";
|
|
4749
3154
|
|
|
4750
3155
|
// src/core/sources/portable-text.ts
|
|
4751
3156
|
var HEADING_STYLES = new Map([
|
|
@@ -4756,11 +3161,9 @@ var HEADING_STYLES = new Map([
|
|
|
4756
3161
|
["h5", "##### "],
|
|
4757
3162
|
["h6", "###### "]
|
|
4758
3163
|
]);
|
|
4759
|
-
var MARKDOWN_SPECIALS = /[\\`*_[\]~<]/gu;
|
|
4760
|
-
var escapeText = (text) => text.replaceAll(MARKDOWN_SPECIALS, String.raw`\$&`);
|
|
4761
3164
|
var renderSpan = (span, defs) => {
|
|
4762
3165
|
const isCode = span.marks?.includes("code") ?? false;
|
|
4763
|
-
let text = isCode ? span.text ?? "" :
|
|
3166
|
+
let text = isCode ? span.text ?? "" : escapeMarkdownText(span.text ?? "");
|
|
4764
3167
|
if (!span.marks || span.marks.length === 0) {
|
|
4765
3168
|
return text;
|
|
4766
3169
|
}
|
|
@@ -4798,7 +3201,7 @@ var renderChildren = (block) => {
|
|
|
4798
3201
|
return (block.children ?? []).map((span) => renderSpan(span, defs)).join("");
|
|
4799
3202
|
};
|
|
4800
3203
|
var isAltText = (value) => typeof value === "string";
|
|
4801
|
-
var
|
|
3204
|
+
var renderBlock3 = (block, options) => {
|
|
4802
3205
|
const custom = options.serializers?.[block._type];
|
|
4803
3206
|
if (custom) {
|
|
4804
3207
|
return custom(block);
|
|
@@ -4806,10 +3209,10 @@ var renderBlock = (block, options) => {
|
|
|
4806
3209
|
if (block._type === "image") {
|
|
4807
3210
|
const url = options.imageUrl?.(block);
|
|
4808
3211
|
const alt = isAltText(block.alt) ? block.alt : "";
|
|
4809
|
-
return url ?
|
|
3212
|
+
return url ? image(alt, url) : "";
|
|
4810
3213
|
}
|
|
4811
3214
|
if (block._type !== "block") {
|
|
4812
|
-
return
|
|
3215
|
+
return unsupported(`Portable Text block: ${block._type}`, writesMdx(options.serializers));
|
|
4813
3216
|
}
|
|
4814
3217
|
const inline = renderChildren(block);
|
|
4815
3218
|
if (block.listItem) {
|
|
@@ -4823,7 +3226,7 @@ var renderBlock = (block, options) => {
|
|
|
4823
3226
|
return `${HEADING_STYLES.get(block.style ?? "normal") ?? ""}${inline}`;
|
|
4824
3227
|
};
|
|
4825
3228
|
var portableTextToMarkdown = (blocks, options = {}) => {
|
|
4826
|
-
const lines = blocks.map((block) =>
|
|
3229
|
+
const lines = blocks.map((block) => renderBlock3(block, options));
|
|
4827
3230
|
const out = [];
|
|
4828
3231
|
for (let i = 0;i < lines.length; i += 1) {
|
|
4829
3232
|
const line = lines[i] ?? "";
|
|
@@ -4843,20 +3246,6 @@ var portableTextToMarkdown = (blocks, options = {}) => {
|
|
|
4843
3246
|
|
|
4844
3247
|
// src/core/sources/sanity.ts
|
|
4845
3248
|
var IMAGE_REF = /^image-(?<id>[a-f0-9]+)-(?<dims>\d+x\d+)-(?<ext>\w+)$/u;
|
|
4846
|
-
var isTraversable = (value) => typeof value === "object" && value !== null;
|
|
4847
|
-
var getPath = (doc, path) => {
|
|
4848
|
-
let current = doc;
|
|
4849
|
-
for (const key of path.split(".")) {
|
|
4850
|
-
if (isTraversable(current)) {
|
|
4851
|
-
current = current[key];
|
|
4852
|
-
} else {
|
|
4853
|
-
return;
|
|
4854
|
-
}
|
|
4855
|
-
}
|
|
4856
|
-
return current;
|
|
4857
|
-
};
|
|
4858
|
-
var isStringValue2 = (value) => typeof value === "string";
|
|
4859
|
-
var asString = (value) => isStringValue2(value) ? value : undefined;
|
|
4860
3249
|
var imageUrlFromRef = (ref, projectId, dataset) => {
|
|
4861
3250
|
const match = ref.match(IMAGE_REF);
|
|
4862
3251
|
if (!match?.groups) {
|
|
@@ -4865,13 +3254,13 @@ var imageUrlFromRef = (ref, projectId, dataset) => {
|
|
|
4865
3254
|
const { id, dims, ext } = match.groups;
|
|
4866
3255
|
return `https://cdn.sanity.io/images/${projectId}/${dataset}/${id}-${dims}.${ext}`;
|
|
4867
3256
|
};
|
|
4868
|
-
var resolveClient =
|
|
3257
|
+
var resolveClient = (options, preview) => {
|
|
4869
3258
|
if (options.client) {
|
|
4870
3259
|
return options.client;
|
|
4871
3260
|
}
|
|
4872
3261
|
let createClient;
|
|
4873
3262
|
try {
|
|
4874
|
-
({ createClient } =
|
|
3263
|
+
({ createClient } = nodeRequire("@sanity/client"));
|
|
4875
3264
|
} catch {
|
|
4876
3265
|
throw new BlumeError({
|
|
4877
3266
|
code: "BLUME_SOURCE_SDK_MISSING",
|
|
@@ -4890,11 +3279,11 @@ var resolveClient = async (options, preview) => {
|
|
|
4890
3279
|
};
|
|
4891
3280
|
var sanitySource = (options, ctx) => {
|
|
4892
3281
|
const fields = options.fields ?? {};
|
|
4893
|
-
const cache = snapshotCache(ctx?.cacheDir ??
|
|
3282
|
+
const cache = snapshotCache(ctx?.cacheDir ?? join6(".blume", "cache", options.name));
|
|
4894
3283
|
let snapshot = new Map;
|
|
4895
3284
|
const toEntry = (doc) => {
|
|
4896
3285
|
const slugValue = asString(getPath(doc, fields.slug ?? "slug.current")) ?? asString(doc._id) ?? "untitled";
|
|
4897
|
-
const slug = slugifyPath(slugValue) ||
|
|
3286
|
+
const slug = slugifyPath(slugValue) || slugify(asString(doc._id) ?? "") || "untitled";
|
|
4898
3287
|
const data = {};
|
|
4899
3288
|
const title = asString(getPath(doc, fields.title ?? "title"));
|
|
4900
3289
|
const description = asString(getPath(doc, fields.description ?? "description"));
|
|
@@ -4912,19 +3301,20 @@ var sanitySource = (options, ctx) => {
|
|
|
4912
3301
|
},
|
|
4913
3302
|
serializers: options.serializers
|
|
4914
3303
|
}) : "";
|
|
3304
|
+
const format = writesMdx(options.serializers) ? "mdx" : "md";
|
|
4915
3305
|
const raw = frontmatter_default.stringify(markdown, data);
|
|
4916
3306
|
return {
|
|
4917
|
-
body: { format
|
|
3307
|
+
body: { format, text: markdown },
|
|
4918
3308
|
data: { ...data },
|
|
4919
3309
|
hash: hashText(raw),
|
|
4920
3310
|
lastModified: asString(getPath(doc, fields.lastModified ?? "_updatedAt")),
|
|
4921
3311
|
raw,
|
|
4922
|
-
ref: `${slug}
|
|
3312
|
+
ref: `${slug}.${format}`
|
|
4923
3313
|
};
|
|
4924
3314
|
};
|
|
4925
3315
|
const load = async (refresh = ctx?.refresh ?? true) => {
|
|
4926
3316
|
const result = await loadWithCache(options.name, cache, async () => {
|
|
4927
|
-
const client =
|
|
3317
|
+
const client = resolveClient(options, ctx?.preview ?? false);
|
|
4928
3318
|
const docs = await client.fetch(options.query);
|
|
4929
3319
|
return docs.map(toEntry);
|
|
4930
3320
|
}, refresh);
|
|
@@ -4949,6 +3339,162 @@ var sanitySource = (options, ctx) => {
|
|
|
4949
3339
|
};
|
|
4950
3340
|
};
|
|
4951
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
|
+
|
|
4952
3498
|
// src/core/sources/resolve.ts
|
|
4953
3499
|
var uniqueNamer = () => {
|
|
4954
3500
|
const used = new Set;
|
|
@@ -4965,8 +3511,8 @@ var uniqueNamer = () => {
|
|
|
4965
3511
|
};
|
|
4966
3512
|
var sourceContext = (context, name, runtime) => ({
|
|
4967
3513
|
assetsBaseUrl: `/blume-assets/${name}`,
|
|
4968
|
-
assetsDir:
|
|
4969
|
-
cacheDir:
|
|
3514
|
+
assetsDir: join7(context.outDir, "public", "blume-assets", name),
|
|
3515
|
+
cacheDir: join7(context.outDir, "cache", name),
|
|
4970
3516
|
mode: runtime.mode,
|
|
4971
3517
|
preview: runtime.preview,
|
|
4972
3518
|
projectRoot: context.root,
|
|
@@ -4976,119 +3522,61 @@ var typeFrontmatterKeys = (config) => Object.fromEntries(Object.entries(config.c
|
|
|
4976
3522
|
type,
|
|
4977
3523
|
Object.keys(def.frontmatter)
|
|
4978
3524
|
]));
|
|
4979
|
-
var buildSource = (
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
|
|
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
|
-
name,
|
|
5023
|
-
prefix: def.prefix,
|
|
5024
|
-
typeFrontmatterKeys: typeFrontmatterKeys(config),
|
|
5025
|
-
vault: def.vault,
|
|
5026
|
-
versions: config.versions
|
|
5027
|
-
}, sourceContext(context, name, runtime));
|
|
5028
|
-
}
|
|
5029
|
-
if (def.type === "github-releases") {
|
|
5030
|
-
return githubReleasesSource({
|
|
5031
|
-
drafts: def.drafts,
|
|
5032
|
-
limit: def.limit,
|
|
5033
|
-
name,
|
|
5034
|
-
owner: def.owner,
|
|
5035
|
-
pollInterval: def.pollInterval,
|
|
5036
|
-
prefix: def.prefix,
|
|
5037
|
-
prereleases: def.prereleases,
|
|
5038
|
-
repo: def.repo
|
|
5039
|
-
}, sourceContext(context, name, runtime));
|
|
5040
|
-
}
|
|
5041
|
-
return mdxRemoteSource({
|
|
5042
|
-
files: def.files,
|
|
5043
|
-
github: def.github,
|
|
5044
|
-
include: def.include,
|
|
5045
|
-
name,
|
|
5046
|
-
pollInterval: def.pollInterval,
|
|
5047
|
-
prefix: def.prefix,
|
|
5048
|
-
url: def.url
|
|
5049
|
-
}, sourceContext(context, name, runtime));
|
|
5050
|
-
};
|
|
5051
|
-
var resolveRoot = (projectRoot, root) => isAbsolute4(root) ? root : join9(resolve4(projectRoot), root);
|
|
5052
|
-
var resolveDocsCollection = (config, context) => {
|
|
5053
|
-
const filesystem = (config.content.sources ?? []).filter((def) => def.type === "filesystem");
|
|
5054
|
-
const only = filesystem.length === 1 ? filesystem[0] : undefined;
|
|
5055
|
-
if (only) {
|
|
5056
|
-
return {
|
|
5057
|
-
base: resolveRoot(context.root, only.root),
|
|
5058
|
-
exclude: only.exclude,
|
|
5059
|
-
include: only.include
|
|
5060
|
-
};
|
|
5061
|
-
}
|
|
5062
|
-
return {
|
|
5063
|
-
base: context.contentRoot,
|
|
5064
|
-
exclude: config.content.exclude,
|
|
5065
|
-
include: config.content.include
|
|
5066
|
-
};
|
|
5067
|
-
};
|
|
5068
|
-
var baseName = (def) => {
|
|
5069
|
-
if (def.type === "custom") {
|
|
5070
|
-
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
|
+
}
|
|
5071
3568
|
}
|
|
5072
|
-
return
|
|
3569
|
+
return mdxRemoteSource({ ...adapter.options, name }, sourceContext(context, name, runtime));
|
|
5073
3570
|
};
|
|
5074
|
-
var
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
return [
|
|
5078
|
-
filesystemSource({
|
|
5079
|
-
exclude: config.content.exclude,
|
|
5080
|
-
include: config.content.include,
|
|
5081
|
-
name: "filesystem",
|
|
5082
|
-
projectRoot: context.root,
|
|
5083
|
-
root: config.content.root
|
|
5084
|
-
})
|
|
5085
|
-
];
|
|
3571
|
+
var baseName = (adapter) => {
|
|
3572
|
+
if (adapter.kind === "custom") {
|
|
3573
|
+
return adapter.options.name;
|
|
5086
3574
|
}
|
|
5087
|
-
|
|
5088
|
-
return defs.map((def) => buildSource(def, nameFor(baseName(def)), config, context, runtime));
|
|
3575
|
+
return adapter.options.prefix ?? adapter.kind;
|
|
5089
3576
|
};
|
|
5090
3577
|
var resolveSources = (config, context, runtime) => {
|
|
5091
|
-
const
|
|
3578
|
+
const nameFor = uniqueNamer();
|
|
3579
|
+
const sources = config.content.sources.map((adapter) => buildSource(adapter, nameFor(baseName(adapter)), config, context, runtime));
|
|
5092
3580
|
const references = blumeReferences(config);
|
|
5093
3581
|
if (references.length > 0) {
|
|
5094
3582
|
sources.push(openApiSource(references, sourceContext(context, "openapi", runtime)));
|
|
@@ -5098,25 +3586,18 @@ var resolveSources = (config, context, runtime) => {
|
|
|
5098
3586
|
|
|
5099
3587
|
// src/core/project-graph.ts
|
|
5100
3588
|
var isWithin = (dir, path) => {
|
|
5101
|
-
const rel =
|
|
5102
|
-
return !(rel.startsWith("..") ||
|
|
3589
|
+
const rel = relative5(dir, path);
|
|
3590
|
+
return !(rel.startsWith("..") || isAbsolute3(rel));
|
|
5103
3591
|
};
|
|
5104
3592
|
var applyConfigOverrides = (config, overrides) => {
|
|
5105
3593
|
if (!overrides) {
|
|
5106
3594
|
return config;
|
|
5107
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;
|
|
5108
3598
|
return {
|
|
5109
3599
|
...config,
|
|
5110
|
-
content: {
|
|
5111
|
-
...config.content,
|
|
5112
|
-
root: overrides.contentRoot ?? config.content.root
|
|
5113
|
-
},
|
|
5114
|
-
deployment: {
|
|
5115
|
-
...config.deployment,
|
|
5116
|
-
adapter: overrides.adapter ?? config.deployment.adapter,
|
|
5117
|
-
base: overrides.base ?? config.deployment.base,
|
|
5118
|
-
output: overrides.output ?? config.deployment.output
|
|
5119
|
-
}
|
|
3600
|
+
content: { ...config.content, sources }
|
|
5120
3601
|
};
|
|
5121
3602
|
};
|
|
5122
3603
|
var entryIdDiagnostics = (pages, collectionBase) => {
|
|
@@ -5127,7 +3608,7 @@ var entryIdDiagnostics = (pages, collectionBase) => {
|
|
|
5127
3608
|
continue;
|
|
5128
3609
|
}
|
|
5129
3610
|
seen.add(page.sourcePath);
|
|
5130
|
-
const expected =
|
|
3611
|
+
const expected = relative5(collectionBase, page.sourcePath).split("\\").join("/");
|
|
5131
3612
|
const entryId = page.entryId ?? page.source.ref;
|
|
5132
3613
|
if (expected !== entryId) {
|
|
5133
3614
|
diagnostics.push({
|
|
@@ -5135,7 +3616,7 @@ var entryIdDiagnostics = (pages, collectionBase) => {
|
|
|
5135
3616
|
file: page.sourcePath,
|
|
5136
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.`,
|
|
5137
3618
|
severity: "error",
|
|
5138
|
-
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."
|
|
5139
3620
|
});
|
|
5140
3621
|
}
|
|
5141
3622
|
}
|
|
@@ -5157,6 +3638,7 @@ var normalizeLoadedEntries = (loaded, config) => {
|
|
|
5157
3638
|
frontmatterExtend,
|
|
5158
3639
|
i18n: config.i18n,
|
|
5159
3640
|
source: {
|
|
3641
|
+
monolingual: source.monolingual,
|
|
5160
3642
|
name: source.name,
|
|
5161
3643
|
prefix: source.prefix,
|
|
5162
3644
|
staged: source.staged
|
|
@@ -5173,13 +3655,15 @@ var normalizeLoadedEntries = (loaded, config) => {
|
|
|
5173
3655
|
}
|
|
5174
3656
|
return { diagnostics: allDiagnostics, droppedPages, pages };
|
|
5175
3657
|
};
|
|
3658
|
+
var isLogoShorthand = (logo) => typeof logo === "string";
|
|
3659
|
+
var logoHref = (logo) => logo === undefined || isLogoShorthand(logo) ? "/" : logo.href ?? "/";
|
|
5176
3660
|
var scanProject = async (root, options = {}) => {
|
|
5177
3661
|
const mode = options.mode ?? "dev";
|
|
5178
3662
|
const preview = options.preview ?? false;
|
|
5179
3663
|
const configResult = await loadConfig(root, {
|
|
5180
3664
|
devServerUrl: options.devServerUrl
|
|
5181
3665
|
});
|
|
5182
|
-
const config =
|
|
3666
|
+
const config = applyConfigOverrides(configResult.config, options.overrides);
|
|
5183
3667
|
const context = resolveProjectContext(root, config, {
|
|
5184
3668
|
runtimeDir: options.runtimeDir
|
|
5185
3669
|
});
|
|
@@ -5243,8 +3727,14 @@ var scanProject = async (root, options = {}) => {
|
|
|
5243
3727
|
const undated = pages.filter((page) => page.sourcePath && !page.lastModified && contentRoots.some((dir) => isWithin(dir, page.sourcePath ?? ""))).length;
|
|
5244
3728
|
lastModifiedWarnings.push(...lastModifiedShallowWarning(context.root, undated));
|
|
5245
3729
|
}
|
|
3730
|
+
const customPages = context.pagesRoot ? await discoverPages(context.pagesRoot) : [];
|
|
5246
3731
|
const graph = buildContentGraph(pages, {
|
|
5247
3732
|
basePath: config.basePath,
|
|
3733
|
+
brandHref: logoHref(config.logo),
|
|
3734
|
+
extraRoutes: new Set([
|
|
3735
|
+
...customStaticRoutes(customPages),
|
|
3736
|
+
...hasChangelogIndex(pages, config) ? [CHANGELOG_INDEX_ROUTE] : []
|
|
3737
|
+
]),
|
|
5248
3738
|
folderMeta: folderMeta.meta,
|
|
5249
3739
|
i18n: config.i18n,
|
|
5250
3740
|
navigation: config.navigation,
|
|
@@ -5261,7 +3751,7 @@ var scanProject = async (root, options = {}) => {
|
|
|
5261
3751
|
...contentDiagnostics,
|
|
5262
3752
|
...includeDiagnostics,
|
|
5263
3753
|
...folderMeta.diagnostics,
|
|
5264
|
-
...entryIdDiagnostics(pages, resolveDocsCollection(config, context).base),
|
|
3754
|
+
...entryIdDiagnostics(pages, resolveDocsCollection(config, context.root).base),
|
|
5265
3755
|
...graph.diagnostics,
|
|
5266
3756
|
...i18nWarnings,
|
|
5267
3757
|
...versionWarnings,
|
|
@@ -5276,7 +3766,7 @@ var scanProject = async (root, options = {}) => {
|
|
|
5276
3766
|
};
|
|
5277
3767
|
};
|
|
5278
3768
|
|
|
5279
|
-
export {
|
|
3769
|
+
export { validateSearchPopularIcons, validateNavTargets, contentIndexable, buildManifest, isWithin, scanProject };
|
|
5280
3770
|
|
|
5281
|
-
//# debugId=
|
|
5282
|
-
//# sourceMappingURL=chunk-
|
|
3771
|
+
//# debugId=EBFFBF92D39DE54464756E2164756E21
|
|
3772
|
+
//# sourceMappingURL=chunk-zg2gtj10.js.map
|