
Drawio
Render .drawio architecture diagrams to PNG for READMEs, specs, and agent context using CLI or headless viewer fallbacks.
Install
npx skills add https://github.com/ilteoood/harness --skill drawioWhat is this skill?
- drawio-to-png.mjs converts single files or whole directories of .drawio sources
- Three renderer modes: draw.io CLI, official viewer in headless browser, and auto selection
- Official draw.io viewer JS path for pixel-perfect edges and shape routing when CLI is missing
- Supports compressed diagram payloads via zlib inflate before render
- Puppeteer-core drives headless rendering when network-backed viewer is required
Adoption & trust: 1 installs on skills.sh; 2 GitHub stars; 2/3 security scanners passed (skills.sh audits); trending (+100% hot-view momentum).
Recommended Skills
Lark Doclarksuite/cli
Lark Wikilarksuite/cli
Opensource Guide Coachxixu-me/skills
Readme I18nxixu-me/skills
Doc Coauthoringanthropics/skills
Obsidian Markdownkepano/obsidian-skills
Journey fit
Common Questions / FAQ
Is Drawio safe to install?
skills.sh reports 2 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.
SKILL.md
READMESKILL.md - Drawio
/** * drawio-to-png.mjs - Convert .drawio files to PNG with accurate rendering. * * Rendering priority: * 1. draw.io CLI (if installed) — pixel-perfect, fastest * 2. Official draw.io viewer JS in headless browser — pixel-perfect, needs network * * Usage: node drawio-to-png.mjs <input.drawio> [output.png] * node drawio-to-png.mjs --dir <directory> (converts all .drawio files in directory) * node drawio-to-png.mjs --renderer=cli|viewer|auto <input.drawio> [output.png] */ import { readFileSync, writeFileSync, readdirSync, statSync } from "fs"; import { join, basename, dirname, resolve } from "path"; import { spawnSync } from "child_process"; import { inflateRawSync } from "zlib"; import puppeteer from "puppeteer-core"; // --- Build HTML that uses the official draw.io viewer for rendering --- function buildViewerHtml(rawFileContent) { // Escape for embedding in a JS template literal const escaped = rawFileContent .replace(/\\/g, "\\\\") .replace(/`/g, "\\`") .replace(/\$/g, "\\$"); // The official draw.io viewer (viewer-static.min.js) contains the full mxGraph // rendering engine — it handles orthogonal edge routing, all shape types, // container layouts, and compressed/uncompressed diagram formats. return `<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <style> * { margin: 0; padding: 0; } body { background: white; } </style> </head> <body> <div id="diagram-host"></div> <script> // Prepare diagram XML and set up the viewer target div (function() { var raw = \`${escaped}\`; // Wrap raw mxGraphModel in mxfile if needed (viewer expects mxfile format) var xmlStr = raw.trim(); if (xmlStr.startsWith('<mxGraphModel')) { xmlStr = '<mxfile><diagram name="Page-1">' + xmlStr + '</diagram></mxfile>'; } else if (!xmlStr.startsWith('<mxfile')) { // Assume it's already an mxfile or a diagram element if (xmlStr.startsWith('<diagram')) { xmlStr = '<mxfile>' + xmlStr + '</mxfile>'; } } var config = { xml: xmlStr, highlight: "none", nav: false, resize: true, toolbar: null, "toolbar-nohide": true, edit: null, lightbox: false, "auto-fit": true, "check-visible-state": false }; var div = document.createElement('div'); div.className = 'mxgraph'; div.setAttribute('data-mxgraph', JSON.stringify(config)); document.getElementById('diagram-host').appendChild(div); })(); // Poll until the viewer renders the diagram (viewer script loaded separately) window.__pollStarted = false; window.__startPoll = function() { if (window.__pollStarted) return; window.__pollStarted = true; // Explicitly trigger viewer processing if (typeof GraphViewer !== 'undefined' && GraphViewer.processElements) { GraphViewer.processElements(); } (function poll() { // Viewer places SVG directly inside .mxgraph div var mxDiv = document.querySelector('.mxgraph'); if (mxDiv) { var svg = mxDiv.querySelector('svg'); if (svg) { var rect = mxDiv.getBoundingClientRect(); if (rect.width > 10 && rect.height > 10) { window.__renderComplete = true; window.__renderWidth = rect.width; window.__renderHeight = rect.height; return; } } } setTimeout(poll, 150); })(); }; </script> </body> </html>`; } // --- Extract mxGraph XML from .drawio input (supports mxGraphModel and mxfile) --- function extractMxGraphModelXml(inputXml) { const trimmed = inputXml.trim(); if (trimmed.startsWith("<mxGraphModel")) { return trimmed; } const diagramMatch = trimmed.match(/<diagram\b[^>]*>([\s\S]*?)<\/diagram>/i); if (!diagramMatch) { throw new Error("Unsupported .drawio format: missing <mxGraphM