60 lines
1.7 KiB
TypeScript
60 lines
1.7 KiB
TypeScript
import { Browser, launch } from 'puppeteer'
|
|
|
|
let browserPromise: Promise<Browser> | null = null
|
|
|
|
function getBrowser() {
|
|
if (!browserPromise) {
|
|
browserPromise = launch({ headless: true })
|
|
}
|
|
return browserPromise
|
|
}
|
|
|
|
/**
|
|
* Closes the Puppeteer browser instance if it exists.
|
|
* This function is useful for cleaning up resources when the application is shutting down or when the browser is no longer needed.
|
|
*/
|
|
export async function closeMermaidBrowser() {
|
|
if (browserPromise) {
|
|
const browser = await browserPromise
|
|
await browser.close()
|
|
browserPromise = null
|
|
}
|
|
}
|
|
|
|
const cache = new Map<string, string>()
|
|
|
|
/**
|
|
* Renders a Mermaid chart to SVG using Puppeteer and caches the result.
|
|
* @param chart - The Mermaid chart definition as a string.
|
|
* @returns A promise that resolves to the rendered SVG string.
|
|
*/
|
|
export async function renderMermaidToSvg(chart: string): Promise<string> {
|
|
const cached = cache.get(chart)
|
|
if (cached) return cached
|
|
|
|
const browser = await getBrowser()
|
|
const page = await browser.newPage()
|
|
|
|
try {
|
|
await page.setContent(`
|
|
<!DOCTYPE html>
|
|
<html><body><div id="target"></div></body></html>
|
|
`)
|
|
await page.addScriptTag({
|
|
url: 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js',
|
|
})
|
|
|
|
const svg = await page.evaluate(async (source) => {
|
|
// @ts-expect-error mermaid is loaded globally via the script tag above
|
|
window.mermaid.initialize({ startOnLoad: false, theme: 'neutral' })
|
|
// @ts-expect-error same as above
|
|
const { svg: renderedSvg } = await window.mermaid.render('mermaid-diagram', source)
|
|
return renderedSvg
|
|
}, chart)
|
|
|
|
cache.set(chart, svg)
|
|
return svg
|
|
} finally {
|
|
await page.close()
|
|
}
|
|
}
|