#!/usr/bin/env node /** * Render a .drawio file to PNG via a real draw.io instance (embed.diagrams.net), * driven headlessly with Puppeteer -- this is an actual render, not an * approximation, so switch icons, patch panel styling, and port labels all * come out exactly as they'd look opening the file in the app. * * Needs `npm install puppeteer` first (downloads its own Chromium; not the * system browser). Needs network access to embed.diagrams.net. * * Usage: * node render_png.js Field-Switch-Topology.drawio Field-Switch-Topology.png */ const puppeteer = require('puppeteer'); const fs = require('fs'); const path = require('path'); const xmlPath = process.argv[2]; const outPath = process.argv[3]; if (!xmlPath || !outPath) { console.error('usage: node render_png.js '); process.exit(1); } const xml = fs.readFileSync(xmlPath, 'utf8'); (async () => { const browser = await puppeteer.launch({ headless: 'new', args: ['--no-sandbox', '--disable-setuid-sandbox'], }); const page = await browser.newPage(); await page.setViewport({ width: 1700, height: 1300 }); page.on('pageerror', (err) => console.error('PAGE ERROR:', err)); await page.evaluateOnNewDocument((x) => { window.__XML__ = x; }, xml); await page.goto('file://' + path.join(__dirname, 'render_host.html'), { waitUntil: 'load', timeout: 30000, }); let dataUrl = null; const deadline = Date.now() + 60000; while (Date.now() < deadline) { dataUrl = await page.evaluate(() => window.__RESULT__); const err = await page.evaluate(() => window.__ERR__); if (err) throw new Error('draw.io export error: ' + err); if (dataUrl) break; await new Promise((r) => setTimeout(r, 500)); } if (!dataUrl) throw new Error('timed out waiting for draw.io to export (network to embed.diagrams.net?)'); const base64 = dataUrl.split(',')[1]; fs.writeFileSync(outPath, Buffer.from(base64, 'base64')); console.log('wrote', outPath, fs.statSync(outPath).size, 'bytes'); await browser.close(); })().catch((e) => { console.error(e); process.exit(1); });