blume 2.0.3 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -0
- package/CHANGELOG.md +142 -0
- package/README.md +1 -1
- package/dist/cli/{chunk-5f86nr5m.js → chunk-073rdvgb.js} +21 -48
- package/dist/cli/{chunk-5f86nr5m.js.map → chunk-073rdvgb.js.map} +4 -5
- package/dist/cli/{chunk-ga0pf4aj.js → chunk-0n9xkp3d.js} +12 -3
- package/dist/cli/{chunk-ga0pf4aj.js.map → chunk-0n9xkp3d.js.map} +3 -3
- package/dist/cli/chunk-150jk7km.js +52 -0
- package/dist/cli/chunk-150jk7km.js.map +10 -0
- package/dist/cli/{chunk-9t7a85s3.js → chunk-313vnn40.js} +30 -19
- package/dist/cli/chunk-313vnn40.js.map +10 -0
- package/dist/cli/{chunk-tkacnehg.js → chunk-3v3ffbrj.js} +2 -2
- package/dist/cli/{chunk-q58y5e6a.js → chunk-3x6x3pph.js} +46 -24
- package/dist/cli/chunk-3x6x3pph.js.map +10 -0
- package/dist/cli/{chunk-1d7ve1dm.js → chunk-42t4jxdx.js} +37 -5
- package/dist/cli/chunk-42t4jxdx.js.map +12 -0
- package/dist/cli/{chunk-8ktnccpt.js → chunk-54ztw1nj.js} +21 -2
- package/dist/cli/chunk-54ztw1nj.js.map +10 -0
- package/dist/cli/{chunk-hm3vjy5s.js → chunk-5vjtgs6e.js} +28 -10
- package/dist/cli/{chunk-hm3vjy5s.js.map → chunk-5vjtgs6e.js.map} +4 -4
- package/dist/cli/chunk-66w9j7p6.js +322 -0
- package/dist/cli/chunk-66w9j7p6.js.map +14 -0
- package/dist/cli/{chunk-2hsdwb9n.js → chunk-7ppf1rva.js} +34 -18
- package/dist/cli/chunk-7ppf1rva.js.map +10 -0
- package/dist/cli/{chunk-r9rcc4w7.js → chunk-8y2kmjv8.js} +7 -7
- package/dist/cli/{chunk-r20tn01b.js → chunk-c1y538kd.js} +8 -2
- package/dist/cli/{chunk-r20tn01b.js.map → chunk-c1y538kd.js.map} +3 -3
- package/dist/cli/{chunk-2eytanqx.js → chunk-c887fj0s.js} +2 -2
- package/dist/cli/{chunk-p3v96n38.js → chunk-cfyg47zg.js} +16 -6
- package/dist/cli/chunk-cfyg47zg.js.map +10 -0
- package/dist/cli/chunk-cm89scdv.js +443 -0
- package/dist/cli/chunk-cm89scdv.js.map +11 -0
- package/dist/cli/{chunk-akbpwfxc.js → chunk-dzwehpy7.js} +2 -2
- package/dist/cli/{chunk-wrr3j9w9.js → chunk-e6atmn4h.js} +299 -72
- package/dist/cli/chunk-e6atmn4h.js.map +36 -0
- package/dist/cli/{chunk-tzmab476.js → chunk-e8xw9qkh.js} +8 -6
- package/dist/cli/{chunk-tzmab476.js.map → chunk-e8xw9qkh.js.map} +3 -3
- package/dist/cli/{chunk-6dsbexzp.js → chunk-e9q7a2ak.js} +17 -15
- package/dist/cli/{chunk-6dsbexzp.js.map → chunk-e9q7a2ak.js.map} +2 -2
- package/dist/cli/{chunk-pv29h0wf.js → chunk-ehweg4fr.js} +5155 -1249
- package/dist/cli/chunk-ehweg4fr.js.map +218 -0
- package/dist/cli/{chunk-c8chx29p.js → chunk-ep6nd0rn.js} +390 -318
- package/dist/cli/chunk-ep6nd0rn.js.map +36 -0
- package/dist/cli/{chunk-p73c0m7w.js → chunk-fdrkhpjy.js} +18 -15
- package/dist/cli/{chunk-p73c0m7w.js.map → chunk-fdrkhpjy.js.map} +3 -3
- package/dist/cli/{chunk-2z928egk.js → chunk-ft9vfys6.js} +5 -5
- package/dist/cli/{chunk-5m5nmvyq.js → chunk-gb420vvz.js} +316 -79
- package/dist/cli/chunk-gb420vvz.js.map +17 -0
- package/dist/cli/{chunk-vg9r4eb9.js → chunk-hebn0tpx.js} +86 -13
- package/dist/cli/chunk-hebn0tpx.js.map +14 -0
- package/dist/cli/{chunk-35d4wj9f.js → chunk-htrwgabr.js} +41 -23
- package/dist/cli/chunk-htrwgabr.js.map +15 -0
- package/dist/cli/{chunk-g4hq16wv.js → chunk-hx3xqnk9.js} +16 -14
- package/dist/cli/{chunk-g4hq16wv.js.map → chunk-hx3xqnk9.js.map} +2 -2
- package/dist/cli/chunk-j134vrp2.js +65 -0
- package/dist/cli/chunk-j134vrp2.js.map +10 -0
- package/dist/cli/{chunk-a58773jm.js → chunk-kma9f6sf.js} +2 -2
- package/dist/cli/chunk-kwrg63tm.js +31 -0
- package/dist/cli/chunk-kwrg63tm.js.map +10 -0
- package/dist/cli/{chunk-ey84smr6.js → chunk-mrcccgnh.js} +6 -6
- package/dist/cli/{chunk-ey84smr6.js.map → chunk-mrcccgnh.js.map} +1 -1
- package/dist/cli/{chunk-yfyb25rh.js → chunk-n0v7m8ry.js} +24 -8
- package/dist/cli/chunk-n0v7m8ry.js.map +14 -0
- package/dist/cli/{chunk-j85vccga.js → chunk-ncj7w596.js} +576 -367
- package/dist/cli/chunk-ncj7w596.js.map +35 -0
- package/dist/cli/{chunk-5xvm6tfj.js → chunk-nq1d20w2.js} +17 -15
- package/dist/cli/{chunk-5xvm6tfj.js.map → chunk-nq1d20w2.js.map} +2 -2
- package/dist/cli/{chunk-pehfxfta.js → chunk-nrns10mj.js} +6 -98
- package/dist/cli/chunk-nrns10mj.js.map +10 -0
- package/dist/cli/{chunk-crgn1q09.js → chunk-sds923fa.js} +4 -4
- package/dist/cli/chunk-t2m5j4pr.js +104 -0
- package/dist/cli/chunk-t2m5j4pr.js.map +11 -0
- package/dist/cli/{chunk-acanzt5p.js → chunk-tdqhyxfz.js} +6 -6
- package/dist/cli/chunk-tphac74f.js +126 -0
- package/dist/cli/chunk-tphac74f.js.map +11 -0
- package/dist/cli/chunk-w1r4vase.js +18 -0
- package/dist/cli/chunk-w1r4vase.js.map +10 -0
- package/dist/cli/{chunk-3em5wd2y.js → chunk-zccbjcj0.js} +4 -3
- package/dist/cli/{chunk-3em5wd2y.js.map → chunk-zccbjcj0.js.map} +2 -2
- package/dist/cli/index.js +31 -20
- package/dist/cli/index.js.map +5 -5
- package/dist/types/ai/agent-surface.d.ts +8 -7
- package/dist/types/ai/ai-catalog.d.ts +7 -0
- package/dist/types/ai/ask-context.d.ts +26 -0
- package/dist/types/ai/ask.d.ts +271 -58
- package/dist/types/ai/component-markdown.d.ts +2 -0
- package/dist/types/ai/index.d.ts +2 -2
- package/dist/types/ai/openapi-components.d.ts +4 -1
- package/dist/types/ai/site-skill.d.ts +26 -0
- package/dist/types/ai/skills.d.ts +16 -0
- package/dist/types/astro/integration.d.ts +9 -0
- package/dist/types/astro/markdown-negotiation.d.ts +3 -0
- package/dist/types/astro/pages.d.ts +10 -0
- package/dist/types/captcha/hcaptcha.d.ts +27 -0
- package/dist/types/captcha/index.d.ts +28 -0
- package/dist/types/captcha/schema.d.ts +29 -0
- package/dist/types/captcha/turnstile.d.ts +28 -0
- package/dist/types/cli/init/scaffold.d.ts +1 -1
- package/dist/types/components/content/api-field.d.ts +62 -0
- package/dist/types/components/content/api-page.d.ts +100 -0
- package/dist/types/components/layout/nav-utils.d.ts +26 -0
- package/dist/types/components/openapi/code-samples.d.ts +29 -0
- package/dist/types/components/openapi/helpers.d.ts +158 -0
- package/dist/types/components/openapi/security.d.ts +95 -0
- package/dist/types/components/openapi/snippets.d.ts +60 -0
- package/dist/types/consent/ethyca.d.ts +48 -0
- package/dist/types/consent/index.d.ts +37 -0
- package/dist/types/consent/native.d.ts +28 -0
- package/dist/types/consent/osano.d.ts +42 -0
- package/dist/types/consent/schema.d.ts +110 -0
- package/dist/types/core/changelog-index.d.ts +8 -0
- package/dist/types/core/config-input.d.ts +217 -23
- package/dist/types/core/data.d.ts +53 -4
- package/dist/types/core/footer.d.ts +8 -0
- package/dist/types/core/i18n-ui.d.ts +88 -0
- package/dist/types/core/includes.d.ts +8 -2
- package/dist/types/core/links.d.ts +8 -0
- package/dist/types/core/localizable.d.ts +7 -0
- package/dist/types/core/page-modes.d.ts +29 -0
- package/dist/types/core/probe.d.ts +2 -0
- package/dist/types/core/project-graph.d.ts +6 -0
- package/dist/types/core/redirect-patterns.d.ts +152 -0
- package/dist/types/core/related.d.ts +40 -0
- package/dist/types/core/schema.d.ts +670 -56
- package/dist/types/core/sources/cache.d.ts +3 -0
- package/dist/types/core/sources/contentful-rich-text.d.ts +11 -2
- package/dist/types/core/sources/contentful.d.ts +17 -1
- package/dist/types/core/sources/lexical.d.ts +5 -0
- package/dist/types/core/sources/normalize.d.ts +20 -1
- package/dist/types/core/sources/read.d.ts +5 -0
- package/dist/types/core/sources/remote.d.ts +37 -10
- package/dist/types/core/sources/sanity.d.ts +1 -1
- package/dist/types/core/types.d.ts +18 -1
- package/dist/types/core/variables.d.ts +42 -0
- package/dist/types/deploy/adapter-output.d.ts +2 -1
- package/dist/types/deploy/adapters/cloudflare.d.ts +7 -5
- package/dist/types/deploy/adapters/node.d.ts +58 -23
- package/dist/types/deploy/adapters/registry.d.ts +10 -0
- package/dist/types/deploy/adapters/types.d.ts +3 -2
- package/dist/types/deploy/node-headers.d.ts +13 -2
- package/dist/types/deploy/platforms/cloudflare.d.ts +15 -7
- package/dist/types/deploy/platforms/netlify.d.ts +7 -0
- package/dist/types/deploy/platforms/node.d.ts +3 -1
- package/dist/types/deploy/platforms/types.d.ts +18 -7
- package/dist/types/deploy/platforms/vercel.d.ts +26 -1
- package/dist/types/deploy/redirects.d.ts +55 -11
- package/dist/types/deploy/sitemap.d.ts +2 -1
- package/dist/types/deploy/vercel-negotiation.d.ts +51 -21
- package/dist/types/markdown/code-title.d.ts +17 -0
- package/dist/types/markdown/features.d.ts +3 -2
- package/dist/types/narration/build.d.ts +70 -0
- package/dist/types/narration/provider.d.ts +26 -0
- package/dist/types/narration/script.d.ts +154 -0
- package/dist/types/openapi/checks.d.ts +27 -0
- package/dist/types/openapi/graphql.d.ts +6 -0
- package/dist/types/openapi/model.d.ts +27 -10
- package/dist/types/openapi/overlay.d.ts +54 -0
- package/dist/types/openapi/parse.d.ts +16 -0
- package/dist/types/openapi/references.d.ts +30 -4
- package/dist/types/ratelimit/cloudflare.d.ts +39 -0
- package/dist/types/ratelimit/index.d.ts +27 -0
- package/dist/types/ratelimit/memory.d.ts +36 -0
- package/dist/types/ratelimit/schema.d.ts +119 -0
- package/dist/types/ratelimit/upstash.d.ts +46 -0
- package/dist/types/ratelimit/wrangler.d.ts +23 -0
- package/dist/types/reference/asyncapi.d.ts +10 -10
- package/dist/types/reference/graphql.d.ts +89 -11
- package/dist/types/reference/index.d.ts +1 -1
- package/dist/types/reference/openapi.d.ts +33 -12
- package/dist/types/reference/options.d.ts +82 -6
- package/dist/types/reference/scalar.d.ts +13 -0
- package/dist/types/reference/schema.d.ts +144 -36
- package/dist/types/search/adapters/registry.d.ts +3 -0
- package/dist/types/search/adapters/typesense.d.ts +14 -4
- package/dist/types/search/build.d.ts +3 -1
- package/dist/types/search/documents.d.ts +12 -1
- package/dist/types/search/orama-index.d.ts +13 -9
- package/dist/types/search/sync/algolia.d.ts +5 -2
- package/dist/types/search/sync/index.d.ts +3 -1
- package/dist/types/search/sync/typesense.d.ts +11 -7
- package/dist/types/seo/metatags.d.ts +20 -0
- package/dist/types/sources/contentful.d.ts +16 -0
- package/dist/types/sources/github-releases.d.ts +8 -1
- package/dist/types/sources/payload.d.ts +2 -0
- package/dist/types/sources/registry.d.ts +54 -0
- package/dist/types/sources/shared.d.ts +3 -0
- package/dist/types/sources/strapi.d.ts +2 -0
- package/docs/01-quickstart.mdx +4 -2
- package/docs/02-deployment.mdx +71 -17
- package/docs/03-upgrading.mdx +4 -4
- package/docs/04-migrating.mdx +1 -1
- package/docs/advanced/changelog.mdx +13 -2
- package/docs/advanced/skills.mdx +15 -1
- package/docs/cli/audit.mdx +51 -8
- package/docs/cli/doctor.mdx +5 -1
- package/docs/cli/evals.mdx +4 -4
- package/docs/cli/index.mdx +1 -0
- package/docs/cli/translate.mdx +1 -0
- package/docs/cli/validate.mdx +4 -3
- package/docs/configuration/analytics.mdx +3 -1
- package/docs/configuration/assistant.mdx +194 -38
- package/docs/configuration/consent.mdx +100 -0
- package/docs/configuration/customization.mdx +8 -6
- package/docs/configuration/export.mdx +5 -3
- package/docs/configuration/index.mdx +64 -5
- package/docs/configuration/meta.ts +3 -0
- package/docs/configuration/narration.mdx +119 -0
- package/docs/configuration/rate-limiting.mdx +90 -0
- package/docs/configuration/search.mdx +63 -12
- package/docs/configuration/theming.mdx +3 -1
- package/docs/content/components.mdx +108 -2
- package/docs/content/frontmatter.mdx +80 -2
- package/docs/content/i18n.mdx +39 -4
- package/docs/content/includes.mdx +16 -0
- package/docs/content/meta.mdx +1 -0
- package/docs/content/meta.ts +1 -0
- package/docs/content/navigation.mdx +32 -10
- package/docs/content/sources/contentful.mdx +35 -0
- package/docs/content/sources/custom.mdx +43 -0
- package/docs/content/sources/github-releases.mdx +39 -0
- package/docs/content/sources/index.mdx +91 -0
- package/docs/content/sources/meta.ts +16 -0
- package/docs/content/sources/notion.mdx +32 -0
- package/docs/content/sources/obsidian.mdx +37 -0
- package/docs/content/sources/payload.mdx +31 -0
- package/docs/content/sources/remote-mdx.mdx +44 -0
- package/docs/content/sources/sanity.mdx +29 -0
- package/docs/content/sources/strapi.mdx +32 -0
- package/docs/content/syntax.mdx +69 -4
- package/docs/content/variables.mdx +41 -0
- package/docs/discoverability/agent-discovery.mdx +29 -2
- package/docs/discoverability/index.mdx +2 -2
- package/docs/discoverability/json-api.mdx +2 -0
- package/docs/discoverability/llms-txt.mdx +2 -2
- package/docs/discoverability/markdown.mdx +3 -1
- package/docs/discoverability/mcp.mdx +4 -0
- package/docs/discoverability/metadata.mdx +17 -0
- package/docs/discoverability/sitemap-and-robots.mdx +1 -1
- package/docs/references/api-pages.mdx +74 -0
- package/docs/references/asyncapi.mdx +4 -2
- package/docs/references/graphql.mdx +14 -2
- package/docs/references/meta.ts +1 -1
- package/docs/references/openapi.mdx +148 -7
- package/docs/references/scalar.mdx +3 -1
- package/package.json +43 -8
- package/skills/blume/SKILL.md +3 -0
- package/skills/blume-migrate/SKILL.md +6 -6
- package/skills/blume-migrate/references/docusaurus.md +7 -7
- package/skills/blume-migrate/references/fumadocs.md +17 -13
- package/skills/blume-migrate/references/mintlify.md +37 -19
- package/skills/blume-migrate/references/nextra.md +10 -7
- package/skills/blume-migrate/references/starlight.md +11 -8
- package/skills/blume-migrate/scripts/mintlify-codemod.mjs +60 -14
- package/skills/blume-write-skill/SKILL.md +82 -0
- package/src/ai/agent-readability.ts +2 -1
- package/src/ai/agent-surface.ts +9 -7
- package/src/ai/ai-catalog.ts +6 -3
- package/src/ai/ask-context.ts +103 -20
- package/src/ai/ask-data.ts +6 -0
- package/src/ai/ask-limits.ts +13 -0
- package/src/ai/ask-tools.ts +142 -0
- package/src/ai/ask.ts +354 -76
- package/src/ai/changelog-markdown.ts +11 -6
- package/src/ai/component-markdown.ts +76 -1
- package/src/ai/cors.ts +14 -3
- package/src/ai/index.ts +12 -0
- package/src/ai/llms.ts +6 -2
- package/src/ai/markdown.ts +2 -1
- package/src/ai/mcp/data.ts +6 -0
- package/src/ai/mcp/query.ts +14 -6
- package/src/ai/openapi-components.ts +36 -6
- package/src/ai/relative-links.ts +4 -38
- package/src/ai/site-skill.ts +274 -0
- package/src/ai/skills.ts +35 -2
- package/src/ai/write-skill.ts +97 -0
- package/src/astro/generate.ts +210 -66
- package/src/astro/index.ts +1 -0
- package/src/astro/integration.ts +42 -4
- package/src/astro/markdown-negotiation.ts +3 -0
- package/src/astro/module-types.ts +9 -1
- package/src/astro/pages.ts +23 -0
- package/src/astro/templates.ts +406 -108
- package/src/astro/variables.ts +31 -0
- package/src/audit/catalog.ts +38 -3
- package/src/audit/checks/contrast.ts +183 -0
- package/src/audit/checks/i18n.ts +2 -3
- package/src/audit/checks/indexability.ts +2 -3
- package/src/audit/checks/links.ts +19 -13
- package/src/audit/checks/network.ts +110 -6
- package/src/audit/checks/redirects.ts +6 -4
- package/src/audit/checks/robots.ts +58 -2
- package/src/audit/checks/sitemap.ts +2 -3
- package/src/audit/redirects.ts +46 -15
- package/src/audit/run.ts +5 -0
- package/src/audit/types.ts +4 -1
- package/src/audit/url.ts +14 -5
- package/src/blume-modules.d.ts +12 -1
- package/src/captcha/client.ts +152 -0
- package/src/captcha/hcaptcha.ts +36 -0
- package/src/captcha/index.ts +28 -0
- package/src/captcha/schema.ts +32 -0
- package/src/captcha/turnstile.ts +38 -0
- package/src/captcha/verify.ts +71 -0
- package/src/cli/args.ts +51 -0
- package/src/cli/build-failure.ts +23 -0
- package/src/cli/command-meta.ts +5 -0
- package/src/cli/commands/audit.ts +10 -1
- package/src/cli/commands/dev.ts +18 -2
- package/src/cli/commands/doctor.ts +67 -28
- package/src/cli/commands/eval.ts +36 -4
- package/src/cli/commands/init.ts +6 -4
- package/src/cli/commands/skill.ts +96 -0
- package/src/cli/commands/validate.ts +10 -1
- package/src/cli/index.ts +5 -0
- package/src/cli/init/scaffold.ts +3 -3
- package/src/cli/prepare.ts +6 -3
- package/src/cli/required-secrets.ts +72 -30
- package/src/components/BlumePage.astro +2 -0
- package/src/components/content/ApiEndpoint.astro +18 -0
- package/src/components/content/ApiField.astro +79 -0
- package/src/components/content/ApiPlayground.astro +66 -0
- package/src/components/content/ApiRail.astro +19 -0
- package/src/components/content/Color.astro +1 -0
- package/src/components/content/FileTree.astro +1 -0
- package/src/components/content/GithubInfo.astro +1 -0
- package/src/components/content/Panel.astro +1 -0
- package/src/components/content/ParamField.astro +25 -0
- package/src/components/content/RequestExample.astro +17 -0
- package/src/components/content/ResponseExample.astro +17 -0
- package/src/components/content/ResponseField.astro +32 -0
- package/src/components/content/Step.astro +1 -0
- package/src/components/content/Tile.astro +1 -0
- package/src/components/content/Tooltip.astro +1 -0
- package/src/components/content/Tree.astro +1 -0
- package/src/components/content/TypeTable.astro +4 -1
- package/src/components/content/View.astro +21 -0
- package/src/components/content/ViewSwitcher.astro +168 -0
- package/src/components/content/api-field.ts +103 -0
- package/src/components/content/api-page.ts +248 -0
- package/src/components/content/mermaid-element.ts +15 -1
- package/src/components/content/view-switcher.ts +71 -0
- package/src/components/index.ts +2 -0
- package/src/components/islands/Assistant.astro +10 -1
- package/src/components/islands/assistant.tsx +104 -14
- package/src/components/islands/code-question.ts +62 -0
- package/src/components/islands/hooks.ts +136 -21
- package/src/components/islands/support-link.ts +68 -0
- package/src/components/layout/Analytics.astro +11 -2
- package/src/components/layout/Banner.astro +14 -10
- package/src/components/layout/Breadcrumbs.astro +6 -2
- package/src/components/layout/ConsentBanner.astro +62 -0
- package/src/components/layout/ConsentHead.astro +38 -0
- package/src/components/layout/Directory.astro +94 -0
- package/src/components/layout/DrawerSwitchers.astro +51 -0
- package/src/components/layout/Empty.astro +2 -2
- package/src/components/layout/Header.astro +122 -80
- package/src/components/layout/LanguageSwitcher.astro +48 -15
- package/src/components/layout/NarrationPlayer.astro +1085 -0
- package/src/components/layout/NavSelector.astro +33 -7
- package/src/components/layout/PageActions.astro +139 -24
- package/src/components/layout/PageFeedback.astro +54 -49
- package/src/components/layout/PageLayout.astro +71 -3
- package/src/components/layout/ReferenceLayout.astro +17 -6
- package/src/components/layout/RelatedPages.astro +42 -0
- package/src/components/layout/RootLayout.astro +318 -47
- package/src/components/layout/Search.astro +47 -19
- package/src/components/layout/SiteFooter.astro +124 -0
- package/src/components/layout/SiteMetatags.astro +16 -0
- package/src/components/layout/TableOfContents.astro +24 -17
- package/src/components/layout/consent/native.ts +79 -0
- package/src/components/layout/consent/types.ts +37 -0
- package/src/components/layout/footer-links.ts +53 -0
- package/src/components/layout/footer-socials.ts +87 -0
- package/src/components/layout/head-scripts.ts +6 -1
- package/src/components/layout/locale-redirect.ts +107 -0
- package/src/components/layout/nav-utils.ts +83 -0
- package/src/components/layout/page-feedback.ts +96 -0
- package/src/components/layout/search/algolia.ts +10 -1
- package/src/components/layout/search/analytics.ts +126 -0
- package/src/components/layout/search/endpoint.ts +48 -5
- package/src/components/layout/search/flexsearch.ts +17 -5
- package/src/components/layout/search/orama-cloud.ts +26 -14
- package/src/components/layout/search/pagefind.ts +114 -5
- package/src/components/layout/search/types.ts +32 -0
- package/src/components/layout/search/typesense.ts +19 -3
- package/src/components/openapi/AsyncApiOperation.astro +14 -7
- package/src/components/openapi/Authorization.astro +10 -0
- package/src/components/openapi/GraphqlOperation.astro +5 -0
- package/src/components/openapi/Operation.astro +184 -13
- package/src/components/openapi/ParametersTable.astro +8 -4
- package/src/components/openapi/Playground.astro +7 -1
- package/src/components/openapi/RequestBody.astro +24 -5
- package/src/components/openapi/RequestPanel.astro +59 -7
- package/src/components/openapi/Responses.astro +7 -4
- package/src/components/openapi/SchemaTable.astro +15 -3
- package/src/components/openapi/async-snippets.ts +65 -9
- package/src/components/openapi/async.ts +123 -29
- package/src/components/openapi/code-samples.ts +97 -0
- package/src/components/openapi/graphql-helpers.ts +35 -12
- package/src/components/openapi/helpers.ts +36 -2
- package/src/components/openapi/message-model.ts +54 -11
- package/src/components/openapi/message.ts +14 -4
- package/src/components/openapi/operation-model.ts +16 -7
- package/src/components/openapi/playground-client.ts +24 -5
- package/src/components/openapi/playground-schema.ts +1 -1
- package/src/components/openapi/schema-tree.ts +44 -14
- package/src/components/openapi/security.ts +16 -3
- package/src/components/openapi/snippets.ts +873 -10
- package/src/components/openapi/validate-json.ts +4 -3
- package/src/components/props.ts +6 -0
- package/src/consent/client.ts +95 -0
- package/src/consent/clients.ts +19 -0
- package/src/consent/ethyca.ts +71 -0
- package/src/consent/head.ts +24 -0
- package/src/consent/index.ts +37 -0
- package/src/consent/init.ts +29 -0
- package/src/consent/native.ts +36 -0
- package/src/consent/osano.ts +59 -0
- package/src/consent/schema.ts +30 -0
- package/src/core/builtin-tags.ts +5 -0
- package/src/core/changelog-index.ts +31 -1
- package/src/core/client-address.ts +19 -0
- package/src/core/component-diagnostics.ts +53 -0
- package/src/core/component-overrides.ts +32 -0
- package/src/core/config-input.ts +225 -23
- package/src/core/data.ts +46 -4
- package/src/core/diagnostics.ts +8 -2
- package/src/core/footer.ts +26 -0
- package/src/core/graph.ts +39 -36
- package/src/core/i18n-ui.ts +84 -2
- package/src/core/includes.ts +21 -4
- package/src/core/links.ts +63 -19
- package/src/core/localizable.ts +26 -0
- package/src/core/navigation.ts +43 -12
- package/src/core/page-modes.ts +56 -0
- package/src/core/probe.ts +26 -6
- package/src/core/project-graph.ts +163 -16
- package/src/core/redirect-patterns.ts +520 -0
- package/src/core/related.ts +131 -0
- package/src/core/schema.ts +339 -66
- package/src/core/sources/cache.ts +6 -0
- package/src/core/sources/contentful-rich-text.ts +29 -6
- package/src/core/sources/contentful.ts +135 -25
- package/src/core/sources/filesystem.ts +26 -4
- package/src/core/sources/github-releases.ts +12 -1
- package/src/core/sources/lexical.ts +15 -10
- package/src/core/sources/mdx-remote.ts +62 -10
- package/src/core/sources/normalize.ts +228 -41
- package/src/core/sources/notion.ts +7 -1
- package/src/core/sources/obsidian.ts +16 -3
- package/src/core/sources/payload.ts +38 -15
- package/src/core/sources/read.ts +8 -3
- package/src/core/sources/remote.ts +72 -15
- package/src/core/sources/resolve.ts +11 -1
- package/src/core/sources/sanity.ts +43 -25
- package/src/core/sources/strapi.ts +2 -2
- package/src/core/types.ts +19 -1
- package/src/core/ui-packs/ar.ts +44 -0
- package/src/core/ui-packs/bg.ts +46 -0
- package/src/core/ui-packs/bn.ts +44 -0
- package/src/core/ui-packs/ca.ts +47 -0
- package/src/core/ui-packs/cs.ts +45 -0
- package/src/core/ui-packs/da.ts +46 -0
- package/src/core/ui-packs/de.ts +47 -0
- package/src/core/ui-packs/el.ts +46 -0
- package/src/core/ui-packs/es.ts +47 -0
- package/src/core/ui-packs/fa.ts +46 -0
- package/src/core/ui-packs/fi.ts +46 -0
- package/src/core/ui-packs/fr.ts +47 -0
- package/src/core/ui-packs/he.ts +44 -0
- package/src/core/ui-packs/hi.ts +45 -0
- package/src/core/ui-packs/hr.ts +46 -0
- package/src/core/ui-packs/hu.ts +45 -0
- package/src/core/ui-packs/id.ts +46 -0
- package/src/core/ui-packs/it.ts +46 -0
- package/src/core/ui-packs/ja.ts +46 -0
- package/src/core/ui-packs/ko.ts +45 -0
- package/src/core/ui-packs/nl.ts +47 -0
- package/src/core/ui-packs/no.ts +45 -0
- package/src/core/ui-packs/pl.ts +46 -0
- package/src/core/ui-packs/pt-br.ts +47 -0
- package/src/core/ui-packs/pt.ts +46 -0
- package/src/core/ui-packs/ro.ts +46 -0
- package/src/core/ui-packs/ru.ts +46 -0
- package/src/core/ui-packs/sk.ts +45 -0
- package/src/core/ui-packs/sr.ts +46 -0
- package/src/core/ui-packs/sv.ts +45 -0
- package/src/core/ui-packs/th.ts +44 -0
- package/src/core/ui-packs/tr.ts +46 -0
- package/src/core/ui-packs/uk.ts +46 -0
- package/src/core/ui-packs/vi.ts +46 -0
- package/src/core/ui-packs/zh-tw.ts +44 -0
- package/src/core/ui-packs/zh.ts +44 -0
- package/src/core/variables.ts +103 -0
- package/src/deploy/adapter-output.ts +7 -2
- package/src/deploy/adapters/cloudflare.ts +7 -5
- package/src/deploy/adapters/node.ts +47 -9
- package/src/deploy/adapters/types.ts +7 -3
- package/src/deploy/artifacts.ts +79 -9
- package/src/deploy/cloudflare-negotiation.ts +35 -5
- package/src/deploy/headers.ts +2 -1
- package/src/deploy/node-headers.ts +63 -9
- package/src/deploy/platforms/cloudflare.ts +45 -9
- package/src/deploy/platforms/netlify.ts +35 -2
- package/src/deploy/platforms/node.ts +12 -2
- package/src/deploy/platforms/types.ts +21 -7
- package/src/deploy/platforms/vercel.ts +149 -17
- package/src/deploy/redirects.ts +151 -24
- package/src/deploy/rss.ts +3 -1
- package/src/deploy/sitemap.ts +39 -5
- package/src/deploy/vercel-negotiation.ts +326 -102
- package/src/eval/agents.ts +18 -1
- package/src/eval/prompts.ts +6 -3
- package/src/eval/report.ts +34 -13
- package/src/eval/run.ts +5 -0
- package/src/markdown/api-rail.ts +259 -0
- package/src/markdown/code-title.ts +35 -9
- package/src/markdown/features.ts +3 -2
- package/src/markdown/fence-meta.ts +2 -0
- package/src/markdown/include.ts +11 -1
- package/src/markdown/index.ts +28 -5
- package/src/markdown/math.ts +4 -4
- package/src/markdown/relative-links.ts +3 -2
- package/src/markdown/variables.ts +56 -0
- package/src/markdown/views.ts +82 -0
- package/src/narration/build.ts +412 -0
- package/src/narration/player.ts +249 -0
- package/src/narration/provider.ts +29 -0
- package/src/narration/script.ts +592 -0
- package/src/og/card.ts +7 -6
- package/src/openapi/checks.ts +273 -0
- package/src/openapi/graphql-build.ts +21 -0
- package/src/openapi/graphql.ts +11 -0
- package/src/openapi/model.ts +72 -27
- package/src/openapi/overlay.ts +256 -0
- package/src/openapi/parse.ts +182 -4
- package/src/openapi/references.ts +64 -8
- package/src/openapi/render-mdx.ts +5 -1
- package/src/openapi/scalar.ts +40 -6
- package/src/openapi/source.ts +40 -15
- package/src/ratelimit/cloudflare.ts +54 -0
- package/src/ratelimit/index.ts +30 -0
- package/src/ratelimit/memory.ts +45 -0
- package/src/ratelimit/runtime.ts +247 -0
- package/src/ratelimit/schema.ts +28 -0
- package/src/ratelimit/upstash.ts +60 -0
- package/src/ratelimit/wrangler.ts +70 -0
- package/src/reference/asyncapi.ts +2 -2
- package/src/reference/graphql.ts +20 -3
- package/src/reference/index.ts +1 -0
- package/src/reference/openapi.ts +21 -7
- package/src/reference/options.ts +80 -8
- package/src/reference/scalar.ts +33 -8
- package/src/registry/eject.ts +23 -5
- package/src/registry/registry.ts +7 -0
- package/src/search/adapters/locale-scope.ts +30 -0
- package/src/search/adapters/typesense.ts +14 -4
- package/src/search/build.ts +21 -3
- package/src/search/documents.ts +26 -2
- package/src/search/orama-index.ts +191 -34
- package/src/search/pagefind-ranking.ts +39 -0
- package/src/search/source-pages.ts +29 -0
- package/src/search/sync/algolia.ts +111 -10
- package/src/search/sync/index.ts +52 -13
- package/src/search/sync/orama-cloud.ts +3 -0
- package/src/search/sync/typesense.ts +76 -26
- package/src/seo/metatags.ts +67 -0
- package/src/sources/contentful.ts +12 -0
- package/src/sources/github-releases.ts +7 -1
- package/src/sources/shared.ts +3 -0
- package/src/theme/chrome-icons.ts +1 -0
- package/src/theme/color.ts +500 -0
- package/src/theme/entry.ts +85 -6
- package/src/theme/palette.ts +121 -45
- package/src/translate/prompts.ts +1 -0
- package/src/translate/validate.ts +31 -3
- package/src/upgrade/upgrade.ts +4 -171
- package/dist/cli/chunk-1d7ve1dm.js.map +0 -12
- package/dist/cli/chunk-2hsdwb9n.js.map +0 -10
- package/dist/cli/chunk-35d4wj9f.js.map +0 -15
- package/dist/cli/chunk-364znk6q.js +0 -75
- package/dist/cli/chunk-364znk6q.js.map +0 -11
- package/dist/cli/chunk-5m5nmvyq.js.map +0 -13
- package/dist/cli/chunk-8ktnccpt.js.map +0 -10
- package/dist/cli/chunk-9t7a85s3.js.map +0 -10
- package/dist/cli/chunk-b07cmahc.js +0 -145
- package/dist/cli/chunk-b07cmahc.js.map +0 -11
- package/dist/cli/chunk-c8chx29p.js.map +0 -36
- package/dist/cli/chunk-e04dxsz1.js +0 -39
- package/dist/cli/chunk-e04dxsz1.js.map +0 -10
- package/dist/cli/chunk-j85vccga.js.map +0 -36
- package/dist/cli/chunk-p3v96n38.js.map +0 -10
- package/dist/cli/chunk-pehfxfta.js.map +0 -10
- package/dist/cli/chunk-pv29h0wf.js.map +0 -190
- package/dist/cli/chunk-q58y5e6a.js.map +0 -10
- package/dist/cli/chunk-vg9r4eb9.js.map +0 -14
- package/dist/cli/chunk-wrr3j9w9.js.map +0 -35
- package/dist/cli/chunk-yfyb25rh.js.map +0 -14
- package/docs/content/sources.mdx +0 -334
- /package/dist/cli/{chunk-tkacnehg.js.map → chunk-3v3ffbrj.js.map} +0 -0
- /package/dist/cli/{chunk-r9rcc4w7.js.map → chunk-8y2kmjv8.js.map} +0 -0
- /package/dist/cli/{chunk-2eytanqx.js.map → chunk-c887fj0s.js.map} +0 -0
- /package/dist/cli/{chunk-akbpwfxc.js.map → chunk-dzwehpy7.js.map} +0 -0
- /package/dist/cli/{chunk-2z928egk.js.map → chunk-ft9vfys6.js.map} +0 -0
- /package/dist/cli/{chunk-a58773jm.js.map → chunk-kma9f6sf.js.map} +0 -0
- /package/dist/cli/{chunk-crgn1q09.js.map → chunk-sds923fa.js.map} +0 -0
- /package/dist/cli/{chunk-acanzt5p.js.map → chunk-tdqhyxfz.js.map} +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
|
|
3
3
|
import GithubSlugger from "github-slugger";
|
|
4
|
+
import type { YAMLException } from "js-yaml";
|
|
4
5
|
import type { Nodes } from "mdast";
|
|
5
6
|
import { extname } from "pathe";
|
|
6
7
|
import { markdownToMdast } from "satteri";
|
|
@@ -14,6 +15,7 @@ import { occupySlug, parseHeadingMarkers } from "../heading-markers.ts";
|
|
|
14
15
|
import { localePlacement, localizeRoute } from "../i18n.ts";
|
|
15
16
|
import { titleWord } from "../navigation.ts";
|
|
16
17
|
import { stripOrderingPrefix } from "../ordering-prefix.ts";
|
|
18
|
+
import { relatedPageLinks } from "../related.ts";
|
|
17
19
|
import { pageMetaSchema } from "../schema.ts";
|
|
18
20
|
import type {
|
|
19
21
|
FrontmatterExtend,
|
|
@@ -21,7 +23,13 @@ import type {
|
|
|
21
23
|
ResolvedI18nConfig,
|
|
22
24
|
} from "../schema.ts";
|
|
23
25
|
import { trimChar } from "../trim.ts";
|
|
24
|
-
import type {
|
|
26
|
+
import type {
|
|
27
|
+
Diagnostic,
|
|
28
|
+
ExampleUse,
|
|
29
|
+
Heading,
|
|
30
|
+
PageLink,
|
|
31
|
+
PageRecord,
|
|
32
|
+
} from "../types.ts";
|
|
25
33
|
import { detectVersionRef, versionizeRoute } from "../versions.ts";
|
|
26
34
|
import type { NormalizeContext, SourceEntry } from "./types.ts";
|
|
27
35
|
|
|
@@ -126,6 +134,29 @@ export const unloadablePathDiagnostic = (
|
|
|
126
134
|
}
|
|
127
135
|
: undefined;
|
|
128
136
|
|
|
137
|
+
/**
|
|
138
|
+
* The error for a content file whose front matter isn't valid YAML — most
|
|
139
|
+
* often an unquoted value holding `: `, which YAML reads as a nested mapping.
|
|
140
|
+
* Thrown out of a source's scan, it would fail every command with
|
|
141
|
+
* BLUME_INTERNAL; a source leaves the file out and reports this instead, like
|
|
142
|
+
* a page whose front matter fails the schema. js-yaml counts lines from the
|
|
143
|
+
* text after the opening `---`, which starts with the rest of that fence
|
|
144
|
+
* line, so its 0-based line is already the file's line minus one.
|
|
145
|
+
*/
|
|
146
|
+
export const frontmatterYamlDiagnostic = (
|
|
147
|
+
error: YAMLException,
|
|
148
|
+
file: string
|
|
149
|
+
): Diagnostic => ({
|
|
150
|
+
code: "BLUME_FRONTMATTER_INVALID",
|
|
151
|
+
column: error.mark ? error.mark.column + 1 : undefined,
|
|
152
|
+
file,
|
|
153
|
+
line: error.mark ? error.mark.line + 1 : undefined,
|
|
154
|
+
message: `Front matter isn't valid YAML (${error.reason}), so the page was left out of the site.`,
|
|
155
|
+
severity: "error",
|
|
156
|
+
suggestion:
|
|
157
|
+
'Wrap the value at that line in double quotes, e.g. description: "Setup: the easy way".',
|
|
158
|
+
});
|
|
159
|
+
|
|
129
160
|
/**
|
|
130
161
|
* Fold one raw path part into the accumulating route segments/groups.
|
|
131
162
|
* `ordered` parts are file or folder names, whose ordering prefix is dropped.
|
|
@@ -234,9 +265,11 @@ const PROMPT_CLOSE = /<\/Prompt>/u;
|
|
|
234
265
|
// the same marker — and the only spelling that survives the MDX parser, where
|
|
235
266
|
// a bare `{…}` is a JSX expression and `#id` is not a valid one (`Could not
|
|
236
267
|
// parse expression with acorn`). Further bracket markers may follow the brace
|
|
237
|
-
// (`{#id} [toc]`), nothing else.
|
|
268
|
+
// (`{#id} [toc]`), nothing else. The spaced `{ #id }` and kramdown's
|
|
269
|
+
// `{: #id }` (MkDocs `attr_list` writes both) fail the compile the same way,
|
|
270
|
+
// so they match too, though neither is an anchor in `.md`.
|
|
238
271
|
const BARE_CURLY_MARKER =
|
|
239
|
-
/(?<!\\)
|
|
272
|
+
/(?<!\\)(?<marker>\{:?\s*#(?<id>[^\s}]+)\s*\})(?:\s*\[(?:#[^\s\]]+|!?toc)\])*\s*$/u;
|
|
240
273
|
|
|
241
274
|
// A raw HTML element carrying an `id` — `<a id="…">`, `<section id='…'>`,
|
|
242
275
|
// the unquoted `<a id=plain>`, or the JSX spelling `<div id={"…"}>` — whose
|
|
@@ -258,6 +291,8 @@ export interface CurlyMarker {
|
|
|
258
291
|
id: string;
|
|
259
292
|
/** 1-based line of the heading (a setext heading's first text line) in the body. */
|
|
260
293
|
line: number;
|
|
294
|
+
/** The braces as written (`{#id}`, `{ #id }`, `{: #id }`). */
|
|
295
|
+
marker: string;
|
|
261
296
|
}
|
|
262
297
|
|
|
263
298
|
/** Scanner state: the open fence plus the paragraph lines accumulated so far. */
|
|
@@ -627,9 +662,9 @@ const noteCurlyMarker = (
|
|
|
627
662
|
line: number,
|
|
628
663
|
state: HeadingScanState
|
|
629
664
|
): void => {
|
|
630
|
-
const
|
|
631
|
-
if (id !== undefined) {
|
|
632
|
-
state.curlyMarkers.push({ id, line });
|
|
665
|
+
const groups = text.match(BARE_CURLY_MARKER)?.groups;
|
|
666
|
+
if (groups?.id !== undefined && groups.marker !== undefined) {
|
|
667
|
+
state.curlyMarkers.push({ id: groups.id, line, marker: groups.marker });
|
|
633
668
|
}
|
|
634
669
|
};
|
|
635
670
|
|
|
@@ -889,6 +924,42 @@ export const targetOffsetIn = (
|
|
|
889
924
|
title: string | undefined
|
|
890
925
|
): number => matched.length - 1 - (title?.length ?? 0) - target.length;
|
|
891
926
|
|
|
927
|
+
// A link-reference definition's destination, at the start of what follows its
|
|
928
|
+
// `[label]:` (see `REF_DEFINITION`): `<…>`, which may hold spaces, or else the
|
|
929
|
+
// run up to the first space, before any title.
|
|
930
|
+
const DEFINITION_DESTINATION = /^(?:<(?<angle>[^<>]*)>|(?<bare>\S+))/u;
|
|
931
|
+
|
|
932
|
+
// A CommonMark autolink (`<https://example.com>`). Only http(s) targets are
|
|
933
|
+
// ever checked, so no other scheme is read. MDX rejects the syntax, so in
|
|
934
|
+
// practice it's a `.md` page's.
|
|
935
|
+
const AUTOLINK = /<(?<target>https?:\/\/[^\s<>]*)>/giu;
|
|
936
|
+
|
|
937
|
+
/**
|
|
938
|
+
* Record the destination of a link-reference definition on `line`: a
|
|
939
|
+
* reference link (`[text][label]`, `[label]`) renders with it, so it's the
|
|
940
|
+
* target to check, once for every link that cites it. A footnote definition
|
|
941
|
+
* (`[^1]: …`) is no link; the links inside it are read like any others.
|
|
942
|
+
*/
|
|
943
|
+
const scanDefinition = (
|
|
944
|
+
line: string,
|
|
945
|
+
lineNumber: number,
|
|
946
|
+
links: PageLink[]
|
|
947
|
+
): void => {
|
|
948
|
+
const groups = line.match(REF_DEFINITION)?.groups;
|
|
949
|
+
if (groups?.label === undefined || groups.label.startsWith("^")) {
|
|
950
|
+
return;
|
|
951
|
+
}
|
|
952
|
+
const rest = groups.rest ?? "";
|
|
953
|
+
const destination = rest.match(DEFINITION_DESTINATION)?.groups;
|
|
954
|
+
const target = destination?.angle ?? destination?.bare;
|
|
955
|
+
if (target) {
|
|
956
|
+
// `rest` runs to the end of the line; an angle-bracketed target starts
|
|
957
|
+
// one past its `<`.
|
|
958
|
+
const at = line.length - rest.length + (destination?.angle ? 1 : 0);
|
|
959
|
+
links.push({ column: at + 1, line: lineNumber, target });
|
|
960
|
+
}
|
|
961
|
+
};
|
|
962
|
+
|
|
892
963
|
/**
|
|
893
964
|
* Extract link targets from a markdown body for later validation, recording the
|
|
894
965
|
* 1-based line/column of each target. Skips fenced code blocks and inline code.
|
|
@@ -953,18 +1024,32 @@ const scanLinkLine = (
|
|
|
953
1024
|
});
|
|
954
1025
|
}
|
|
955
1026
|
}
|
|
1027
|
+
for (const match of masked.matchAll(AUTOLINK)) {
|
|
1028
|
+
const target = match.groups?.target ?? "";
|
|
1029
|
+
links.push({ column: match.index + 2, line: lineNumber, target });
|
|
1030
|
+
}
|
|
1031
|
+
scanDefinition(masked, lineNumber, links);
|
|
956
1032
|
return next;
|
|
957
1033
|
};
|
|
958
1034
|
|
|
959
1035
|
/**
|
|
960
|
-
* A component's string `href` (`<Card href="./install" />`)
|
|
961
|
-
* may sit on a later line than the tag name, where
|
|
962
|
-
* element, so the gap between them spans lines. An
|
|
963
|
-
* `href={…}` isn't a literal target,
|
|
964
|
-
*
|
|
1036
|
+
* A component's string `href` (`<Card href="./install" />`), or a lowercase
|
|
1037
|
+
* `<a href>`: the attribute may sit on a later line than the tag name, where
|
|
1038
|
+
* a formatter wraps a long element, so the gap between them spans lines. An
|
|
1039
|
+
* expression-valued `href={…}` isn't a literal target, so it isn't matched,
|
|
1040
|
+
* and no other lowercase tag is a link.
|
|
965
1041
|
*/
|
|
966
|
-
const
|
|
967
|
-
/<[A-Z][\w.]
|
|
1042
|
+
const ELEMENT_HREF =
|
|
1043
|
+
/<(?:[A-Z][\w.]*|(?<anchor>a))(?=[\s/>])[^<>]*?\shref=(?:"(?<double>[^"]*)"|'(?<single>[^']*)')/gu;
|
|
1044
|
+
|
|
1045
|
+
/**
|
|
1046
|
+
* An inline link whose label wraps onto later lines of its paragraph
|
|
1047
|
+
* (`[a long⏎label](/x)`), as a formatter leaves one: the line scan can't see
|
|
1048
|
+
* it. The label holds a line break but no blank line (which would end the
|
|
1049
|
+
* paragraph) and no brackets, so a match never repeats a one-line link.
|
|
1050
|
+
*/
|
|
1051
|
+
const WRAPPED_LINK =
|
|
1052
|
+
/\[[^[\]\n]*(?:\n(?![ \t]*(?:\n|$))[^[\]\n]*)+\]\((?<target>(?:[^()\s]|\([^()\s]*\))+)(?<title>\s+"[^"]*")?\)/gu;
|
|
968
1053
|
|
|
969
1054
|
/** The body with fenced blocks and inline code blanked, shape preserved. */
|
|
970
1055
|
const maskCode = (lines: readonly string[]): string => {
|
|
@@ -980,24 +1065,83 @@ const maskCode = (lines: readonly string[]): string => {
|
|
|
980
1065
|
return masked.join("\n");
|
|
981
1066
|
};
|
|
982
1067
|
|
|
983
|
-
/**
|
|
984
|
-
const
|
|
1068
|
+
/** The offset each of `lines` starts at once they're joined with `\n`. */
|
|
1069
|
+
const lineStartsOf = (lines: readonly string[]): number[] => {
|
|
1070
|
+
const starts: number[] = [];
|
|
1071
|
+
let at = 0;
|
|
1072
|
+
for (const line of lines) {
|
|
1073
|
+
starts.push(at);
|
|
1074
|
+
at += line.length + 1;
|
|
1075
|
+
}
|
|
1076
|
+
return starts;
|
|
1077
|
+
};
|
|
1078
|
+
|
|
1079
|
+
/**
|
|
1080
|
+
* The 1-based position of offset `at` in the joined text whose `lineStarts`
|
|
1081
|
+
* are given, lines shifted by `lineOffset`. A binary search, so a page with
|
|
1082
|
+
* many links isn't rescanned from the top for each one.
|
|
1083
|
+
*/
|
|
1084
|
+
const positionIn = (
|
|
1085
|
+
lineStarts: readonly number[],
|
|
1086
|
+
at: number,
|
|
1087
|
+
lineOffset: number
|
|
1088
|
+
): Pick<PageLink, "column" | "line"> => {
|
|
1089
|
+
let low = 0;
|
|
1090
|
+
let high = lineStarts.length - 1;
|
|
1091
|
+
while (low < high) {
|
|
1092
|
+
const mid = Math.ceil((low + high) / 2);
|
|
1093
|
+
if ((lineStarts[mid] ?? 0) <= at) {
|
|
1094
|
+
low = mid;
|
|
1095
|
+
} else {
|
|
1096
|
+
high = mid - 1;
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
return {
|
|
1100
|
+
column: at - (lineStarts[low] ?? 0) + 1,
|
|
1101
|
+
line: lineOffset + low + 1,
|
|
1102
|
+
};
|
|
1103
|
+
};
|
|
1104
|
+
|
|
1105
|
+
/**
|
|
1106
|
+
* Every link in `body` that can span lines, with its 1-based position: an
|
|
1107
|
+
* element's `href` (see `ELEMENT_HREF`) and a link whose label wraps (see
|
|
1108
|
+
* `WRAPPED_LINK`). A lowercase `<a>` is raw HTML in `.md` and a plain element
|
|
1109
|
+
* in `.mdx`; the Markdown pipeline passes either through as written, so its
|
|
1110
|
+
* target is marked `raw`.
|
|
1111
|
+
*/
|
|
1112
|
+
const multilineLinks = (
|
|
985
1113
|
lines: readonly string[],
|
|
986
1114
|
lineOffset: number
|
|
987
1115
|
): PageLink[] => {
|
|
988
1116
|
const links: PageLink[] = [];
|
|
989
1117
|
const text = maskCode(lines);
|
|
990
|
-
|
|
1118
|
+
const lineStarts = lineStartsOf(lines);
|
|
1119
|
+
for (const match of text.matchAll(ELEMENT_HREF)) {
|
|
991
1120
|
const target = match.groups?.double ?? match.groups?.single ?? "";
|
|
992
1121
|
// The value ends one character (its closing quote) before the match does.
|
|
993
1122
|
const at = match.index + match[0].length - target.length - 1;
|
|
994
|
-
const
|
|
995
|
-
|
|
996
|
-
links.push({
|
|
997
|
-
column: at - lineStart + 1,
|
|
998
|
-
line: lineOffset + before.split("\n").length,
|
|
1123
|
+
const link: PageLink = {
|
|
1124
|
+
...positionIn(lineStarts, at, lineOffset),
|
|
999
1125
|
target,
|
|
1000
|
-
}
|
|
1126
|
+
};
|
|
1127
|
+
if (match.groups?.anchor) {
|
|
1128
|
+
link.raw = true;
|
|
1129
|
+
}
|
|
1130
|
+
links.push(link);
|
|
1131
|
+
}
|
|
1132
|
+
for (const match of text.matchAll(WRAPPED_LINK)) {
|
|
1133
|
+
const target = match.groups?.target ?? "";
|
|
1134
|
+
const at =
|
|
1135
|
+
match.index + targetOffsetIn(match[0], target, match.groups?.title);
|
|
1136
|
+
const link: PageLink = {
|
|
1137
|
+
...positionIn(lineStarts, at, lineOffset),
|
|
1138
|
+
target,
|
|
1139
|
+
};
|
|
1140
|
+
// As on one line, a preceding `!` makes it an image embed.
|
|
1141
|
+
if (text[match.index - 1] === "!") {
|
|
1142
|
+
link.image = true;
|
|
1143
|
+
}
|
|
1144
|
+
links.push(link);
|
|
1001
1145
|
}
|
|
1002
1146
|
return links;
|
|
1003
1147
|
};
|
|
@@ -1013,9 +1157,37 @@ export const extractLinks = (body: string, lineOffset = 0): PageLink[] => {
|
|
|
1013
1157
|
fence = scanLinkLine(line, lineNumber, fence, links);
|
|
1014
1158
|
}
|
|
1015
1159
|
|
|
1016
|
-
return
|
|
1017
|
-
|
|
1018
|
-
|
|
1160
|
+
return [...links, ...multilineLinks(lines, lineOffset)];
|
|
1161
|
+
};
|
|
1162
|
+
|
|
1163
|
+
/**
|
|
1164
|
+
* A `<Component>` example's string `path` (`<Component path="forms/login" />`),
|
|
1165
|
+
* wrapped onto a later line or not, read the way `ELEMENT_HREF` reads an
|
|
1166
|
+
* `href`. An expression-valued `path={…}` isn't a literal, so it isn't matched.
|
|
1167
|
+
*/
|
|
1168
|
+
const COMPONENT_PATH =
|
|
1169
|
+
/<Component(?=[\s/>])[^<>]*?\spath=(?:"(?<double>[^"]*)"|'(?<single>[^']*)')/gu;
|
|
1170
|
+
|
|
1171
|
+
/**
|
|
1172
|
+
* Every `<Component path>` in an `.mdx` body, with the 1-based position of its
|
|
1173
|
+
* value; lines are shifted by `lineOffset`, as {@link extractLinks} does. Code
|
|
1174
|
+
* blocks and inline code are skipped.
|
|
1175
|
+
*/
|
|
1176
|
+
export const extractExampleUses = (
|
|
1177
|
+
body: string,
|
|
1178
|
+
lineOffset = 0
|
|
1179
|
+
): ExampleUse[] => {
|
|
1180
|
+
if (!body.includes("<Component")) {
|
|
1181
|
+
return [];
|
|
1182
|
+
}
|
|
1183
|
+
const lines = body.split("\n");
|
|
1184
|
+
const lineStarts = lineStartsOf(lines);
|
|
1185
|
+
return [...maskCode(lines).matchAll(COMPONENT_PATH)].map((match) => {
|
|
1186
|
+
const path = match.groups?.double ?? match.groups?.single ?? "";
|
|
1187
|
+
// The value ends one character (its closing quote) before the match does.
|
|
1188
|
+
const at = match.index + match[0].length - path.length - 1;
|
|
1189
|
+
return { ...positionIn(lineStarts, at, lineOffset), path };
|
|
1190
|
+
});
|
|
1019
1191
|
};
|
|
1020
1192
|
|
|
1021
1193
|
// Double-quoted strings hold JSX attribute values and JSON in `{...}` props; a
|
|
@@ -1081,23 +1253,29 @@ export const strippedLineOffset = (
|
|
|
1081
1253
|
const entryLineOffset = (entry: SourceEntry): number =>
|
|
1082
1254
|
entry.bodyLineOffset ?? strippedLineOffset(entry.raw, entry.body.text);
|
|
1083
1255
|
|
|
1256
|
+
/** A link (or `<Component>` example) found in a body: its line, and file. */
|
|
1257
|
+
interface Located {
|
|
1258
|
+
file?: string;
|
|
1259
|
+
line: number;
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1084
1262
|
/**
|
|
1085
1263
|
* Map links extracted from include-expanded text back to the file and raw
|
|
1086
1264
|
* line each expanded line came from, so a broken link inside a partial is
|
|
1087
1265
|
* reported against the partial. Links whose origin is the page's own source
|
|
1088
1266
|
* carry no `file` override (origins already hold raw-file lines).
|
|
1089
1267
|
*/
|
|
1090
|
-
const remapExpandedLinks = (
|
|
1091
|
-
links:
|
|
1268
|
+
const remapExpandedLinks = <T extends Located>(
|
|
1269
|
+
links: T[],
|
|
1092
1270
|
origins: { file: string; line: number }[],
|
|
1093
1271
|
sourcePath: string | undefined
|
|
1094
|
-
):
|
|
1272
|
+
): T[] =>
|
|
1095
1273
|
links.map((link) => {
|
|
1096
1274
|
const origin = origins[link.line - 1];
|
|
1097
1275
|
if (!origin) {
|
|
1098
1276
|
return link;
|
|
1099
1277
|
}
|
|
1100
|
-
const remapped:
|
|
1278
|
+
const remapped: T = { ...link, line: origin.line };
|
|
1101
1279
|
if (origin.file !== sourcePath) {
|
|
1102
1280
|
remapped.file = origin.file;
|
|
1103
1281
|
}
|
|
@@ -1111,22 +1289,26 @@ const entryIncludes = (entry: SourceEntry): string[] | undefined =>
|
|
|
1111
1289
|
: undefined;
|
|
1112
1290
|
|
|
1113
1291
|
/**
|
|
1114
|
-
* Extract an entry's links for validation. When
|
|
1115
|
-
* extraction runs over the expanded text (origins
|
|
1116
|
-
* lines); otherwise over the stripped body, shifted by
|
|
1117
|
-
* matter block's height.
|
|
1292
|
+
* Extract an entry's links (or `<Component>` examples) for validation. When
|
|
1293
|
+
* the scan expanded includes, extraction runs over the expanded text (origins
|
|
1294
|
+
* already hold raw-file lines); otherwise over the stripped body, shifted by
|
|
1295
|
+
* the stripped front matter block's height.
|
|
1118
1296
|
*/
|
|
1119
|
-
const entryLinks =
|
|
1297
|
+
const entryLinks = <T extends Located>(
|
|
1298
|
+
entry: SourceEntry,
|
|
1299
|
+
extract: (body: string, lineOffset?: number) => T[]
|
|
1300
|
+
): T[] =>
|
|
1120
1301
|
entry.expanded
|
|
1121
1302
|
? remapExpandedLinks(
|
|
1122
|
-
|
|
1303
|
+
extract(entry.expanded.text),
|
|
1123
1304
|
entry.expanded.origins,
|
|
1124
1305
|
entry.sourcePath
|
|
1125
1306
|
)
|
|
1126
|
-
:
|
|
1307
|
+
: extract(entry.body.text, entryLineOffset(entry));
|
|
1127
1308
|
|
|
1128
1309
|
/**
|
|
1129
|
-
* Diagnostics for `{#id}` heading markers
|
|
1310
|
+
* Diagnostics for `{#id}` heading markers (and the spaced `{ #id }` and
|
|
1311
|
+
* kramdown `{: #id }` spellings) in an `.mdx` page. The MDX parser
|
|
1130
1312
|
* reads a bare `{…}` as a JSX expression, so the page fails to compile —
|
|
1131
1313
|
* reported here, at the marker's source line, instead of as a raw acorn error
|
|
1132
1314
|
* at render time. An included `.md` partial is spliced into the including
|
|
@@ -1139,7 +1321,7 @@ const curlyMarkerDiagnostics = (
|
|
|
1139
1321
|
markers: CurlyMarker[],
|
|
1140
1322
|
sourceName: string
|
|
1141
1323
|
): Diagnostic[] =>
|
|
1142
|
-
markers.map(({ id, line }) => {
|
|
1324
|
+
markers.map(({ id, line, marker }) => {
|
|
1143
1325
|
const origin = entry.expanded?.origins[line - 1];
|
|
1144
1326
|
const page = entry.sourcePath ?? `${sourceName}:${entry.ref}`;
|
|
1145
1327
|
const inPartial = origin !== undefined && origin.file !== entry.sourcePath;
|
|
@@ -1148,8 +1330,8 @@ const curlyMarkerDiagnostics = (
|
|
|
1148
1330
|
file: origin?.file ?? page,
|
|
1149
1331
|
line: origin?.line ?? line + entryLineOffset(entry),
|
|
1150
1332
|
message: inPartial
|
|
1151
|
-
?
|
|
1152
|
-
:
|
|
1333
|
+
? `\`${marker}\` is a JSX expression once this partial is included in ${page} (.mdx), so that page fails to compile.`
|
|
1334
|
+
: `\`${marker}\` is a JSX expression in .mdx, so this page fails to compile.`,
|
|
1153
1335
|
severity: "error",
|
|
1154
1336
|
suggestion: `Write \`[#${id}]\` or escape it as \`\\{#${id}\\}\` — both pin the same anchor in .md and .mdx.`,
|
|
1155
1337
|
};
|
|
@@ -1548,13 +1730,18 @@ export const normalizeEntry = (
|
|
|
1548
1730
|
description: meta.description,
|
|
1549
1731
|
editUrl: entry.editUrl,
|
|
1550
1732
|
entryId: staged ? `${ctx.source.name}/${entry.ref}` : undefined,
|
|
1733
|
+
examplesUsed:
|
|
1734
|
+
format === "mdx" ? entryLinks(entry, extractExampleUses) : undefined,
|
|
1551
1735
|
format,
|
|
1552
1736
|
groups,
|
|
1553
1737
|
headings,
|
|
1554
1738
|
id: `${ctx.source.name}:${entry.ref}`,
|
|
1555
1739
|
includes: entryIncludes(entry),
|
|
1556
1740
|
lastModified: meta.lastModified ?? entry.lastModified,
|
|
1557
|
-
links:
|
|
1741
|
+
links: [
|
|
1742
|
+
...entryLinks(entry, extractLinks),
|
|
1743
|
+
...relatedPageLinks(meta.related),
|
|
1744
|
+
],
|
|
1558
1745
|
meta,
|
|
1559
1746
|
monolingual: ctx.source.monolingual,
|
|
1560
1747
|
navPath,
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
renderInline,
|
|
25
25
|
} from "./lower.ts";
|
|
26
26
|
import { slugify, slugifyPath } from "./normalize.ts";
|
|
27
|
+
import { missingSecretError } from "./remote.ts";
|
|
27
28
|
import type {
|
|
28
29
|
ContentSource,
|
|
29
30
|
SourceContext,
|
|
@@ -446,7 +447,12 @@ export const notionSource = (
|
|
|
446
447
|
severity: "error",
|
|
447
448
|
});
|
|
448
449
|
}
|
|
449
|
-
|
|
450
|
+
// Every Notion API call needs the integration token.
|
|
451
|
+
const auth = options.token ?? process.env.NOTION_TOKEN;
|
|
452
|
+
if (!auth) {
|
|
453
|
+
throw missingSecretError(options.name, "NOTION_TOKEN");
|
|
454
|
+
}
|
|
455
|
+
return new Client({ auth });
|
|
450
456
|
};
|
|
451
457
|
|
|
452
458
|
const childrenOf = (
|
|
@@ -2,6 +2,7 @@ import { existsSync, watch as fsWatch, statSync } from "node:fs";
|
|
|
2
2
|
import type { Dirent } from "node:fs";
|
|
3
3
|
import { readdir, readFile, stat } from "node:fs/promises";
|
|
4
4
|
|
|
5
|
+
import { YAMLException } from "js-yaml";
|
|
5
6
|
import { basename, isAbsolute, join, relative, resolve } from "pathe";
|
|
6
7
|
|
|
7
8
|
import { nextFenceState } from "../code-fences.ts";
|
|
@@ -19,6 +20,7 @@ import {
|
|
|
19
20
|
localizedRoute,
|
|
20
21
|
placeEntryRef,
|
|
21
22
|
resolveEntryRoute,
|
|
23
|
+
frontmatterYamlDiagnostic,
|
|
22
24
|
slugifyPath,
|
|
23
25
|
strippedLineOffset,
|
|
24
26
|
unloadablePathDiagnostic,
|
|
@@ -785,13 +787,14 @@ const noteToEntry = (
|
|
|
785
787
|
* Read and split one note, or null when it vanished between the walk and the
|
|
786
788
|
* read. Obsidian renames and deletes notes while a dev server watches the
|
|
787
789
|
* vault, and one file disappearing mid-load must not fail the whole reload.
|
|
788
|
-
*
|
|
790
|
+
* A note whose front matter isn't valid YAML comes back as its diagnostic,
|
|
791
|
+
* so it's left out the same way. Any other read failure still throws.
|
|
789
792
|
*/
|
|
790
793
|
const readNote = async (
|
|
791
794
|
vaultDir: string,
|
|
792
795
|
rel: string,
|
|
793
796
|
options: Pick<ObsidianSourceOptions, "i18n" | "versions">
|
|
794
|
-
): Promise<ParsedNote | null> => {
|
|
797
|
+
): Promise<ParsedNote | Diagnostic | null> => {
|
|
795
798
|
const absPath = join(vaultDir, rel);
|
|
796
799
|
try {
|
|
797
800
|
const file = await readFile(absPath, "utf-8");
|
|
@@ -808,6 +811,9 @@ const readNote = async (
|
|
|
808
811
|
rel,
|
|
809
812
|
};
|
|
810
813
|
} catch (error) {
|
|
814
|
+
if (error instanceof YAMLException) {
|
|
815
|
+
return frontmatterYamlDiagnostic(error, absPath);
|
|
816
|
+
}
|
|
811
817
|
// SAFETY: a rejected `readFile` always yields a Node system error, whose
|
|
812
818
|
// `code` is the only field read here.
|
|
813
819
|
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
|
|
@@ -976,7 +982,14 @@ export const obsidianSource = (
|
|
|
976
982
|
const read = await Promise.all(
|
|
977
983
|
files.map((rel) => readNote(vaultDir, rel, options))
|
|
978
984
|
);
|
|
979
|
-
const notes = read.filter(
|
|
985
|
+
const notes = read.filter(
|
|
986
|
+
(note): note is ParsedNote => note !== null && "rel" in note
|
|
987
|
+
);
|
|
988
|
+
skipped.push(
|
|
989
|
+
...read.filter(
|
|
990
|
+
(note): note is Diagnostic => note !== null && "code" in note
|
|
991
|
+
)
|
|
992
|
+
);
|
|
980
993
|
// Resolving `[[Note#H]]` needs the target's route and headings, so every
|
|
981
994
|
// note is parsed and indexed before any body is rewritten.
|
|
982
995
|
const { index, pairs } = buildLinkIndex(notes, options);
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import type { Diagnostic } from "../types.ts";
|
|
1
2
|
import type { JsonObject } from "./json.ts";
|
|
2
3
|
import { asObject, asString, isJsonObject, objectsIn } from "./json.ts";
|
|
3
4
|
import { lexicalToMarkdown } from "./lexical.ts";
|
|
4
5
|
import { writesMdx } from "./lower.ts";
|
|
5
|
-
import type { RemoteFieldMap, RestClient } from "./remote.ts";
|
|
6
|
+
import type { RemoteFieldMap, RemoteFields, RestClient } from "./remote.ts";
|
|
6
7
|
import {
|
|
7
8
|
documentEntry,
|
|
8
9
|
fetchJson,
|
|
@@ -44,7 +45,7 @@ export interface PayloadSourceOptions {
|
|
|
44
45
|
|
|
45
46
|
const PAGE_SIZE = 100;
|
|
46
47
|
|
|
47
|
-
const DEFAULT_FIELDS:
|
|
48
|
+
const DEFAULT_FIELDS: RemoteFields = {
|
|
48
49
|
body: "content",
|
|
49
50
|
description: "description",
|
|
50
51
|
lastModified: "updatedAt",
|
|
@@ -64,13 +65,45 @@ export const payloadSource = (
|
|
|
64
65
|
const fields = { ...DEFAULT_FIELDS, ...options.fields };
|
|
65
66
|
const origin = options.url.replace(/\/+$/u, "");
|
|
66
67
|
|
|
67
|
-
const lower = (body: JsonObject): string =>
|
|
68
|
+
const lower = (body: JsonObject, leftOut: Set<string>): string =>
|
|
68
69
|
lexicalToMarkdown(body, {
|
|
69
70
|
baseUrl: origin,
|
|
71
|
+
onUnsupported: (what) => leftOut.add(what),
|
|
70
72
|
serializers: options.serializers,
|
|
71
73
|
});
|
|
72
74
|
|
|
73
|
-
|
|
75
|
+
// A document mapped to its entry, with a warning for each kind of node its
|
|
76
|
+
// body left out as a comment.
|
|
77
|
+
const toEntry = (
|
|
78
|
+
doc: JsonObject,
|
|
79
|
+
draft: boolean,
|
|
80
|
+
warn: (diagnostic: Diagnostic) => void
|
|
81
|
+
): SourceEntry => {
|
|
82
|
+
const leftOut = new Set<string>();
|
|
83
|
+
const id = asString(doc.id) ?? String(doc.id ?? "");
|
|
84
|
+
const entry = documentEntry(
|
|
85
|
+
doc,
|
|
86
|
+
fields,
|
|
87
|
+
id,
|
|
88
|
+
(body) => (isJsonObject(body) ? lower(body, leftOut) : ""),
|
|
89
|
+
draft,
|
|
90
|
+
writesMdx(options.serializers)
|
|
91
|
+
);
|
|
92
|
+
for (const what of leftOut) {
|
|
93
|
+
warn({
|
|
94
|
+
code: "BLUME_SOURCE_UNSUPPORTED_NODE",
|
|
95
|
+
message: `Source "${options.name}": "${entry.ref}" has content Blume has no Markdown for (${what}), left out as a comment.`,
|
|
96
|
+
severity: "warning",
|
|
97
|
+
suggestion:
|
|
98
|
+
"Map a block type to a component with a serializer on payloadSource, passed to custom(); other nodes have no Markdown equivalent.",
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
return entry;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const fetchEntries = async (
|
|
105
|
+
warn: (diagnostic: Diagnostic) => void
|
|
106
|
+
): Promise<SourceEntry[]> => {
|
|
74
107
|
const preview = ctx?.preview ?? false;
|
|
75
108
|
const token = options.token ?? process.env.PAYLOAD_API_KEY;
|
|
76
109
|
const client: RestClient = {
|
|
@@ -105,17 +138,7 @@ export const payloadSource = (
|
|
|
105
138
|
if (draft && !preview) {
|
|
106
139
|
continue;
|
|
107
140
|
}
|
|
108
|
-
|
|
109
|
-
entries.push(
|
|
110
|
-
documentEntry(
|
|
111
|
-
doc,
|
|
112
|
-
fields,
|
|
113
|
-
id,
|
|
114
|
-
(body) => (isJsonObject(body) ? lower(body) : ""),
|
|
115
|
-
draft,
|
|
116
|
-
writesMdx(options.serializers)
|
|
117
|
-
)
|
|
118
|
-
);
|
|
141
|
+
entries.push(toEntry(doc, draft, warn));
|
|
119
142
|
}
|
|
120
143
|
more = result.hasNextPage === true;
|
|
121
144
|
page += 1;
|
package/src/core/sources/read.ts
CHANGED
|
@@ -2,10 +2,14 @@ import { readFile } from "node:fs/promises";
|
|
|
2
2
|
|
|
3
3
|
import { expandIncludes, hasIncludeStatements } from "../includes.ts";
|
|
4
4
|
import type { PageRecord } from "../types.ts";
|
|
5
|
+
import { substituteVariablesInBody } from "../variables.ts";
|
|
6
|
+
import type { ContentVariables } from "../variables.ts";
|
|
5
7
|
import type { ContentSource } from "./types.ts";
|
|
6
8
|
|
|
7
9
|
/** The subset of a scanned project the entry reader needs. */
|
|
8
10
|
export interface EntryReadContext {
|
|
11
|
+
/** The site's content variables, substituted into what's read. */
|
|
12
|
+
config?: { variables?: ContentVariables };
|
|
9
13
|
/** The instantiated sources, keyed for `read()` lookups. */
|
|
10
14
|
sources?: ContentSource[];
|
|
11
15
|
}
|
|
@@ -48,9 +52,10 @@ export const readExpandedEntryText = async (
|
|
|
48
52
|
ctx: EntryReadContext,
|
|
49
53
|
page: PageRecord
|
|
50
54
|
): Promise<string> => {
|
|
55
|
+
const variables = ctx.config?.variables;
|
|
51
56
|
const raw = await readEntryText(ctx, page);
|
|
52
57
|
if (!(page.sourcePath && hasIncludeStatements(raw))) {
|
|
53
|
-
return raw;
|
|
58
|
+
return substituteVariablesInBody(raw, variables);
|
|
54
59
|
}
|
|
55
60
|
const source = ctx.sources?.find(
|
|
56
61
|
(candidate) => candidate.name === page.source.name
|
|
@@ -61,11 +66,11 @@ export const readExpandedEntryText = async (
|
|
|
61
66
|
// here would splice text the rest of the pipeline never validated, with no
|
|
62
67
|
// content-root bound on resolution.
|
|
63
68
|
if (!source || source.staged || !source.contentRoot) {
|
|
64
|
-
return raw;
|
|
69
|
+
return substituteVariablesInBody(raw, variables);
|
|
65
70
|
}
|
|
66
71
|
const expansion = await expandIncludes(raw, {
|
|
67
72
|
contentRoot: source.contentRoot,
|
|
68
73
|
sourcePath: page.sourcePath,
|
|
69
74
|
});
|
|
70
|
-
return expansion.text;
|
|
75
|
+
return substituteVariablesInBody(expansion.text, variables);
|
|
71
76
|
};
|