Skip to content

Repository files navigation

drawio-themer

Apply modern, semantic visual themes to existing draw.io / diagrams.net .drawio files — from the command line, without touching geometry, topology, or shape semantics.

Checks Node License: MIT

Before After — dark-neon-mode theme
Layered architecture diagram before theming Layered architecture diagram after applying a dark neon theme

Table of contents

Why

Manually restyling every shape in a .drawio file — fills, strokes, fonts, corner radius, edge arrows — is tedious and error-prone, and generic "convert to X" tools tend to mangle geometry, connections, or shape semantics (a database cylinder becoming a plain rectangle, for example). drawio-themer rewrites only presentational style properties via a small YAML theme, leaving everything else — layout, connections, embedded images/icons, shape types — untouched.

Features

  • Safe by construction — a style-property allow-list (see docs/PRD.md) guarantees geometry, topology, and shape type are never rewritten.
  • Semantic classification — nodes, edges, containers, and database shapes are classified automatically and themed with distinct rules.
  • Multi-page & compressed diagrams — supports both inline and raw-deflate + base64 compressed page content.
  • Idempotent — re-applying a theme to an already-themed file is a no-op.
  • Bundled themes — ships with 10 built-in themes covering light and dark, muted and vibrant, professional and accessibility-first styles (shadcn-modern, dark-neon-mode, nord, dracula, solarized-light, gruvbox, catppuccin-mocha, monokai, github-light, high-contrast); write your own in a few lines of YAML.

Install

Run the published CLI without installing it:

npx --yes drawio-themer@latest --help

For a persistent global installation:

npm install --global drawio-themer

After global installation, the drawio-themer command is available directly.

For local development from a checkout:

npm install
npm run build

To use the locally built command directly, install this checkout globally:

make install-global

Usage

drawio-themer apply input.drawio -t shadcn-modern -o output.drawio

Or run the published CLI with npx, without a global install:

npx --yes drawio-themer@latest apply input.drawio -t shadcn-modern -o output.drawio

Or without an npm install, run the built CLI directly from a checkout:

node dist/cli.js apply input.drawio -t shadcn-modern -o output.drawio

Or during development, without a build step:

npx tsx src/cli.ts apply input.drawio -t shadcn-modern -o output.drawio

Options

drawio-themer apply <input>
Options:
  -t, --theme <theme>       Built-in theme name or theme file
  -o, --output <file>       Output .drawio file
      --dry-run             Analyze without writing
      --format <format>     preserve | compressed | uncompressed
      --verbose             Show matching/transformation details
      --no-theme-metadata   Do not annotate generated file
      --png-original <file> Render the input (pre-theme) file as an
                            approximate PNG render
      --png-themed, --png <file>
                            Render the themed output as an approximate
                            PNG render
      --svg-original <file> Render the input (pre-theme) file as an
                            approximate SVG render
      --svg-themed, --svg <file>
                            Render the themed output as an approximate
                            SVG render
      --renderer <backend>  resvg (default) | chromium
  -h, --help

PNG/SVG renders are an offline, approximate rasterization of the diagram (rects, database cylinders, edges clipped to node borders, labels) meant for a quick visual check — not a substitute for opening the file in real draw.io (no waypoints, groups, rotation, or HTML labels support):

node dist/cli.js apply input.drawio -t dark-neon-mode -o output.drawio \
  --png-original before.png \
  --png-themed after.png \
  --svg-original before.svg \
  --svg-themed after.svg

Rendering backends: resvg vs chromium

--png-* rasterization uses one of two backends, selected with --renderer <backend>:

  • resvg (default) — a native, offline, zero-setup static SVG rasterizer (@resvg/resvg-js). Fast and dependency-light, but structurally limited: no <foreignObject>/HTML label support, no real web font loading, and only partial CSS filter support.

  • chromium (opt-in) — drives a real headless Chromium via playwright-core for higher-fidelity output closer to real draw.io's own Electron-based PNG export. Requires a one-time npx playwright install chromium (not downloaded by default npm install/make install):

    npx playwright install chromium
    node dist/cli.js apply input.drawio -t dark-neon-mode -o output.drawio \
      --png-themed after.png --renderer chromium

    Known limitation: with glow-enabled themes (e.g. dark-neon-mode), --renderer chromium can drop perfectly axis-aligned (horizontal or vertical) edges due to a degenerate SVG filter region on zero-width/ height bounding boxes (see issue #71). --renderer resvg is unaffected.

Themes

A theme is a YAML file of design tokens plus a small set of rules matched against classified cells (node, edge, container, database) or explicit tags. Ten themes are bundled:

  • shadcn-modern — light, shadcn/ui-inspired default
  • dark-neon-mode — dark zinc base with a violet/cyan glow accent (shown in the demo above)
  • nord — cool arctic blues, muted, professional-dark
  • dracula — vibrant purple/pink/green dark
  • solarized-light — warm cream, low-contrast, eye-friendly
  • gruvbox — warm retro browns/oranges, dark
  • catppuccin-mocha — soft pastel dark
  • monokai — classic yellow/green/pink code-editor dark
  • github-light — clean corporate/professional light
  • high-contrast — WCAG-AA-oriented black/white/yellow, accessibility-first

Each render below shows the same fixture (docs/assets/fixtures/layered-architecture.drawio) via apply --png-themed (see Usage above). Only the vibrant/neon-leaning dark themes (dark-neon-mode, dracula, monokai) opt into the render's glow filter (glow: true in their YAML) — muted, light, retro, or accessibility-focused themes render flat/crisp on purpose.

Theme Render
shadcn-modern shadcn-modern
dark-neon-mode dark-neon-mode
nord nord
dracula dracula
solarized-light solarized-light
gruvbox gruvbox
catppuccin-mocha catppuccin-mocha
monokai monokai
github-light github-light
high-contrast high-contrast

See docs/PRD.md for the full theme format and style allow-list.

Development

Common tasks are wrapped in a Makefile with a dependency chain (format-check -> lint -> build/test -> run -> release-*), so each target re-verifies the gates before it:

make format          # prettier --write (mutates files)
make format-check    # prettier --check (CI-safe, no mutation)
make lint            # format-check + eslint
make test            # lint + build + vitest
make run             # test + `node dist/cli.js --version`
make install-global  # build + `npm install -g .` (adds `drawio-themer` to PATH)
make release-patch   # run + npm version patch + git push --follow-tags
make release-minor   # run + npm version minor + git push --follow-tags
make release-major   # run + npm version major + git push --follow-tags

Plain npm scripts are also available (npm run build|lint|test|format|format:check).

CI runs make format-check, make lint, and make test as separate required checks (Checks / Format, Checks / Lint, Checks / Tests) on every pull request.

License

MIT

The offline PNG/SVG preview renderer (--png-*/--svg-* flags) bundles src/render/assets/NotoSans-Regular.ttf (Noto Sans, SIL Open Font License 1.1 — see src/render/assets/NotoSans-LICENSE.txt) so labels render in a proportional sans-serif font even on hosts without it installed, instead of silently falling back to resvg's default monospace font.

About

Apply modern, semantic visual themes to existing draw.io / diagrams.net files from the CLI, without touching geometry, topology, or shape semantics.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages