UNPKG

bpmn-to-image

Version:

Convert a BPMN 2.0 diagrams to PDF, SVG or PNG images

160 lines (124 loc) 2.94 kB
import puppeteer from 'puppeteer'; import { basename, } from 'node:path'; import { readFileSync, writeFileSync } from 'node:fs'; /** @typedef { import('puppeteer').Page } Page */ /** @typedef { PrintOptions } any */ /** * @param { Page } page * @param { PrintOptions } options * * @return {Promise<void>} */ async function printDiagram(page, options) { const { input, outputs, minDimensions, footer, title = true, deviceScaleFactor } = options; const diagramXML = readFileSync(input, 'utf8'); const diagramTitle = title === false ? false : ( title.length ? title : basename(input) ); await page.goto(new URL('./skeleton.html', import.meta.url)); const viewerScript = import.meta.resolve('bpmn-js/dist/bpmn-viewer.production.min.js'); const desiredViewport = await page.evaluate(async function(diagramXML, options) { const { viewerScript, ...openOptions } = options; await loadScript(viewerScript); // returns desired viewport return openDiagram(diagramXML, openOptions); }, diagramXML, { minDimensions, title: diagramTitle, viewerScript, footer });; page.setViewport({ width: Math.round(desiredViewport.width), height: Math.round(desiredViewport.height), deviceScaleFactor }); await page.evaluate(() => resize()); for (const output of outputs) { console.log(`writing ${output}`); if (output.endsWith('.pdf')) { await page.pdf({ path: output, width: desiredViewport.width, height: desiredViewport.diagramHeight }); } else if (output.endsWith('.png')) { await page.screenshot({ path: output, clip: { x: 0, y: 0, width: desiredViewport.width, height: desiredViewport.diagramHeight } }); } else if (output.endsWith('.svg')) { const svg = await page.evaluate(() => toSVG()); writeFileSync(output, svg, 'utf8'); } else { console.error(`Unknown output file format: ${output}`); } } } async function withPage(fn) { let browser; try { browser = await puppeteer.launch({ headless: 'new' }); await fn(await browser.newPage()); } finally { if (browser) { await browser.close(); } } } export async function convertAll(conversions, options={}) { const { minDimensions, footer, title, deviceScaleFactor } = options; await withPage(async function(page) { for (const conversion of conversions) { const { input, outputs } = conversion; await printDiagram(page, { input, outputs, minDimensions, title, footer, deviceScaleFactor }); } }); } export async function convert(input, output) { return await convertAll([ { input, outputs: [ output ] } ]); }