| 18 | "https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js"; |
| 19 | |
| 20 | export async function renderDiagram(code: string): Promise<Buffer> { |
| 21 | const browser = await getBrowser(); |
| 22 | |
| 23 | // ── Stage 1: DSL → sanitized SVG string ───────────────────────────── |
| 24 | const renderPage = await browser.newPage(); |
| 25 | let svg: string; |
| 26 | try { |
| 27 | await renderPage.setContent( |
| 28 | `<!doctype html><html><head>` + |
| 29 | `<link rel="preconnect" href="https://fonts.googleapis.com">` + |
| 30 | `<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>` + |
| 31 | `<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600&display=swap" rel="stylesheet">` + |
| 32 | `</head><body></body></html>`, |
| 33 | ); |
| 34 | await renderPage.addScriptTag({ url: MERMAID_CDN }); |
| 35 | const result = await renderPage.evaluate(async (code) => { |
| 36 | await document.fonts.ready; |
| 37 | // @ts-expect-error mermaid is injected by the CDN script |
| 38 | mermaid.initialize({ |
| 39 | startOnLoad: false, |
| 40 | securityLevel: "strict", |
| 41 | theme: "base", |
| 42 | look: "classic", |
| 43 | themeVariables: { |
| 44 | // The sanitized SVG is rendered in a second, script-free page. Use a |
| 45 | // built-in font so Mermaid's measured node widths remain identical |
| 46 | // across both documents; a downloaded web font clips label endings. |
| 47 | fontFamily: "Arial, sans-serif", |
| 48 | fontSize: "16px", |
| 49 | background: "transparent", |
| 50 | primaryColor: "rgba(255, 172, 77, 0.2)", |
| 51 | primaryTextColor: "#010507", |
| 52 | primaryBorderColor: "#dbdbe5", |
| 53 | secondaryColor: "#F3F3FC", |
| 54 | secondaryBorderColor: "#C9C9DA", |
| 55 | tertiaryColor: "rgba(255, 243, 136, 0.3)", |
| 56 | tertiaryBorderColor: "#dbdbe5", |
| 57 | lineColor: "#57575b", |
| 58 | edgeLabelBackground: "#fafcfa", |
| 59 | clusterBkg: "#F3F3FC", |
| 60 | clusterBorder: "#ffffff", |
| 61 | noteBkgColor: "#fafcfa", |
| 62 | noteBorderColor: "#dbdbe5", |
| 63 | }, |
| 64 | flowchart: { |
| 65 | curve: "basis", |
| 66 | nodeSpacing: 44, |
| 67 | rankSpacing: 56, |
| 68 | padding: 16, |
| 69 | useMaxWidth: false, |
| 70 | }, |