Skip to main content

Universal diagram rendering platform — render any diagram language to SVG or PNG

Project description

PiDraw

Universal diagram rendering platform — convert any diagram language to SVG or PNG.

PiDraw renders source code from 14+ diagram languages into optimized SVG and PNG. It supports native (pure Python) rendering for 5 formats, external CLI tools for others, SVG optimization, quality enhancement, caching, parallel batch processing, file watching, plugin architecture, and async APIs.


Table of Contents


Installation

# Install from PyPI (recommended)
pip install pidraw

# Or install from source
git clone https://github.com/devasishpal/PiDraw.git
cd PiDraw
pip install -e .

# For PNG export (optional)
pip install playwright
playwright install chromium

On first import, missing CLI tools are automatically installed in a background thread. You can also trigger setup manually:

pidraw setup

Quick Start

1. Create a diagram file

Save this as flowchart.mmd:

graph TD
    A[Start] --> B{Is it working?}
    B -->|Yes| C[Great!]
    B -->|No| D[Fix it]
    D --> B

2. Render to SVG

pidraw render flowchart.mmd
# Output: flowchart.svg created

3. Render to PNG

pidraw render flowchart.mmd -f png
# Output: flowchart.png created

4. Detect language automatically

pidraw detect diagram.txt
# Output: Language: mermaid | Confidence: 98% | Renderer: MermaidRenderer

5. Analyze with full diagnostics

pidraw analyze diagram.puml
# Output: Language: plantuml, Confidence: 95%, Nodes: 3, Edges: 2, Warnings: 0

6. Batch render all diagrams in a folder

pidraw batch *.mmd --output-dir ./svg --optimize --workers 4

7. Watch for changes while editing

pidraw watch *.mmd --output-dir ./svg
# Watches for file changes and auto-renders on save

CLI Reference

pidraw render <file> [options]

Render a single diagram file to SVG or PNG.

Option Shorthand Description Default
--output -o Output file path Auto-derived
--language -l Explicit diagram language Auto-detected
--format -f Output format: svg or png svg
--optimize -O Optimise the output SVG Off

Examples:

# Basic SVG render
pidraw render diagram.mmd

# Render to PNG
pidraw render diagram.mmd -f png -o output.png

# Force language (useful for ambiguous extensions)
pidraw render diagram.txt -l mermaid -o diagram.svg

# Render with optimization
pidraw render diagram.mmd -O -o optimized-output.svg

pidraw docs <file> [options]

Render diagram code blocks in a Markdown file to HTML, Markdown, or DOCX.

Option Shorthand Description Default
--output -o Output file path Auto-derived
--output-format html, md, or docx html
--format -f Diagram format: svg or png svg
--no-bg Remove background from diagrams Off

Example:

# Convert README with diagrams to a self-contained HTML page
pidraw docs README.md -o README-with-diagrams.html

# Output as Markdown with inline SVGs
pidraw docs README.md --output-format md

# Generate a DOCX for Word
pidraw docs README.md --output-format docx

pidraw detect <file> [options]

Detect the diagram language used in a file.

Example:

pidraw detect unknown.diag
# Language: graphviz | Confidence: 92% | Renderer: GraphvizRenderer

pidraw analyze <file> [options]

Full diagnostic report: detected language, confidence, renderer, element count, warnings, and optimization stats.

Option Description Default
--render / --no-render Run the renderer during analysis --render
--optimize / --no-optimize Optimize the output SVG --optimize

Example:

pidraw analyze large-diagram.mmd --no-render
# Language:     mermaid
# Confidence:   98%
# Nodes:        47
# Edges:        62
# Warnings:     none
# SVG length:   (skipped — render disabled)

pidraw optimize <file> [options]

Optimize an existing SVG file (removes comments, metadata, unused defs, merges groups, etc.).

Option Shorthand Description Default
--output -o Output file path Overwrites input

Example:

pidraw optimize diagram.svg -o diagram-min.svg
# Before: 24.5 KB | After: 11.2 KB | Saved: 54%

pidraw batch <paths...> [options]

Render multiple diagram files in parallel.

Option Shorthand Description Default
--output-dir Output directory for SVGs Current directory
--language -l Language override for all files Auto-detect
--optimize -O Enable optimization Off
--recursive -r Scan directories recursively Off
--workers -w Parallel worker count CPU count

Examples:

# Render all Mermaid files
pidraw batch *.mmd

# Recursive batch with 8 workers
pidraw batch ./docs -r -w 8 --output-dir ./rendered

# Batch render with optimization
pidraw batch *.mmd *.puml -O --output-dir ./svg-output

pidraw watch <paths...> [options]

Watch files for changes and auto-render on every save.

Option Shorthand Description Default
--output-dir Output directory for SVGs Current directory
--language -l Language override Auto-detect
--optimize -O Enable optimization Off
--recursive -r Watch subdirectories Off
--debounce Debounce interval in seconds 1.0

Example:

# Watch current directory, render on save
pidraw watch *.mmd --recursive

# Watch with 2-second debounce
pidraw watch *.mmd --debounce 2.0 --output-dir ./auto-rendered

pidraw plugins [options]

List all registered and discovered renderer plugins.

pidraw plugins
# Total: 4 registered, 15 available renderers

pidraw version

Show the PiDraw version.

pidraw version
# pidraw v1.2.1

pidraw formats [options]

List all supported diagram formats with live availability status.

pidraw formats

Shows a table with availability, converter support, CLI tool requirements, and notes for each of the 14+ supported languages.


pidraw setup

Auto-install missing CLI tools (npm packages, Java tools, Playwright browser).

pidraw setup

pidraw benchmark [--quick]

Run the PiDraw benchmark suite to measure render speed, optimization performance, and cache efficiency.

pidraw benchmark
pidraw benchmark --quick

Supported Formats

Format Language ID File Extensions Render Method
Mermaid mermaid .mmd, .mermaid Native (pure Python)
PlantUML plantuml .puml, .plantuml, .iuml Native (pure Python)
Graphviz DOT graphviz .dot, .gv Native (pure Python)
D2 d2 .d2 Native (pure Python)
ASCII Art ascii .txt Native (pure Python)
BPMN 2.0 bpmn .bpmn CLI (bpmn-svg)
Markmap markmap .mm CLI (markmap + Playwright)
Nomnoml nomnoml .noml CLI (nomnoml)
WaveDrom wavedrom .json CLI (wavedrom-cli)
Structurizr structurizr .dsl CLI (structurizr-cli)
Vega vega .json CLI (vg2svg)
Vega-Lite vega-lite .json Native or CLI
Excalidraw excalidraw .json, .excalidraw Native (pure Python)
Kroki kroki .txt, .kroki HTTP API (no CLI needed)
TikZ tikz .tex CLI (pdflatex + pdf2svg)

5 formats work immediately with no extra tools — mermaid, plantuml, graphviz, d2, ascii.


Python API

Basic rendering

from pidraw import render

# Mermaid
svg = render("graph TD; A-->B", language="mermaid")

# PlantUML
svg = render("@startuml\nA-->B\n@enduml", language="plantuml")

# Graphviz
svg = render("digraph { A -> B }", language="graphviz")

# D2
svg = render("A -> B", language="d2")

# Auto-detect language
svg = render("graph TD; A-->B")

Optimization and quality

from pidraw import render

# With optimization
svg = render(source, language="mermaid", optimize="balanced")

# With quality enhancement
svg = render(source, language="plantuml", quality=True)

# Maximum optimization (for production)
svg = render(source, language="graphviz", optimize="maximum")

File-based rendering

from pidraw import render_file

# Render from file path (auto-detect language)
svg = render_file("diagram.mmd")

# Explicit language
svg = render_file("diagram.txt", language="mermaid")

# With options
svg = render_file("diagram.puml", optimize="fast", quality=True)

Async API

import asyncio
from pidraw import arender

async def main():
    svg = await arender("graph TD; A-->B", language="mermaid")
    print(len(svg))

asyncio.run(main())
from pidraw import arender_file

svg = await arender_file("diagram.mmd")

Batch rendering

from pidraw import render_many

sources = [
    "graph TD; A-->B",
    "@startuml\nA-->B\n@enduml",
    "digraph { A -> B }",
]
svgs = render_many(sources, language=None)  # auto-detect each

Layout control

from pidraw import render, LayoutType

# Force a specific layout engine
svg = render(source, language="mermaid", layout=LayoutType.LAYERED)
svg = render(source, language="graphviz", layout=LayoutType.TREE)
svg = render(source, language="d2", layout=LayoutType.GRID)
svg = render(source, language="plantuml", layout=LayoutType.FLOW)

PNG conversion

from pidraw.backend.png import svg_to_png

png_bytes = svg_to_png(svg_string, width=800, height=600)
with open("diagram.png", "wb") as f:
    f.write(png_bytes)

Architecture

Source Code (string or file)
    │
    ▼
detect_language()  ──►  Language ID (e.g. "mermaid")
    │
    ▼
get_renderer(language)  ──►  Engine Registry
    │
    ├── CLI-Based Renderer
    │       └── subprocess → temp file/pipe → SVG
    │
    ├── NativeRenderer (for converter-supported languages)
    │       ├── converter.parse(source) → Diagram model
    │       ├── apply_layout(diagram) → positioned nodes
    │       ├── apply_theme(diagram) → styled diagram
    │       └── SvgBackend.render(diagram) → SVG string
    │
    ├── KrokiRenderer (HTTP POST to kroki.io)
    │
    └── ExcalidrawRenderer (pure Python JSON → SVG)
    │
    ▼
[Optional] optimize_svg(svg, level="balanced")
    │   10 passes: comments → metadata → defs → groups → paths → ...
    ▼
[Optional] QualityProcessor.process(svg)
    │   viewBox → text alignment → arrow heads → spacing → paths
    ▼
Output SVG string

Engines

Each diagram format has a dedicated renderer engine in pidraw/engines/. Engines auto-register on import; if a CLI tool is missing and no native fallback exists, a placeholder is registered that raises a helpful error at render time.

Converters

5 formats have pure-Python parsers (pidraw/core/converters/) that produce an internal Diagram model, which SvgBackend renders to SVG — no CLI tools needed:

Converter What it parses
MermaidConverter graph TD, flowchart, sequenceDiagram, classDiagram, stateDiagram, ER, journey, gantt, pie, gitgraph, mindmap, timeline, block, C4, network, packet, quadrant, requirement, sankey, xy_chart
PlantUMLConverter @startuml blocks, participants, actors, arrows
GraphvizConverter digraph/graph statements with attributes
D2Converter D2 node/edge syntax with shapes and styles
ASCIIConverter Simple box-drawing diagrams (+--+ boxes, --> arrows)

SVG Optimizer

Three optimization levels (pidraw/optimizer/):

Level Passes Description
fast 3 Remove comments, editor metadata, trim whitespace
balanced 10 All fast passes + unused defs, duplicate merging, group collapsing, empty elements, transform normalization, path simplification, attribute ordering
maximum 10 Same 10 passes (maximum available)

Layout Engines

4 layout strategies for native-rendered diagrams (pidraw/layout/):

Engine Algorithm
FlowLayout Topological sort, single-row/column
GridLayout Square-ish grid (√N columns)
LayeredLayout Sugiyama-style layered layout
TreeLayout Recursive subtree positioning

Themes

5 built-in themes (pidraw/themes/):

Theme Description
light White background, dark text, sans-serif
dark Dark background (#1e1e1e), light text
minimal Light minimal (#fafafa), thin strokes, Helvetica
professional Colorful node palette, shadows, Segoe UI
blueprint Blue-on-light-blue, monospace, engineering aesthetic

Apply a theme:

from pidraw import render, apply_theme

svg = render("graph TD; A-->B", language="mermaid")
svg = apply_theme(svg, "dark")

Caching

PiDraw includes a two-tier content-addressable cache:

  • Memory tier: LRU-eviction dict (default 10,000 entries)
  • Disk tier: JSON files in configurable directory
  • Cache key: SHA-256 hash of language + "\x00" + source
  • Configurable TTL per entry (default: 1 hour)
from pidraw.cache import CacheManager

cache = CacheManager(enable_disk=True, ttl=3600)

Used automatically by RenderPool (parallel rendering) and IncrementalRenderer.


Plugin System

Extend PiDraw with custom renderers via entry points:

# pyproject.toml
[project.entry-points."pidraw.renderers"]
myengine = "mypackage:MyRenderer"

Your class must extend BaseRenderer and implement render(source: str) -> str:

from pidraw.engines.base import BaseRenderer

class MyRenderer(BaseRenderer):
    name = "myformat"
    
    def render(self, source: str) -> str:
        # ... return SVG string
        pass

Plugins are auto-discovered on import and appear in pidraw plugins output.


Recovery & Error Handling

Mechanism Description
render_with_retry() Exponential backoff retry with optional fallback renderer
safe_render() Returns a red-box error SVG instead of raising
RecoverableRenderingError Distinguishable from hard failures
from pidraw import safe_render, render_with_retry

# Never raises — returns error SVG on failure
svg = safe_render("graph TD; A-->B")

# Retry up to 3 times with backoff
svg = render_with_retry(source, language="mermaid", retries=3)

Large File Support

Files up to 10 MB are handled with streaming reads and chunked SVG writes. Language detection reads only the first 512 KB for efficiency. The render_large_file() function provides memory-efficient processing:

from pidraw import render_large_file
svg = render_large_file("massive-diagram.mmd")

Parallel Rendering

RenderPool uses ThreadPoolExecutor (I/O-bound subprocess calls) or ProcessPoolExecutor (CPU-bound work) with auto-configured worker count.

from pidraw import render_many

# Batch render 100 diagrams in parallel
sources = [f"graph TD; A{i}-->B{i}" for i in range(100)]
svgs = render_many(sources, language="mermaid")

Requirements

  • Python >= 3.10
  • Optional: Node.js + npm (for CLI-based formats like nomnoml, markmap, wavedrom)
  • Optional: Java Runtime (for structurizr-cli)
  • Optional: Playwright (for PNG export via -f png)

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pidraw-1.2.1.tar.gz (118.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pidraw-1.2.1-py3-none-any.whl (119.3 kB view details)

Uploaded Python 3

File details

Details for the file pidraw-1.2.1.tar.gz.

File metadata

  • Download URL: pidraw-1.2.1.tar.gz
  • Upload date:
  • Size: 118.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for pidraw-1.2.1.tar.gz
Algorithm Hash digest
SHA256 435f35a5cf5bbc59146f21df0203119b4ce2edd48cd1d35eba1f6e6f6fa84174
MD5 4668fa3a90b7dd4fa2085260bdf73c88
BLAKE2b-256 0643fdaac0db810efb8302299cb6bb8b27b409dc5ba0f080e62ef9989ce9bbd0

See more details on using hashes here.

File details

Details for the file pidraw-1.2.1-py3-none-any.whl.

File metadata

  • Download URL: pidraw-1.2.1-py3-none-any.whl
  • Upload date:
  • Size: 119.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for pidraw-1.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 10af4c0683216bf281a386236a9b15439347461f9bf039c7f24f07c21ceba09b
MD5 91e2f2da9649c6f511e577a43e4bb1a8
BLAKE2b-256 1a18693c0eeb79f44353d24d39193dd0e8cc72a7b0673ad60795367ca564d160

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page