@wildo-ai/saas-website 1.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/LICENSE +34 -0
- package/dist/esm/.builder.pid +9 -0
- package/dist/esm/astro/blog-post-bridge.d.ts +324 -0
- package/dist/esm/astro/blog-post-bridge.d.ts.map +1 -0
- package/dist/esm/astro/blog-post-bridge.js +57 -0
- package/dist/esm/astro/blog-post-bridge.js.map +1 -0
- package/dist/esm/astro/blog-post-head.renderer.d.ts +129 -0
- package/dist/esm/astro/blog-post-head.renderer.d.ts.map +1 -0
- package/dist/esm/astro/blog-post-head.renderer.js +139 -0
- package/dist/esm/astro/blog-post-head.renderer.js.map +1 -0
- package/dist/esm/astro/bridge-runtime.d.ts +224 -0
- package/dist/esm/astro/bridge-runtime.d.ts.map +1 -0
- package/dist/esm/astro/bridge-runtime.js +30 -0
- package/dist/esm/astro/bridge-runtime.js.map +1 -0
- package/dist/esm/astro/collect-expected-label-keys.d.ts +65 -0
- package/dist/esm/astro/collect-expected-label-keys.d.ts.map +1 -0
- package/dist/esm/astro/collect-expected-label-keys.js +101 -0
- package/dist/esm/astro/collect-expected-label-keys.js.map +1 -0
- package/dist/esm/astro/headers-renderer.d.ts +32 -0
- package/dist/esm/astro/headers-renderer.d.ts.map +1 -0
- package/dist/esm/astro/headers-renderer.js +64 -0
- package/dist/esm/astro/headers-renderer.js.map +1 -0
- package/dist/esm/astro/i18n-routing.helper.d.ts +91 -0
- package/dist/esm/astro/i18n-routing.helper.d.ts.map +1 -0
- package/dist/esm/astro/i18n-routing.helper.js +23 -0
- package/dist/esm/astro/i18n-routing.helper.js.map +1 -0
- package/dist/esm/astro/internal/html-escape.d.ts +31 -0
- package/dist/esm/astro/internal/html-escape.d.ts.map +1 -0
- package/dist/esm/astro/internal/html-escape.js +40 -0
- package/dist/esm/astro/internal/html-escape.js.map +1 -0
- package/dist/esm/astro/label-pack-loader.d.ts +134 -0
- package/dist/esm/astro/label-pack-loader.d.ts.map +1 -0
- package/dist/esm/astro/label-pack-loader.js +298 -0
- package/dist/esm/astro/label-pack-loader.js.map +1 -0
- package/dist/esm/astro/llms-txt-server.d.ts +28 -0
- package/dist/esm/astro/llms-txt-server.d.ts.map +1 -0
- package/dist/esm/astro/llms-txt-server.js +33 -0
- package/dist/esm/astro/llms-txt-server.js.map +1 -0
- package/dist/esm/astro/pick-labels-for-page.d.ts +63 -0
- package/dist/esm/astro/pick-labels-for-page.d.ts.map +1 -0
- package/dist/esm/astro/pick-labels-for-page.js +73 -0
- package/dist/esm/astro/pick-labels-for-page.js.map +1 -0
- package/dist/esm/astro/robots-renderer.d.ts +85 -0
- package/dist/esm/astro/robots-renderer.d.ts.map +1 -0
- package/dist/esm/astro/robots-renderer.js +157 -0
- package/dist/esm/astro/robots-renderer.js.map +1 -0
- package/dist/esm/astro/sitemap-coverage.d.ts +101 -0
- package/dist/esm/astro/sitemap-coverage.d.ts.map +1 -0
- package/dist/esm/astro/sitemap-coverage.js +67 -0
- package/dist/esm/astro/sitemap-coverage.js.map +1 -0
- package/dist/esm/astro/structured-data.renderer.d.ts +21 -0
- package/dist/esm/astro/structured-data.renderer.d.ts.map +1 -0
- package/dist/esm/astro/structured-data.renderer.js +142 -0
- package/dist/esm/astro/structured-data.renderer.js.map +1 -0
- package/dist/esm/astro/website-page-head.renderer.d.ts +93 -0
- package/dist/esm/astro/website-page-head.renderer.d.ts.map +1 -0
- package/dist/esm/astro/website-page-head.renderer.js +184 -0
- package/dist/esm/astro/website-page-head.renderer.js.map +1 -0
- package/dist/esm/astro/website-page-runtime.helper.d.ts +112 -0
- package/dist/esm/astro/website-page-runtime.helper.d.ts.map +1 -0
- package/dist/esm/astro/website-page-runtime.helper.js +60 -0
- package/dist/esm/astro/website-page-runtime.helper.js.map +1 -0
- package/dist/esm/astro/website-site-context.d.ts +126 -0
- package/dist/esm/astro/website-site-context.d.ts.map +1 -0
- package/dist/esm/astro/website-site-context.js +37 -0
- package/dist/esm/astro/website-site-context.js.map +1 -0
- package/dist/esm/astro-island.d.ts +56 -0
- package/dist/esm/astro-island.d.ts.map +1 -0
- package/dist/esm/astro-island.js +61 -0
- package/dist/esm/astro-island.js.map +1 -0
- package/dist/esm/astro.d.ts +151 -0
- package/dist/esm/astro.d.ts.map +1 -0
- package/dist/esm/astro.js +151 -0
- package/dist/esm/astro.js.map +1 -0
- package/dist/esm/companion-exports.d.ts +38 -0
- package/dist/esm/companion-exports.d.ts.map +1 -0
- package/dist/esm/companion-exports.js +38 -0
- package/dist/esm/companion-exports.js.map +1 -0
- package/dist/esm/components/low-level/WebsiteButton.d.ts +73 -0
- package/dist/esm/components/low-level/WebsiteButton.d.ts.map +1 -0
- package/dist/esm/components/low-level/WebsiteButton.js +68 -0
- package/dist/esm/components/low-level/WebsiteButton.js.map +1 -0
- package/dist/esm/components/low-level/WebsiteHeading.d.ts +78 -0
- package/dist/esm/components/low-level/WebsiteHeading.d.ts.map +1 -0
- package/dist/esm/components/low-level/WebsiteHeading.js +41 -0
- package/dist/esm/components/low-level/WebsiteHeading.js.map +1 -0
- package/dist/esm/components/low-level/WebsiteImage.d.ts +73 -0
- package/dist/esm/components/low-level/WebsiteImage.d.ts.map +1 -0
- package/dist/esm/components/low-level/WebsiteImage.js +21 -0
- package/dist/esm/components/low-level/WebsiteImage.js.map +1 -0
- package/dist/esm/components/low-level/WebsiteInternalButton.d.ts +90 -0
- package/dist/esm/components/low-level/WebsiteInternalButton.d.ts.map +1 -0
- package/dist/esm/components/low-level/WebsiteInternalButton.js +47 -0
- package/dist/esm/components/low-level/WebsiteInternalButton.js.map +1 -0
- package/dist/esm/components/low-level/WebsiteInternalLink.d.ts +99 -0
- package/dist/esm/components/low-level/WebsiteInternalLink.d.ts.map +1 -0
- package/dist/esm/components/low-level/WebsiteInternalLink.js +68 -0
- package/dist/esm/components/low-level/WebsiteInternalLink.js.map +1 -0
- package/dist/esm/components/low-level/WebsiteLink.d.ts +50 -0
- package/dist/esm/components/low-level/WebsiteLink.d.ts.map +1 -0
- package/dist/esm/components/low-level/WebsiteLink.js +22 -0
- package/dist/esm/components/low-level/WebsiteLink.js.map +1 -0
- package/dist/esm/components/low-level/WebsiteText.d.ts +57 -0
- package/dist/esm/components/low-level/WebsiteText.d.ts.map +1 -0
- package/dist/esm/components/low-level/WebsiteText.js +57 -0
- package/dist/esm/components/low-level/WebsiteText.js.map +1 -0
- package/dist/esm/config/define-website-config.d.ts +83 -0
- package/dist/esm/config/define-website-config.d.ts.map +1 -0
- package/dist/esm/config/define-website-config.js +126 -0
- package/dist/esm/config/define-website-config.js.map +1 -0
- package/dist/esm/config/index.d.ts +38 -0
- package/dist/esm/config/index.d.ts.map +1 -0
- package/dist/esm/config/index.js +38 -0
- package/dist/esm/config/index.js.map +1 -0
- package/dist/esm/config/load-website-config.d.ts +136 -0
- package/dist/esm/config/load-website-config.d.ts.map +1 -0
- package/dist/esm/config/load-website-config.js +177 -0
- package/dist/esm/config/load-website-config.js.map +1 -0
- package/dist/esm/config/wildo-website-config.schemas.d.ts +251 -0
- package/dist/esm/config/wildo-website-config.schemas.d.ts.map +1 -0
- package/dist/esm/config/wildo-website-config.schemas.js +302 -0
- package/dist/esm/config/wildo-website-config.schemas.js.map +1 -0
- package/dist/esm/config-loader.d.ts +35 -0
- package/dist/esm/config-loader.d.ts.map +1 -0
- package/dist/esm/config-loader.js +35 -0
- package/dist/esm/config-loader.js.map +1 -0
- package/dist/esm/core/anonymous-session/InboundContactForm.d.ts +38 -0
- package/dist/esm/core/anonymous-session/InboundContactForm.d.ts.map +1 -0
- package/dist/esm/core/anonymous-session/InboundContactForm.js +77 -0
- package/dist/esm/core/anonymous-session/InboundContactForm.js.map +1 -0
- package/dist/esm/core/anonymous-session/inbound-contact-form.schema.d.ts +41 -0
- package/dist/esm/core/anonymous-session/inbound-contact-form.schema.d.ts.map +1 -0
- package/dist/esm/core/anonymous-session/inbound-contact-form.schema.js +58 -0
- package/dist/esm/core/anonymous-session/inbound-contact-form.schema.js.map +1 -0
- package/dist/esm/core/anonymous-session/website-anonymous-session-client.d.ts +81 -0
- package/dist/esm/core/anonymous-session/website-anonymous-session-client.d.ts.map +1 -0
- package/dist/esm/core/anonymous-session/website-anonymous-session-client.js +177 -0
- package/dist/esm/core/anonymous-session/website-anonymous-session-client.js.map +1 -0
- package/dist/esm/core/contexts/WebsitePageContext.d.ts +40 -0
- package/dist/esm/core/contexts/WebsitePageContext.d.ts.map +1 -0
- package/dist/esm/core/contexts/WebsitePageContext.js +8 -0
- package/dist/esm/core/contexts/WebsitePageContext.js.map +1 -0
- package/dist/esm/core/contexts/WebsiteRuntimeContext.d.ts +162 -0
- package/dist/esm/core/contexts/WebsiteRuntimeContext.d.ts.map +1 -0
- package/dist/esm/core/contexts/WebsiteRuntimeContext.js +22 -0
- package/dist/esm/core/contexts/WebsiteRuntimeContext.js.map +1 -0
- package/dist/esm/core/contexts/WebsiteSectionContext.d.ts +47 -0
- package/dist/esm/core/contexts/WebsiteSectionContext.d.ts.map +1 -0
- package/dist/esm/core/contexts/WebsiteSectionContext.js +8 -0
- package/dist/esm/core/contexts/WebsiteSectionContext.js.map +1 -0
- package/dist/esm/core/contexts/useWebsitePage.d.ts +13 -0
- package/dist/esm/core/contexts/useWebsitePage.d.ts.map +1 -0
- package/dist/esm/core/contexts/useWebsitePage.js +22 -0
- package/dist/esm/core/contexts/useWebsitePage.js.map +1 -0
- package/dist/esm/core/contexts/useWebsiteRuntime.d.ts +19 -0
- package/dist/esm/core/contexts/useWebsiteRuntime.d.ts.map +1 -0
- package/dist/esm/core/contexts/useWebsiteRuntime.js +28 -0
- package/dist/esm/core/contexts/useWebsiteRuntime.js.map +1 -0
- package/dist/esm/core/contexts/useWebsiteSection.d.ts +12 -0
- package/dist/esm/core/contexts/useWebsiteSection.d.ts.map +1 -0
- package/dist/esm/core/contexts/useWebsiteSection.js +22 -0
- package/dist/esm/core/contexts/useWebsiteSection.js.map +1 -0
- package/dist/esm/core/external-providers/frontend-provider-registry.website.d.ts +17 -0
- package/dist/esm/core/external-providers/frontend-provider-registry.website.d.ts.map +1 -0
- package/dist/esm/core/external-providers/frontend-provider-registry.website.js +23 -0
- package/dist/esm/core/external-providers/frontend-provider-registry.website.js.map +1 -0
- package/dist/esm/core/factories/define-website-page-manifest.d.ts +70 -0
- package/dist/esm/core/factories/define-website-page-manifest.d.ts.map +1 -0
- package/dist/esm/core/factories/define-website-page-manifest.js +51 -0
- package/dist/esm/core/factories/define-website-page-manifest.js.map +1 -0
- package/dist/esm/core/factories/define-website-section.d.ts +101 -0
- package/dist/esm/core/factories/define-website-section.d.ts.map +1 -0
- package/dist/esm/core/factories/define-website-section.js +71 -0
- package/dist/esm/core/factories/define-website-section.js.map +1 -0
- package/dist/esm/core/hooks/useWebsiteDesignTokens.d.ts +23 -0
- package/dist/esm/core/hooks/useWebsiteDesignTokens.d.ts.map +1 -0
- package/dist/esm/core/hooks/useWebsiteDesignTokens.js +25 -0
- package/dist/esm/core/hooks/useWebsiteDesignTokens.js.map +1 -0
- package/dist/esm/core/hooks/useWebsiteLabel.d.ts +68 -0
- package/dist/esm/core/hooks/useWebsiteLabel.d.ts.map +1 -0
- package/dist/esm/core/hooks/useWebsiteLabel.js +103 -0
- package/dist/esm/core/hooks/useWebsiteLabel.js.map +1 -0
- package/dist/esm/core/layouts/WebsitePageLayout.d.ts +87 -0
- package/dist/esm/core/layouts/WebsitePageLayout.d.ts.map +1 -0
- package/dist/esm/core/layouts/WebsitePageLayout.js +170 -0
- package/dist/esm/core/layouts/WebsitePageLayout.js.map +1 -0
- package/dist/esm/core/layouts/WebsiteSection.d.ts +91 -0
- package/dist/esm/core/layouts/WebsiteSection.d.ts.map +1 -0
- package/dist/esm/core/layouts/WebsiteSection.js +26 -0
- package/dist/esm/core/layouts/WebsiteSection.js.map +1 -0
- package/dist/esm/core/routing/internal-routing.utils.d.ts +65 -0
- package/dist/esm/core/routing/internal-routing.utils.d.ts.map +1 -0
- package/dist/esm/core/routing/internal-routing.utils.js +14 -0
- package/dist/esm/core/routing/internal-routing.utils.js.map +1 -0
- package/dist/esm/index.d.ts +129 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +129 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/mdx/BlogPost.d.ts +193 -0
- package/dist/esm/mdx/BlogPost.d.ts.map +1 -0
- package/dist/esm/mdx/BlogPost.js +161 -0
- package/dist/esm/mdx/BlogPost.js.map +1 -0
- package/dist/esm/mdx/blog-post-collection.config.d.ts +139 -0
- package/dist/esm/mdx/blog-post-collection.config.d.ts.map +1 -0
- package/dist/esm/mdx/blog-post-collection.config.js +27 -0
- package/dist/esm/mdx/blog-post-collection.config.js.map +1 -0
- package/dist/esm/mdx/blog-post-frontmatter-source.d.ts +12 -0
- package/dist/esm/mdx/blog-post-frontmatter-source.d.ts.map +1 -0
- package/dist/esm/mdx/blog-post-frontmatter-source.js +13 -0
- package/dist/esm/mdx/blog-post-frontmatter-source.js.map +1 -0
- package/dist/esm/mdx/index.d.ts +22 -0
- package/dist/esm/mdx/index.d.ts.map +1 -0
- package/dist/esm/mdx/index.js +22 -0
- package/dist/esm/mdx/index.js.map +1 -0
- package/dist/esm/mdx/website-mdx-provider.d.ts +90 -0
- package/dist/esm/mdx/website-mdx-provider.d.ts.map +1 -0
- package/dist/esm/mdx/website-mdx-provider.js +8 -0
- package/dist/esm/mdx/website-mdx-provider.js.map +1 -0
- package/dist/esm/mdx.d.ts +38 -0
- package/dist/esm/mdx.d.ts.map +1 -0
- package/dist/esm/mdx.js +38 -0
- package/dist/esm/mdx.js.map +1 -0
- package/dist/esm/schemas/blog/blog-post-frontmatter.shared.schemas.d.ts +75 -0
- package/dist/esm/schemas/blog/blog-post-frontmatter.shared.schemas.d.ts.map +1 -0
- package/dist/esm/schemas/blog/blog-post-frontmatter.shared.schemas.js +85 -0
- package/dist/esm/schemas/blog/blog-post-frontmatter.shared.schemas.js.map +1 -0
- package/dist/esm/schemas/design-tokens/website-design-tokens.shared.schemas.d.ts +120 -0
- package/dist/esm/schemas/design-tokens/website-design-tokens.shared.schemas.d.ts.map +1 -0
- package/dist/esm/schemas/design-tokens/website-design-tokens.shared.schemas.js +152 -0
- package/dist/esm/schemas/design-tokens/website-design-tokens.shared.schemas.js.map +1 -0
- package/dist/esm/schemas/label-keys/website-label-key.schemas.d.ts +73 -0
- package/dist/esm/schemas/label-keys/website-label-key.schemas.d.ts.map +1 -0
- package/dist/esm/schemas/label-keys/website-label-key.schemas.js +76 -0
- package/dist/esm/schemas/label-keys/website-label-key.schemas.js.map +1 -0
- package/dist/esm/schemas/manifests/website-page-manifest.shared.schemas.d.ts +209 -0
- package/dist/esm/schemas/manifests/website-page-manifest.shared.schemas.d.ts.map +1 -0
- package/dist/esm/schemas/manifests/website-page-manifest.shared.schemas.js +218 -0
- package/dist/esm/schemas/manifests/website-page-manifest.shared.schemas.js.map +1 -0
- package/dist/esm/schemas/manifests/website-root-config.shared.schemas.d.ts +431 -0
- package/dist/esm/schemas/manifests/website-root-config.shared.schemas.d.ts.map +1 -0
- package/dist/esm/schemas/manifests/website-root-config.shared.schemas.js +438 -0
- package/dist/esm/schemas/manifests/website-root-config.shared.schemas.js.map +1 -0
- package/dist/esm/schemas/refs/page-ref.schemas.d.ts +40 -0
- package/dist/esm/schemas/refs/page-ref.schemas.d.ts.map +1 -0
- package/dist/esm/schemas/refs/page-ref.schemas.js +43 -0
- package/dist/esm/schemas/refs/page-ref.schemas.js.map +1 -0
- package/dist/esm/schemas/refs/section-ref.schemas.d.ts +41 -0
- package/dist/esm/schemas/refs/section-ref.schemas.d.ts.map +1 -0
- package/dist/esm/schemas/refs/section-ref.schemas.js +44 -0
- package/dist/esm/schemas/refs/section-ref.schemas.js.map +1 -0
- package/dist/esm/schemas/sections/website-section-category.shared.d.ts +63 -0
- package/dist/esm/schemas/sections/website-section-category.shared.d.ts.map +1 -0
- package/dist/esm/schemas/sections/website-section-category.shared.js +64 -0
- package/dist/esm/schemas/sections/website-section-category.shared.js.map +1 -0
- package/dist/esm/schemas/sections/website-section-definition.shared.schemas.d.ts +114 -0
- package/dist/esm/schemas/sections/website-section-definition.shared.schemas.d.ts.map +1 -0
- package/dist/esm/schemas/sections/website-section-definition.shared.schemas.js +69 -0
- package/dist/esm/schemas/sections/website-section-definition.shared.schemas.js.map +1 -0
- package/dist/esm/schemas/structured-data/structured-data-reconciliation.shared.d.ts +100 -0
- package/dist/esm/schemas/structured-data/structured-data-reconciliation.shared.d.ts.map +1 -0
- package/dist/esm/schemas/structured-data/structured-data-reconciliation.shared.js +355 -0
- package/dist/esm/schemas/structured-data/structured-data-reconciliation.shared.js.map +1 -0
- package/dist/esm/schemas/structured-data/website-structured-data.shared.schemas.d.ts +58 -0
- package/dist/esm/schemas/structured-data/website-structured-data.shared.schemas.d.ts.map +1 -0
- package/dist/esm/schemas/structured-data/website-structured-data.shared.schemas.js +2 -0
- package/dist/esm/schemas/structured-data/website-structured-data.shared.schemas.js.map +1 -0
- package/dist/esm/schemas/validators/label-pack.validator.d.ts +144 -0
- package/dist/esm/schemas/validators/label-pack.validator.d.ts.map +1 -0
- package/dist/esm/schemas/validators/label-pack.validator.js +100 -0
- package/dist/esm/schemas/validators/label-pack.validator.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/package.json +143 -0
- package/src/__tests__/bundle-isolation.test.ts +607 -0
- package/src/astro/__tests__/blog-post-bridge.test.tsx +288 -0
- package/src/astro/__tests__/blog-post-head.renderer.test.ts +249 -0
- package/src/astro/__tests__/bridge-runtime.test.tsx +198 -0
- package/src/astro/__tests__/collect-expected-label-keys.test.ts +69 -0
- package/src/astro/__tests__/headers-renderer.test.ts +143 -0
- package/src/astro/__tests__/i18n-routing.helper.test.ts +116 -0
- package/src/astro/__tests__/label-pack-loader.test.ts +305 -0
- package/src/astro/__tests__/llms-txt-server.test.ts +127 -0
- package/src/astro/__tests__/pick-labels-for-page.test.ts +60 -0
- package/src/astro/__tests__/robots-renderer.test.ts +228 -0
- package/src/astro/__tests__/sitemap-coverage.test.ts +230 -0
- package/src/astro/__tests__/structured-data.renderer.test.ts +172 -0
- package/src/astro/__tests__/website-page-head.renderer.test.ts +424 -0
- package/src/astro/__tests__/website-page-runtime.helper.test.ts +157 -0
- package/src/astro/__tests__/website-site-context.test.ts +121 -0
- package/src/astro/blog-post-bridge.tsx +404 -0
- package/src/astro/blog-post-head.renderer.ts +293 -0
- package/src/astro/bridge-runtime.tsx +270 -0
- package/src/astro/collect-expected-label-keys.ts +113 -0
- package/src/astro/headers-renderer.ts +82 -0
- package/src/astro/i18n-routing.helper.ts +116 -0
- package/src/astro/internal/html-escape.ts +41 -0
- package/src/astro/label-pack-loader.ts +385 -0
- package/src/astro/llms-txt-server.ts +56 -0
- package/src/astro/pick-labels-for-page.ts +85 -0
- package/src/astro/robots-renderer.ts +171 -0
- package/src/astro/sitemap-coverage.ts +186 -0
- package/src/astro/structured-data.renderer.ts +171 -0
- package/src/astro/website-page-head.renderer.ts +279 -0
- package/src/astro/website-page-runtime.helper.ts +188 -0
- package/src/astro/website-site-context.ts +136 -0
- package/src/astro-island.ts +61 -0
- package/src/astro.ts +151 -0
- package/src/companion-exports.ts +38 -0
- package/src/components/low-level/WebsiteButton.tsx +118 -0
- package/src/components/low-level/WebsiteHeading.tsx +96 -0
- package/src/components/low-level/WebsiteImage.tsx +96 -0
- package/src/components/low-level/WebsiteInternalButton.tsx +172 -0
- package/src/components/low-level/WebsiteInternalLink.tsx +193 -0
- package/src/components/low-level/WebsiteLink.tsx +71 -0
- package/src/components/low-level/WebsiteText.tsx +75 -0
- package/src/components/low-level/__tests__/WebsiteInternalButton.test.tsx +169 -0
- package/src/components/low-level/__tests__/WebsiteInternalLink.test.tsx +202 -0
- package/src/components/low-level/__tests__/primitives.test.tsx +141 -0
- package/src/config/__tests__/define-website-config.test.ts +231 -0
- package/src/config/__tests__/load-website-config.test.ts +215 -0
- package/src/config/define-website-config.ts +134 -0
- package/src/config/index.ts +38 -0
- package/src/config/load-website-config.ts +229 -0
- package/src/config/wildo-website-config.schemas.ts +322 -0
- package/src/config-loader.ts +35 -0
- package/src/core/__tests__/WebsitePageLayout.test.tsx +184 -0
- package/src/core/__tests__/WebsiteSection.test.tsx +85 -0
- package/src/core/__tests__/contexts.test.tsx +133 -0
- package/src/core/__tests__/core-boundary.test.ts +85 -0
- package/src/core/__tests__/define-website-page-manifest.test.tsx +111 -0
- package/src/core/__tests__/define-website-section.test.tsx +89 -0
- package/src/core/__tests__/useWebsiteDesignTokens.test.tsx +41 -0
- package/src/core/__tests__/useWebsiteLabel.test.tsx +117 -0
- package/src/core/anonymous-session/InboundContactForm.tsx +157 -0
- package/src/core/anonymous-session/__tests__/inbound-contact-form.schema.test.ts +44 -0
- package/src/core/anonymous-session/inbound-contact-form.schema.ts +62 -0
- package/src/core/anonymous-session/website-anonymous-session-client.ts +194 -0
- package/src/core/contexts/WebsitePageContext.tsx +52 -0
- package/src/core/contexts/WebsiteRuntimeContext.tsx +175 -0
- package/src/core/contexts/WebsiteSectionContext.tsx +59 -0
- package/src/core/contexts/useWebsitePage.ts +28 -0
- package/src/core/contexts/useWebsiteRuntime.ts +34 -0
- package/src/core/contexts/useWebsiteSection.ts +28 -0
- package/src/core/external-providers/frontend-provider-registry.website.ts +62 -0
- package/src/core/factories/define-website-page-manifest.ts +102 -0
- package/src/core/factories/define-website-section.ts +128 -0
- package/src/core/hooks/useWebsiteDesignTokens.ts +26 -0
- package/src/core/hooks/useWebsiteLabel.ts +121 -0
- package/src/core/layouts/WebsitePageLayout.tsx +311 -0
- package/src/core/layouts/WebsiteSection.tsx +139 -0
- package/src/core/routing/__tests__/internal-routing.utils.test.ts +134 -0
- package/src/core/routing/internal-routing.utils.ts +77 -0
- package/src/index.ts +132 -0
- package/src/mdx/BlogPost.tsx +296 -0
- package/src/mdx/__tests__/BlogPost.test.tsx +218 -0
- package/src/mdx/__tests__/blog-post-collection.config.test.ts +127 -0
- package/src/mdx/__tests__/website-mdx-provider.test.tsx +82 -0
- package/src/mdx/blog-post-collection.config.ts +177 -0
- package/src/mdx/blog-post-frontmatter-source.ts +31 -0
- package/src/mdx/index.ts +39 -0
- package/src/mdx/website-mdx-provider.tsx +95 -0
- package/src/mdx.ts +38 -0
- package/src/schemas/__tests__/blog-frontmatter.test.ts +50 -0
- package/src/schemas/__tests__/companion-exports-react-free.test.ts +51 -0
- package/src/schemas/__tests__/design-tokens.test.ts +163 -0
- package/src/schemas/__tests__/label-key.test.ts +46 -0
- package/src/schemas/__tests__/label-pack-validator.test.ts +146 -0
- package/src/schemas/__tests__/page-manifest.test.ts +66 -0
- package/src/schemas/__tests__/refs.test.ts +37 -0
- package/src/schemas/__tests__/root-config.test.ts +292 -0
- package/src/schemas/__tests__/section-definition.test.ts +47 -0
- package/src/schemas/__tests__/structured-data-reconciliation.test.ts +543 -0
- package/src/schemas/blog/blog-post-frontmatter.shared.schemas.ts +111 -0
- package/src/schemas/design-tokens/website-design-tokens.shared.schemas.ts +166 -0
- package/src/schemas/label-keys/website-label-key.schemas.ts +88 -0
- package/src/schemas/manifests/website-page-manifest.shared.schemas.ts +266 -0
- package/src/schemas/manifests/website-root-config.shared.schemas.ts +504 -0
- package/src/schemas/refs/page-ref.schemas.ts +49 -0
- package/src/schemas/refs/section-ref.schemas.ts +50 -0
- package/src/schemas/sections/website-section-category.shared.ts +65 -0
- package/src/schemas/sections/website-section-definition.shared.schemas.ts +120 -0
- package/src/schemas/structured-data/structured-data-reconciliation.shared.ts +579 -0
- package/src/schemas/structured-data/website-structured-data.shared.schemas.ts +62 -0
- package/src/schemas/validators/label-pack.validator.ts +201 -0
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
import type { ComponentType, FunctionComponent, ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
import type { FrontendProvidersBlock } from '@wildo-ai/saas-models/public-runtime';
|
|
4
|
+
import type { AvailableLanguage } from '@wildo-ai/saas-models/public-runtime';
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
WebsiteRuntimeContextProvider,
|
|
8
|
+
type WebsiteRuntimeContextValue,
|
|
9
|
+
} from '../core/contexts/WebsiteRuntimeContext';
|
|
10
|
+
import { createFrontendWebsiteProviderRegistry } from '../core/external-providers/frontend-provider-registry.website';
|
|
11
|
+
import { BlogPost, BLOG_POST_PAGE_REF } from '../mdx/BlogPost';
|
|
12
|
+
import type { WebsiteMdxComponentsMap } from '../mdx/website-mdx-provider';
|
|
13
|
+
import type { WebsiteDesignTokens } from '../schemas/design-tokens/website-design-tokens.shared.schemas';
|
|
14
|
+
import type { WebsiteLabelKey } from '../schemas/label-keys/website-label-key.schemas';
|
|
15
|
+
import type { WebsiteNavigationConfig } from '../schemas/manifests/website-root-config.shared.schemas';
|
|
16
|
+
import type { LabelPack } from '../schemas/validators/label-pack.validator';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @wildo_source:part:start saas.website.blog.bridge facet:layer:astro facet:family:website
|
|
20
|
+
*
|
|
21
|
+
* `createWebsiteBlogPostBridgeIsland(deps)` — factory that returns the
|
|
22
|
+
* React island a consumer's per-locale `*.bridge.tsx` module exports for
|
|
23
|
+
* mounting blog post pages. **Sibling** of `createWebsitePageBridgeIsland`
|
|
24
|
+
* but adapted to the dynamic-routing constraint of the marketing-blog
|
|
25
|
+
* adapter (Phase 7, D-6 = Option A).
|
|
26
|
+
*
|
|
27
|
+
* # Why blog posts cannot reuse the page bridge factory
|
|
28
|
+
*
|
|
29
|
+
* Three structural differences between marketing pages and blog posts
|
|
30
|
+
* forced this dedicated factory shape:
|
|
31
|
+
*
|
|
32
|
+
* 1. **Per-slug body resolution.** A marketing page (`landing`,
|
|
33
|
+
* `pricing`, etc.) has ONE `PageComponent` known at bridge-module
|
|
34
|
+
* load time — the page bridge closes over it. A blog post's body
|
|
35
|
+
* is the compiled MDX module, which varies per slug. Closing the
|
|
36
|
+
* MDX body inside the factory at module load time would force one
|
|
37
|
+
* bridge file per post (defeats Q16=B "one MDX file per post").
|
|
38
|
+
* Instead, the factory closes over a `slugToMdxBody: Record<string,
|
|
39
|
+
* ComponentType>` map — typically built from
|
|
40
|
+
* `import.meta.glob('./content/blog/<locale>/*.mdx', { eager: true })`
|
|
41
|
+
* on the consumer side — and the island accepts the active `slug`
|
|
42
|
+
* as a primitive (JSON-serializable) prop.
|
|
43
|
+
*
|
|
44
|
+
* 2. **Layout already wrapped by `<BlogPost>`.** The page bridge wraps
|
|
45
|
+
* its `PageComponent` in `<WebsitePageLayout pageRef={…}>`. The
|
|
46
|
+
* `<BlogPost>` renderer ALREADY wraps its tree in
|
|
47
|
+
* `<WebsitePageLayout pageRef={BLOG_POST_PAGE_REF}>` (the framework
|
|
48
|
+
* reserves the page ref for the entire blog surface — see
|
|
49
|
+
* `BLOG_POST_PAGE_REF` JSDoc in `BlogPost.tsx`). Reusing the page
|
|
50
|
+
* bridge would double-wrap the layout. This factory instead
|
|
51
|
+
* provides the runtime context and yields directly to `<BlogPost>`,
|
|
52
|
+
* which owns the layout boundary itself.
|
|
53
|
+
*
|
|
54
|
+
* 3. **Astro's React-children context-propagation gap.** Astro
|
|
55
|
+
* renders React component children INDEPENDENTLY of the parent
|
|
56
|
+
* component when the boundary is `.astro` ↔ `.tsx`, even on the
|
|
57
|
+
* server side. This means
|
|
58
|
+
* `<BlogPost client:load><Content /></BlogPost>` written in an
|
|
59
|
+
* `.astro` file would NOT propagate the `<WebsiteMdxProvider>`
|
|
60
|
+
* context to the React components embedded inside `<Content />`
|
|
61
|
+
* (the embedded `<CTASection />` would render WITHOUT the engine's
|
|
62
|
+
* MDX provider scope; the `mdxComponents` map would be ignored).
|
|
63
|
+
* Confirmed via the Astro docs, `@astrojs/react` integration
|
|
64
|
+
* readme, and the documented "Bridging two JSX runtimes" gotcha.
|
|
65
|
+
*
|
|
66
|
+
* The fix: the entire blog post tree (BlogPost + MDX body +
|
|
67
|
+
* embedded section components) lives inside ONE React island. The
|
|
68
|
+
* MDX module is imported as a React component via Astro's
|
|
69
|
+
* `import.meta.glob`, and the bridge renders it as JSX children
|
|
70
|
+
* of `<BlogPost>` from INSIDE the island — no `.astro` ↔ `.tsx`
|
|
71
|
+
* boundary is crossed during the body render.
|
|
72
|
+
*
|
|
73
|
+
* # Why hydration is required (vs. pure SSR)
|
|
74
|
+
*
|
|
75
|
+
* The `WebsiteRuntimeContextProvider` + `<BlogPost>` tree could in
|
|
76
|
+
* theory render on the server only (no `client:*` directive). But:
|
|
77
|
+
*
|
|
78
|
+
* - Embedded sections (`<CTASection />`) typically have their own
|
|
79
|
+
* interactivity (analytics handlers, A/B variant flippers, etc.)
|
|
80
|
+
* that need React event listeners to attach client-side.
|
|
81
|
+
* - The framework's `useWebsiteLabel(...)` hook chain assumes a live
|
|
82
|
+
* React render tree — a pure-SSR tree would freeze label resolution
|
|
83
|
+
* at build time, but any future client-driven label override (e.g.
|
|
84
|
+
* a debug-mode label inspector) would silently break.
|
|
85
|
+
*
|
|
86
|
+
* The factory therefore returns an island that the consumer's `.astro`
|
|
87
|
+
* mounts with `client:load` (or `client:idle` for posts known to be
|
|
88
|
+
* non-interactive). The hydration cost is bounded by the per-locale MDX
|
|
89
|
+
* glob — see "Bundle scaling cliff" below.
|
|
90
|
+
*
|
|
91
|
+
* # Bundle scaling cliff (deferred trade-off)
|
|
92
|
+
*
|
|
93
|
+
* `import.meta.glob({ eager: true })` materializes EVERY post's
|
|
94
|
+
* compiled JS into the per-locale React-island bundle (~5–20 KB per
|
|
95
|
+
* post depending on length and embedded section count). For the
|
|
96
|
+
* Phase 7 dogfood (≤10 posts) this is fine and matches the documented
|
|
97
|
+
* Astro+MDX pattern. Past ~50 posts this becomes a real budget concern.
|
|
98
|
+
* The factory's API is forward-compatible with `{ eager: false }`
|
|
99
|
+
* (lazy loaders): swap the consumer's glob to lazy mode and the
|
|
100
|
+
* `slugToMdxBody[slug]` lookup returns a `() => Promise<{ default:
|
|
101
|
+
* ComponentType }>`; wrap in `React.lazy()` + `<Suspense>` and the
|
|
102
|
+
* factory call site stays unchanged. The migration is a consumer-side
|
|
103
|
+
* change, not an engine API break.
|
|
104
|
+
*
|
|
105
|
+
* # Authoring pattern
|
|
106
|
+
*
|
|
107
|
+
* **Per-locale bridge file** (consumer side, ONE per locale):
|
|
108
|
+
*
|
|
109
|
+
* ```tsx
|
|
110
|
+
* // examples/<app>/website/src/pages-impl/blog-post-en.bridge.tsx
|
|
111
|
+
* import type { ComponentType } from 'react';
|
|
112
|
+
*
|
|
113
|
+
* import { createWebsiteBlogPostBridgeIsland }
|
|
114
|
+
* from '@wildo-ai/saas-website/mdx';
|
|
115
|
+
* import { BLOG_POST_MDX_COMPONENTS }
|
|
116
|
+
* from './blog-post.mdx-components';
|
|
117
|
+
* import { WEBSITE_ROOT_CONFIG } from '../website-root.config';
|
|
118
|
+
*
|
|
119
|
+
* // Static analyzable glob — Vite resolves at build time. The glob
|
|
120
|
+
* // pattern MUST be a single string literal (no concatenation, no
|
|
121
|
+
* // variable interpolation); Vite parses it AST-side. The `as` cast
|
|
122
|
+
* // narrows the unknown record to the per-MDX-file shape Astro's mdx
|
|
123
|
+
* // integration emits (default export = the compiled React component).
|
|
124
|
+
* const rawModules = import.meta.glob('./content/blog/en/*.mdx', {
|
|
125
|
+
* eager: true,
|
|
126
|
+
* }) as Record<string, { default: ComponentType }>;
|
|
127
|
+
*
|
|
128
|
+
* const slugToMdxBody: Record<string, ComponentType> = {};
|
|
129
|
+
* for (const [path, mod] of Object.entries(rawModules)) {
|
|
130
|
+
* // './content/blog/en/why-context.mdx' -> 'why-context'
|
|
131
|
+
* const slug = path.split('/').pop()!.replace(/\.mdx$/, '');
|
|
132
|
+
* slugToMdxBody[slug] = mod.default;
|
|
133
|
+
* }
|
|
134
|
+
*
|
|
135
|
+
* export const BlogPostEnBridgeIsland =
|
|
136
|
+
* createWebsiteBlogPostBridgeIsland({
|
|
137
|
+
* slugToMdxBody,
|
|
138
|
+
* navigation: WEBSITE_ROOT_CONFIG.navigation,
|
|
139
|
+
* mdxComponents: BLOG_POST_MDX_COMPONENTS,
|
|
140
|
+
* });
|
|
141
|
+
* ```
|
|
142
|
+
*
|
|
143
|
+
* **Per-locale `[slug].astro` shell** (consumer side):
|
|
144
|
+
*
|
|
145
|
+
* ```astro
|
|
146
|
+
* ---
|
|
147
|
+
* import { getCollection } from 'astro:content';
|
|
148
|
+
* import {
|
|
149
|
+
* loadWebsitePageRuntime,
|
|
150
|
+
* renderBlogPostHeadHtml,
|
|
151
|
+
* renderWebsiteDesignTokensCss,
|
|
152
|
+
* } from '@wildo-ai/saas-website/astro';
|
|
153
|
+
* import { parseBlogPostFrontmatter } from '@wildo-ai/saas-website/mdx';
|
|
154
|
+
* import { BlogPostEnBridgeIsland } from '@/pages-impl/blog-post-en.bridge';
|
|
155
|
+
* import { BLOG_POST_PAGE_MANIFEST } from '@/pages-impl/blog-post.page';
|
|
156
|
+
* import { WEBSITE_SITE_CONTEXT } from '@/website-site-context';
|
|
157
|
+
*
|
|
158
|
+
* export async function getStaticPaths() {
|
|
159
|
+
* const posts = await getCollection('blog');
|
|
160
|
+
* const defaultLocale = WEBSITE_SITE_CONTEXT.websiteConfig.defaultLocale;
|
|
161
|
+
* return posts
|
|
162
|
+
* .filter((p) => p.data.locale === defaultLocale)
|
|
163
|
+
* .map((p) => ({ params: { slug: p.data.slug }, props: { entry: p } }));
|
|
164
|
+
* }
|
|
165
|
+
* const { entry } = Astro.props;
|
|
166
|
+
*
|
|
167
|
+
* const runtime = loadWebsitePageRuntime({
|
|
168
|
+
* manifest: BLOG_POST_PAGE_MANIFEST,
|
|
169
|
+
* siteContext: WEBSITE_SITE_CONTEXT,
|
|
170
|
+
* labelPacksDir: './src/i18n',
|
|
171
|
+
* astroLocale: Astro.currentLocale,
|
|
172
|
+
* });
|
|
173
|
+
* const frontmatter = parseBlogPostFrontmatter(entry.data, { source: entry.id });
|
|
174
|
+
* const headHtml = renderBlogPostHeadHtml({
|
|
175
|
+
* siteContext: WEBSITE_SITE_CONTEXT,
|
|
176
|
+
* locale: runtime.locale,
|
|
177
|
+
* routePath: `/blog/${frontmatter.slug}`,
|
|
178
|
+
* frontmatter,
|
|
179
|
+
* });
|
|
180
|
+
* const designTokensCss = renderWebsiteDesignTokensCss(
|
|
181
|
+
* WEBSITE_SITE_CONTEXT.rootConfig.designTokens,
|
|
182
|
+
* );
|
|
183
|
+
* ---
|
|
184
|
+
* <!doctype html>
|
|
185
|
+
* <html lang={runtime.locale}>
|
|
186
|
+
* <head>
|
|
187
|
+
* <meta charset="UTF-8" />
|
|
188
|
+
* <meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
|
189
|
+
* <Fragment set:html={headHtml} />
|
|
190
|
+
* <style set:html={designTokensCss}></style>
|
|
191
|
+
* </head>
|
|
192
|
+
* <body>
|
|
193
|
+
* <BlogPostEnBridgeIsland
|
|
194
|
+
* client:load
|
|
195
|
+
* slug={frontmatter.slug}
|
|
196
|
+
* rawFrontmatter={entry.data}
|
|
197
|
+
* source={entry.id}
|
|
198
|
+
* locale={runtime.locale}
|
|
199
|
+
* defaultLocale={runtime.defaultLocale}
|
|
200
|
+
* labelPack={runtime.labelPack}
|
|
201
|
+
* designTokens={WEBSITE_SITE_CONTEXT.rootConfig.designTokens}
|
|
202
|
+
* skipToMainContentLabelKey={
|
|
203
|
+
* WEBSITE_SITE_CONTEXT.rootConfig.skipToMainContentLabelKey
|
|
204
|
+
* }
|
|
205
|
+
* />
|
|
206
|
+
* </body>
|
|
207
|
+
* </html>
|
|
208
|
+
* ```
|
|
209
|
+
*
|
|
210
|
+
* # Boundary
|
|
211
|
+
*
|
|
212
|
+
* Strictly client-bundle-safe (re-exported from `mdx.ts` — NOT from
|
|
213
|
+
* `astro-island.ts`, because this module hard-imports the MDX adapter
|
|
214
|
+
* whose `@mdx-js/react` peer is optional; walked by the
|
|
215
|
+
* bundle-isolation test). MUST stay clear of `node:*` and SSR-tier
|
|
216
|
+
* specifiers.
|
|
217
|
+
*/
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Module-load-time dependencies — closed over inside the returned
|
|
221
|
+
* island. NEVER cross the hydration boundary as serialized props.
|
|
222
|
+
*/
|
|
223
|
+
export interface CreateWebsiteBlogPostBridgeIslandDeps {
|
|
224
|
+
/**
|
|
225
|
+
* Per-slug map of compiled MDX bodies (each entry is a React
|
|
226
|
+
* component — the `.default` export of the MDX module). Typically
|
|
227
|
+
* built from `import.meta.glob('./content/blog/<locale>/*.mdx',
|
|
228
|
+
* { eager: true })` with the path-key normalized to the slug. Closed
|
|
229
|
+
* over at module-load time so the entire MDX body graph for the
|
|
230
|
+
* locale lands inside ONE React island bundle (D-6 Option A) — this
|
|
231
|
+
* is the structural fix for Astro's React-children context-propagation
|
|
232
|
+
* gap (see file preamble).
|
|
233
|
+
*
|
|
234
|
+
* The map is read by `slugToMdxBody[props.slug]` at island render
|
|
235
|
+
* time. A missing slug throws a clear framework-owned error (rather than
|
|
236
|
+
* rendering an empty body silently); the consumer's `getStaticPaths`
|
|
237
|
+
* is responsible for not emitting routes for slugs absent from the
|
|
238
|
+
* map.
|
|
239
|
+
*
|
|
240
|
+
* **Why `ComponentType<any>` and not a stricter generic**: matches
|
|
241
|
+
* the upstream `@mdx-js/react` convention (`MDXContent` from
|
|
242
|
+
* `mdx/types` is parameterized over an open `MDXProps` shape). MDX
|
|
243
|
+
* compilation hands the body a compiler-managed props object that
|
|
244
|
+
* the type system cannot narrow at the framework boundary; using
|
|
245
|
+
* `<any>` here keeps the consumer's
|
|
246
|
+
* `import.meta.glob(...) as Record<string, { default: ComponentType }>`
|
|
247
|
+
* cast assignable without an additional wrap/unwrap. Same posture
|
|
248
|
+
* as `WebsiteMdxComponentsMap` (intentional symmetry).
|
|
249
|
+
*/
|
|
250
|
+
slugToMdxBody: Readonly<Record<string, ComponentType<any>>>;
|
|
251
|
+
/**
|
|
252
|
+
* Site-wide navigation slot bindings (header / footer components).
|
|
253
|
+
* Closed over here for the same reason as the page bridge: both
|
|
254
|
+
* fields are `ComponentType` refs that cannot survive Astro's
|
|
255
|
+
* serialization boundary.
|
|
256
|
+
*/
|
|
257
|
+
navigation: WebsiteNavigationConfig;
|
|
258
|
+
/**
|
|
259
|
+
* MDX-tag → React-component map forwarded into `<BlogPost>` and
|
|
260
|
+
* scoped via `<WebsiteMdxProvider>`. Typically a small object
|
|
261
|
+
* literal exporting the consumer-authored business sections that
|
|
262
|
+
* blog posts can embed (`<CTASection />`, etc.). Closed over here
|
|
263
|
+
* (rather than passed as an island prop) because the values are
|
|
264
|
+
* `ComponentType` refs.
|
|
265
|
+
*/
|
|
266
|
+
mdxComponents?: WebsiteMdxComponentsMap;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Hydration-boundary props — what the consumer's `.astro` page passes
|
|
271
|
+
* to `<BlogPostEnBridgeIsland client:load ...{primitiveProps}/>`.
|
|
272
|
+
* Every field is JSON-serializable.
|
|
273
|
+
*/
|
|
274
|
+
export interface WebsiteBlogPostBridgeIslandProps {
|
|
275
|
+
/**
|
|
276
|
+
* Slug of the post being rendered. Used by the island to look up
|
|
277
|
+
* the matching MDX body in `deps.slugToMdxBody`. Carried as a plain
|
|
278
|
+
* string (not the branded `BlogPostSlug`) because Astro's
|
|
279
|
+
* serialization boundary unwraps brands.
|
|
280
|
+
*/
|
|
281
|
+
slug: string;
|
|
282
|
+
/**
|
|
283
|
+
* Raw frontmatter object Astro hands the page from `entry.data`.
|
|
284
|
+
* Forwarded straight to `<BlogPost>` for strict Zod-4 validation.
|
|
285
|
+
* The bridge does NOT re-validate (single validation surface, owned
|
|
286
|
+
* by the renderer).
|
|
287
|
+
*/
|
|
288
|
+
rawFrontmatter: unknown;
|
|
289
|
+
/**
|
|
290
|
+
* Diagnostic source identifier echoed into validation errors —
|
|
291
|
+
* typically `entry.id` from Astro's content collection. Optional
|
|
292
|
+
* but recommended for actionable error messages.
|
|
293
|
+
*/
|
|
294
|
+
source?: string;
|
|
295
|
+
/** The locale Astro resolved (with default-locale fallback). */
|
|
296
|
+
locale: AvailableLanguage;
|
|
297
|
+
/**
|
|
298
|
+
* The site's default locale. Required for `WebsiteInternalLink`
|
|
299
|
+
* locale-prefix logic (mirrors the page bridge's `defaultLocale`
|
|
300
|
+
* island prop).
|
|
301
|
+
*/
|
|
302
|
+
defaultLocale: AvailableLanguage;
|
|
303
|
+
/** Already-loaded + already-shape-validated label pack. */
|
|
304
|
+
labelPack: LabelPack;
|
|
305
|
+
/** Design-token bundle from `WebsiteRootConfig.designTokens`. */
|
|
306
|
+
designTokens: WebsiteDesignTokens;
|
|
307
|
+
/**
|
|
308
|
+
* Fully-composed label key the framework reads to render the
|
|
309
|
+
* "Skip to main content" affordance. Mirrors
|
|
310
|
+
* `WebsiteRootConfig.skipToMainContentLabelKey`. Carried as a
|
|
311
|
+
* primitive island prop for the same reason as the page bridge.
|
|
312
|
+
*/
|
|
313
|
+
skipToMainContentLabelKey: WebsiteLabelKey;
|
|
314
|
+
/** Optional website-facing public providers materialized at build time. */
|
|
315
|
+
frontendProviders?: FrontendProvidersBlock;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const EMPTY_MDX_COMPONENTS: WebsiteMdxComponentsMap = Object.freeze({});
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Returns a FUNCTION component, not the wider `ComponentType` union. The island IS a function
|
|
322
|
+
* component — Astro hydrates nothing else here — and the union is not callable, so declaring it
|
|
323
|
+
* cost callers the ability to invoke the island directly (which the bridge suites do, to observe
|
|
324
|
+
* the synchronous throw for an unregistered slug without routing it through React's reconciler
|
|
325
|
+
* error path). `FunctionComponent` is assignable to `ComponentType`, so no consumer narrows.
|
|
326
|
+
*/
|
|
327
|
+
export function createWebsiteBlogPostBridgeIsland(
|
|
328
|
+
deps: CreateWebsiteBlogPostBridgeIslandDeps,
|
|
329
|
+
): FunctionComponent<WebsiteBlogPostBridgeIslandProps> {
|
|
330
|
+
const {
|
|
331
|
+
slugToMdxBody,
|
|
332
|
+
navigation,
|
|
333
|
+
mdxComponents = EMPTY_MDX_COMPONENTS,
|
|
334
|
+
} = deps;
|
|
335
|
+
|
|
336
|
+
function WebsiteBlogPostBridgeIsland({
|
|
337
|
+
slug,
|
|
338
|
+
rawFrontmatter,
|
|
339
|
+
source,
|
|
340
|
+
locale,
|
|
341
|
+
defaultLocale,
|
|
342
|
+
labelPack,
|
|
343
|
+
designTokens,
|
|
344
|
+
skipToMainContentLabelKey,
|
|
345
|
+
frontendProviders,
|
|
346
|
+
}: WebsiteBlogPostBridgeIslandProps): ReactNode {
|
|
347
|
+
const MdxBody = slugToMdxBody[slug];
|
|
348
|
+
if (MdxBody === undefined) {
|
|
349
|
+
/**
|
|
350
|
+
* Loud failure — the consumer's `getStaticPaths` is supposed to
|
|
351
|
+
* only emit routes for slugs present in the MDX glob. A missing
|
|
352
|
+
* lookup means the glob and the collection are out of sync; the
|
|
353
|
+
* operator needs an actionable error string with the offending
|
|
354
|
+
* slug + the keys that ARE present (truncated to keep the build
|
|
355
|
+
* log readable).
|
|
356
|
+
*/
|
|
357
|
+
const knownKeys = Object.keys(slugToMdxBody);
|
|
358
|
+
const known =
|
|
359
|
+
knownKeys.length <= 5
|
|
360
|
+
? knownKeys.join(', ')
|
|
361
|
+
: `${knownKeys.slice(0, 5).join(', ')}, … (${knownKeys.length} total)`;
|
|
362
|
+
throw new Error(
|
|
363
|
+
`[blog-post-bridge] No MDX body registered for slug="${slug}". ` +
|
|
364
|
+
`The bridge factory's slugToMdxBody map only knows: ${known}. ` +
|
|
365
|
+
`Verify the consumer's import.meta.glob('...content/blog/<locale>/*.mdx') ` +
|
|
366
|
+
`pattern matches the source file naming.`,
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
const runtimeValue: WebsiteRuntimeContextValue = {
|
|
371
|
+
locale,
|
|
372
|
+
defaultLocale,
|
|
373
|
+
labelPack,
|
|
374
|
+
designTokens,
|
|
375
|
+
navigation,
|
|
376
|
+
skipToMainContentLabelKey,
|
|
377
|
+
frontendProviderRegistry: createFrontendWebsiteProviderRegistry(frontendProviders),
|
|
378
|
+
};
|
|
379
|
+
return (
|
|
380
|
+
<WebsiteRuntimeContextProvider value={runtimeValue}>
|
|
381
|
+
<BlogPost
|
|
382
|
+
rawFrontmatter={rawFrontmatter}
|
|
383
|
+
source={source}
|
|
384
|
+
mdxComponents={mdxComponents}
|
|
385
|
+
>
|
|
386
|
+
<MdxBody />
|
|
387
|
+
</BlogPost>
|
|
388
|
+
</WebsiteRuntimeContextProvider>
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
WebsiteBlogPostBridgeIsland.displayName = 'WebsiteBlogPostBridgeIsland';
|
|
392
|
+
|
|
393
|
+
return WebsiteBlogPostBridgeIsland;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Re-export of the framework-reserved blog-post page ref. Consumers
|
|
398
|
+
* authoring `BLOG_POST_PAGE_MANIFEST` need this constant to satisfy
|
|
399
|
+
* the manifest's `ref` field; re-exporting it from the bridge module
|
|
400
|
+
* means the consumer's per-locale bridge file can grab both symbols
|
|
401
|
+
* from the one `@wildo-ai/saas-website/mdx` import it already has.
|
|
402
|
+
*/
|
|
403
|
+
export { BLOG_POST_PAGE_REF };
|
|
404
|
+
/** @wildo_source:part:end saas.website.blog.bridge */
|