diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e3e55323483..b1fb5d330d3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -24,12 +24,14 @@ pnpm install-conflict # This will reset the lockfile to the upstream version and pnpm build ``` -- (Optional) Install [Playwright](https://playwright.dev/) browsers for UI testing +- (Optional) Install [Playwright](https://playwright.dev/) browsers for UI testing and server-side Mermaid diagram rendering in the website ```bash -npx playwright install +npx playwright install --with-deps chromium ``` +> **Note:** Without Playwright, `pnpm build` still succeeds. Mermaid diagrams in the website will fall back to client-side rendering instead of being pre-rendered as SVGs. + - Start the build in watch mode to automatically rebuild on save ```bash diff --git a/website/astro.config.mjs b/website/astro.config.mjs index b867e435c2e..aeeeaaa4bff 100644 --- a/website/astro.config.mjs +++ b/website/astro.config.mjs @@ -46,6 +46,36 @@ const base = process.env.TYPESPEC_WEBSITE_BASE_PATH ?? "/"; const initJsIntegrity = computeSriHash("1ds-init.js"); +/** + * Detect whether a Playwright browser can be launched. + * In CI environments, always returns 'inline-svg' for server-side SVG pre-rendering. + * Locally, returns 'inline-svg' if Playwright is available, or 'pre-mermaid' as a + * fallback for client-side rendering when Playwright is not installed. + * @returns {Promise<'inline-svg' | 'pre-mermaid'>} + */ +async function getMermaidStrategy() { + if (process.env.CI) { + return "inline-svg"; + } + try { + const { chromium } = await import("playwright"); + const browser = await chromium.launch(); + await browser.close(); + return "inline-svg"; + } catch { + // eslint-disable-next-line no-console + console.warn( + "[rehype-mermaid] Playwright is not available or browser system dependencies are missing.\n" + + " Mermaid diagrams will use client-side rendering (pre-mermaid strategy).\n" + + " To enable server-side SVG rendering, install Playwright:\n" + + " npx playwright install --with-deps chromium", + ); + return "pre-mermaid"; + } +} + +const mermaidStrategy = await getMermaidStrategy(); + // https://astro.build/config export default defineConfig({ base, @@ -135,7 +165,7 @@ export default defineConfig({ // @ts-expect-error wrong type remarkPlugins: [remarkHeadingID], rehypePlugins: [ - rehypeMermaid, + [rehypeMermaid, { strategy: mermaidStrategy }], [rehypeAstroRelativeMarkdownLinks, { base, collectionBase: false, trailingSlash: "always" }], ], shikiConfig: {