blume 2.0.1 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +147 -0
- package/dist/cli/{chunk-qwsrynx5.js → chunk-1d7ve1dm.js} +38 -19
- package/dist/cli/{chunk-qwsrynx5.js.map → chunk-1d7ve1dm.js.map} +4 -4
- package/dist/cli/{chunk-s6jhgk0q.js → chunk-2eytanqx.js} +2 -2
- package/dist/cli/{chunk-kdp5q7ke.js → chunk-2hsdwb9n.js} +18 -19
- package/dist/cli/{chunk-kdp5q7ke.js.map → chunk-2hsdwb9n.js.map} +2 -2
- package/dist/cli/{chunk-hdpx1tax.js → chunk-2z928egk.js} +5 -5
- package/dist/cli/{chunk-jwyddg7y.js → chunk-35d4wj9f.js} +30 -24
- package/dist/cli/chunk-35d4wj9f.js.map +15 -0
- package/dist/cli/{chunk-ah61y8py.js → chunk-364znk6q.js} +2 -2
- package/dist/cli/{chunk-jts8mvcz.js → chunk-3em5wd2y.js} +25 -6
- package/dist/cli/{chunk-jts8mvcz.js.map → chunk-3em5wd2y.js.map} +3 -3
- package/dist/cli/{chunk-s1p84fyh.js → chunk-5f86nr5m.js} +63 -22
- package/dist/cli/chunk-5f86nr5m.js.map +11 -0
- package/dist/cli/{chunk-2hn4b8z7.js → chunk-5m5nmvyq.js} +170 -76
- package/dist/cli/chunk-5m5nmvyq.js.map +13 -0
- package/dist/cli/{chunk-epjnccmv.js → chunk-5xvm6tfj.js} +18 -15
- package/dist/cli/chunk-5xvm6tfj.js.map +10 -0
- package/dist/cli/{chunk-fz5wtpmh.js → chunk-6dsbexzp.js} +18 -15
- package/dist/cli/chunk-6dsbexzp.js.map +10 -0
- package/dist/cli/{chunk-vtk4a6dg.js → chunk-8ktnccpt.js} +1 -1
- package/dist/cli/{chunk-6hsn950k.js → chunk-9t7a85s3.js} +178 -48
- package/dist/cli/chunk-9t7a85s3.js.map +10 -0
- package/dist/cli/{chunk-fxypxtvm.js → chunk-a58773jm.js} +2 -2
- package/dist/cli/{chunk-mb2919y2.js → chunk-acanzt5p.js} +17 -6
- package/dist/cli/chunk-acanzt5p.js.map +10 -0
- package/dist/cli/{chunk-27g6wdth.js → chunk-akbpwfxc.js} +90 -26
- package/dist/cli/chunk-akbpwfxc.js.map +10 -0
- package/dist/cli/{chunk-wm7js3j9.js → chunk-b07cmahc.js} +2 -2
- package/dist/cli/{chunk-wgm7m9qk.js → chunk-c8chx29p.js} +179 -51
- package/dist/cli/chunk-c8chx29p.js.map +36 -0
- package/dist/cli/{chunk-qs4q5p4e.js → chunk-crgn1q09.js} +32 -14
- package/dist/cli/chunk-crgn1q09.js.map +10 -0
- package/dist/cli/chunk-e04dxsz1.js +39 -0
- package/dist/cli/chunk-e04dxsz1.js.map +10 -0
- package/dist/cli/{chunk-yt5n7ppj.js → chunk-ey84smr6.js} +17 -7
- package/dist/cli/chunk-ey84smr6.js.map +10 -0
- package/dist/cli/{chunk-f2z5v128.js → chunk-g4hq16wv.js} +14 -15
- package/dist/cli/{chunk-f2z5v128.js.map → chunk-g4hq16wv.js.map} +2 -2
- package/dist/cli/{chunk-fa25z98p.js → chunk-ga0pf4aj.js} +9 -8
- package/dist/cli/chunk-ga0pf4aj.js.map +11 -0
- package/dist/cli/{chunk-kpf8rrjc.js → chunk-hm3vjy5s.js} +109 -58
- package/dist/cli/chunk-hm3vjy5s.js.map +19 -0
- package/dist/cli/{chunk-fs23ddbb.js → chunk-j85vccga.js} +625 -750
- package/dist/cli/chunk-j85vccga.js.map +36 -0
- package/dist/cli/{chunk-ch6g3ar0.js → chunk-p3v96n38.js} +6 -6
- package/dist/cli/{chunk-ch6g3ar0.js.map → chunk-p3v96n38.js.map} +3 -3
- package/dist/cli/{chunk-q5163e60.js → chunk-p73c0m7w.js} +21 -19
- package/dist/cli/chunk-p73c0m7w.js.map +11 -0
- package/dist/cli/{chunk-dh8cwk36.js → chunk-pehfxfta.js} +24 -9
- package/dist/cli/chunk-pehfxfta.js.map +10 -0
- package/dist/cli/{chunk-qkqwkpte.js → chunk-pv29h0wf.js} +3688 -1313
- package/dist/cli/chunk-pv29h0wf.js.map +190 -0
- package/dist/cli/{chunk-6vm74dry.js → chunk-q58y5e6a.js} +10 -10
- package/dist/cli/{chunk-6vm74dry.js.map → chunk-q58y5e6a.js.map} +3 -3
- package/dist/cli/{chunk-zxcczpyx.js → chunk-r20tn01b.js} +1 -1
- package/dist/cli/{chunk-m3vmjgmq.js → chunk-r9rcc4w7.js} +16 -8
- package/dist/cli/chunk-r9rcc4w7.js.map +10 -0
- package/dist/cli/{chunk-5shv93fd.js → chunk-tkacnehg.js} +2 -2
- package/dist/cli/{chunk-zxh4d9vy.js → chunk-tzmab476.js} +4 -4
- package/dist/cli/{chunk-yw7dm696.js → chunk-vg9r4eb9.js} +24 -11
- package/dist/cli/chunk-vg9r4eb9.js.map +14 -0
- package/dist/cli/{chunk-79jhk4py.js → chunk-wrr3j9w9.js} +260 -132
- package/dist/cli/chunk-wrr3j9w9.js.map +35 -0
- package/dist/cli/{chunk-6crbhc3x.js → chunk-yfyb25rh.js} +54 -27
- package/dist/cli/chunk-yfyb25rh.js.map +14 -0
- package/dist/cli/index.js +162 -35
- package/dist/cli/index.js.map +4 -4
- package/dist/types/ai/agent-surface.d.ts +32 -0
- package/dist/types/ai/api-catalog.d.ts +7 -1
- package/dist/types/ai/ask-context.d.ts +7 -0
- package/dist/types/ai/component-markdown.d.ts +4 -4
- package/dist/types/ai/link-headers.d.ts +8 -1
- package/dist/types/ai/openapi-components.d.ts +5 -2
- package/dist/types/ai/relative-links.d.ts +11 -4
- package/dist/types/ai/skills.d.ts +4 -1
- package/dist/types/ai/static-expression.d.ts +28 -0
- package/dist/types/ai/tar.d.ts +1 -3
- package/dist/types/analytics/databuddy.d.ts +43 -0
- package/dist/types/analytics/index.d.ts +4 -0
- package/dist/types/analytics/one-dollar-stats.d.ts +48 -0
- package/dist/types/analytics/schema.d.ts +28 -0
- package/dist/types/astro/integration.d.ts +3 -2
- package/dist/types/cli/env.d.ts +5 -0
- package/dist/types/cli/init/scaffold.d.ts +19 -3
- package/dist/types/cli/init/starter-spec.d.ts +11 -0
- package/dist/types/core/base-path.d.ts +24 -1
- package/dist/types/core/config-input.d.ts +13 -11
- package/dist/types/core/config.d.ts +2 -2
- package/dist/types/core/directive-diagnostics.d.ts +12 -0
- package/dist/types/core/graph.d.ts +2 -0
- package/dist/types/core/heading-markers.d.ts +5 -7
- package/dist/types/core/i18n-ui.d.ts +31 -0
- package/dist/types/core/i18n.d.ts +9 -1
- package/dist/types/core/last-modified.d.ts +10 -0
- package/dist/types/core/links.d.ts +3 -1
- package/dist/types/core/load-module.d.ts +10 -0
- package/dist/types/core/locale-links.d.ts +12 -2
- package/dist/types/core/meta.d.ts +13 -1
- package/dist/types/core/nav-diagnostics.d.ts +10 -0
- package/dist/types/core/navigation.d.ts +38 -0
- package/dist/types/core/ordering-prefix.d.ts +4 -0
- package/dist/types/core/safe-links.d.ts +3 -1
- package/dist/types/core/schema.d.ts +59 -13
- package/dist/types/core/sources/github-releases.d.ts +5 -0
- package/dist/types/core/sources/lower.d.ts +38 -13
- package/dist/types/core/sources/normalize.d.ts +23 -2
- package/dist/types/core/sources/remote.d.ts +11 -1
- package/dist/types/core/sources/resolve.d.ts +12 -0
- package/dist/types/core/sources/types.d.ts +31 -0
- package/dist/types/core/sources/watch.d.ts +12 -5
- package/dist/types/core/standard-schema.d.ts +5 -0
- package/dist/types/core/types.d.ts +9 -0
- package/dist/types/deploy/adapters/node.d.ts +5 -2
- package/dist/types/deploy/adapters/types.d.ts +7 -0
- package/dist/types/deploy/artifacts.d.ts +6 -4
- package/dist/types/deploy/cloudflare-negotiation.d.ts +3 -2
- package/dist/types/deploy/headers.d.ts +36 -7
- package/dist/types/deploy/node-headers.d.ts +43 -8
- package/dist/types/deploy/platforms/netlify.d.ts +27 -2
- package/dist/types/deploy/platforms/node.d.ts +6 -5
- package/dist/types/deploy/platforms/types.d.ts +15 -0
- package/dist/types/deploy/platforms/vercel.d.ts +3 -2
- package/dist/types/deploy/redirects.d.ts +31 -15
- package/dist/types/deploy/vercel-negotiation.d.ts +3 -2
- package/dist/types/markdown/directives.d.ts +62 -0
- package/dist/types/markdown/features.d.ts +21 -0
- package/dist/types/markdown/mdast.d.ts +63 -0
- package/dist/types/openapi/asyncapi.d.ts +4 -2
- package/dist/types/openapi/model.d.ts +20 -6
- package/dist/types/search/sync/algolia.d.ts +3 -1
- package/docs/01-quickstart.mdx +3 -2
- package/docs/02-deployment.mdx +20 -9
- package/docs/08-faq.mdx +10 -3
- package/docs/advanced/changelog.mdx +1 -1
- package/docs/advanced/custom-pages.mdx +7 -5
- package/docs/cli/audit.mdx +19 -3
- package/docs/cli/doctor.mdx +2 -2
- package/docs/cli/evals.mdx +4 -4
- package/docs/cli/index.mdx +4 -1
- package/docs/cli/translate.mdx +4 -4
- package/docs/cli/version.mdx +1 -1
- package/docs/configuration/analytics.mdx +42 -2
- package/docs/configuration/assistant.mdx +1 -1
- package/docs/configuration/customization.mdx +6 -3
- package/docs/configuration/index.mdx +5 -3
- package/docs/configuration/search.mdx +2 -2
- package/docs/content/components.mdx +2 -2
- package/docs/content/frontmatter.mdx +5 -1
- package/docs/content/i18n.mdx +3 -1
- package/docs/content/index.mdx +8 -4
- package/docs/content/islands.mdx +1 -1
- package/docs/content/meta.mdx +7 -3
- package/docs/content/navigation.mdx +29 -4
- package/docs/content/sources.mdx +18 -16
- package/docs/content/syntax.mdx +14 -0
- package/docs/content/versioning.mdx +2 -1
- package/docs/discoverability/agent-discovery.mdx +22 -8
- package/docs/discoverability/index.mdx +4 -3
- package/docs/discoverability/llms-txt.mdx +2 -5
- package/docs/discoverability/markdown.mdx +6 -4
- package/docs/discoverability/mcp.mdx +4 -0
- package/docs/discoverability/metadata.mdx +3 -2
- package/docs/discoverability/open-graph.mdx +8 -4
- package/docs/discoverability/rss.mdx +4 -2
- package/docs/references/asyncapi.mdx +2 -2
- package/docs/references/graphql.mdx +2 -2
- package/docs/references/openapi.mdx +6 -4
- package/package.json +1 -1
- package/skills/blume-migrate/SKILL.md +6 -6
- package/skills/blume-migrate/references/docusaurus.md +6 -6
- package/skills/blume-migrate/references/fumadocs.md +1 -1
- package/skills/blume-migrate/references/mintlify.md +3 -3
- package/skills/blume-migrate/references/monorepo.md +1 -1
- package/skills/blume-migrate/references/nextra.md +2 -2
- package/skills/blume-migrate/references/starlight.md +5 -5
- package/skills/blume-migrate/scripts/mintlify-codemod.mjs +9 -4
- package/skills/blume-update-docs/references/audit-checklist.md +1 -1
- package/src/ai/agent-readability.ts +2 -2
- package/src/ai/agent-surface.ts +56 -0
- package/src/ai/ai-catalog.ts +6 -2
- package/src/ai/api/handlers.ts +2 -2
- package/src/ai/api/spec.ts +17 -4
- package/src/ai/api-catalog.ts +13 -3
- package/src/ai/ask-context.ts +14 -2
- package/src/ai/ask-data.ts +26 -12
- package/src/ai/changelog-markdown.ts +2 -2
- package/src/ai/component-markdown.ts +43 -37
- package/src/ai/link-headers.ts +22 -8
- package/src/ai/llms.ts +22 -10
- package/src/ai/markdown.ts +23 -11
- package/src/ai/mcp/discovery.ts +2 -2
- package/src/ai/mcp/query.ts +2 -2
- package/src/ai/mcp/server.ts +80 -9
- package/src/ai/openapi-components.ts +22 -6
- package/src/ai/relative-links.ts +99 -15
- package/src/ai/serializers.ts +2 -1
- package/src/ai/skills.ts +14 -1
- package/src/ai/static-expression.ts +416 -0
- package/src/ai/tar.ts +139 -12
- package/src/ai/visibility.ts +45 -14
- package/src/analytics/databuddy.ts +67 -0
- package/src/analytics/head.ts +8 -0
- package/src/analytics/index.ts +7 -0
- package/src/analytics/one-dollar-stats.ts +86 -0
- package/src/analytics/posthog.ts +21 -3
- package/src/analytics/schema.ts +4 -0
- package/src/astro/generate.ts +72 -28
- package/src/astro/include-hmr.ts +31 -12
- package/src/astro/include-refresh.ts +19 -8
- package/src/astro/integration.ts +108 -14
- package/src/astro/runtime-modules.ts +28 -13
- package/src/astro/templates.ts +139 -57
- package/src/audit/catalog.ts +2 -2
- package/src/audit/checks/assets.ts +25 -5
- package/src/audit/checks/content.ts +20 -2
- package/src/audit/checks/i18n.ts +46 -8
- package/src/audit/checks/indexability.ts +39 -19
- package/src/audit/checks/links.ts +22 -1
- package/src/audit/checks/llms.ts +6 -3
- package/src/audit/checks/network.ts +3 -1
- package/src/audit/checks/og-image.ts +10 -0
- package/src/audit/checks/robots.ts +6 -1
- package/src/audit/checks/sitemap.ts +56 -31
- package/src/audit/checks/social.ts +21 -2
- package/src/audit/crawl.ts +88 -15
- package/src/audit/graph.ts +3 -1
- package/src/audit/report.ts +54 -17
- package/src/audit/run.ts +13 -9
- package/src/audit/snapshot.ts +5 -0
- package/src/audit/types.ts +18 -0
- package/src/audit/url.ts +37 -6
- package/src/cli/args.ts +32 -0
- package/src/cli/build-failure.ts +50 -0
- package/src/cli/commands/audit.ts +11 -1
- package/src/cli/commands/build.ts +19 -5
- package/src/cli/commands/check.ts +2 -0
- package/src/cli/commands/doctor.ts +3 -1
- package/src/cli/commands/eval.ts +20 -18
- package/src/cli/commands/init.ts +15 -5
- package/src/cli/commands/preview.ts +15 -0
- package/src/cli/commands/sync.ts +2 -0
- package/src/cli/commands/translate.ts +18 -18
- package/src/cli/commands/upgrade.ts +11 -0
- package/src/cli/commands/validate.ts +3 -1
- package/src/cli/dev-lock.ts +157 -37
- package/src/cli/eject-scripts.ts +32 -7
- package/src/cli/env.ts +12 -1
- package/src/cli/init/scaffold.ts +117 -11
- package/src/cli/init/starter-spec.ts +235 -0
- package/src/cli/report-format.ts +11 -6
- package/src/components/colors.ts +19 -0
- package/src/components/content/AccordionItem.astro +26 -22
- package/src/components/content/Badge.astro +7 -12
- package/src/components/content/Card.astro +2 -2
- package/src/components/content/Component.astro +11 -5
- package/src/components/content/Expandable.astro +5 -1
- package/src/components/content/Frame.astro +2 -7
- package/src/components/content/GithubInfo.astro +12 -2
- package/src/components/content/Prompt.astro +2 -7
- package/src/components/content/Tab.astro +0 -1
- package/src/components/content/Tabs.astro +58 -5
- package/src/components/content/Tile.astro +1 -1
- package/src/components/content/Tooltip.astro +69 -7
- package/src/components/content/Tree.astro +7 -2
- package/src/components/content/TypeTable.astro +10 -5
- package/src/components/content/Update.astro +8 -2
- package/src/components/content/auto-type-table.ts +4 -1
- package/src/components/content/badge-color.ts +20 -0
- package/src/components/content/base-href.ts +14 -22
- package/src/components/content/inline-markdown.ts +27 -7
- package/src/components/copy-feedback.ts +35 -8
- package/src/components/islands/assistant.tsx +37 -6
- package/src/components/islands/base-path.ts +47 -10
- package/src/components/islands/hooks.ts +42 -21
- package/src/components/islands/webmcp.ts +16 -10
- package/src/components/layout/Banner.astro +23 -4
- package/src/components/layout/Breadcrumbs.astro +5 -2
- package/src/components/layout/DiscoveryLinks.astro +9 -5
- package/src/components/layout/Header.astro +23 -10
- package/src/components/layout/LanguageSwitcher.astro +2 -2
- package/src/components/layout/Logo.astro +5 -0
- package/src/components/layout/NavSelector.astro +8 -3
- package/src/components/layout/NavTabMenu.astro +133 -0
- package/src/components/layout/NavTree.astro +31 -12
- package/src/components/layout/NavTreeCache.astro +5 -2
- package/src/components/layout/NavTreeScript.astro +45 -5
- package/src/components/layout/PageActions.astro +4 -3
- package/src/components/layout/PageLayout.astro +28 -13
- package/src/components/layout/Pagination.astro +3 -3
- package/src/components/layout/ReferenceLayout.astro +4 -1
- package/src/components/layout/RootLayout.astro +25 -12
- package/src/components/layout/Search.astro +38 -14
- package/src/components/layout/VersionBanner.astro +2 -2
- package/src/components/layout/analytics-client.ts +14 -0
- package/src/components/layout/toc-active.ts +41 -0
- package/src/components/layout/toc-element.ts +8 -14
- package/src/components/openapi/ApiTagOperations.astro +2 -2
- package/src/components/openapi/AsyncApiOperation.astro +7 -4
- package/src/components/openapi/GraphqlChip.astro +2 -2
- package/src/components/openapi/GraphqlType.astro +11 -3
- package/src/components/openapi/MessageComposer.astro +1 -1
- package/src/components/openapi/Operation.astro +23 -5
- package/src/components/openapi/PanelTabs.astro +4 -1
- package/src/components/openapi/Playground.astro +8 -2
- package/src/components/openapi/RequestPanel.astro +13 -6
- package/src/components/openapi/SchemaProperty.astro +11 -33
- package/src/components/openapi/SchemaTable.astro +34 -52
- package/src/components/openapi/async.ts +38 -6
- package/src/components/openapi/helpers.ts +100 -12
- package/src/components/openapi/message-composer.ts +14 -1
- package/src/components/openapi/message-model.ts +12 -2
- package/src/components/openapi/message.ts +21 -3
- package/src/components/openapi/operation-model.ts +119 -17
- package/src/components/openapi/panel.ts +31 -5
- package/src/components/openapi/param-style.ts +181 -0
- package/src/components/openapi/playground-client.ts +110 -23
- package/src/components/openapi/playground-schema.ts +25 -6
- package/src/components/openapi/request.ts +192 -26
- package/src/components/openapi/schema-tree.ts +209 -0
- package/src/components/openapi/snippets.ts +113 -19
- package/src/components/openapi/validate-json.ts +1 -1
- package/src/components/openapi/ws-client.ts +18 -2
- package/src/core/base-path.ts +69 -8
- package/src/core/config-input.ts +13 -11
- package/src/core/config.ts +18 -4
- package/src/core/diagnostics.ts +219 -30
- package/src/core/directive-diagnostics.ts +99 -0
- package/src/core/frontmatter.ts +21 -18
- package/src/core/graph.ts +120 -11
- package/src/core/heading-markers.ts +5 -18
- package/src/core/i18n-ui.ts +39 -2
- package/src/core/i18n.ts +44 -5
- package/src/core/last-modified.ts +25 -3
- package/src/core/links.ts +7 -4
- package/src/core/load-module.ts +20 -0
- package/src/core/locale-links.ts +22 -18
- package/src/core/manifest.ts +3 -2
- package/src/core/meta.ts +89 -12
- package/src/core/nav-diagnostics.ts +56 -1
- package/src/core/navigation.ts +272 -83
- package/src/core/ordering-prefix.ts +27 -0
- package/src/core/project-graph.ts +50 -6
- package/src/core/safe-href.ts +53 -1
- package/src/core/safe-links.ts +11 -2
- package/src/core/schema.ts +94 -18
- package/src/core/sources/assets.ts +83 -41
- package/src/core/sources/contentful-rich-text.ts +28 -20
- package/src/core/sources/contentful.ts +25 -12
- package/src/core/sources/filesystem.ts +25 -3
- package/src/core/sources/github-releases.ts +131 -11
- package/src/core/sources/lexical.ts +30 -20
- package/src/core/sources/lower.ts +276 -56
- package/src/core/sources/mdx-remote.ts +52 -16
- package/src/core/sources/normalize.ts +456 -119
- package/src/core/sources/notion.ts +77 -34
- package/src/core/sources/obsidian.ts +40 -9
- package/src/core/sources/payload.ts +1 -0
- package/src/core/sources/portable-text.ts +85 -49
- package/src/core/sources/remote.ts +18 -2
- package/src/core/sources/resolve.ts +52 -33
- package/src/core/sources/sanity.ts +1 -0
- package/src/core/sources/strapi-blocks.ts +28 -19
- package/src/core/sources/strapi.ts +1 -0
- package/src/core/sources/types.ts +31 -0
- package/src/core/sources/watch.ts +20 -7
- package/src/core/standard-schema.ts +10 -6
- package/src/core/types.ts +9 -0
- package/src/core/ui-packs/ar.ts +13 -0
- package/src/core/ui-packs/bg.ts +13 -0
- package/src/core/ui-packs/bn.ts +13 -0
- package/src/core/ui-packs/ca.ts +13 -0
- package/src/core/ui-packs/cs.ts +13 -0
- package/src/core/ui-packs/da.ts +13 -0
- package/src/core/ui-packs/de.ts +13 -0
- package/src/core/ui-packs/el.ts +13 -0
- package/src/core/ui-packs/es.ts +13 -0
- package/src/core/ui-packs/fa.ts +13 -0
- package/src/core/ui-packs/fi.ts +13 -0
- package/src/core/ui-packs/fr.ts +13 -0
- package/src/core/ui-packs/he.ts +13 -0
- package/src/core/ui-packs/hi.ts +13 -0
- package/src/core/ui-packs/hr.ts +13 -0
- package/src/core/ui-packs/hu.ts +13 -0
- package/src/core/ui-packs/id.ts +13 -0
- package/src/core/ui-packs/it.ts +13 -0
- package/src/core/ui-packs/ja.ts +13 -0
- package/src/core/ui-packs/ko.ts +13 -0
- package/src/core/ui-packs/nl.ts +13 -0
- package/src/core/ui-packs/no.ts +13 -0
- package/src/core/ui-packs/pl.ts +13 -0
- package/src/core/ui-packs/pt-br.ts +13 -0
- package/src/core/ui-packs/pt.ts +13 -0
- package/src/core/ui-packs/ro.ts +13 -0
- package/src/core/ui-packs/ru.ts +13 -0
- package/src/core/ui-packs/sk.ts +13 -0
- package/src/core/ui-packs/sr.ts +13 -0
- package/src/core/ui-packs/sv.ts +13 -0
- package/src/core/ui-packs/th.ts +13 -0
- package/src/core/ui-packs/tr.ts +13 -0
- package/src/core/ui-packs/uk.ts +13 -0
- package/src/core/ui-packs/vi.ts +13 -0
- package/src/core/ui-packs/zh-tw.ts +13 -0
- package/src/core/ui-packs/zh.ts +13 -0
- package/src/core/version-cut.ts +69 -17
- package/src/core/versions.ts +4 -1
- package/src/deploy/adapters/node.ts +5 -2
- package/src/deploy/adapters/registry.ts +2 -1
- package/src/deploy/adapters/types.ts +13 -1
- package/src/deploy/artifacts.ts +52 -11
- package/src/deploy/cloudflare-negotiation.ts +27 -16
- package/src/deploy/headers.ts +75 -55
- package/src/deploy/node-headers.ts +148 -27
- package/src/deploy/platforms/cloudflare.ts +13 -3
- package/src/deploy/platforms/netlify.ts +83 -5
- package/src/deploy/platforms/node.ts +8 -5
- package/src/deploy/platforms/static.ts +2 -0
- package/src/deploy/platforms/types.ts +15 -0
- package/src/deploy/platforms/vercel.ts +10 -3
- package/src/deploy/redirects.ts +68 -21
- package/src/deploy/robots.ts +2 -2
- package/src/deploy/rss.ts +4 -3
- package/src/deploy/sitemap.ts +7 -5
- package/src/deploy/vercel-negotiation.ts +35 -3
- package/src/eval/agents.ts +10 -2
- package/src/eval/run.ts +25 -0
- package/src/markdown/base-links.ts +74 -29
- package/src/markdown/directives.ts +242 -36
- package/src/markdown/features.ts +17 -0
- package/src/markdown/index.ts +13 -9
- package/src/markdown/mdast.ts +5 -2
- package/src/markdown/relative-links.ts +15 -27
- package/src/markdown/route-snapshot.ts +37 -0
- package/src/og/card.ts +149 -9
- package/src/og/derive.ts +156 -5
- package/src/og/index.ts +1 -0
- package/src/openapi/asyncapi.ts +4 -2
- package/src/openapi/graphql-build.ts +28 -2
- package/src/openapi/model.ts +99 -27
- package/src/openapi/proxy.ts +63 -10
- package/src/openapi/render-mdx.ts +51 -3
- package/src/registry/eject.ts +297 -43
- package/src/search/adapters/version-scope.ts +30 -0
- package/src/search/documents.ts +89 -27
- package/src/search/popular.ts +2 -1
- package/src/search/sync/algolia.ts +36 -2
- package/src/seo/jsonld.ts +7 -3
- package/src/sources/registry.ts +5 -0
- package/src/theme/entry.ts +11 -4
- package/src/translate/agents.ts +6 -1
- package/src/translate/ledger.ts +26 -3
- package/src/translate/meta.ts +76 -24
- package/src/translate/run.ts +14 -8
- package/src/translate/validate.ts +14 -2
- package/src/translate/work-list.ts +91 -19
- package/src/upgrade/upgrade.ts +36 -4
- package/dist/cli/chunk-27g6wdth.js.map +0 -10
- package/dist/cli/chunk-2hn4b8z7.js.map +0 -12
- package/dist/cli/chunk-6crbhc3x.js.map +0 -14
- package/dist/cli/chunk-6hsn950k.js.map +0 -10
- package/dist/cli/chunk-79jhk4py.js.map +0 -35
- package/dist/cli/chunk-82bbrxdn.js +0 -51
- package/dist/cli/chunk-82bbrxdn.js.map +0 -10
- package/dist/cli/chunk-abh8yjkn.js +0 -31
- package/dist/cli/chunk-abh8yjkn.js.map +0 -10
- package/dist/cli/chunk-ce574jw2.js +0 -23
- package/dist/cli/chunk-ce574jw2.js.map +0 -10
- package/dist/cli/chunk-dh8cwk36.js.map +0 -10
- package/dist/cli/chunk-epjnccmv.js.map +0 -10
- package/dist/cli/chunk-fa25z98p.js.map +0 -11
- package/dist/cli/chunk-fs23ddbb.js.map +0 -35
- package/dist/cli/chunk-fz5wtpmh.js.map +0 -10
- package/dist/cli/chunk-jwyddg7y.js.map +0 -15
- package/dist/cli/chunk-kpf8rrjc.js.map +0 -19
- package/dist/cli/chunk-m3vmjgmq.js.map +0 -10
- package/dist/cli/chunk-mb2919y2.js.map +0 -10
- package/dist/cli/chunk-q5163e60.js.map +0 -11
- package/dist/cli/chunk-qkqwkpte.js.map +0 -182
- package/dist/cli/chunk-qs4q5p4e.js.map +0 -10
- package/dist/cli/chunk-s1p84fyh.js.map +0 -10
- package/dist/cli/chunk-wgm7m9qk.js.map +0 -36
- package/dist/cli/chunk-yt5n7ppj.js.map +0 -10
- package/dist/cli/chunk-yw7dm696.js.map +0 -14
- /package/dist/cli/{chunk-s6jhgk0q.js.map → chunk-2eytanqx.js.map} +0 -0
- /package/dist/cli/{chunk-hdpx1tax.js.map → chunk-2z928egk.js.map} +0 -0
- /package/dist/cli/{chunk-ah61y8py.js.map → chunk-364znk6q.js.map} +0 -0
- /package/dist/cli/{chunk-vtk4a6dg.js.map → chunk-8ktnccpt.js.map} +0 -0
- /package/dist/cli/{chunk-fxypxtvm.js.map → chunk-a58773jm.js.map} +0 -0
- /package/dist/cli/{chunk-wm7js3j9.js.map → chunk-b07cmahc.js.map} +0 -0
- /package/dist/cli/{chunk-zxcczpyx.js.map → chunk-r20tn01b.js.map} +0 -0
- /package/dist/cli/{chunk-5shv93fd.js.map → chunk-tkacnehg.js.map} +0 -0
- /package/dist/cli/{chunk-zxh4d9vy.js.map → chunk-tzmab476.js.map} +0 -0
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
resolveFallbackLocale,
|
|
4
|
+
localizeRoute,
|
|
5
|
+
localizeInternalPath,
|
|
6
|
+
i18nDiagnostics,
|
|
3
7
|
blumeReferences,
|
|
4
8
|
frontmatter_default,
|
|
5
9
|
resolveDocsCollection,
|
|
@@ -12,10 +16,11 @@ import {
|
|
|
12
16
|
pollingWatch,
|
|
13
17
|
snapshotCache,
|
|
14
18
|
loadWithCache,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
MDX_BODY_FEATURES,
|
|
20
|
+
normalizeRef,
|
|
21
|
+
isPageRef,
|
|
22
|
+
pagesByRef,
|
|
23
|
+
buildNavigation,
|
|
19
24
|
PUBLIC_API_URL,
|
|
20
25
|
pageMetaSchema,
|
|
21
26
|
folderMetaSchema,
|
|
@@ -23,6 +28,7 @@ import {
|
|
|
23
28
|
versionsDiagnostics,
|
|
24
29
|
slugify,
|
|
25
30
|
slugifyPath,
|
|
31
|
+
unloadablePathDiagnostic,
|
|
26
32
|
extractHeadings,
|
|
27
33
|
strippedLineOffset,
|
|
28
34
|
isStringValue,
|
|
@@ -35,8 +41,10 @@ import {
|
|
|
35
41
|
parseYouTubeId,
|
|
36
42
|
nodeRequire,
|
|
37
43
|
escapeMarkdownText,
|
|
44
|
+
guardBlockStart,
|
|
38
45
|
renderInline,
|
|
39
|
-
|
|
46
|
+
destination,
|
|
47
|
+
linkParts,
|
|
40
48
|
headingPrefix,
|
|
41
49
|
blockquote,
|
|
42
50
|
listItem,
|
|
@@ -51,10 +59,15 @@ import {
|
|
|
51
59
|
neutralizeUnsafeLinks,
|
|
52
60
|
columnsPrefix,
|
|
53
61
|
openApiSource,
|
|
62
|
+
BLUME_IGNORE_DIRS,
|
|
63
|
+
baselineScanIgnore,
|
|
64
|
+
BLUME_WATCH_IGNORE_DIRS,
|
|
65
|
+
excludeDirSegments,
|
|
66
|
+
ignoringWatchListener,
|
|
54
67
|
createModuleLoader,
|
|
55
68
|
resolveProjectContext,
|
|
56
69
|
loadConfig
|
|
57
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-pv29h0wf.js";
|
|
58
71
|
import {
|
|
59
72
|
getBlumeVersion,
|
|
60
73
|
BlumeError,
|
|
@@ -64,15 +77,8 @@ import {
|
|
|
64
77
|
trimChar,
|
|
65
78
|
isInternalPath,
|
|
66
79
|
withBasePath,
|
|
67
|
-
|
|
68
|
-
} from "./chunk-
|
|
69
|
-
import {
|
|
70
|
-
BLUME_IGNORE_DIRS,
|
|
71
|
-
baselineScanIgnore,
|
|
72
|
-
BLUME_WATCH_IGNORE_DIRS,
|
|
73
|
-
excludeDirSegments,
|
|
74
|
-
ignoringWatchListener
|
|
75
|
-
} from "./chunk-abh8yjkn.js";
|
|
80
|
+
mountBasePath
|
|
81
|
+
} from "./chunk-3em5wd2y.js";
|
|
76
82
|
|
|
77
83
|
// src/core/manifest.ts
|
|
78
84
|
var versionAlternateKey = (versionKey, locale) => `${versionKey}\x00${locale}`;
|
|
@@ -105,7 +111,7 @@ var buildFallbackRoutes = (graph, i18n, alternatesByKey, basePath, versionAltern
|
|
|
105
111
|
if (present.has(key)) {
|
|
106
112
|
continue;
|
|
107
113
|
}
|
|
108
|
-
const path =
|
|
114
|
+
const path = mountBasePath(basePath, localizeRoute(key, code, i18n));
|
|
109
115
|
const versionAlternates = versionAlternatesByKey ? versionAlternatesFor(versionAlternatesByKey, source.versionKey, code) : [];
|
|
110
116
|
if (versionAlternatesByKey) {
|
|
111
117
|
versionAlternates.push({ path, version: source.version });
|
|
@@ -155,6 +161,7 @@ var buildManifest = (options) => {
|
|
|
155
161
|
}
|
|
156
162
|
}
|
|
157
163
|
const routes = graph.pages.map((page) => ({
|
|
164
|
+
aiExclude: page.meta.ai.exclude,
|
|
158
165
|
alternates: alternatesByKey.get(page.translationKey) ?? [],
|
|
159
166
|
collection: page.collection ?? "docs",
|
|
160
167
|
contentType: page.contentType,
|
|
@@ -198,6 +205,103 @@ var buildManifest = (options) => {
|
|
|
198
205
|
// src/core/project-graph.ts
|
|
199
206
|
import { isAbsolute as isAbsolute3, relative as relative5 } from "pathe";
|
|
200
207
|
|
|
208
|
+
// src/core/directive-diagnostics.ts
|
|
209
|
+
import { mdxToMdast } from "satteri";
|
|
210
|
+
|
|
211
|
+
// src/markdown/directives.ts
|
|
212
|
+
import { toString as mdastToString } from "mdast-util-to-string";
|
|
213
|
+
var CALLOUT_TYPES = new Set([
|
|
214
|
+
"danger",
|
|
215
|
+
"info",
|
|
216
|
+
"note",
|
|
217
|
+
"success",
|
|
218
|
+
"tip",
|
|
219
|
+
"warning"
|
|
220
|
+
]);
|
|
221
|
+
var CALLOUT_ALIASES = {
|
|
222
|
+
caution: "warning",
|
|
223
|
+
error: "danger",
|
|
224
|
+
important: "note",
|
|
225
|
+
warn: "warning"
|
|
226
|
+
};
|
|
227
|
+
var calloutTypeFor = (name) => {
|
|
228
|
+
const lower = name.toLowerCase();
|
|
229
|
+
if (CALLOUT_TYPES.has(lower)) {
|
|
230
|
+
return lower;
|
|
231
|
+
}
|
|
232
|
+
return CALLOUT_ALIASES[lower] ?? null;
|
|
233
|
+
};
|
|
234
|
+
var LITERAL_MARKERS = new Map([
|
|
235
|
+
["leafDirective", "::"],
|
|
236
|
+
["textDirective", ":"]
|
|
237
|
+
]);
|
|
238
|
+
var labelSource = (label) => label.length > 0 ? `[${mdastToString(label, { includeImageAlt: false })}]` : "";
|
|
239
|
+
var attributeSource = (node) => {
|
|
240
|
+
const attributes = Object.entries(node.attributes ?? {}).map(([key, value]) => value ? `${key}="${value}"` : key);
|
|
241
|
+
return attributes.length > 0 ? `{${attributes.join(" ")}}` : "";
|
|
242
|
+
};
|
|
243
|
+
var spannedSource = (node, source) => {
|
|
244
|
+
const start = node.position?.start?.offset;
|
|
245
|
+
const end = node.position?.end?.offset;
|
|
246
|
+
return start !== undefined && end !== undefined ? source.slice(start, end) : null;
|
|
247
|
+
};
|
|
248
|
+
var directiveSource = (node, marker, source) => {
|
|
249
|
+
const opening = `${marker}${node.name}`;
|
|
250
|
+
const slice = spannedSource(node, source);
|
|
251
|
+
if (slice?.startsWith(opening)) {
|
|
252
|
+
return slice;
|
|
253
|
+
}
|
|
254
|
+
return `${opening}${labelSource(node.children ?? [])}${attributeSource(node)}`;
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
// src/core/directive-diagnostics.ts
|
|
258
|
+
var CONTAINER_OPENING = /^[\t >]*:{3,}(?<name>[a-z][\w-]*)/gimu;
|
|
259
|
+
var codeList = (names) => [...names].map((name) => `\`${name}\``).join(", ");
|
|
260
|
+
var CALLOUT_NAMES = `${codeList(CALLOUT_TYPES)} (or the aliases ${codeList(Object.keys(CALLOUT_ALIASES))})`;
|
|
261
|
+
var unknownContainers = (text) => {
|
|
262
|
+
const named = [...text.matchAll(CONTAINER_OPENING)].some((match) => calloutTypeFor(match.groups?.name ?? "") === null);
|
|
263
|
+
if (!named) {
|
|
264
|
+
return [];
|
|
265
|
+
}
|
|
266
|
+
let tree;
|
|
267
|
+
try {
|
|
268
|
+
tree = mdxToMdast(text, { features: MDX_BODY_FEATURES });
|
|
269
|
+
} catch {
|
|
270
|
+
return [];
|
|
271
|
+
}
|
|
272
|
+
const found = [];
|
|
273
|
+
const walk = (node) => {
|
|
274
|
+
if (node.type === "containerDirective" && calloutTypeFor(node.name) === null) {
|
|
275
|
+
found.push({ line: node.position?.start.line ?? 1, name: node.name });
|
|
276
|
+
}
|
|
277
|
+
if ("children" in node) {
|
|
278
|
+
for (const child of node.children) {
|
|
279
|
+
walk(child);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
walk(tree);
|
|
284
|
+
return found;
|
|
285
|
+
};
|
|
286
|
+
var unknownDirectiveDiagnostics = (entry, sourceName) => {
|
|
287
|
+
if (entry.body.format !== "mdx") {
|
|
288
|
+
return [];
|
|
289
|
+
}
|
|
290
|
+
const page = entry.sourcePath ?? `${sourceName}:${entry.ref}`;
|
|
291
|
+
const offset = entry.bodyLineOffset ?? strippedLineOffset(entry.raw, entry.body.text);
|
|
292
|
+
return unknownContainers(entry.expanded?.text ?? entry.body.text).map(({ line, name }) => {
|
|
293
|
+
const origin = entry.expanded?.origins[line - 1];
|
|
294
|
+
return {
|
|
295
|
+
code: "BLUME_UNKNOWN_DIRECTIVE",
|
|
296
|
+
file: origin?.file ?? page,
|
|
297
|
+
line: origin?.line ?? line + offset,
|
|
298
|
+
message: `\`:::${name}\` isn't a callout type, so the page shows its \`:::\` lines as written around its content.`,
|
|
299
|
+
severity: "warning",
|
|
300
|
+
suggestion: `Use a callout type — ${CALLOUT_NAMES} — or remove the \`:::\` lines to keep the content as plain prose.`
|
|
301
|
+
};
|
|
302
|
+
});
|
|
303
|
+
};
|
|
304
|
+
|
|
201
305
|
// src/theme/icon-kind.ts
|
|
202
306
|
var IMAGE_ICON = /^(?:https?:\/\/|data:image\/|\/|\.{1,2}\/)|\.(?:avif|gif|jpe?g|png|svg|webp)$/iu;
|
|
203
307
|
var INLINE_SVG = /^\s*<svg[\s\S]*<\/svg>\s*$/u;
|
|
@@ -315,7 +419,7 @@ var validateNavTargets = (navigation, routes) => {
|
|
|
315
419
|
if (!isInternalPath(path) || path.startsWith("/#") || seen.has(path)) {
|
|
316
420
|
continue;
|
|
317
421
|
}
|
|
318
|
-
if (!resolvesToPages(routes, path.split(
|
|
422
|
+
if (!resolvesToPages(routes, path.split(/[?#]/u)[0] ?? path)) {
|
|
319
423
|
seen.add(path);
|
|
320
424
|
diagnostics.push({
|
|
321
425
|
code: "BLUME_NAV_MISSING_PAGE",
|
|
@@ -327,6 +431,44 @@ var validateNavTargets = (navigation, routes) => {
|
|
|
327
431
|
}
|
|
328
432
|
return diagnostics;
|
|
329
433
|
};
|
|
434
|
+
var validateSidebarItems = (items, resolves) => {
|
|
435
|
+
const diagnostics = [];
|
|
436
|
+
const walk = (list) => {
|
|
437
|
+
for (const item of list) {
|
|
438
|
+
if (isPageRef(item)) {
|
|
439
|
+
if (!resolves(normalizeRef(item))) {
|
|
440
|
+
diagnostics.push({
|
|
441
|
+
code: "BLUME_NAV_MISSING_PAGE",
|
|
442
|
+
message: `Sidebar entry "${item}" matches no page, so it's left out of the sidebar.`,
|
|
443
|
+
severity: "warning",
|
|
444
|
+
suggestion: "Fix the route, or add a page at it."
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
continue;
|
|
448
|
+
}
|
|
449
|
+
if (item.root && !resolves(normalizeRef(item.root))) {
|
|
450
|
+
diagnostics.push({
|
|
451
|
+
code: "BLUME_NAV_MISSING_PAGE",
|
|
452
|
+
message: `Sidebar entry "${item.label}" has root "${item.root}", but no page matches it, so its link leads nowhere.`,
|
|
453
|
+
severity: "warning",
|
|
454
|
+
suggestion: "Fix the root, or add a page at that route."
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
if (item.items) {
|
|
458
|
+
walk(item.items);
|
|
459
|
+
} else if (!(item.root || item.href)) {
|
|
460
|
+
diagnostics.push({
|
|
461
|
+
code: "BLUME_NAV_EMPTY_ITEM",
|
|
462
|
+
message: `Sidebar entry "${item.label}" has no page, href, root, or items, so it's left out of the sidebar.`,
|
|
463
|
+
severity: "warning",
|
|
464
|
+
suggestion: "Give it an href or a root to link somewhere, or items to make it a group."
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
};
|
|
469
|
+
walk(items);
|
|
470
|
+
return diagnostics;
|
|
471
|
+
};
|
|
330
472
|
var duplicateLabelDiagnostics = (navigation) => {
|
|
331
473
|
const diagnostics = [];
|
|
332
474
|
const checkLevel = (nodes, where) => {
|
|
@@ -386,541 +528,6 @@ var validateNavStructure = (navigation, pages) => [
|
|
|
386
528
|
...hiddenInSidebarDiagnostics(navigation, pages)
|
|
387
529
|
];
|
|
388
530
|
|
|
389
|
-
// src/core/navigation.ts
|
|
390
|
-
import { extname } from "pathe";
|
|
391
|
-
var NUMERIC_PREFIX = /^(?<order>\d+)[-_.]/u;
|
|
392
|
-
var GROUP_FOLDER = /^\((?<label>.+)\)$/u;
|
|
393
|
-
var WORD_SPLIT = /[-_]/u;
|
|
394
|
-
var isUnderPath = (route, base) => base === "/" || route === base || route.startsWith(`${base}/`);
|
|
395
|
-
var isRootTab = (tab, root) => isUnderPath(root, tab.path);
|
|
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(" ");
|
|
436
|
-
var numericOrder = (segment) => {
|
|
437
|
-
const value = segment.match(NUMERIC_PREFIX)?.groups?.order;
|
|
438
|
-
return value ? Math.trunc(Number(value)) : Number.POSITIVE_INFINITY;
|
|
439
|
-
};
|
|
440
|
-
var segmentKey = (raw) => {
|
|
441
|
-
const group = raw.match(GROUP_FOLDER)?.groups?.label;
|
|
442
|
-
return (group ?? raw).replace(NUMERIC_PREFIX, "");
|
|
443
|
-
};
|
|
444
|
-
var isIndexStem = (stem) => stem.replace(NUMERIC_PREFIX, "") === "index";
|
|
445
|
-
var stemOf = (filename) => filename.replace(extname(filename), "");
|
|
446
|
-
var navStem = (navPath) => stemOf(navPath.split("/").at(-1) ?? navPath);
|
|
447
|
-
var createGroup = (key, path, label, order) => ({
|
|
448
|
-
children: [],
|
|
449
|
-
index: new Map,
|
|
450
|
-
key,
|
|
451
|
-
kind: "group",
|
|
452
|
-
label,
|
|
453
|
-
order,
|
|
454
|
-
path
|
|
455
|
-
});
|
|
456
|
-
var ensureGroup = (parent, rawSegment) => {
|
|
457
|
-
const existing = parent.index.get(rawSegment);
|
|
458
|
-
if (existing) {
|
|
459
|
-
return existing;
|
|
460
|
-
}
|
|
461
|
-
const path = parent.path ? `${parent.path}/${rawSegment}` : rawSegment;
|
|
462
|
-
const group = createGroup(segmentKey(rawSegment), path, humanize(rawSegment.match(GROUP_FOLDER)?.groups?.label ?? rawSegment), numericOrder(rawSegment));
|
|
463
|
-
parent.index.set(rawSegment, group);
|
|
464
|
-
parent.children.push(group);
|
|
465
|
-
return group;
|
|
466
|
-
};
|
|
467
|
-
var pageOrder = (page, filename) => {
|
|
468
|
-
if (page.meta.sidebar.order !== undefined) {
|
|
469
|
-
return { order: page.meta.sidebar.order, orderIsAuthored: true };
|
|
470
|
-
}
|
|
471
|
-
if (isIndexStem(stemOf(filename))) {
|
|
472
|
-
return { order: Number.NEGATIVE_INFINITY, orderIsAuthored: false };
|
|
473
|
-
}
|
|
474
|
-
if (page.contentType === "changelog") {
|
|
475
|
-
const iso = page.meta.date ?? page.meta.changelog?.date;
|
|
476
|
-
const time = iso ? Date.parse(iso) : Number.NaN;
|
|
477
|
-
if (!Number.isNaN(time)) {
|
|
478
|
-
return { order: -time, orderIsAuthored: false };
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
const order = numericOrder(filename);
|
|
482
|
-
return {
|
|
483
|
-
order,
|
|
484
|
-
orderIsAuthored: page.contentType !== "changelog" && Number.isFinite(order)
|
|
485
|
-
};
|
|
486
|
-
};
|
|
487
|
-
var metaKey = (path, metaPrefix) => {
|
|
488
|
-
if (!metaPrefix) {
|
|
489
|
-
return path;
|
|
490
|
-
}
|
|
491
|
-
return path ? `${metaPrefix}/${path}` : metaPrefix;
|
|
492
|
-
};
|
|
493
|
-
var applyFolderMeta = (group, folderMeta, sharedMeta, metaPrefix, sharedMetaPrefix, indexDisplay, indexRoute) => {
|
|
494
|
-
group.route = indexRoute.get(group.path);
|
|
495
|
-
const meta = folderMeta.get(metaKey(group.path, metaPrefix)) ?? sharedMeta.get(metaKey(group.path, sharedMetaPrefix));
|
|
496
|
-
group.display = indexDisplay.get(group.path) ?? meta?.display;
|
|
497
|
-
if (meta) {
|
|
498
|
-
group.label = meta.title ?? group.label;
|
|
499
|
-
group.icon = meta.icon ?? group.icon;
|
|
500
|
-
group.order = meta.order ?? group.order;
|
|
501
|
-
group.collapsed = meta.collapsed ?? group.collapsed;
|
|
502
|
-
if (meta.pages) {
|
|
503
|
-
const rank = new Map(meta.pages.map((key, i) => [key, i]));
|
|
504
|
-
for (const child of group.children) {
|
|
505
|
-
const position = rank.get(child.key);
|
|
506
|
-
if (position !== undefined) {
|
|
507
|
-
child.order = position;
|
|
508
|
-
if (child.kind === "page") {
|
|
509
|
-
child.orderIsAuthored = true;
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
for (const child of group.children) {
|
|
516
|
-
if (child.kind === "group") {
|
|
517
|
-
applyFolderMeta(child, folderMeta, sharedMeta, metaPrefix, sharedMetaPrefix, indexDisplay, indexRoute);
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
};
|
|
521
|
-
var indexTitleMismatchDiagnostic = (page, folderPath, folderMeta, sharedMeta, metaPrefix, sharedMetaPrefix) => {
|
|
522
|
-
if (!(page.meta.title && page.meta.sidebar.hidden) || page.fallback || folderPath === "") {
|
|
523
|
-
return;
|
|
524
|
-
}
|
|
525
|
-
const meta = folderMeta.get(metaKey(folderPath, metaPrefix)) ?? sharedMeta.get(metaKey(folderPath, sharedMetaPrefix));
|
|
526
|
-
if (!meta?.title || meta.title === page.title) {
|
|
527
|
-
return;
|
|
528
|
-
}
|
|
529
|
-
return {
|
|
530
|
-
code: "BLUME_NAV_INDEX_TITLE_MISMATCH",
|
|
531
|
-
file: page.sourcePath ?? page.id,
|
|
532
|
-
message: `Index page "${page.navPath}" has title "${page.title}", but its folder's meta.title is "${meta.title}" — the sidebar shows the folder title while the page's own <title>/heading still say "${page.title}".`,
|
|
533
|
-
severity: "warning",
|
|
534
|
-
suggestion: `Update the page's frontmatter title to match ("${meta.title}"), or leave it if the divergence is intentional.`
|
|
535
|
-
};
|
|
536
|
-
};
|
|
537
|
-
var sidebarDisplayIgnoredDiagnostics = (pages, explicitSidebar) => {
|
|
538
|
-
const diagnostics = [];
|
|
539
|
-
for (const page of pages) {
|
|
540
|
-
if (!page.meta.sidebar.display) {
|
|
541
|
-
continue;
|
|
542
|
-
}
|
|
543
|
-
const isIndex = isIndexStem(navStem(page.navPath));
|
|
544
|
-
if (explicitSidebar) {
|
|
545
|
-
diagnostics.push({
|
|
546
|
-
code: "BLUME_SIDEBAR_DISPLAY_IGNORED",
|
|
547
|
-
file: page.sourcePath ?? page.id,
|
|
548
|
-
message: `"${page.navPath}" sets sidebar.display, but the explicit navigation.sidebar config owns each group's display mode — the value is ignored.`,
|
|
549
|
-
severity: "warning",
|
|
550
|
-
suggestion: "Set display on the matching group in navigation.sidebar, or remove the frontmatter key."
|
|
551
|
-
});
|
|
552
|
-
continue;
|
|
553
|
-
}
|
|
554
|
-
if (isIndex && !page.navPath.includes("/")) {
|
|
555
|
-
diagnostics.push({
|
|
556
|
-
code: "BLUME_SIDEBAR_DISPLAY_IGNORED",
|
|
557
|
-
file: page.sourcePath ?? page.id,
|
|
558
|
-
message: `"${page.navPath}" sets sidebar.display, but the content root is not a sidebar group — the value is ignored.`,
|
|
559
|
-
severity: "warning",
|
|
560
|
-
suggestion: "Set navigation.sidebar.display in blume.config to change the sidebar-wide mode."
|
|
561
|
-
});
|
|
562
|
-
continue;
|
|
563
|
-
}
|
|
564
|
-
if (isIndex) {
|
|
565
|
-
continue;
|
|
566
|
-
}
|
|
567
|
-
diagnostics.push({
|
|
568
|
-
code: "BLUME_SIDEBAR_DISPLAY_IGNORED",
|
|
569
|
-
file: page.sourcePath ?? page.id,
|
|
570
|
-
message: `"${page.navPath}" sets sidebar.display, but only a folder's index page can set its group's display mode — the value is ignored.`,
|
|
571
|
-
severity: "warning",
|
|
572
|
-
suggestion: "Move display to the folder's index page frontmatter, or set it in the folder's meta.ts."
|
|
573
|
-
});
|
|
574
|
-
}
|
|
575
|
-
return diagnostics;
|
|
576
|
-
};
|
|
577
|
-
var isAuthoredOrder = (node) => node.kind === "group" || node.orderIsAuthored;
|
|
578
|
-
var duplicateOrderDiagnostics = (nodes) => {
|
|
579
|
-
const byOrder = new Map;
|
|
580
|
-
for (const node of nodes) {
|
|
581
|
-
if (!Number.isFinite(node.order) || !isAuthoredOrder(node)) {
|
|
582
|
-
continue;
|
|
583
|
-
}
|
|
584
|
-
const tied = byOrder.get(node.order);
|
|
585
|
-
if (tied) {
|
|
586
|
-
tied.push(node);
|
|
587
|
-
} else {
|
|
588
|
-
byOrder.set(node.order, [node]);
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
const diagnostics = [];
|
|
592
|
-
for (const [order, tied] of byOrder) {
|
|
593
|
-
if (tied.length > 1) {
|
|
594
|
-
const names = tied.map((node) => `"${node.label}"`);
|
|
595
|
-
const list = names.length > 2 ? `${names.slice(0, -1).join(", ")}, and ${names.at(-1)}` : names.join(" and ");
|
|
596
|
-
const verb = tied.length > 2 ? "all have" : "both have";
|
|
597
|
-
const file = tied.find((node) => node.kind === "page")?.file;
|
|
598
|
-
diagnostics.push({
|
|
599
|
-
code: "BLUME_DUPLICATE_SIDEBAR_ORDER",
|
|
600
|
-
file,
|
|
601
|
-
message: `${list} ${verb} sidebar order ${order}; falling back to alphabetical order.`,
|
|
602
|
-
severity: "warning",
|
|
603
|
-
suggestion: "Give each item a distinct sidebar.order (or folder meta order)."
|
|
604
|
-
});
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
return diagnostics;
|
|
608
|
-
};
|
|
609
|
-
var sortNodes = (nodes, diagnostics) => {
|
|
610
|
-
diagnostics.push(...duplicateOrderDiagnostics(nodes));
|
|
611
|
-
nodes.sort((a, b) => {
|
|
612
|
-
if (a.order !== b.order) {
|
|
613
|
-
return a.order - b.order;
|
|
614
|
-
}
|
|
615
|
-
return a.label.localeCompare(b.label);
|
|
616
|
-
});
|
|
617
|
-
for (const node of nodes) {
|
|
618
|
-
if (node.kind === "group") {
|
|
619
|
-
sortNodes(node.children, diagnostics);
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
};
|
|
623
|
-
var hoistPages = (nodes, display, hoist) => {
|
|
624
|
-
const groups = nodes.filter((node) => node.kind === "group");
|
|
625
|
-
if (hoist || groups.some((group) => (group.display ?? display) === "flat")) {
|
|
626
|
-
const pages = nodes.filter((node) => node.kind === "page");
|
|
627
|
-
nodes.splice(0, nodes.length, ...pages, ...groups);
|
|
628
|
-
}
|
|
629
|
-
for (const group of groups) {
|
|
630
|
-
hoistPages(group.children, display, false);
|
|
631
|
-
}
|
|
632
|
-
};
|
|
633
|
-
var hoistTabSections = (nodes, tabPaths, display) => {
|
|
634
|
-
for (const node of nodes) {
|
|
635
|
-
if (node.kind !== "group") {
|
|
636
|
-
continue;
|
|
637
|
-
}
|
|
638
|
-
if (node.routePath !== undefined && tabPaths.has(node.routePath)) {
|
|
639
|
-
hoistPages(node.children, display, true);
|
|
640
|
-
}
|
|
641
|
-
hoistTabSections(node.children, tabPaths, display);
|
|
642
|
-
}
|
|
643
|
-
};
|
|
644
|
-
var toNavNode = (node, display) => {
|
|
645
|
-
if (node.kind === "page") {
|
|
646
|
-
return {
|
|
647
|
-
badge: node.badge,
|
|
648
|
-
deprecated: node.deprecated || undefined,
|
|
649
|
-
description: node.description,
|
|
650
|
-
icon: node.icon,
|
|
651
|
-
kind: "page",
|
|
652
|
-
label: node.label,
|
|
653
|
-
pageId: node.pageId,
|
|
654
|
-
route: node.route
|
|
655
|
-
};
|
|
656
|
-
}
|
|
657
|
-
return {
|
|
658
|
-
children: node.children.map((child) => toNavNode(child, display)),
|
|
659
|
-
collapsed: node.collapsed,
|
|
660
|
-
display: node.display ?? display,
|
|
661
|
-
icon: node.icon,
|
|
662
|
-
kind: "group",
|
|
663
|
-
label: node.label,
|
|
664
|
-
path: node.routePath,
|
|
665
|
-
route: node.route
|
|
666
|
-
};
|
|
667
|
-
};
|
|
668
|
-
var buildFileSystemSidebar = (pages, folderMeta, sharedMeta, metaPrefix, sharedMetaPrefix, display, tabPaths, diagnostics = []) => {
|
|
669
|
-
const root = createGroup("", "", "", 0);
|
|
670
|
-
const indexDisplay = new Map;
|
|
671
|
-
const indexRoute = new Map;
|
|
672
|
-
for (const page of pages) {
|
|
673
|
-
const parts = page.navPath.split("/");
|
|
674
|
-
const filename = parts.at(-1) ?? page.navPath;
|
|
675
|
-
const stem = stemOf(filename);
|
|
676
|
-
const dirs = parts.slice(0, -1);
|
|
677
|
-
if (isIndexStem(stem)) {
|
|
678
|
-
const diagnostic = indexTitleMismatchDiagnostic(page, dirs.join("/"), folderMeta, sharedMeta, metaPrefix, sharedMetaPrefix);
|
|
679
|
-
if (diagnostic) {
|
|
680
|
-
diagnostics.push(diagnostic);
|
|
681
|
-
}
|
|
682
|
-
if (page.meta.sidebar.display && !page.fallback) {
|
|
683
|
-
indexDisplay.set(dirs.join("/"), page.meta.sidebar.display);
|
|
684
|
-
}
|
|
685
|
-
if (dirs.length > 0) {
|
|
686
|
-
indexRoute.set(dirs.join("/"), page.route);
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
if (page.meta.sidebar.hidden) {
|
|
690
|
-
continue;
|
|
691
|
-
}
|
|
692
|
-
const routeSegments = page.route.split("/").filter(Boolean);
|
|
693
|
-
const folderParts = isIndexStem(stem) ? routeSegments : routeSegments.slice(0, -1);
|
|
694
|
-
const routeDirCount = dirs.filter((dir) => !GROUP_FOLDER.test(dir)).length;
|
|
695
|
-
const offset = Math.max(0, folderParts.length - routeDirCount);
|
|
696
|
-
let parent = root;
|
|
697
|
-
let consumed = offset;
|
|
698
|
-
for (const dir of dirs) {
|
|
699
|
-
parent = ensureGroup(parent, dir);
|
|
700
|
-
if (!GROUP_FOLDER.test(dir)) {
|
|
701
|
-
consumed += 1;
|
|
702
|
-
}
|
|
703
|
-
parent.routePath ??= `/${folderParts.slice(0, consumed).join("/")}`;
|
|
704
|
-
}
|
|
705
|
-
const { order, orderIsAuthored } = pageOrder(page, filename);
|
|
706
|
-
parent.children.push({
|
|
707
|
-
badge: page.meta.sidebar.badge,
|
|
708
|
-
deprecated: page.meta.deprecated || undefined,
|
|
709
|
-
description: page.description,
|
|
710
|
-
file: page.sourcePath,
|
|
711
|
-
icon: sidebarIcon(page),
|
|
712
|
-
key: segmentKey(stem),
|
|
713
|
-
kind: "page",
|
|
714
|
-
label: page.meta.sidebar.label ?? page.title,
|
|
715
|
-
order,
|
|
716
|
-
orderIsAuthored,
|
|
717
|
-
pageId: page.id,
|
|
718
|
-
route: page.route
|
|
719
|
-
});
|
|
720
|
-
}
|
|
721
|
-
applyFolderMeta(root, folderMeta, sharedMeta, metaPrefix, sharedMetaPrefix, indexDisplay, indexRoute);
|
|
722
|
-
sortNodes(root.children, diagnostics);
|
|
723
|
-
hoistPages(root.children, display, true);
|
|
724
|
-
hoistTabSections(root.children, tabPaths, display);
|
|
725
|
-
return root.children.map((child) => toNavNode(child, display));
|
|
726
|
-
};
|
|
727
|
-
var normalizeRef = (ref) => {
|
|
728
|
-
if (ref === "index") {
|
|
729
|
-
return "/";
|
|
730
|
-
}
|
|
731
|
-
const withSlash = ref.startsWith("/") ? ref : `/${ref}`;
|
|
732
|
-
const noTrailing = withSlash.replace(/\/+$/u, "");
|
|
733
|
-
const trimmed = noTrailing.endsWith("/index") ? noTrailing.slice(0, -"/index".length) : noTrailing;
|
|
734
|
-
return trimmed === "" ? "/" : trimmed;
|
|
735
|
-
};
|
|
736
|
-
var routeForRef = (ref, byRoute, basePath) => {
|
|
737
|
-
if (!ref) {
|
|
738
|
-
return;
|
|
739
|
-
}
|
|
740
|
-
const normalized = normalizeRef(ref);
|
|
741
|
-
return byRoute.get(normalized)?.route ?? withBasePath(basePath, normalized);
|
|
742
|
-
};
|
|
743
|
-
var isPageRef = (item) => typeof item === "string";
|
|
744
|
-
var configItemToNode = (item, byRoute, basePath) => {
|
|
745
|
-
if (isPageRef(item)) {
|
|
746
|
-
const page = byRoute.get(normalizeRef(item));
|
|
747
|
-
if (!page) {
|
|
748
|
-
return null;
|
|
749
|
-
}
|
|
750
|
-
return {
|
|
751
|
-
badge: page.meta.sidebar.badge,
|
|
752
|
-
deprecated: page.meta.deprecated || undefined,
|
|
753
|
-
description: page.description,
|
|
754
|
-
icon: sidebarIcon(page),
|
|
755
|
-
kind: "page",
|
|
756
|
-
label: page.meta.sidebar.label ?? page.title,
|
|
757
|
-
pageId: page.id,
|
|
758
|
-
route: page.route
|
|
759
|
-
};
|
|
760
|
-
}
|
|
761
|
-
if (item.root) {
|
|
762
|
-
const page = byRoute.get(normalizeRef(item.root));
|
|
763
|
-
return {
|
|
764
|
-
badge: item.badge,
|
|
765
|
-
deprecated: page?.meta.deprecated || undefined,
|
|
766
|
-
icon: item.icon,
|
|
767
|
-
kind: "page",
|
|
768
|
-
label: item.label,
|
|
769
|
-
pageId: page?.id ?? "",
|
|
770
|
-
route: page?.route ?? withBasePath(basePath, normalizeRef(item.root))
|
|
771
|
-
};
|
|
772
|
-
}
|
|
773
|
-
if (item.href) {
|
|
774
|
-
return {
|
|
775
|
-
badge: item.badge,
|
|
776
|
-
icon: item.icon,
|
|
777
|
-
kind: "page",
|
|
778
|
-
label: item.label,
|
|
779
|
-
pageId: "",
|
|
780
|
-
route: withBasePath(basePath, item.href)
|
|
781
|
-
};
|
|
782
|
-
}
|
|
783
|
-
return null;
|
|
784
|
-
};
|
|
785
|
-
var buildConfigSidebar = (items, byRoute, display, basePath) => {
|
|
786
|
-
const nodes = [];
|
|
787
|
-
for (const item of items) {
|
|
788
|
-
if (!isPageRef(item) && item.items) {
|
|
789
|
-
nodes.push({
|
|
790
|
-
badge: item.badge,
|
|
791
|
-
children: buildConfigSidebar(item.items, byRoute, display, basePath),
|
|
792
|
-
collapsed: item.collapsed,
|
|
793
|
-
directory: item.directory,
|
|
794
|
-
display: item.display ?? display,
|
|
795
|
-
icon: item.icon,
|
|
796
|
-
kind: "group",
|
|
797
|
-
label: item.label,
|
|
798
|
-
route: routeForRef(item.root, byRoute, basePath)
|
|
799
|
-
});
|
|
800
|
-
continue;
|
|
801
|
-
}
|
|
802
|
-
const node = configItemToNode(item, byRoute, basePath);
|
|
803
|
-
if (node) {
|
|
804
|
-
nodes.push(node);
|
|
805
|
-
}
|
|
806
|
-
}
|
|
807
|
-
return nodes;
|
|
808
|
-
};
|
|
809
|
-
var resolveTabHref = (sidebar, path, extraRoutes, basePath) => {
|
|
810
|
-
if (extraRoutes.has(path)) {
|
|
811
|
-
return path;
|
|
812
|
-
}
|
|
813
|
-
let first;
|
|
814
|
-
const walk = (nodes) => {
|
|
815
|
-
for (const node of nodes) {
|
|
816
|
-
const { route } = node;
|
|
817
|
-
if (route === path) {
|
|
818
|
-
return true;
|
|
819
|
-
}
|
|
820
|
-
if (first === undefined && route !== undefined && route.startsWith(`${path}/`)) {
|
|
821
|
-
first = route;
|
|
822
|
-
}
|
|
823
|
-
if (node.kind === "group" && walk(node.children)) {
|
|
824
|
-
return true;
|
|
825
|
-
}
|
|
826
|
-
}
|
|
827
|
-
return false;
|
|
828
|
-
};
|
|
829
|
-
if (walk(sidebar)) {
|
|
830
|
-
return path;
|
|
831
|
-
}
|
|
832
|
-
const bare = stripBasePath(basePath, path);
|
|
833
|
-
return extraRoutes.has(bare) ? bare : first ?? path;
|
|
834
|
-
};
|
|
835
|
-
var withTabHrefs = (tabs, sidebar, extraRoutes, basePath) => tabs.map((tab) => {
|
|
836
|
-
const href = tab.href ?? resolveTabHref(sidebar, tab.path, extraRoutes, basePath);
|
|
837
|
-
return href === tab.path ? tab : { ...tab, href };
|
|
838
|
-
});
|
|
839
|
-
var rebaseNavChrome = (basePath, options) => {
|
|
840
|
-
const actions = options.actions ?? [];
|
|
841
|
-
const cta = options.cta ?? null;
|
|
842
|
-
const featured = options.featured ?? [];
|
|
843
|
-
const selectors = options.selectors ?? [];
|
|
844
|
-
const tabs = options.tabs ?? [];
|
|
845
|
-
if (!basePath) {
|
|
846
|
-
return { actions, cta, featured, selectors, tabs };
|
|
847
|
-
}
|
|
848
|
-
const rebaseHref = (item) => ({
|
|
849
|
-
...item,
|
|
850
|
-
href: withBasePath(basePath, item.href)
|
|
851
|
-
});
|
|
852
|
-
const rebasePath = (item) => ({
|
|
853
|
-
...item,
|
|
854
|
-
path: withBasePath(basePath, item.path)
|
|
855
|
-
});
|
|
856
|
-
return {
|
|
857
|
-
actions: actions.map(rebaseHref),
|
|
858
|
-
cta: cta ? rebaseHref(cta) : null,
|
|
859
|
-
featured: featured.map(rebaseHref),
|
|
860
|
-
selectors: selectors.map((selector) => ({
|
|
861
|
-
...selector,
|
|
862
|
-
items: selector.items.map(rebasePath)
|
|
863
|
-
})),
|
|
864
|
-
tabs: tabs.map((tab) => {
|
|
865
|
-
const rebased = {
|
|
866
|
-
...tab,
|
|
867
|
-
items: tab.items?.map(rebasePath),
|
|
868
|
-
path: withBasePath(basePath, tab.path)
|
|
869
|
-
};
|
|
870
|
-
if (tab.href) {
|
|
871
|
-
rebased.href = withBasePath(basePath, tab.href);
|
|
872
|
-
}
|
|
873
|
-
return rebased;
|
|
874
|
-
})
|
|
875
|
-
};
|
|
876
|
-
};
|
|
877
|
-
var buildNavigation = (pages, options) => {
|
|
878
|
-
const basePath = options.basePath ?? "";
|
|
879
|
-
const display = options.display ?? "flat";
|
|
880
|
-
const metaPrefix = options.metaPrefix ?? "";
|
|
881
|
-
const sharedMetaPrefix = options.sharedMetaPrefix ?? "";
|
|
882
|
-
const sharedFolderMeta = options.sharedFolderMeta ?? new Map;
|
|
883
|
-
const extraRoutes = options.extraRoutes ?? new Set;
|
|
884
|
-
const { actions, cta, featured, selectors, tabs } = rebaseNavChrome(basePath, options);
|
|
885
|
-
const byRoute = new Map(pages.map((page) => [
|
|
886
|
-
options.refByLogical ? page.translationKey : page.route,
|
|
887
|
-
page
|
|
888
|
-
]));
|
|
889
|
-
if (basePath && !options.refByLogical) {
|
|
890
|
-
for (const page of pages) {
|
|
891
|
-
const bare = stripBasePath(basePath, page.route);
|
|
892
|
-
if (!byRoute.has(bare)) {
|
|
893
|
-
byRoute.set(bare, page);
|
|
894
|
-
}
|
|
895
|
-
}
|
|
896
|
-
}
|
|
897
|
-
const rootTabPath = withBasePath(basePath, options.localizedRoot ?? "/");
|
|
898
|
-
const diagnostics = options.diagnostics ?? [];
|
|
899
|
-
diagnostics.push(...sidebarDisplayIgnoredDiagnostics(pages, Boolean(options.sidebar)));
|
|
900
|
-
if (options.sidebar) {
|
|
901
|
-
const sidebar = buildConfigSidebar(options.sidebar, byRoute, display, basePath);
|
|
902
|
-
return {
|
|
903
|
-
actions,
|
|
904
|
-
cta,
|
|
905
|
-
featured,
|
|
906
|
-
root: rootTabPath,
|
|
907
|
-
selectors,
|
|
908
|
-
sidebar,
|
|
909
|
-
tabs: withTabHrefs(tabs, sidebar, extraRoutes, basePath)
|
|
910
|
-
};
|
|
911
|
-
}
|
|
912
|
-
const sidebar = buildFileSystemSidebar(pages, options.folderMeta, sharedFolderMeta, metaPrefix, sharedMetaPrefix, display, new Set(tabs.flatMap((tab) => isRootTab(tab, rootTabPath) ? [] : [tab.path])), diagnostics);
|
|
913
|
-
return {
|
|
914
|
-
actions,
|
|
915
|
-
cta,
|
|
916
|
-
featured,
|
|
917
|
-
root: rootTabPath,
|
|
918
|
-
selectors,
|
|
919
|
-
sidebar,
|
|
920
|
-
tabs: withTabHrefs(tabs, sidebar, extraRoutes, basePath)
|
|
921
|
-
};
|
|
922
|
-
};
|
|
923
|
-
|
|
924
531
|
// src/core/graph.ts
|
|
925
532
|
var collectRoutes = (pages) => {
|
|
926
533
|
const routes = new Map;
|
|
@@ -953,7 +560,7 @@ var localePagesFor = (code, real, fallback, fallbackByKey, i18n, basePath) => {
|
|
|
953
560
|
...source,
|
|
954
561
|
fallback: true,
|
|
955
562
|
locale: code,
|
|
956
|
-
route:
|
|
563
|
+
route: mountBasePath(basePath, localizeRoute(key, code, i18n))
|
|
957
564
|
});
|
|
958
565
|
}
|
|
959
566
|
}
|
|
@@ -966,6 +573,19 @@ var resolveLabel = (label, locale, defaultLocale) => {
|
|
|
966
573
|
}
|
|
967
574
|
return label[locale] ?? (defaultLocale === undefined ? undefined : label[defaultLocale]) ?? Object.values(label)[0] ?? "";
|
|
968
575
|
};
|
|
576
|
+
var localizeSidebarHrefs = (items, localize) => items.map((item) => {
|
|
577
|
+
if (isPageRef(item)) {
|
|
578
|
+
return item;
|
|
579
|
+
}
|
|
580
|
+
const localized = { ...item };
|
|
581
|
+
if (item.href !== undefined) {
|
|
582
|
+
localized.href = localize(item.href);
|
|
583
|
+
}
|
|
584
|
+
if (item.items) {
|
|
585
|
+
localized.items = localizeSidebarHrefs(item.items, localize);
|
|
586
|
+
}
|
|
587
|
+
return localized;
|
|
588
|
+
});
|
|
969
589
|
var resolveTabLabels = (tabs, locale, defaultLocale) => (tabs ?? []).map((tab) => ({
|
|
970
590
|
...tab,
|
|
971
591
|
items: tab.items?.map((item) => ({
|
|
@@ -974,6 +594,7 @@ var resolveTabLabels = (tabs, locale, defaultLocale) => (tabs ?? []).map((tab) =
|
|
|
974
594
|
})),
|
|
975
595
|
label: resolveLabel(tab.label, locale, defaultLocale)
|
|
976
596
|
}));
|
|
597
|
+
var mountConfiguredLink = (path, basePath, extraRoutes) => extraRoutes.has(path) ? path : withBasePath(basePath, path);
|
|
977
598
|
var buildLocaleNavigation = (code, pages, fallback, fallbackByKey, options, i18n, diagnostics, version = "") => {
|
|
978
599
|
const basePath = options.basePath ?? "";
|
|
979
600
|
const real = pages.filter((page) => page.locale === code);
|
|
@@ -1009,12 +630,15 @@ var buildLocaleNavigation = (code, pages, fallback, fallbackByKey, options, i18n
|
|
|
1009
630
|
}
|
|
1010
631
|
return localized;
|
|
1011
632
|
});
|
|
1012
|
-
const
|
|
633
|
+
const localeDirOf = (locale) => i18n.parser === "dir" && locale !== i18n.defaultLocale ? locale : "";
|
|
634
|
+
const localeDir = localeDirOf(code);
|
|
635
|
+
const fallbackMetaPrefix = fallback && code !== fallback ? [version, localeDirOf(fallback)].filter(Boolean).join("/") : undefined;
|
|
1013
636
|
const localizeHref = (item) => ({
|
|
1014
637
|
...item,
|
|
1015
638
|
href: localizeServed(item.href, false)
|
|
1016
639
|
});
|
|
1017
640
|
const { actions, cta, featured } = options.navigation;
|
|
641
|
+
const sidebarItems = options.navigation.sidebar.items;
|
|
1018
642
|
const navigation = buildNavigation(localePages, {
|
|
1019
643
|
actions: actions?.map(localizeHref),
|
|
1020
644
|
basePath,
|
|
@@ -1022,6 +646,7 @@ var buildLocaleNavigation = (code, pages, fallback, fallbackByKey, options, i18n
|
|
|
1022
646
|
diagnostics,
|
|
1023
647
|
display: options.navigation.sidebar.display,
|
|
1024
648
|
extraRoutes: options.extraRoutes,
|
|
649
|
+
fallbackMetaPrefix,
|
|
1025
650
|
featured: featured?.map(localizeHref),
|
|
1026
651
|
folderMeta: options.folderMeta,
|
|
1027
652
|
localizedRoot: localizeRoute(versionizeRoute("/", version), code, i18n),
|
|
@@ -1030,10 +655,19 @@ var buildLocaleNavigation = (code, pages, fallback, fallbackByKey, options, i18n
|
|
|
1030
655
|
selectors: options.navigation.selectors,
|
|
1031
656
|
sharedFolderMeta: options.sharedFolderMeta,
|
|
1032
657
|
sharedMetaPrefix: version,
|
|
1033
|
-
sidebar: version ? undefined :
|
|
658
|
+
sidebar: version || !sidebarItems ? undefined : localizeSidebarHrefs(sidebarItems, (href) => localizeServed(href, false)),
|
|
659
|
+
tabRoot: localizeRoute("/", code, i18n),
|
|
1034
660
|
tabs
|
|
1035
661
|
});
|
|
1036
|
-
|
|
662
|
+
const localizedBrand = (href) => {
|
|
663
|
+
const localized = localizeServed(href, false);
|
|
664
|
+
return localized === href ? localized : withBasePath(basePath, localized);
|
|
665
|
+
};
|
|
666
|
+
const branded = options.brandHref === undefined ? navigation : { ...navigation, brandHref: localizedBrand(options.brandHref) };
|
|
667
|
+
return options.bannerHref === undefined ? branded : {
|
|
668
|
+
...branded,
|
|
669
|
+
bannerHref: mountConfiguredLink(localizeServed(options.bannerHref, false), basePath, extraRoutes)
|
|
670
|
+
};
|
|
1037
671
|
};
|
|
1038
672
|
var buildI18nNavigation = (pages, options, i18n, diagnostics, version = "") => {
|
|
1039
673
|
const fallback = resolveFallbackLocale(i18n);
|
|
@@ -1088,6 +722,7 @@ var buildVersionNavigation = (id, versionPages, options, diagnostics) => {
|
|
|
1088
722
|
selectors: options.navigation.selectors,
|
|
1089
723
|
sharedFolderMeta: options.sharedFolderMeta,
|
|
1090
724
|
sharedMetaPrefix: id,
|
|
725
|
+
tabRoot: "/",
|
|
1091
726
|
tabs: resolveTabLabels(options.navigation.tabs, "")
|
|
1092
727
|
})
|
|
1093
728
|
};
|
|
@@ -1115,12 +750,24 @@ var buildContentGraph = (pages, options) => {
|
|
|
1115
750
|
sidebar: options.navigation.sidebar.items,
|
|
1116
751
|
tabs: resolveTabLabels(options.navigation.tabs, "")
|
|
1117
752
|
});
|
|
753
|
+
if (options.bannerHref !== undefined) {
|
|
754
|
+
navigation = {
|
|
755
|
+
...navigation,
|
|
756
|
+
bannerHref: mountConfiguredLink(options.bannerHref, options.basePath ?? "", options.extraRoutes ?? new Set)
|
|
757
|
+
};
|
|
758
|
+
}
|
|
1118
759
|
}
|
|
1119
760
|
const navigationByVersion = {};
|
|
1120
761
|
for (const { id } of options.versions?.archived ?? []) {
|
|
1121
762
|
navigationByVersion[id] = buildVersionNavigation(id, pages.filter((page) => page.version === id), options, diagnostics);
|
|
1122
763
|
}
|
|
1123
764
|
diagnostics.push(...validateNavIcons(navigation), ...validateNavStructure(navigation, currentPages));
|
|
765
|
+
const sidebarItems = options.navigation.sidebar.items;
|
|
766
|
+
if (sidebarItems) {
|
|
767
|
+
const byRef = pagesByRef(currentPages, options.basePath ?? "", Boolean(i18n));
|
|
768
|
+
const extraRoutes = options.extraRoutes ?? new Set;
|
|
769
|
+
diagnostics.push(...validateSidebarItems(sidebarItems, (route) => byRef.has(route) || extraRoutes.has(route)));
|
|
770
|
+
}
|
|
1124
771
|
return {
|
|
1125
772
|
diagnostics,
|
|
1126
773
|
navigation,
|
|
@@ -1133,7 +780,8 @@ var buildContentGraph = (pages, options) => {
|
|
|
1133
780
|
|
|
1134
781
|
// src/core/last-modified.ts
|
|
1135
782
|
import { execFileSync } from "node:child_process";
|
|
1136
|
-
import {
|
|
783
|
+
import { realpathSync } from "node:fs";
|
|
784
|
+
import { normalize as normalize2, relative } from "pathe";
|
|
1137
785
|
var GIT_LOCATION_VARS = new Set([
|
|
1138
786
|
"GIT_COMMON_DIR",
|
|
1139
787
|
"GIT_DIR",
|
|
@@ -1157,6 +805,13 @@ var parseGitLog = (output) => {
|
|
|
1157
805
|
}
|
|
1158
806
|
return times;
|
|
1159
807
|
};
|
|
808
|
+
var realPath = (path) => {
|
|
809
|
+
try {
|
|
810
|
+
return normalize2(realpathSync.native(path));
|
|
811
|
+
} catch {
|
|
812
|
+
return path;
|
|
813
|
+
}
|
|
814
|
+
};
|
|
1160
815
|
var gitRepositoryRoot = (root) => {
|
|
1161
816
|
try {
|
|
1162
817
|
return execFileSync("git", ["-C", root, "rev-parse", "--show-toplevel"], { encoding: "utf-8", env: gitEnv(), stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
@@ -1172,6 +827,7 @@ var gitLastModifiedTimes = (root, contentRoots, sourcePaths, repositoryRoot) =>
|
|
|
1172
827
|
if (gitRoot === null) {
|
|
1173
828
|
return new Map;
|
|
1174
829
|
}
|
|
830
|
+
const top = realPath(gitRoot);
|
|
1175
831
|
try {
|
|
1176
832
|
const output = execFileSync("git", [
|
|
1177
833
|
"-C",
|
|
@@ -1182,12 +838,12 @@ var gitLastModifiedTimes = (root, contentRoots, sourcePaths, repositoryRoot) =>
|
|
|
1182
838
|
"--format=%x00%cI",
|
|
1183
839
|
"--name-only",
|
|
1184
840
|
"--",
|
|
1185
|
-
...contentRoots
|
|
841
|
+
...contentRoots.map(realPath)
|
|
1186
842
|
], { encoding: "utf-8", env: gitEnv(), maxBuffer: 256 * 1024 * 1024 });
|
|
1187
843
|
const byRepoPath = parseGitLog(output);
|
|
1188
844
|
const result = new Map;
|
|
1189
845
|
for (const sourcePath of sourcePaths) {
|
|
1190
|
-
const iso = byRepoPath.get(relative(
|
|
846
|
+
const iso = byRepoPath.get(relative(top, realPath(sourcePath)));
|
|
1191
847
|
if (iso) {
|
|
1192
848
|
result.set(sourcePath, iso);
|
|
1193
849
|
}
|
|
@@ -1224,7 +880,7 @@ var lastModifiedShallowWarning = (root, undatedCount) => {
|
|
|
1224
880
|
|
|
1225
881
|
// src/core/meta.ts
|
|
1226
882
|
import { basename, dirname, relative as relative2 } from "pathe";
|
|
1227
|
-
import { glob } from "tinyglobby";
|
|
883
|
+
import { glob, isDynamicPattern } from "tinyglobby";
|
|
1228
884
|
var META_FILES = [
|
|
1229
885
|
"**/meta.ts",
|
|
1230
886
|
"**/meta.js",
|
|
@@ -1235,6 +891,34 @@ var META_FILES = [
|
|
|
1235
891
|
];
|
|
1236
892
|
var isMetaFactory = (mod) => typeof mod === "function";
|
|
1237
893
|
var resolveMeta = async (mod) => isMetaFactory(mod) ? await mod() : mod;
|
|
894
|
+
var globBase = (pattern) => {
|
|
895
|
+
const literal = [];
|
|
896
|
+
for (const segment of pattern.split("/").slice(0, -1)) {
|
|
897
|
+
if (isDynamicPattern(segment)) {
|
|
898
|
+
break;
|
|
899
|
+
}
|
|
900
|
+
if (segment !== "" && segment !== ".") {
|
|
901
|
+
literal.push(segment);
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
return literal.join("/");
|
|
905
|
+
};
|
|
906
|
+
var onPathOf = (dir, base) => dir === base || base === "" || dir === "" || dir.startsWith(`${base}/`) || base.startsWith(`${dir}/`);
|
|
907
|
+
var withinInclude = (dir, include) => include === undefined || include.some((pattern) => !pattern.startsWith("!") && onPathOf(dir, globBase(pattern)));
|
|
908
|
+
var findFolderMetaFiles = async (source, patterns = META_FILES) => {
|
|
909
|
+
const found = await glob([...patterns], {
|
|
910
|
+
absolute: true,
|
|
911
|
+
cwd: source.root,
|
|
912
|
+
ignore: [
|
|
913
|
+
...source.exclude ?? [],
|
|
914
|
+
"**/node_modules/**",
|
|
915
|
+
"**/.blume/**",
|
|
916
|
+
"**/dist/**"
|
|
917
|
+
],
|
|
918
|
+
onlyFiles: true
|
|
919
|
+
});
|
|
920
|
+
return found.filter((file) => withinInclude(relative2(source.root, dirname(file)), source.include));
|
|
921
|
+
};
|
|
1238
922
|
var metaKeyFor = (prefix, dir) => {
|
|
1239
923
|
const clean = prefix ? trimChar(prefix, "/") : "";
|
|
1240
924
|
if (!clean) {
|
|
@@ -1244,19 +928,14 @@ var metaKeyFor = (prefix, dir) => {
|
|
|
1244
928
|
};
|
|
1245
929
|
var discoverFolderMeta = async (sources, options = {}) => {
|
|
1246
930
|
const list = Array.isArray(sources) ? sources : [{ root: sources }];
|
|
1247
|
-
const localeDirs = new
|
|
931
|
+
const localeDirs = new Map((options.localeDirs ?? []).map((code) => [code.toLowerCase(), code]));
|
|
1248
932
|
const versionDirs = new Set(options.versionDirs);
|
|
1249
933
|
const load = createModuleLoader();
|
|
1250
934
|
const meta = new Map;
|
|
1251
935
|
const shared = new Map;
|
|
1252
936
|
const diagnostics = [];
|
|
1253
937
|
const perSource = await Promise.all(list.map(async (source) => {
|
|
1254
|
-
const files = await
|
|
1255
|
-
absolute: true,
|
|
1256
|
-
cwd: source.root,
|
|
1257
|
-
ignore: ["**/node_modules/**", "**/.blume/**", "**/dist/**"],
|
|
1258
|
-
onlyFiles: true
|
|
1259
|
-
});
|
|
938
|
+
const files = await findFolderMetaFiles(source);
|
|
1260
939
|
const loaded = await Promise.all(files.map(async (file) => {
|
|
1261
940
|
try {
|
|
1262
941
|
return {
|
|
@@ -1277,7 +956,7 @@ var discoverFolderMeta = async (sources, options = {}) => {
|
|
|
1277
956
|
const version = head && versionDirs.has(head) ? head : "";
|
|
1278
957
|
const afterVersion = version ? tail : [head ?? "", ...tail];
|
|
1279
958
|
const [localeHead, ...localeTail] = afterVersion;
|
|
1280
|
-
const locale = localeHead
|
|
959
|
+
const locale = localeHead ? localeDirs.get(localeHead.toLowerCase()) ?? "" : "";
|
|
1281
960
|
const rest = (locale ? localeTail : afterVersion).filter(Boolean).join("/");
|
|
1282
961
|
const key = [version, locale, metaKeyFor(source.prefix, rest)].filter(Boolean).join("/");
|
|
1283
962
|
if (!entry.ok) {
|
|
@@ -1397,30 +1076,31 @@ var embeddedEntry = (node, options) => {
|
|
|
1397
1076
|
}
|
|
1398
1077
|
return unsupported(`Contentful embedded entry${contentType ? `: ${contentType}` : ""}`, writesMdx(options.serializers));
|
|
1399
1078
|
};
|
|
1400
|
-
var
|
|
1401
|
-
var
|
|
1079
|
+
var inlineParts = (nodes, options) => nodes.flatMap((node) => inlineNodeParts(node, options));
|
|
1080
|
+
var inlineNodeParts = (node, options) => {
|
|
1402
1081
|
switch (asString(node.nodeType)) {
|
|
1403
1082
|
case "text": {
|
|
1404
|
-
return
|
|
1083
|
+
return [{ marks: marksOf(node), text: asString(node.value) ?? "" }];
|
|
1405
1084
|
}
|
|
1406
1085
|
case "hyperlink": {
|
|
1407
|
-
return
|
|
1086
|
+
return linkParts(inlineParts(children(node), options), asString(getPath(node, "data.uri")));
|
|
1408
1087
|
}
|
|
1409
1088
|
case "asset-hyperlink": {
|
|
1410
|
-
return
|
|
1089
|
+
return linkParts(inlineParts(children(node), options), linkedAsset(node, options)?.url);
|
|
1411
1090
|
}
|
|
1412
1091
|
case "embedded-entry-inline": {
|
|
1413
|
-
return embeddedEntry(node, options);
|
|
1092
|
+
return [{ markdown: embeddedEntry(node, options) }];
|
|
1414
1093
|
}
|
|
1415
1094
|
default: {
|
|
1416
|
-
return
|
|
1095
|
+
return inlineParts(children(node), options);
|
|
1417
1096
|
}
|
|
1418
1097
|
}
|
|
1419
1098
|
};
|
|
1099
|
+
var blockText = (node, options) => guardBlockStart(renderInline(inlineParts(children(node), options)));
|
|
1420
1100
|
var renderList = (items, marker, options) => items.map((item, index) => listItem(marker(index), children(item).map((child) => renderBlock(child, options)).filter((block) => block !== "").join(`
|
|
1421
1101
|
`))).join(`
|
|
1422
1102
|
`);
|
|
1423
|
-
var cellText = (cell, options) => children(cell).map((paragraph) =>
|
|
1103
|
+
var cellText = (cell, options) => children(cell).map((paragraph) => blockText(paragraph, options)).join(" ").replaceAll(CELL_BREAK, " ").replaceAll(CELL_PIPE, String.raw`\|`);
|
|
1424
1104
|
var tableRow = (cells) => `| ${cells.join(" | ")} |`;
|
|
1425
1105
|
var renderTable = (node, options) => {
|
|
1426
1106
|
const rows = children(node).map((row) => children(row).map((cell) => cellText(cell, options)));
|
|
@@ -1439,11 +1119,11 @@ var renderBlock = (node, options) => {
|
|
|
1439
1119
|
const type = asString(node.nodeType) ?? "";
|
|
1440
1120
|
const heading = HEADING.exec(type)?.groups?.level;
|
|
1441
1121
|
if (heading) {
|
|
1442
|
-
return `${headingPrefix(Number(heading))}${
|
|
1122
|
+
return `${headingPrefix(Number(heading))}${blockText(node, options)}`;
|
|
1443
1123
|
}
|
|
1444
1124
|
switch (type) {
|
|
1445
1125
|
case "paragraph": {
|
|
1446
|
-
return
|
|
1126
|
+
return blockText(node, options);
|
|
1447
1127
|
}
|
|
1448
1128
|
case "blockquote": {
|
|
1449
1129
|
return blockquote(joinBlocks(children(node).map((child) => renderBlock(child, options))));
|
|
@@ -1480,6 +1160,7 @@ var remoteSource = (options, ctx) => {
|
|
|
1480
1160
|
const cache = snapshotCache(ctx?.cacheDir ?? join(".blume", "cache", options.name));
|
|
1481
1161
|
let snapshot = new Map;
|
|
1482
1162
|
const load = async (refresh = ctx?.refresh ?? true) => {
|
|
1163
|
+
options.assertConfigured?.();
|
|
1483
1164
|
const result = await loadWithCache(options.name, cache, options.fetchEntries, refresh);
|
|
1484
1165
|
snapshot = new Map(result.entries.map((entry) => [entry.ref, entry]));
|
|
1485
1166
|
return result;
|
|
@@ -1498,7 +1179,8 @@ var remoteSource = (options, ctx) => {
|
|
|
1498
1179
|
prefix: options.prefix,
|
|
1499
1180
|
read,
|
|
1500
1181
|
staged: true,
|
|
1501
|
-
watch: options.pollInterval ? pollingWatch(() => load(true), options.pollInterval, () => load()) : undefined
|
|
1182
|
+
watch: options.pollInterval ? pollingWatch(() => load(true), options.pollInterval, () => load()) : undefined,
|
|
1183
|
+
withContext: options.withContext
|
|
1502
1184
|
};
|
|
1503
1185
|
};
|
|
1504
1186
|
var stagedEntry = (slug, data, markdown, lastModified, format = "md") => {
|
|
@@ -1552,8 +1234,8 @@ var documentEntry = (doc, fields, id, lower, draft = false, lowersToMdx = false)
|
|
|
1552
1234
|
let markdown = "";
|
|
1553
1235
|
let format = "md";
|
|
1554
1236
|
if (isStringValue2(body)) {
|
|
1555
|
-
markdown = `${body.trimEnd()}
|
|
1556
|
-
|
|
1237
|
+
markdown = neutralizeUnsafeLinks(`${body.trimEnd()}
|
|
1238
|
+
`);
|
|
1557
1239
|
} else if (body !== undefined) {
|
|
1558
1240
|
markdown = lower(body);
|
|
1559
1241
|
format = lowersToMdx ? "mdx" : "md";
|
|
@@ -1588,14 +1270,20 @@ var contentfulSource = (options, ctx) => {
|
|
|
1588
1270
|
serializers: options.serializers
|
|
1589
1271
|
}) : "", false, writesMdx(options.serializers));
|
|
1590
1272
|
};
|
|
1591
|
-
const
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1273
|
+
const preview = ctx?.preview ?? false;
|
|
1274
|
+
const previewToken = () => options.previewToken ?? process.env.CONTENTFUL_PREVIEW_TOKEN;
|
|
1275
|
+
const assertConfigured = () => {
|
|
1276
|
+
if (preview && !previewToken()) {
|
|
1277
|
+
throw new BlumeError({
|
|
1278
|
+
code: "BLUME_SOURCE_MISCONFIGURED",
|
|
1279
|
+
message: `Source "${options.name}": Contentful --preview needs a Preview API token.`,
|
|
1280
|
+
severity: "error",
|
|
1281
|
+
suggestion: "Set previewToken on contentfulSource, or the CONTENTFUL_PREVIEW_TOKEN environment variable."
|
|
1282
|
+
});
|
|
1597
1283
|
}
|
|
1598
|
-
|
|
1284
|
+
};
|
|
1285
|
+
const fetchEntries = async () => {
|
|
1286
|
+
const token = preview ? previewToken() : options.token ?? process.env.CONTENTFUL_ACCESS_TOKEN;
|
|
1599
1287
|
const client = {
|
|
1600
1288
|
fetchImpl: options.fetchImpl,
|
|
1601
1289
|
headers: token ? { authorization: `Bearer ${token}` } : {}
|
|
@@ -1630,17 +1318,19 @@ var contentfulSource = (options, ctx) => {
|
|
|
1630
1318
|
return entries;
|
|
1631
1319
|
};
|
|
1632
1320
|
return remoteSource({
|
|
1321
|
+
assertConfigured,
|
|
1633
1322
|
fetchEntries,
|
|
1634
1323
|
name: options.name,
|
|
1635
1324
|
pollInterval: options.pollInterval,
|
|
1636
|
-
prefix: options.prefix
|
|
1325
|
+
prefix: options.prefix,
|
|
1326
|
+
withContext: (next) => contentfulSource(options, next)
|
|
1637
1327
|
}, ctx);
|
|
1638
1328
|
};
|
|
1639
1329
|
|
|
1640
1330
|
// src/core/sources/filesystem.ts
|
|
1641
1331
|
import { existsSync, watch as fsWatch } from "node:fs";
|
|
1642
1332
|
import { readFile } from "node:fs/promises";
|
|
1643
|
-
import { extname
|
|
1333
|
+
import { extname, isAbsolute, join as join2, relative as relative3, resolve } from "pathe";
|
|
1644
1334
|
import { glob as glob2 } from "tinyglobby";
|
|
1645
1335
|
var filesystemSource = (options) => {
|
|
1646
1336
|
const contentRoot = isAbsolute(options.root) ? options.root : join2(resolve(options.projectRoot), options.root);
|
|
@@ -1652,9 +1342,19 @@ var filesystemSource = (options) => {
|
|
|
1652
1342
|
onlyFiles: true
|
|
1653
1343
|
});
|
|
1654
1344
|
files.sort();
|
|
1655
|
-
const
|
|
1345
|
+
const diagnostics = [];
|
|
1346
|
+
const loadable = [];
|
|
1347
|
+
for (const file of files) {
|
|
1348
|
+
const unloadable = unloadablePathDiagnostic(relative3(contentRoot, file), file);
|
|
1349
|
+
if (unloadable) {
|
|
1350
|
+
diagnostics.push(unloadable);
|
|
1351
|
+
} else {
|
|
1352
|
+
loadable.push(file);
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
const entries = await Promise.all(loadable.map(async (file) => {
|
|
1656
1356
|
const source = await readFile(file, "utf-8");
|
|
1657
|
-
const ext =
|
|
1357
|
+
const ext = extname(file).toLowerCase();
|
|
1658
1358
|
const format = ext === ".mdx" ? "mdx" : "md";
|
|
1659
1359
|
const parsed = frontmatter_default(source);
|
|
1660
1360
|
return {
|
|
@@ -1665,7 +1365,7 @@ var filesystemSource = (options) => {
|
|
|
1665
1365
|
sourcePath: file
|
|
1666
1366
|
};
|
|
1667
1367
|
}));
|
|
1668
|
-
return { diagnostics
|
|
1368
|
+
return { diagnostics, entries };
|
|
1669
1369
|
};
|
|
1670
1370
|
const validate = () => {
|
|
1671
1371
|
if (!existsSync(contentRoot)) {
|
|
@@ -1674,7 +1374,7 @@ var filesystemSource = (options) => {
|
|
|
1674
1374
|
file: contentRoot,
|
|
1675
1375
|
message: `Content root not found: ${options.root}`,
|
|
1676
1376
|
severity: "error",
|
|
1677
|
-
suggestion: `Create a "${options.root}" folder with at least one .md or .mdx file, or
|
|
1377
|
+
suggestion: `Create a "${options.root}" folder with at least one .md or .mdx file, or point Blume at your docs folder: content.root in blume.config.ts, or the filesystem() source's root when you list content.sources.`
|
|
1678
1378
|
});
|
|
1679
1379
|
}
|
|
1680
1380
|
};
|
|
@@ -1691,6 +1391,8 @@ var filesystemSource = (options) => {
|
|
|
1691
1391
|
};
|
|
1692
1392
|
return {
|
|
1693
1393
|
contentRoot,
|
|
1394
|
+
exclude: options.exclude,
|
|
1395
|
+
include: options.include,
|
|
1694
1396
|
load,
|
|
1695
1397
|
name: options.name,
|
|
1696
1398
|
prefix: options.prefix,
|
|
@@ -1704,7 +1406,7 @@ var filesystemSource = (options) => {
|
|
|
1704
1406
|
// src/core/sources/github-releases.ts
|
|
1705
1407
|
import { fromMarkdown } from "mdast-util-from-markdown";
|
|
1706
1408
|
import { gfmFromMarkdown } from "mdast-util-gfm";
|
|
1707
|
-
import { toString as
|
|
1409
|
+
import { toString as mdastToString2 } from "mdast-util-to-string";
|
|
1708
1410
|
import { gfm } from "micromark-extension-gfm";
|
|
1709
1411
|
import stringWidth from "string-width";
|
|
1710
1412
|
var DEFAULT_LIMIT = 100;
|
|
@@ -1723,7 +1425,7 @@ var releaseDescription = (body) => {
|
|
|
1723
1425
|
extensions: [gfm()],
|
|
1724
1426
|
mdastExtensions: [gfmFromMarkdown()]
|
|
1725
1427
|
});
|
|
1726
|
-
const text = tree.children.filter((node) => !NON_PROSE.has(node.type)).map((node) =>
|
|
1428
|
+
const text = tree.children.filter((node) => !NON_PROSE.has(node.type)).map((node) => mdastToString2(node, { includeHtml: false, includeImageAlt: false })).join(" ").replaceAll(WHITESPACE, " ").trim();
|
|
1727
1429
|
if (!text) {
|
|
1728
1430
|
return;
|
|
1729
1431
|
}
|
|
@@ -1763,6 +1465,62 @@ var liftHeadings = (body) => {
|
|
|
1763
1465
|
}
|
|
1764
1466
|
return lifted;
|
|
1765
1467
|
};
|
|
1468
|
+
var WEB_PROTOCOL = /^https?:$/u;
|
|
1469
|
+
var TITLE_SPECIALS = /["\\]/gu;
|
|
1470
|
+
var webOrigin = (site) => {
|
|
1471
|
+
const parsed = site ? URL.parse(site) : null;
|
|
1472
|
+
return parsed && WEB_PROTOCOL.test(parsed.protocol) ? parsed.origin : null;
|
|
1473
|
+
};
|
|
1474
|
+
var titleSuffix = (title) => title ? ` "${title.replaceAll(TITLE_SPECIALS, String.raw`\$&`)}"` : "";
|
|
1475
|
+
var rewrittenLink = (markdown, node, path) => {
|
|
1476
|
+
const target = `${destination(path)}${titleSuffix(node.title)}`;
|
|
1477
|
+
if (node.type === "definition") {
|
|
1478
|
+
return `[${node.label ?? node.identifier}]: ${target}`;
|
|
1479
|
+
}
|
|
1480
|
+
const start = node.position?.start.offset ?? 0;
|
|
1481
|
+
if (markdown[start] !== "[") {
|
|
1482
|
+
return `[${escapeMarkdownText(mdastToString2(node))}](${target})`;
|
|
1483
|
+
}
|
|
1484
|
+
const first = node.children.at(0)?.position?.start.offset ?? start + 1;
|
|
1485
|
+
const last = node.children.at(-1)?.position?.end.offset ?? first;
|
|
1486
|
+
return `[${markdown.slice(first, last)}](${target})`;
|
|
1487
|
+
};
|
|
1488
|
+
var relativizeOwnLinks = (markdown, site) => {
|
|
1489
|
+
const origin = webOrigin(site);
|
|
1490
|
+
if (!origin) {
|
|
1491
|
+
return markdown;
|
|
1492
|
+
}
|
|
1493
|
+
const spans = [];
|
|
1494
|
+
const visit = (node) => {
|
|
1495
|
+
if (node.type === "link" || node.type === "definition") {
|
|
1496
|
+
const parsed = URL.parse(node.url);
|
|
1497
|
+
if (parsed?.origin === origin) {
|
|
1498
|
+
spans.push({
|
|
1499
|
+
end: node.position?.end.offset ?? 0,
|
|
1500
|
+
start: node.position?.start.offset ?? 0,
|
|
1501
|
+
text: rewrittenLink(markdown, node, `${parsed.pathname}${parsed.search}${parsed.hash}`)
|
|
1502
|
+
});
|
|
1503
|
+
return;
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
if ("children" in node) {
|
|
1507
|
+
for (const child of node.children) {
|
|
1508
|
+
visit(child);
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
};
|
|
1512
|
+
visit(fromMarkdown(markdown, {
|
|
1513
|
+
extensions: [gfm()],
|
|
1514
|
+
mdastExtensions: [gfmFromMarkdown()]
|
|
1515
|
+
}));
|
|
1516
|
+
let out = "";
|
|
1517
|
+
let cursor = 0;
|
|
1518
|
+
for (const span of spans) {
|
|
1519
|
+
out += markdown.slice(cursor, span.start) + span.text;
|
|
1520
|
+
cursor = span.end;
|
|
1521
|
+
}
|
|
1522
|
+
return out + markdown.slice(cursor);
|
|
1523
|
+
};
|
|
1766
1524
|
var slugifyTag = (tag) => tag.toLowerCase().replaceAll(NON_SLUG, "-").replaceAll(EDGE_DASHES, "");
|
|
1767
1525
|
var githubHeaders = () => {
|
|
1768
1526
|
const headers = new Headers({ Accept: "application/vnd.github+json" });
|
|
@@ -1772,14 +1530,14 @@ var githubHeaders = () => {
|
|
|
1772
1530
|
}
|
|
1773
1531
|
return headers;
|
|
1774
1532
|
};
|
|
1775
|
-
var releaseToEntry = (release) => {
|
|
1533
|
+
var releaseToEntry = (release, site) => {
|
|
1776
1534
|
const version = release.tag_name.replace(LEADING_V, "");
|
|
1777
1535
|
const title = release.name?.trim() || release.tag_name;
|
|
1778
1536
|
const date = release.published_at ?? release.created_at;
|
|
1779
1537
|
const category = release.prerelease ? "Prerelease" : "Release";
|
|
1780
|
-
const body = liftHeadings(neutralizeUnsafeLinks((release.body ?? "").replaceAll(`\r
|
|
1538
|
+
const body = liftHeadings(relativizeOwnLinks(neutralizeUnsafeLinks((release.body ?? "").replaceAll(`\r
|
|
1781
1539
|
`, `
|
|
1782
|
-
`)).trim());
|
|
1540
|
+
`)).trim(), site));
|
|
1783
1541
|
const description = releaseDescription(body);
|
|
1784
1542
|
const data = {
|
|
1785
1543
|
changelog: { category, version },
|
|
@@ -1813,11 +1571,21 @@ var githubReleasesSource = (options, ctx) => {
|
|
|
1813
1571
|
const include = (release) => (options.drafts || !release.draft) && (options.prereleases || !release.prerelease);
|
|
1814
1572
|
const fetchPage = async (page) => {
|
|
1815
1573
|
const url = `${base}/repos/${options.owner}/${options.repo}/releases?per_page=${PER_PAGE}&page=${page}`;
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1574
|
+
try {
|
|
1575
|
+
const res = await doFetch(url, {
|
|
1576
|
+
headers: githubHeaders(),
|
|
1577
|
+
signal: AbortSignal.timeout(REMOTE_TIMEOUT_MS)
|
|
1578
|
+
});
|
|
1579
|
+
if (!res.ok) {
|
|
1580
|
+
throw new Error(`${url} -> ${res.status}`);
|
|
1581
|
+
}
|
|
1582
|
+
return await res.json();
|
|
1583
|
+
} catch (error) {
|
|
1584
|
+
if (error instanceof DOMException && error.name === "TimeoutError") {
|
|
1585
|
+
throw new Error(`${url} did not respond within ${REMOTE_TIMEOUT_MS / 1000}s`, { cause: error });
|
|
1586
|
+
}
|
|
1587
|
+
throw error;
|
|
1819
1588
|
}
|
|
1820
|
-
return await res.json();
|
|
1821
1589
|
};
|
|
1822
1590
|
const fetchReleases = async () => {
|
|
1823
1591
|
const collected = [];
|
|
@@ -1836,7 +1604,7 @@ var githubReleasesSource = (options, ctx) => {
|
|
|
1836
1604
|
try {
|
|
1837
1605
|
const result = await loadWithCache(options.name, cache, async () => {
|
|
1838
1606
|
const releases = await fetchReleases();
|
|
1839
|
-
return releases.map(releaseToEntry);
|
|
1607
|
+
return releases.map((release) => releaseToEntry(release, options.site));
|
|
1840
1608
|
}, refresh);
|
|
1841
1609
|
snapshot = new Map(result.entries.map((entry) => [entry.ref, entry]));
|
|
1842
1610
|
return result;
|
|
@@ -1870,7 +1638,8 @@ var githubReleasesSource = (options, ctx) => {
|
|
|
1870
1638
|
prefix: options.prefix,
|
|
1871
1639
|
read,
|
|
1872
1640
|
staged: true,
|
|
1873
|
-
watch: options.pollInterval ? pollingWatch(() => load(true), options.pollInterval, () => load()) : undefined
|
|
1641
|
+
watch: options.pollInterval ? pollingWatch(() => load(true), options.pollInterval, () => load()) : undefined,
|
|
1642
|
+
withContext: (next) => githubReleasesSource(options, next)
|
|
1874
1643
|
};
|
|
1875
1644
|
};
|
|
1876
1645
|
|
|
@@ -1890,15 +1659,29 @@ var githubHeaders2 = (url) => {
|
|
|
1890
1659
|
}
|
|
1891
1660
|
return GITHUB_HOSTS.has(host) ? { authorization: `Bearer ${token}` } : {};
|
|
1892
1661
|
};
|
|
1662
|
+
var fetchText = async (url, doFetch) => {
|
|
1663
|
+
try {
|
|
1664
|
+
const res = await doFetch(url, {
|
|
1665
|
+
headers: githubHeaders2(url),
|
|
1666
|
+
signal: AbortSignal.timeout(REMOTE_TIMEOUT_MS)
|
|
1667
|
+
});
|
|
1668
|
+
if (!res.ok) {
|
|
1669
|
+
throw new Error(`${url} -> ${res.status}`);
|
|
1670
|
+
}
|
|
1671
|
+
return await res.text();
|
|
1672
|
+
} catch (error) {
|
|
1673
|
+
if (error instanceof DOMException && error.name === "TimeoutError") {
|
|
1674
|
+
throw new Error(`${url} did not respond within ${REMOTE_TIMEOUT_MS / 1000}s`, { cause: error });
|
|
1675
|
+
}
|
|
1676
|
+
throw error;
|
|
1677
|
+
}
|
|
1678
|
+
};
|
|
1893
1679
|
var enumerateGithub = async (github, include, doFetch) => {
|
|
1894
1680
|
const { owner, repo, ref } = github;
|
|
1895
1681
|
const base = github.path.replaceAll(/^\/|\/$/gu, "");
|
|
1896
1682
|
const treeUrl = `https://api.github.com/repos/${owner}/${repo}/git/trees/${ref}?recursive=1`;
|
|
1897
|
-
const
|
|
1898
|
-
|
|
1899
|
-
throw new Error(`${treeUrl} -> ${res.status}`);
|
|
1900
|
-
}
|
|
1901
|
-
const body = await res.json();
|
|
1683
|
+
const text = await fetchText(treeUrl, doFetch);
|
|
1684
|
+
const body = JSON.parse(text);
|
|
1902
1685
|
const prefix = base ? `${base}/` : "";
|
|
1903
1686
|
const included = picomatch(include);
|
|
1904
1687
|
const refs = (body.tree ?? []).flatMap((node) => {
|
|
@@ -1943,13 +1726,7 @@ var mdxRemoteSource = (options, ctx) => {
|
|
|
1943
1726
|
return { refs, truncated: false };
|
|
1944
1727
|
};
|
|
1945
1728
|
const fetchEntry = async (item) => {
|
|
1946
|
-
const
|
|
1947
|
-
headers: githubHeaders2(item.fetchUrl)
|
|
1948
|
-
});
|
|
1949
|
-
if (!res.ok) {
|
|
1950
|
-
throw new Error(`${item.fetchUrl} -> ${res.status}`);
|
|
1951
|
-
}
|
|
1952
|
-
const text = await res.text();
|
|
1729
|
+
const text = await fetchText(item.fetchUrl, doFetch);
|
|
1953
1730
|
const parsed = frontmatter_default(text);
|
|
1954
1731
|
const format = item.ref.toLowerCase().endsWith(".mdx") ? "mdx" : "md";
|
|
1955
1732
|
return {
|
|
@@ -1973,13 +1750,16 @@ var mdxRemoteSource = (options, ctx) => {
|
|
|
1973
1750
|
severity: "warning"
|
|
1974
1751
|
});
|
|
1975
1752
|
}
|
|
1753
|
+
const reasons = [];
|
|
1976
1754
|
const settled = await Promise.all(refs.map(async (ref) => {
|
|
1977
1755
|
try {
|
|
1978
1756
|
return await fetchEntry(ref);
|
|
1979
1757
|
} catch (error) {
|
|
1758
|
+
const reason = error.message;
|
|
1759
|
+
reasons.push(reason);
|
|
1980
1760
|
skipped.push({
|
|
1981
1761
|
code: "BLUME_SOURCE_FETCH_FAILED",
|
|
1982
|
-
message: `Source "${options.name}" skipped "${ref.ref}" (${
|
|
1762
|
+
message: `Source "${options.name}" skipped "${ref.ref}" (${reason}); the rest were imported.`,
|
|
1983
1763
|
severity: "warning"
|
|
1984
1764
|
});
|
|
1985
1765
|
return null;
|
|
@@ -1988,7 +1768,7 @@ var mdxRemoteSource = (options, ctx) => {
|
|
|
1988
1768
|
const entries = settled.filter((entry) => entry !== null);
|
|
1989
1769
|
if (refs.length > 0 && entries.length === 0) {
|
|
1990
1770
|
skipped.length = 0;
|
|
1991
|
-
throw new Error(`all ${refs.length} remote file(s) failed to fetch`);
|
|
1771
|
+
throw new Error(`all ${refs.length} remote file(s) failed to fetch (${reasons[0]})`);
|
|
1992
1772
|
}
|
|
1993
1773
|
return entries;
|
|
1994
1774
|
}, refresh);
|
|
@@ -2010,10 +1790,12 @@ var mdxRemoteSource = (options, ctx) => {
|
|
|
2010
1790
|
return {
|
|
2011
1791
|
load,
|
|
2012
1792
|
name: options.name,
|
|
1793
|
+
orderedNames: true,
|
|
2013
1794
|
prefix: options.prefix,
|
|
2014
1795
|
read,
|
|
2015
1796
|
staged: true,
|
|
2016
|
-
watch: options.pollInterval ? pollingWatch(() => load(true), options.pollInterval, () => load()) : undefined
|
|
1797
|
+
watch: options.pollInterval ? pollingWatch(() => load(true), options.pollInterval, () => load()) : undefined,
|
|
1798
|
+
withContext: (next) => mdxRemoteSource(options, next)
|
|
2017
1799
|
};
|
|
2018
1800
|
};
|
|
2019
1801
|
|
|
@@ -2032,34 +1814,45 @@ import {
|
|
|
2032
1814
|
rm,
|
|
2033
1815
|
writeFile
|
|
2034
1816
|
} from "node:fs/promises";
|
|
2035
|
-
import { extname as
|
|
2036
|
-
var MD_IMAGE = /!\[(?<alt>[
|
|
1817
|
+
import { extname as extname2, join as join3 } from "pathe";
|
|
1818
|
+
var MD_IMAGE = /!\[(?<alt>(?:\\.|[^\\\]])*)\]\((?:<(?<pointy>(?:\\.|[^\\<>\n])*)>|(?<bare>(?:\\.|[^\\\s)])+))\)/gu;
|
|
1819
|
+
var DESTINATION_ESCAPE = /\\(?<char>[!-/:-@[-`{-~])/gu;
|
|
2037
1820
|
var HTML_VIDEO_SRC = /(?<open><video\b[^>]*?\ssrc=")(?<url>[^"]+)(?<close>")/gu;
|
|
2038
1821
|
var REMOTE = /^https?:\/\//u;
|
|
2039
|
-
var SAFE_EXT = /^\.[a-z0-9]+$/iu;
|
|
2040
1822
|
var CODE_FENCE_BLOCK = /^(?<fence>`{3,}|~{3,})[^\n]*\n[\s\S]*?^\k<fence>[^\n]*(?=\n|$)/gmu;
|
|
2041
1823
|
var FENCE_TOKEN = /\u0000blume-fence-(?<index>\d+)\u0000/gu;
|
|
2042
1824
|
var EXT_BY_MIME = new Map([
|
|
1825
|
+
["image/apng", ".apng"],
|
|
2043
1826
|
["image/avif", ".avif"],
|
|
1827
|
+
["image/bmp", ".bmp"],
|
|
2044
1828
|
["image/gif", ".gif"],
|
|
2045
1829
|
["image/jpeg", ".jpg"],
|
|
1830
|
+
["image/jpg", ".jpg"],
|
|
2046
1831
|
["image/png", ".png"],
|
|
2047
1832
|
["image/svg+xml", ".svg"],
|
|
1833
|
+
["image/tiff", ".tiff"],
|
|
1834
|
+
["image/vnd.microsoft.icon", ".ico"],
|
|
2048
1835
|
["image/webp", ".webp"],
|
|
1836
|
+
["image/x-icon", ".ico"],
|
|
2049
1837
|
["video/mp4", ".mp4"],
|
|
2050
1838
|
["video/ogg", ".ogv"],
|
|
2051
1839
|
["video/quicktime", ".mov"],
|
|
2052
1840
|
["video/webm", ".webm"]
|
|
2053
1841
|
]);
|
|
2054
|
-
var
|
|
2055
|
-
var
|
|
1842
|
+
var MEDIA_EXTS = new Set([...EXT_BY_MIME.values(), ".jpeg"]);
|
|
1843
|
+
var OPAQUE_TYPES = new Set([
|
|
1844
|
+
"",
|
|
1845
|
+
"application/octet-stream",
|
|
1846
|
+
"binary/octet-stream"
|
|
1847
|
+
]);
|
|
2056
1848
|
var PART_SUFFIX = ".part";
|
|
2057
1849
|
var DEFAULT_TIMEOUT_MS = 120000;
|
|
2058
1850
|
var extFromUrl = (url) => {
|
|
2059
1851
|
const clean = url.split("?")[0] ?? url;
|
|
2060
|
-
const ext =
|
|
2061
|
-
return
|
|
1852
|
+
const ext = extname2(clean).toLowerCase();
|
|
1853
|
+
return MEDIA_EXTS.has(ext) ? ext : null;
|
|
2062
1854
|
};
|
|
1855
|
+
var imageUrl = (pointy, bare) => (pointy ?? bare ?? "").replaceAll(DESTINATION_ESCAPE, "$<char>");
|
|
2063
1856
|
var mediaType = (res) => res.headers.get("content-type")?.split(";")[0]?.trim().toLowerCase() ?? "";
|
|
2064
1857
|
var exists = async (path) => {
|
|
2065
1858
|
try {
|
|
@@ -2076,9 +1869,16 @@ var completedFor = async (dir, stem) => {
|
|
|
2076
1869
|
} catch {
|
|
2077
1870
|
return null;
|
|
2078
1871
|
}
|
|
2079
|
-
const candidates = names.filter((name) => name.startsWith(
|
|
1872
|
+
const candidates = names.filter((name) => name.startsWith(stem) && MEDIA_EXTS.has(name.slice(stem.length)));
|
|
2080
1873
|
return candidates.length === 1 ? candidates[0] ?? null : null;
|
|
2081
1874
|
};
|
|
1875
|
+
var extFor = (type, urlExt) => {
|
|
1876
|
+
const ext = EXT_BY_MIME.get(type) ?? (OPAQUE_TYPES.has(type) ? urlExt : null);
|
|
1877
|
+
if (ext) {
|
|
1878
|
+
return ext;
|
|
1879
|
+
}
|
|
1880
|
+
throw new Error(OPAQUE_TYPES.has(type) ? `responded with ${type || "no content type"} and its URL names no image or video file` : `responded with ${type}, not an image or video`);
|
|
1881
|
+
};
|
|
2082
1882
|
var materializeAssets = async (markdown, ctx) => {
|
|
2083
1883
|
const doFetch = ctx.fetchImpl ?? globalThis.fetch;
|
|
2084
1884
|
const limit = ctx.limit ?? ((task) => task());
|
|
@@ -2090,21 +1890,17 @@ var materializeAssets = async (markdown, ctx) => {
|
|
|
2090
1890
|
fences.push(block);
|
|
2091
1891
|
return `\x00blume-fence-${fences.length - 1}\x00`;
|
|
2092
1892
|
});
|
|
2093
|
-
const
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
urls.add(url);
|
|
2099
|
-
}
|
|
2100
|
-
}
|
|
2101
|
-
}
|
|
1893
|
+
const referenced = [
|
|
1894
|
+
...[...masked.matchAll(MD_IMAGE)].map((match) => imageUrl(match.groups?.pointy, match.groups?.bare)),
|
|
1895
|
+
...[...masked.matchAll(HTML_VIDEO_SRC)].map((match) => match.groups?.url ?? "")
|
|
1896
|
+
];
|
|
1897
|
+
const urls = new Set(referenced.filter((url) => REMOTE.test(url)));
|
|
2102
1898
|
const download = async (url, stem) => {
|
|
2103
1899
|
const urlExt = extFromUrl(url);
|
|
2104
1900
|
if (urlExt && await exists(join3(ctx.assetsDir, `${stem}${urlExt}`))) {
|
|
2105
1901
|
return `${stem}${urlExt}`;
|
|
2106
1902
|
}
|
|
2107
|
-
const completed =
|
|
1903
|
+
const completed = await completedFor(ctx.assetsDir, stem);
|
|
2108
1904
|
if (completed) {
|
|
2109
1905
|
return completed;
|
|
2110
1906
|
}
|
|
@@ -2112,14 +1908,11 @@ var materializeAssets = async (markdown, ctx) => {
|
|
|
2112
1908
|
if (!res.ok) {
|
|
2113
1909
|
throw new Error(`${res.status}`);
|
|
2114
1910
|
}
|
|
2115
|
-
const
|
|
2116
|
-
if (NON_MEDIA_TYPE.test(type)) {
|
|
2117
|
-
throw new Error(`responded with ${type}, not a media file`);
|
|
2118
|
-
}
|
|
1911
|
+
const ext = extFor(mediaType(res), urlExt);
|
|
2119
1912
|
if (!res.body) {
|
|
2120
1913
|
throw new Error("empty response body");
|
|
2121
1914
|
}
|
|
2122
|
-
const file = `${stem}${
|
|
1915
|
+
const file = `${stem}${ext}`;
|
|
2123
1916
|
const target = join3(ctx.assetsDir, file);
|
|
2124
1917
|
await mkdir(ctx.assetsDir, { recursive: true });
|
|
2125
1918
|
const part = `${target}.${randomUUID()}${PART_SUFFIX}`;
|
|
@@ -2165,8 +1958,8 @@ var materializeAssets = async (markdown, ctx) => {
|
|
|
2165
1958
|
});
|
|
2166
1959
|
}
|
|
2167
1960
|
}));
|
|
2168
|
-
const rewritten = masked.replaceAll(MD_IMAGE, (match, alt,
|
|
2169
|
-
const local = rewrites.get(
|
|
1961
|
+
const rewritten = masked.replaceAll(MD_IMAGE, (match, alt, pointy, bare) => {
|
|
1962
|
+
const local = rewrites.get(imageUrl(pointy, bare));
|
|
2170
1963
|
return local ? `` : match;
|
|
2171
1964
|
}).replaceAll(HTML_VIDEO_SRC, (match, open, url, close) => {
|
|
2172
1965
|
const local = rewrites.get(url);
|
|
@@ -2176,12 +1969,27 @@ var materializeAssets = async (markdown, ctx) => {
|
|
|
2176
1969
|
};
|
|
2177
1970
|
|
|
2178
1971
|
// src/core/sources/notion.ts
|
|
2179
|
-
var richToMarkdown = (rich = []) =>
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
1972
|
+
var richToMarkdown = (rich = []) => {
|
|
1973
|
+
const linked = [];
|
|
1974
|
+
for (const { annotations = {}, href, plain_text: text } of rich) {
|
|
1975
|
+
const run = {
|
|
1976
|
+
marks: {
|
|
1977
|
+
bold: annotations.bold,
|
|
1978
|
+
code: annotations.code,
|
|
1979
|
+
italic: annotations.italic,
|
|
1980
|
+
strike: annotations.strikethrough
|
|
1981
|
+
},
|
|
1982
|
+
text
|
|
1983
|
+
};
|
|
1984
|
+
const last = linked.at(-1);
|
|
1985
|
+
if (last && last.href === (href ?? undefined)) {
|
|
1986
|
+
last.runs.push(run);
|
|
1987
|
+
} else {
|
|
1988
|
+
linked.push({ href: href ?? undefined, runs: [run] });
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
return renderInline(linked.flatMap(({ href, runs }) => linkParts(runs, href)));
|
|
1992
|
+
};
|
|
2185
1993
|
var isBlockPayload = (value) => typeof value === "object";
|
|
2186
1994
|
var payloadOf = (block) => {
|
|
2187
1995
|
const value = block[block.type];
|
|
@@ -2202,7 +2010,8 @@ var withNotionRetry = async (call, attempt = 0) => {
|
|
|
2202
2010
|
if (status !== RATE_LIMITED || attempt === MAX_RETRIES) {
|
|
2203
2011
|
throw error;
|
|
2204
2012
|
}
|
|
2205
|
-
const
|
|
2013
|
+
const { headers } = error;
|
|
2014
|
+
const retryAfter = Number(headers?.get?.("retry-after"));
|
|
2206
2015
|
const wait = retryAfter > 0 ? retryAfter * SECOND_MS : BASE_DELAY_MS * 2 ** attempt * (1 + Math.random());
|
|
2207
2016
|
await sleep(wait);
|
|
2208
2017
|
return withNotionRetry(call, attempt + 1);
|
|
@@ -2221,6 +2030,7 @@ var LIST_BLOCKS = new Set([
|
|
|
2221
2030
|
var isListItem = (block) => block !== undefined && LIST_BLOCKS.has(block.type);
|
|
2222
2031
|
var richToPlain = (rich = []) => rich.map((node) => node.plain_text).join("");
|
|
2223
2032
|
var jsxString = (value) => `{${JSON.stringify(value)}}`;
|
|
2033
|
+
var FRAME_ESCAPED = /\\(?=[<>])/gu;
|
|
2224
2034
|
var YOUTUBE_HOST = /(?:^|\.)(?:youtube(?:-nocookie)?\.com|youtu\.be)$/u;
|
|
2225
2035
|
var isYouTubeUrl = (url) => {
|
|
2226
2036
|
const host = URL.parse(url)?.hostname ?? "";
|
|
@@ -2233,14 +2043,14 @@ var renderVideo = (data) => {
|
|
|
2233
2043
|
}
|
|
2234
2044
|
const caption = richToMarkdown(data.caption);
|
|
2235
2045
|
const title = caption ? ` title=${jsxString(richToPlain(data.caption))}` : "";
|
|
2236
|
-
const media = isYouTubeUrl(url) ? `<YouTube${title} url=${
|
|
2237
|
-
return caption ? `<Frame caption=${jsxString(caption)}>
|
|
2046
|
+
const media = isYouTubeUrl(url) ? `<YouTube${title} url=${jsxString(url)} />` : `<video controls src="${url.replaceAll('"', "%22")}" />`;
|
|
2047
|
+
return caption ? `<Frame caption=${jsxString(caption.replaceAll(FRAME_ESCAPED, ""))}>
|
|
2238
2048
|
${media}
|
|
2239
2049
|
</Frame>` : media;
|
|
2240
2050
|
};
|
|
2241
2051
|
var renderLeaf = (block) => {
|
|
2242
2052
|
const data = payloadOf(block) ?? {};
|
|
2243
|
-
const text = richToMarkdown(blockField(block));
|
|
2053
|
+
const text = guardBlockStart(richToMarkdown(blockField(block)));
|
|
2244
2054
|
switch (block.type) {
|
|
2245
2055
|
case "paragraph": {
|
|
2246
2056
|
return text;
|
|
@@ -2320,7 +2130,10 @@ var notionSource = (options, ctx) => {
|
|
|
2320
2130
|
return render(client, await childrenOf(client, target.id));
|
|
2321
2131
|
};
|
|
2322
2132
|
if (block.type === "callout") {
|
|
2323
|
-
const body = [
|
|
2133
|
+
const body = [
|
|
2134
|
+
guardBlockStart(richToMarkdown(blockField(block))),
|
|
2135
|
+
await children(block)
|
|
2136
|
+
].filter(Boolean).join(`
|
|
2324
2137
|
|
|
2325
2138
|
`);
|
|
2326
2139
|
return `<Callout>
|
|
@@ -2420,7 +2233,7 @@ ${nested}`;
|
|
|
2420
2233
|
data.sidebar = { order };
|
|
2421
2234
|
}
|
|
2422
2235
|
const slugProp = richToPlain(page.properties[props.slug ?? "Slug"]?.rich_text);
|
|
2423
|
-
const slug = slugifyPath(slugProp
|
|
2236
|
+
const slug = (slugProp ? slugifyPath(slugProp) : slugify(title.replaceAll("/", "-"))) || page.id;
|
|
2424
2237
|
return { data, slug };
|
|
2425
2238
|
};
|
|
2426
2239
|
const toEntry = async (client, page) => {
|
|
@@ -2494,7 +2307,8 @@ ${nested}`;
|
|
|
2494
2307
|
prefix: options.prefix,
|
|
2495
2308
|
read,
|
|
2496
2309
|
staged: true,
|
|
2497
|
-
watch: options.pollInterval ? pollingWatch(() => load(true), options.pollInterval, () => load()) : undefined
|
|
2310
|
+
watch: options.pollInterval ? pollingWatch(() => load(true), options.pollInterval, () => load()) : undefined,
|
|
2311
|
+
withContext: (next) => notionSource(options, next)
|
|
2498
2312
|
};
|
|
2499
2313
|
};
|
|
2500
2314
|
|
|
@@ -2741,7 +2555,7 @@ var buildLinkIndex = (notes, options) => {
|
|
|
2741
2555
|
if (cached) {
|
|
2742
2556
|
return cached;
|
|
2743
2557
|
}
|
|
2744
|
-
const route = resolveEntryRoute({ ref: note.rel, slug: entrySlugFor(note.placement.navPath) }, ".md", isStringValue(note.data.slug) ? note.data.slug : undefined, options);
|
|
2558
|
+
const route = resolveEntryRoute({ ref: note.rel, slug: entrySlugFor(note.placement.navPath) }, ".md", isStringValue(note.data.slug) ? note.data.slug : undefined, { ...options, orderingPrefixes: true });
|
|
2745
2559
|
const built = {
|
|
2746
2560
|
anchors: new Map,
|
|
2747
2561
|
locales: route.locales,
|
|
@@ -2802,11 +2616,15 @@ var noteToEntry = (pair, index, options, unresolved) => {
|
|
|
2802
2616
|
const keep = keptKeysFor(note.data, options);
|
|
2803
2617
|
const data = Object.fromEntries(Object.entries(note.data).filter(([key]) => !OBSIDIAN_NATIVE_KEYS.has(key) && (PAGE_META_KEYS.has(key) || keep.has(key))));
|
|
2804
2618
|
const merged = title === undefined ? data : { ...data, title };
|
|
2805
|
-
const
|
|
2619
|
+
const body = note.content.trim();
|
|
2620
|
+
const text = transformBody(body, index, pair.self, unresolved);
|
|
2806
2621
|
const raw = frontmatter_default.stringify(`${text}
|
|
2807
2622
|
`, merged);
|
|
2623
|
+
const leading = note.content.slice(0, note.content.indexOf(body));
|
|
2808
2624
|
return {
|
|
2809
2625
|
body: { format: "md", text },
|
|
2626
|
+
bodyLineOffset: note.frontmatterLines + leading.split(`
|
|
2627
|
+
`).length - 1,
|
|
2810
2628
|
data: merged,
|
|
2811
2629
|
hash: hashText(raw),
|
|
2812
2630
|
raw,
|
|
@@ -2818,11 +2636,13 @@ var noteToEntry = (pair, index, options, unresolved) => {
|
|
|
2818
2636
|
var readNote = async (vaultDir, rel, options) => {
|
|
2819
2637
|
const absPath = join5(vaultDir, rel);
|
|
2820
2638
|
try {
|
|
2821
|
-
const
|
|
2639
|
+
const file = await readFile2(absPath, "utf-8");
|
|
2640
|
+
const { content, data } = frontmatter_default(file);
|
|
2822
2641
|
return {
|
|
2823
2642
|
absPath,
|
|
2824
2643
|
content,
|
|
2825
2644
|
data,
|
|
2645
|
+
frontmatterLines: strippedLineOffset(file, content),
|
|
2826
2646
|
placement: placeEntryRef(rel, ".md", options),
|
|
2827
2647
|
rel
|
|
2828
2648
|
};
|
|
@@ -2906,14 +2726,26 @@ var obsidianSource = (options, ctx) => {
|
|
|
2906
2726
|
const vaultDir = resolve2(ctx.projectRoot, options.vault);
|
|
2907
2727
|
const exclude = new Set([...BLUME_IGNORE_DIRS, ...options.exclude ?? []]);
|
|
2908
2728
|
const load = async () => {
|
|
2909
|
-
const
|
|
2729
|
+
const skipped = [];
|
|
2730
|
+
const files = [];
|
|
2731
|
+
for (const rel of await walkVault(vaultDir, vaultDir, exclude)) {
|
|
2732
|
+
const unloadable = unloadablePathDiagnostic(rel, join5(vaultDir, rel));
|
|
2733
|
+
if (unloadable) {
|
|
2734
|
+
skipped.push(unloadable);
|
|
2735
|
+
} else {
|
|
2736
|
+
files.push(rel);
|
|
2737
|
+
}
|
|
2738
|
+
}
|
|
2910
2739
|
const read = await Promise.all(files.map((rel) => readNote(vaultDir, rel, options)));
|
|
2911
2740
|
const notes = read.filter((note) => note !== null);
|
|
2912
2741
|
const { index, pairs } = buildLinkIndex(notes, options);
|
|
2913
2742
|
const unresolved = noTargets();
|
|
2914
2743
|
const entries = pairs.map((pair) => noteToEntry(pair, index, options, unresolved));
|
|
2915
2744
|
return {
|
|
2916
|
-
diagnostics:
|
|
2745
|
+
diagnostics: [
|
|
2746
|
+
...skipped,
|
|
2747
|
+
...unresolvedDiagnostics(options.name, unresolved)
|
|
2748
|
+
],
|
|
2917
2749
|
entries
|
|
2918
2750
|
};
|
|
2919
2751
|
};
|
|
@@ -2956,6 +2788,7 @@ var obsidianSource = (options, ctx) => {
|
|
|
2956
2788
|
contentRoot: vaultDir,
|
|
2957
2789
|
load,
|
|
2958
2790
|
name: options.name,
|
|
2791
|
+
orderedNames: true,
|
|
2959
2792
|
prefix: options.prefix,
|
|
2960
2793
|
read,
|
|
2961
2794
|
staged: true,
|
|
@@ -2990,31 +2823,33 @@ var customBlock = (node, options) => {
|
|
|
2990
2823
|
}
|
|
2991
2824
|
return unsupported(`Lexical block${blockType ? `: ${blockType}` : ""}`, writesMdx(options.serializers));
|
|
2992
2825
|
};
|
|
2993
|
-
var
|
|
2994
|
-
var
|
|
2826
|
+
var inlineParts2 = (nodes, options) => nodes.flatMap((node) => inlineNodeParts2(node, options));
|
|
2827
|
+
var inlineNodeParts2 = (node, options) => {
|
|
2995
2828
|
switch (typeOf(node)) {
|
|
2996
2829
|
case "text": {
|
|
2997
|
-
return
|
|
2830
|
+
return [{ marks: marksOf2(node), text: asString(node.text) ?? "" }];
|
|
2998
2831
|
}
|
|
2999
2832
|
case "linebreak": {
|
|
3000
|
-
return `
|
|
3001
|
-
|
|
2833
|
+
return [{ markdown: `
|
|
2834
|
+
` }];
|
|
3002
2835
|
}
|
|
3003
2836
|
case "tab": {
|
|
3004
|
-
return "\t";
|
|
2837
|
+
return [{ markdown: "\t" }];
|
|
3005
2838
|
}
|
|
3006
2839
|
case "link":
|
|
3007
2840
|
case "autolink": {
|
|
3008
|
-
return
|
|
2841
|
+
return linkParts(inlineParts2(children2(node), options), asString(getPath(node, "fields.url")) ?? asString(node.url));
|
|
3009
2842
|
}
|
|
3010
2843
|
case "inlineBlock": {
|
|
3011
|
-
return customBlock(node, options);
|
|
2844
|
+
return [{ markdown: customBlock(node, options) }];
|
|
3012
2845
|
}
|
|
3013
2846
|
default: {
|
|
3014
|
-
return
|
|
2847
|
+
return inlineParts2(children2(node), options);
|
|
3015
2848
|
}
|
|
3016
2849
|
}
|
|
3017
2850
|
};
|
|
2851
|
+
var inlineText = (nodes, options) => guardBlockStart(renderInline(inlineParts2(nodes, options)));
|
|
2852
|
+
var blockText2 = (node, options) => inlineText(children2(node), options);
|
|
3018
2853
|
var renderUpload = (node, options) => {
|
|
3019
2854
|
const value = asObject(node.value);
|
|
3020
2855
|
const url = value ? asString(value.url) : undefined;
|
|
@@ -3045,7 +2880,7 @@ var renderList2 = (node, options) => {
|
|
|
3045
2880
|
if (listType === "check") {
|
|
3046
2881
|
check = item.checked === true ? "[x] " : "[ ] ";
|
|
3047
2882
|
}
|
|
3048
|
-
const line = `${check}${
|
|
2883
|
+
const line = `${check}${inlineText(inline, options)}`;
|
|
3049
2884
|
items.push(listItem(lastMarker, sub ? `${line}
|
|
3050
2885
|
${sub}` : line));
|
|
3051
2886
|
index += 1;
|
|
@@ -3056,14 +2891,14 @@ ${sub}` : line));
|
|
|
3056
2891
|
var renderBlock2 = (node, options) => {
|
|
3057
2892
|
switch (typeOf(node)) {
|
|
3058
2893
|
case "paragraph": {
|
|
3059
|
-
return
|
|
2894
|
+
return blockText2(node, options);
|
|
3060
2895
|
}
|
|
3061
2896
|
case "heading": {
|
|
3062
2897
|
const level = Number((asString(node.tag) ?? "h1").slice(1));
|
|
3063
|
-
return `${headingPrefix(level)}${
|
|
2898
|
+
return `${headingPrefix(level)}${blockText2(node, options)}`;
|
|
3064
2899
|
}
|
|
3065
2900
|
case "quote": {
|
|
3066
|
-
return blockquote(
|
|
2901
|
+
return blockquote(blockText2(node, options));
|
|
3067
2902
|
}
|
|
3068
2903
|
case "list": {
|
|
3069
2904
|
return renderList2(node, options);
|
|
@@ -3145,7 +2980,8 @@ var payloadSource = (options, ctx) => {
|
|
|
3145
2980
|
fetchEntries,
|
|
3146
2981
|
name: options.name,
|
|
3147
2982
|
pollInterval: options.pollInterval,
|
|
3148
|
-
prefix: options.prefix
|
|
2983
|
+
prefix: options.prefix,
|
|
2984
|
+
withContext: (next) => payloadSource(options, next)
|
|
3149
2985
|
}, ctx);
|
|
3150
2986
|
};
|
|
3151
2987
|
|
|
@@ -3161,47 +2997,49 @@ var HEADING_STYLES = new Map([
|
|
|
3161
2997
|
["h5", "##### "],
|
|
3162
2998
|
["h6", "###### "]
|
|
3163
2999
|
]);
|
|
3164
|
-
var
|
|
3165
|
-
const
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
break;
|
|
3176
|
-
}
|
|
3177
|
-
case "em": {
|
|
3178
|
-
text = `*${text}*`;
|
|
3179
|
-
break;
|
|
3180
|
-
}
|
|
3181
|
-
case "code": {
|
|
3182
|
-
text = `\`${text}\``;
|
|
3183
|
-
break;
|
|
3184
|
-
}
|
|
3185
|
-
case "strike-through": {
|
|
3186
|
-
text = `~~${text}~~`;
|
|
3187
|
-
break;
|
|
3188
|
-
}
|
|
3189
|
-
default: {
|
|
3190
|
-
const def = defs.get(mark);
|
|
3191
|
-
if (def?._type === "link") {
|
|
3192
|
-
link = def;
|
|
3193
|
-
}
|
|
3194
|
-
}
|
|
3195
|
-
}
|
|
3196
|
-
}
|
|
3197
|
-
return link?.href ? `[${text}](${link.href})` : text;
|
|
3000
|
+
var spanRun = (span) => {
|
|
3001
|
+
const marks = span.marks ?? [];
|
|
3002
|
+
return {
|
|
3003
|
+
marks: {
|
|
3004
|
+
bold: marks.includes("strong"),
|
|
3005
|
+
code: marks.includes("code"),
|
|
3006
|
+
italic: marks.includes("em"),
|
|
3007
|
+
strike: marks.includes("strike-through")
|
|
3008
|
+
},
|
|
3009
|
+
text: span.text ?? ""
|
|
3010
|
+
};
|
|
3198
3011
|
};
|
|
3199
3012
|
var renderChildren = (block) => {
|
|
3200
3013
|
const defs = new Map((block.markDefs ?? []).map((def) => [def._key, def]));
|
|
3201
|
-
|
|
3014
|
+
const linked = [];
|
|
3015
|
+
for (const span of block.children ?? []) {
|
|
3016
|
+
const link = (span.marks ?? []).map((mark) => defs.get(mark)).findLast((def) => def?._type === "link");
|
|
3017
|
+
const last = linked.at(-1);
|
|
3018
|
+
if (last && last.link === link) {
|
|
3019
|
+
last.runs.push(spanRun(span));
|
|
3020
|
+
} else {
|
|
3021
|
+
linked.push({ link, runs: [spanRun(span)] });
|
|
3022
|
+
}
|
|
3023
|
+
}
|
|
3024
|
+
return guardBlockStart(renderInline(linked.flatMap(({ link, runs }) => linkParts(runs, link?.href))));
|
|
3202
3025
|
};
|
|
3203
3026
|
var isAltText = (value) => typeof value === "string";
|
|
3204
|
-
var
|
|
3027
|
+
var listMarker = (block) => block.listItem === "number" ? "1." : "-";
|
|
3028
|
+
var listIndents = (blocks) => {
|
|
3029
|
+
const columns = [];
|
|
3030
|
+
return blocks.map((block) => {
|
|
3031
|
+
if (!block.listItem) {
|
|
3032
|
+
columns.length = 0;
|
|
3033
|
+
return 0;
|
|
3034
|
+
}
|
|
3035
|
+
const depth = Math.min(Math.max(0, (block.level ?? 1) - 1), columns.length);
|
|
3036
|
+
const indent = columns[depth - 1] ?? 0;
|
|
3037
|
+
columns.length = depth;
|
|
3038
|
+
columns.push(indent + listMarker(block).length + 1);
|
|
3039
|
+
return indent;
|
|
3040
|
+
});
|
|
3041
|
+
};
|
|
3042
|
+
var renderBlock3 = (block, options, indent) => {
|
|
3205
3043
|
const custom = options.serializers?.[block._type];
|
|
3206
3044
|
if (custom) {
|
|
3207
3045
|
return custom(block);
|
|
@@ -3216,9 +3054,7 @@ var renderBlock3 = (block, options) => {
|
|
|
3216
3054
|
}
|
|
3217
3055
|
const inline = renderChildren(block);
|
|
3218
3056
|
if (block.listItem) {
|
|
3219
|
-
|
|
3220
|
-
const marker = block.listItem === "number" ? "1." : "-";
|
|
3221
|
-
return `${indent}${marker} ${inline}`;
|
|
3057
|
+
return `${" ".repeat(indent)}${listMarker(block)} ${inline}`;
|
|
3222
3058
|
}
|
|
3223
3059
|
if (block.style === "blockquote") {
|
|
3224
3060
|
return `> ${inline}`;
|
|
@@ -3226,7 +3062,8 @@ var renderBlock3 = (block, options) => {
|
|
|
3226
3062
|
return `${HEADING_STYLES.get(block.style ?? "normal") ?? ""}${inline}`;
|
|
3227
3063
|
};
|
|
3228
3064
|
var portableTextToMarkdown = (blocks, options = {}) => {
|
|
3229
|
-
const
|
|
3065
|
+
const indents = listIndents(blocks);
|
|
3066
|
+
const lines = blocks.map((block, i) => renderBlock3(block, options, indents[i] ?? 0));
|
|
3230
3067
|
const out = [];
|
|
3231
3068
|
for (let i = 0;i < lines.length; i += 1) {
|
|
3232
3069
|
const line = lines[i] ?? "";
|
|
@@ -3335,37 +3172,44 @@ var sanitySource = (options, ctx) => {
|
|
|
3335
3172
|
prefix: options.prefix,
|
|
3336
3173
|
read,
|
|
3337
3174
|
staged: true,
|
|
3338
|
-
watch: options.pollInterval ? pollingWatch(() => load(true), options.pollInterval, () => load()) : undefined
|
|
3175
|
+
watch: options.pollInterval ? pollingWatch(() => load(true), options.pollInterval, () => load()) : undefined,
|
|
3176
|
+
withContext: (next) => sanitySource(options, next)
|
|
3339
3177
|
};
|
|
3340
3178
|
};
|
|
3341
3179
|
|
|
3342
3180
|
// src/core/sources/strapi-blocks.ts
|
|
3343
3181
|
var children3 = (node) => objectsIn(node.children);
|
|
3344
3182
|
var typeOf2 = (node) => asString(node.type) ?? "";
|
|
3345
|
-
var
|
|
3346
|
-
var
|
|
3183
|
+
var inlineParts3 = (nodes) => nodes.flatMap((node) => inlineNodeParts3(node));
|
|
3184
|
+
var inlineNodeParts3 = (node) => {
|
|
3347
3185
|
switch (typeOf2(node)) {
|
|
3348
3186
|
case "text": {
|
|
3349
|
-
return
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3187
|
+
return [
|
|
3188
|
+
{
|
|
3189
|
+
marks: {
|
|
3190
|
+
bold: node.bold === true,
|
|
3191
|
+
code: node.code === true,
|
|
3192
|
+
italic: node.italic === true,
|
|
3193
|
+
strike: node.strikethrough === true
|
|
3194
|
+
},
|
|
3195
|
+
text: asString(node.text) ?? ""
|
|
3196
|
+
}
|
|
3197
|
+
];
|
|
3355
3198
|
}
|
|
3356
3199
|
case "link": {
|
|
3357
|
-
return
|
|
3200
|
+
return linkParts(inlineParts3(children3(node)), asString(node.url));
|
|
3358
3201
|
}
|
|
3359
3202
|
default: {
|
|
3360
|
-
return
|
|
3203
|
+
return inlineParts3(children3(node));
|
|
3361
3204
|
}
|
|
3362
3205
|
}
|
|
3363
3206
|
};
|
|
3207
|
+
var blockText3 = (nodes) => guardBlockStart(renderInline(inlineParts3(nodes)));
|
|
3364
3208
|
var renderList3 = (node) => {
|
|
3365
3209
|
const ordered = asString(node.format) === "ordered";
|
|
3366
3210
|
return children3(node).map((item, index) => {
|
|
3367
3211
|
const kids = children3(item);
|
|
3368
|
-
const line =
|
|
3212
|
+
const line = blockText3(kids.filter((kid) => typeOf2(kid) !== "list"));
|
|
3369
3213
|
const sub = kids.filter((kid) => typeOf2(kid) === "list").map((list) => renderList3(list)).join(`
|
|
3370
3214
|
`);
|
|
3371
3215
|
const body = sub ? `${line}
|
|
@@ -3385,13 +3229,13 @@ var renderImage = (node, options) => {
|
|
|
3385
3229
|
var renderBlock4 = (node, options) => {
|
|
3386
3230
|
switch (typeOf2(node)) {
|
|
3387
3231
|
case "paragraph": {
|
|
3388
|
-
return
|
|
3232
|
+
return blockText3(children3(node));
|
|
3389
3233
|
}
|
|
3390
3234
|
case "heading": {
|
|
3391
|
-
return `${headingPrefix(asNumber(node.level) ?? 1)}${
|
|
3235
|
+
return `${headingPrefix(asNumber(node.level) ?? 1)}${blockText3(children3(node))}`;
|
|
3392
3236
|
}
|
|
3393
3237
|
case "quote": {
|
|
3394
|
-
return blockquote(
|
|
3238
|
+
return blockquote(blockText3(children3(node)));
|
|
3395
3239
|
}
|
|
3396
3240
|
case "list": {
|
|
3397
3241
|
return renderList3(node);
|
|
@@ -3491,7 +3335,8 @@ var strapiSource = (options, ctx) => {
|
|
|
3491
3335
|
fetchEntries,
|
|
3492
3336
|
name: options.name,
|
|
3493
3337
|
pollInterval: options.pollInterval,
|
|
3494
|
-
prefix: options.prefix
|
|
3338
|
+
prefix: options.prefix,
|
|
3339
|
+
withContext: (next) => strapiSource(options, next)
|
|
3495
3340
|
}, ctx);
|
|
3496
3341
|
};
|
|
3497
3342
|
|
|
@@ -3509,10 +3354,18 @@ var uniqueNamer = () => {
|
|
|
3509
3354
|
return name;
|
|
3510
3355
|
};
|
|
3511
3356
|
};
|
|
3512
|
-
var
|
|
3357
|
+
var snapshotKey = (adapter, runtime) => {
|
|
3358
|
+
const mode = runtime.preview ? "preview" : "published";
|
|
3359
|
+
if (adapter.kind === "custom") {
|
|
3360
|
+
return mode;
|
|
3361
|
+
}
|
|
3362
|
+
const { pollInterval: _paced, ...fetched } = adapter.options;
|
|
3363
|
+
return `${mode}-${hashText(JSON.stringify(fetched))}`;
|
|
3364
|
+
};
|
|
3365
|
+
var sourceContext = (context, name, runtime, snapshot) => ({
|
|
3513
3366
|
assetsBaseUrl: `/blume-assets/${name}`,
|
|
3514
3367
|
assetsDir: join7(context.outDir, "public", "blume-assets", name),
|
|
3515
|
-
cacheDir: join7(context.outDir, "cache", name),
|
|
3368
|
+
cacheDir: snapshot === undefined ? join7(context.outDir, "cache", name) : join7(context.outDir, "cache", name, snapshot),
|
|
3516
3369
|
mode: runtime.mode,
|
|
3517
3370
|
preview: runtime.preview,
|
|
3518
3371
|
projectRoot: context.root,
|
|
@@ -3523,29 +3376,30 @@ var typeFrontmatterKeys = (config) => Object.fromEntries(Object.entries(config.c
|
|
|
3523
3376
|
Object.keys(def.frontmatter)
|
|
3524
3377
|
]));
|
|
3525
3378
|
var buildSource = (adapter, name, config, context, runtime) => {
|
|
3379
|
+
const ctx = () => sourceContext(context, name, runtime, snapshotKey(adapter, runtime));
|
|
3526
3380
|
switch (adapter.kind) {
|
|
3527
3381
|
case "filesystem": {
|
|
3528
3382
|
const { pollInterval: _ignored, ...options } = adapter.options;
|
|
3529
3383
|
return filesystemSource({ ...options, name, projectRoot: context.root });
|
|
3530
3384
|
}
|
|
3531
3385
|
case "custom": {
|
|
3532
|
-
const source = adapter.options;
|
|
3386
|
+
const source = adapter.options.withContext?.(ctx()) ?? adapter.options;
|
|
3533
3387
|
return source.name === name ? source : { ...source, name };
|
|
3534
3388
|
}
|
|
3535
3389
|
case "sanity": {
|
|
3536
|
-
return sanitySource({ ...adapter.options, name },
|
|
3390
|
+
return sanitySource({ ...adapter.options, name }, ctx());
|
|
3537
3391
|
}
|
|
3538
3392
|
case "notion": {
|
|
3539
|
-
return notionSource({ ...adapter.options, name },
|
|
3393
|
+
return notionSource({ ...adapter.options, name }, ctx());
|
|
3540
3394
|
}
|
|
3541
3395
|
case "contentful": {
|
|
3542
|
-
return contentfulSource({ ...adapter.options, name },
|
|
3396
|
+
return contentfulSource({ ...adapter.options, name }, ctx());
|
|
3543
3397
|
}
|
|
3544
3398
|
case "payload": {
|
|
3545
|
-
return payloadSource({ ...adapter.options, name },
|
|
3399
|
+
return payloadSource({ ...adapter.options, name }, ctx());
|
|
3546
3400
|
}
|
|
3547
3401
|
case "strapi": {
|
|
3548
|
-
return strapiSource({ ...adapter.options, name },
|
|
3402
|
+
return strapiSource({ ...adapter.options, name }, ctx());
|
|
3549
3403
|
}
|
|
3550
3404
|
case "obsidian": {
|
|
3551
3405
|
const { pollInterval: _ignored, ...options } = adapter.options;
|
|
@@ -3557,22 +3411,22 @@ var buildSource = (adapter, name, config, context, runtime) => {
|
|
|
3557
3411
|
name,
|
|
3558
3412
|
typeFrontmatterKeys: typeFrontmatterKeys(config),
|
|
3559
3413
|
versions: config.versions
|
|
3560
|
-
},
|
|
3414
|
+
}, ctx());
|
|
3561
3415
|
}
|
|
3562
3416
|
case "github-releases": {
|
|
3563
|
-
return githubReleasesSource({ ...adapter.options, name },
|
|
3417
|
+
return githubReleasesSource({ ...adapter.options, name, site: config.deployment.options.site }, ctx());
|
|
3564
3418
|
}
|
|
3565
3419
|
default: {
|
|
3566
3420
|
break;
|
|
3567
3421
|
}
|
|
3568
3422
|
}
|
|
3569
|
-
return mdxRemoteSource({ ...adapter.options, name },
|
|
3423
|
+
return mdxRemoteSource({ ...adapter.options, name }, ctx());
|
|
3570
3424
|
};
|
|
3571
3425
|
var baseName = (adapter) => {
|
|
3572
3426
|
if (adapter.kind === "custom") {
|
|
3573
3427
|
return adapter.options.name;
|
|
3574
3428
|
}
|
|
3575
|
-
return adapter.options.prefix ?? adapter.kind;
|
|
3429
|
+
return trimChar(adapter.options.prefix ?? "", "/") || adapter.kind;
|
|
3576
3430
|
};
|
|
3577
3431
|
var resolveSources = (config, context, runtime) => {
|
|
3578
3432
|
const nameFor = uniqueNamer();
|
|
@@ -3640,6 +3494,7 @@ var normalizeLoadedEntries = (loaded, config) => {
|
|
|
3640
3494
|
source: {
|
|
3641
3495
|
monolingual: source.monolingual,
|
|
3642
3496
|
name: source.name,
|
|
3497
|
+
orderedNames: source.orderedNames,
|
|
3643
3498
|
prefix: source.prefix,
|
|
3644
3499
|
staged: source.staged
|
|
3645
3500
|
},
|
|
@@ -3651,12 +3506,24 @@ var normalizeLoadedEntries = (loaded, config) => {
|
|
|
3651
3506
|
}
|
|
3652
3507
|
pages.push(...normalized.pages);
|
|
3653
3508
|
allDiagnostics.push(...normalized.diagnostics);
|
|
3509
|
+
if (normalized.pages.length > 0) {
|
|
3510
|
+
allDiagnostics.push(...unknownDirectiveDiagnostics(entry, source.name));
|
|
3511
|
+
}
|
|
3654
3512
|
}
|
|
3655
3513
|
}
|
|
3656
3514
|
return { diagnostics: allDiagnostics, droppedPages, pages };
|
|
3657
3515
|
};
|
|
3516
|
+
var gitContentRoots = (sources, gitRoot) => {
|
|
3517
|
+
if (gitRoot === null) {
|
|
3518
|
+
return [];
|
|
3519
|
+
}
|
|
3520
|
+
const top = realPath(gitRoot);
|
|
3521
|
+
return sources.flatMap((source) => source.contentRoot ? [source.contentRoot] : []).filter((dir) => isWithin(top, realPath(dir)));
|
|
3522
|
+
};
|
|
3658
3523
|
var isLogoShorthand = (logo) => typeof logo === "string";
|
|
3659
3524
|
var logoHref = (logo) => logo === undefined || isLogoShorthand(logo) ? "/" : logo.href ?? "/";
|
|
3525
|
+
var isBannerShorthand = (banner) => typeof banner === "string";
|
|
3526
|
+
var bannerLinkHref = (banner) => banner === undefined || isBannerShorthand(banner) ? undefined : banner.link?.href;
|
|
3660
3527
|
var scanProject = async (root, options = {}) => {
|
|
3661
3528
|
const mode = options.mode ?? "dev";
|
|
3662
3529
|
const preview = options.preview ?? false;
|
|
@@ -3675,7 +3542,14 @@ var scanProject = async (root, options = {}) => {
|
|
|
3675
3542
|
for (const source of sources) {
|
|
3676
3543
|
source.validate?.();
|
|
3677
3544
|
}
|
|
3678
|
-
const metaSources = sources.flatMap((source) => source.staged || !source.contentRoot ? [] : [
|
|
3545
|
+
const metaSources = sources.flatMap((source) => source.staged || !source.contentRoot ? [] : [
|
|
3546
|
+
{
|
|
3547
|
+
exclude: source.exclude,
|
|
3548
|
+
include: source.include,
|
|
3549
|
+
prefix: source.prefix,
|
|
3550
|
+
root: source.contentRoot
|
|
3551
|
+
}
|
|
3552
|
+
]);
|
|
3679
3553
|
const localeDirs = config.i18n && config.i18n.parser === "dir" ? config.i18n.locales.flatMap((locale) => locale.code === config.i18n?.defaultLocale ? [] : [locale.code]) : undefined;
|
|
3680
3554
|
const [loaded, folderMeta] = await Promise.all([
|
|
3681
3555
|
Promise.all(sources.map(async (source) => ({ source, ...await source.load() }))),
|
|
@@ -3717,7 +3591,7 @@ var scanProject = async (root, options = {}) => {
|
|
|
3717
3591
|
if (lastModified.enabled && lastModified.source === "git") {
|
|
3718
3592
|
const fsPaths = pages.map((page) => page.sourcePath).filter((path) => path !== undefined);
|
|
3719
3593
|
const gitRoot = gitRepositoryRoot(context.root);
|
|
3720
|
-
const contentRoots = sources
|
|
3594
|
+
const contentRoots = gitContentRoots(sources, gitRoot);
|
|
3721
3595
|
const gitTimes = gitLastModifiedTimes(context.root, contentRoots, fsPaths, gitRoot);
|
|
3722
3596
|
for (const page of pages) {
|
|
3723
3597
|
if (!page.lastModified && page.sourcePath) {
|
|
@@ -3729,6 +3603,7 @@ var scanProject = async (root, options = {}) => {
|
|
|
3729
3603
|
}
|
|
3730
3604
|
const customPages = context.pagesRoot ? await discoverPages(context.pagesRoot) : [];
|
|
3731
3605
|
const graph = buildContentGraph(pages, {
|
|
3606
|
+
bannerHref: bannerLinkHref(config.banner),
|
|
3732
3607
|
basePath: config.basePath,
|
|
3733
3608
|
brandHref: logoHref(config.logo),
|
|
3734
3609
|
extraRoutes: new Set([
|
|
@@ -3766,7 +3641,7 @@ var scanProject = async (root, options = {}) => {
|
|
|
3766
3641
|
};
|
|
3767
3642
|
};
|
|
3768
3643
|
|
|
3769
|
-
export { validateSearchPopularIcons, validateNavTargets, contentIndexable, buildManifest, isWithin, scanProject };
|
|
3644
|
+
export { directiveSource, validateSearchPopularIcons, validateNavTargets, contentIndexable, buildManifest, findFolderMetaFiles, isWithin, scanProject };
|
|
3770
3645
|
|
|
3771
|
-
//# debugId=
|
|
3772
|
-
//# sourceMappingURL=chunk-
|
|
3646
|
+
//# debugId=B7A86608D56AB00864756E2164756E21
|
|
3647
|
+
//# sourceMappingURL=chunk-j85vccga.js.map
|