// Renders a fixture through the real render.js in a headless browser, because // everything the page does — Markdown, Mermaid, the DOM fix-ups — only happens // where there is a DOM. Skips itself when no browser can be found. const fs = require("fs"); const path = require("path"); const os = require("os"); const { execFileSync } = require("child_process"); const EXT = path.join(__dirname, ".."); const { buildDocument } = require(path.join(EXT, "Scripts", "render.js")); function findBrowser() { if (process.env.MERMAID_PREVIEW_CHROME) return process.env.MERMAID_PREVIEW_CHROME; const cache = path.join(os.homedir(), "Library", "Caches", "ms-playwright"); if (fs.existsSync(cache)) { for (const entry of fs.readdirSync(cache)) { const candidate = path.join(cache, entry, "chrome-headless-shell-mac-arm64", "chrome-headless-shell"); if (fs.existsSync(candidate)) return candidate; } } const chrome = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"; return fs.existsSync(chrome) ? chrome : null; } const browser = findBrowser(); if (!browser) { console.log("SKIP no headless browser found (set MERMAID_PREVIEW_CHROME to one)"); process.exit(0); } const work = path.join(__dirname, ".tmp", "render"); fs.rmSync(work, { recursive: true, force: true }); fs.mkdirSync(path.join(work, "out", "assets", "vendor"), { recursive: true }); fs.mkdirSync(path.join(work, "docs"), { recursive: true }); for (const name of ["preview.css", "preview.js"]) { fs.copyFileSync(path.join(EXT, "Assets", name), path.join(work, "out", "assets", name)); } for (const name of ["markdown-it.min.js", "mermaid.min.js"]) { fs.copyFileSync(path.join(EXT, "Assets", "vendor", name), path.join(work, "out", "assets", "vendor", name)); } const markdown = fs.readFileSync(path.join(__dirname, "fixtures", "sample.md"), "utf8"); fs.writeFileSync(path.join(work, "docs", "sample.md"), markdown); const results = []; const check = (name, ok) => results.push([ok ? "PASS" : "FAIL", name]); function render(theme) { const page = path.join(work, "out", `sample-${theme}.html`); fs.writeFileSync( page, buildDocument({ markdown, title: "sample.md", sourcePath: path.join(work, "docs", "sample.md"), sourceRelDir: "../docs/", assetsRelDir: "assets", mode: "markdown", theme, contentWidth: 860, }) ); return execFileSync( browser, ["--headless", "--disable-gpu", "--no-sandbox", "--virtual-time-budget=10000", "--dump-dom", `file://${page}`], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], maxBuffer: 32 * 1024 * 1024 } ); } const dom = render("auto"); // Only the rendered
. The Markdown source is embedded further down the // page as data, so a naive slice to end-of-document would find anything. const body = dom.slice(dom.indexOf('id="content"'), dom.indexOf('id="preview-data"')); check("both valid diagrams drawn", (dom.match(/ s === "FAIL") ? 1 : 0;