Files
Netbox/topology/render_png.js
T
dcstephenson b6151b7de5 Add port labels, modernize patch panels, add a real PNG preview
- 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
2026-09-15 13:03:18 -05:00

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); });