diagrams-js
Version:
A TypeScript port of the diagrams Python library for drawing cloud system architecture diagrams as code
266 lines (194 loc) • 7.26 kB
Markdown
---
name: diagrams-js/svg-serialization
description: >
SVG export and import for diagrams. Render diagrams to SVG with embedded metadata for round-trip
serialization. Import previously exported SVG images back into editable diagrams.
Alternative to JSON serialization with self-contained visual + data format.
type: core
library: diagrams-js
library_version: "0.5.0"
requires:
- diagrams-js/getting-started
- diagrams-js/provider-nodes
sources:
- "hatemhosny/diagrams-js:docs/docs/guides/rendering.mdx"
- "hatemhosny/diagrams-js:docs/docs/guides/json.mdx"
- "hatemhosny/diagrams-js:src/plugins/built-in/svg.ts"
---
This skill builds on diagrams-js/getting-started and diagrams-js/provider-nodes. Read them first for foundational concepts.
# diagrams-js — SVG Serialization
Export diagrams to SVG format with embedded metadata and import them back. SVG serves as both a visual image and a self-contained data format, enabling round-trip editing without separate JSON files.
## Setup
```typescript
import { Diagram } from "diagrams-js";
import { EC2 } from "diagrams-js/aws/compute";
const diagram = Diagram("My Architecture");
diagram.add(EC2("Server"));
// Render to SVG (includes embedded metadata by default)
const svg = await diagram.render();
```
## Core Patterns
### Export to SVG
```typescript
const diagram = Diagram("Web Architecture", {
direction: "TB",
theme: "pastel",
});
const web = diagram.add(EC2("Web Server"));
const db = diagram.add(RDS("Database"));
web.to(db);
// Render to SVG with embedded metadata
const svg = await diagram.render();
// Or use the explicit SVG exporter
const svg2 = await diagram.export("svg");
// Save to file
await diagram.save("architecture.svg");
```
### Import from SVG
Restore a diagram from an SVG string using the static `Diagram.fromSVG()` method:
```typescript
import { Diagram } from "diagrams-js";
const svg = await fs.readFile("diagram.svg", "utf8");
// Restore the full diagram with all nodes, edges, and options
const diagram = await Diagram.fromSVG(svg);
const restoredSvg = await diagram.render();
```
### Merge SVG into Existing Diagram
Import an SVG into an existing diagram via the plugin system:
```typescript
const diagram = Diagram("Merged Architecture");
await diagram.import(svgString, "svg");
```
## SVG Data Attributes
The embedded metadata includes:
- **`data-diagram-json`** (root `<svg>`): Base64-encoded full diagram JSON
- **`data-diagram-version`**: Format version for compatibility
- **`data-node-id`**, **`data-node-label`**: Per-node identifiers
- **`data-node-provider`**, **`data-node-type`**, **`data-node-resource`**: Provider metadata
- **`data-node-metadata`**: Base64-encoded custom metadata
- **`data-cluster-label`**, **`data-cluster-nodes`**: Cluster information
- **`data-edge-from`**, **`data-edge-to`**, **`data-edge-label`**: Edge information
These attributes enable DOM querying and third-party tooling.
### Custom Classes and Data Attributes
Nodes, edges, and clusters can have custom CSS classes and data attributes injected into the SVG:
```typescript
const server = diagram.add(
Node("Server", {
className: "highlight",
dataAttrs: { team: "backend", env: "prod" },
}),
);
web.to(
Edge({
className: "critical",
dataAttrs: { latency: "50ms" },
}),
db,
);
const cluster = diagram.cluster("VPC", {
className: "production",
dataAttrs: { region: "us-east-1" },
});
```
Injected SVG output:
```html
<g class="node highlight" data-node-id="Server" data-team="backend" data-env="prod">...</g>
<g
id="diagram_edge_0"
class="edge critical"
data-edge-from="web"
data-edge-to="db"
data-latency="50ms"
>...</g
>
<g class="cluster production" data-cluster-label="VPC" data-region="us-east-1">...</g>
```
Access elements after rendering with `getElement()`:
```typescript
const svg = await diagram.render();
document.body.innerHTML = svg;
server.getElement()?.addEventListener("click", handler);
edge.getElement()?.classList.add("hovered");
cluster.getElement()?.setAttribute("data-active", "true");
```
## Clean SVG Without Metadata
To generate an SVG without embedded data:
```typescript
const cleanSvg = await diagram.render({ embedData: false });
```
This is useful when:
- Distributing diagrams to external parties
- Embedding in contexts where smaller file size matters
- Publishing to documentation where metadata is unnecessary
## Round-trip Consistency
SVG serialization preserves all diagram data:
```typescript
const original = Diagram("Test", { direction: "TB", theme: "blues" });
original.add(EC2("Server", { nodeId: "srv" }));
original.cluster("VPC").add(EC2("Web"));
// Export as SVG
const svg = await original.render();
// Import back
const restored = await Diagram.fromSVG(svg);
// Verify equivalence
const json1 = original.toJSON();
const json2 = restored.toJSON();
// json1 === json2
```
## Comparison: JSON vs SVG Serialization
| Feature | JSON | SVG |
| -------------- | --------------------- | --------------------------- |
| Human-readable | Yes | Partial (markup) |
| Visual preview | No | Yes (it's the image) |
| File size | Small | Larger (contains image) |
| DOM queryable | No | Yes (data attributes) |
| Round-trip | Yes | Yes |
| Best for | Version control, APIs | Distribution, documentation |
## Common Mistakes
### CRITICAL Trying to import plain SVG without embedded data
Wrong:
```typescript
const plainSvg = `<svg xmlns="http://www.w3.org/2000/svg"><text>Hello</text></svg>`;
const diagram = await Diagram.fromSVG(plainSvg);
// Throws: Invalid diagram SVG: missing or corrupted embedded diagram data
```
Correct:
```typescript
// Only SVGs exported/rendered by diagrams-js can be imported
const svg = await diagram.render();
const restored = await Diagram.fromSVG(svg);
```
Source: source code - svg.ts `extractDiagramData` validation
### HIGH Assuming embedData defaults to false
Wrong:
```typescript
const svg = await diagram.render();
// Surprised that SVG contains visible data attributes?
// embedData defaults to true
```
Correct:
```typescript
// Default behavior: embed metadata
const svg = await diagram.render(); // Contains data-diagram-json
// Opt-out when needed
const clean = await diagram.render({ embedData: false });
```
Source: source code - Diagram.ts render() embedData check
### MEDIUM Using diagram.export("svg") expecting different output from render()
Wrong:
```typescript
const rendered = await diagram.render();
const exported = await diagram.export("svg");
// These are identical; export just calls render({ format: "svg" })
```
Correct:
```typescript
// Both produce the same SVG with embedded metadata
const svg = await diagram.render();
// Use render() directly; export is a convenience for plugin consistency
```
Source: source code - svg.ts exporter implementation
## See also
- diagrams-js/json-serialization — JSON export/import guide
- diagrams-js/rendering-export — Output formats and rendering options
- diagrams-js/diagrams-js-plugin-system — Plugin architecture