bpmn-to-image
Version:
Convert a BPMN 2.0 diagrams to PDF, SVG or PNG images
159 lines (120 loc) • 2.89 kB
JavaScript
const puppeteer = require('puppeteer');
const fs = require('fs');
const {
basename,
resolve,
relative
} = require('path');
const {
readFileSync
} = require('fs');
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(`file://${__dirname}/skeleton.html`);
const viewerScript = relative(__dirname, require.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: 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());
fs.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();
}
}
}
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
});
}
});
}
module.exports.convertAll = convertAll;
async function convert(input, output) {
return await convertAll([
{
input,
outputs: [ output ]
}
]);
}
module.exports.convert = convert;