b6151b7de5
- export_topology.py: edges now carry the exact port name on both ends (pulled directly from Cable/CableTermination, not inferred from the trace chain), so the diagram can label each connector. - generate_drawio.py: patch panels are now a small rack-unit shape (header strip + port ticks, parented to the panel body so they move together) instead of a plain box; connectors show 'porta <-> portb' and no longer carry a directional arrowhead (these are physical cables, not directed links); switches keep the network-switch icon. - render_png.js + render_host.html: headless Puppeteer driver for embed.diagrams.net's postMessage export protocol -- an actual render of the .drawio file, not an approximation. Field-Switch- Topology.png is the committed output, for anyone who wants a look without opening draw.io. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NM3nivbufxEWiKKmatEtEe
57 lines
2.1 KiB
JavaScript
57 lines
2.1 KiB
JavaScript
#!/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 <in.drawio> <out.png>');
|
|
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); });
|