A CLAUDE.md is just a markdown file at the root of your repo. Copy the content below into your own project's CLAUDE.md to give your agent the same context.
npx versuz@latest install jgraph-drawio --kind=claude-mdcurl -o CLAUDE.md https://raw.githubusercontent.com/jgraph/drawio/HEAD/CLAUDE.md# VSDX Import/Export Module
## Overview
This folder implements complete **VSDX (Microsoft Visio 2013+ XML)** file format support for draw.io. VSDX files are ZIP archives containing XML documents following the Open Packaging Conventions (OPC) standard.
**4 files, ~893 KB total, ~15,600 lines of code.**
| File | Lines | Size | Purpose |
|------|-------|------|---------|
| `importer.js` | 13,208 | 782 KB | VSDX/VSSX → draw.io import (JSweet-generated from Java) |
| `VsdxExport.js` | 993 | 73 KB | draw.io → VSDX export |
| `mxVsdxCanvas2D.js` | 1,153 | 30 KB | Canvas adapter capturing shape rendering as VSDX geometry |
| `bmpDecoder.js` | 287 | 9 KB | BMP image format decoder for embedded images |
---
## Architecture
```
┌─────────────────────── IMPORT ───────────────────────┐
│ │
│ VSDX ZIP → mxVsdxCodec.decodeVsdx() │
│ │ │
│ ├── JSZip extraction │
│ ├── XML parsing (docData map) │
│ ├── Media extraction (mediaData map) │
│ │ ├── EMF → PNG (server-side) │
│ │ ├── BMP → JPEG (BmpDecoder) │
│ │ └── PNG/JPEG → base64 │
│ │ │
│ ▼ │
│ mxVsdxModel │
│ ├── Stylesheets │
│ ├── Themes (mxVsdxTheme) │
│ ├── Masters (mxVsdxMaster) │
│ └── Pages (mxVsdxPage) │
│ └── Shapes (VsdxShape) │
│ ├── Geometry (Rows) │
│ ├── Style resolution │
│ └── Master inheritance │
│ │ │
│ ▼ │
│ importPage() → mxGraph model → XML │
│ │
└───────────────────────────────────────────────────────┘
┌─────────────────────── EXPORT ───────────────────────┐
│ │
│ mxGraph → VsdxExport.exportCurrentDiagrams() │
│ │ │
│ ├── createVsdxSkeleton() (ZIP init) │
│ │ │
│ ▼ │
│ convertMxModel2Page() │
│ ├── convertMxCell2Shape() per cell │
│ │ ├── createShape() (vertices) │
│ │ ├── createEdge() (connectors) │
│ │ └── mxVsdxCanvas2D (rendering) │
│ ├── applyMxCellStyle() │
│ └── addPagesXML() + addImagesRels() │
│ │ │
│ ▼ │
│ JSZip.generateAsync() → .vsdx download │
│ │
└───────────────────────────────────────────────────────┘
```
---
## File Details
### importer.js
**Origin**: Generated from Java via **JSweet 2.0.0-rc1** transpiler. Uses nested namespaces: `com.mxgraph.io.*`.
**Namespace structure**:
```
com.mxgraph.io.mxVsdxCodec — Main VSDX codec
com.mxgraph.io.mxVssxCodec — Library (VSSX) codec (extends mxVsdxCodec)
com.mxgraph.io.vsdx.Shape — Base shape wrapper
com.mxgraph.io.vsdx.VsdxShape — VSDX-specific shape (extends Shape)
com.mxgraph.io.vsdx.mxVsdxModel — Document model container
com.mxgraph.io.vsdx.mxVsdxPage — Page representation
com.mxgraph.io.vsdx.mxVsdxMaster — Master shape template
com.mxgraph.io.vsdx.mxVsdxTheme — OOXML theme parser
com.mxgraph.io.vsdx.mxVsdxConnect — Connection definition
com.mxgraph.io.vsdx.mxVsdxUtils — XML/style utilities
com.mxgraph.io.vsdx.mxVsdxConstants — XML element/attribute constants
com.mxgraph.io.vsdx.mxPropertiesManager — Color palette manager
com.mxgraph.io.vsdx.mxVsdxGeometry — Single geometry section
com.mxgraph.io.vsdx.mxVsdxGeometryList — Collection of geometry sections
com.mxgraph.io.vsdx.geometry.Row — Base geometry row
com.mxgraph.io.vsdx.geometry.* — 16 Row subclasses
com.mxgraph.io.vsdx.theme.* — Theme/color classes (OoxmlColor, etc.)
```
#### Key Classes
**mxVsdxCodec** — Main entry point for VSDX import.
| Method | Purpose |
|--------|---------|
| `decodeVsdx(file, callback, charset, onerror)` | Main async entry: extracts ZIP, parses XML, builds model, imports pages |
| `createMxGraph()` | Creates configured Graph instance for import |
| `importPage(page, graph, parent, noSanitize)` | Orchestrates page import: shapes → edges → layers (3-pass) |
| `processPage(graph, page)` | Encodes mxGraph model to compressed XML `<diagram>` element |
| `postImportPage(page, graph, callback)` | Async post-processing (image cropping) |
| `addShape(graph, shape, parent, pageId, parentHeight)` | Routes shapes to addVertex/addGroup/edgeShapeMap |
| `addVertex(graph, shape, parent, pageId, parentHeight)` | Creates vertex cell with style and geometry |
| `addGroup(graph, shape, parent, pageId, parentHeight, forceNoFill)` | Creates group container, recursively adds children |
| `addConnectedEdge(graph, connect, pageId, pageHeight)` | Creates edge connecting source/target vertices |
| `addUnconnectedEdge(graph, parent, edgeShape, pageHeight)` | Creates standalone edge (no connections) |
| `processEdgeGeo(edgeShape, edge, parentHeight)` | Handles special edge geometry (line jumps, NURBS curves) |
| `scaleGraph(graph, scale)` | Rescales entire graph for page scale adjustments |
| `sanitiseGraph(graph)` | Post-import cleanup and validation |
**mxVssxCodec** — Library/stencil file importer (extends mxVsdxCodec).
| Method | Purpose |
|--------|---------|
| `decodeVssx(file, callback, charset, onerror)` | Import VSSX library file |
| `normalizeGraph(graph)` | Normalize shapes for library consistency |
| `processPage(graph, page)` | Override: normalizes before encoding |
**mxVsdxModel** — Top-level document model.
| Method | Purpose |
|--------|---------|
| `constructor(doc, docData, mediaData)` | Parses document.xml, initializes stylesheets/themes/masters/pages |
| `initThemes()` | Loads theme XML files, creates mxVsdxTheme objects |
| `initStylesheets()` | Loads StyleSheet elements and resolves references |
| `initMasters()` | Loads masters/masters.xml, creates mxVsdxMaster objects |
| `initPages()` | Loads pages/pages.xml, creates mxVsdxPage objects, links backgrounds |
| `getPages()` / `getMaster(id)` / `getThemes()` | Model accessors |
**mxVsdxPage** — Single page within the VSDX document.
| Method | Purpose |
|--------|---------|
| `constructor(pageElem, model)` | Parses page element, extracts shapes/connects/layers |
| `parseShapes(shapesElement, master, recurse)` | Creates VsdxShape objects from Shape XML elements |
| `createCell(shapeElem, vertex, master)` | Factory for VsdxShape creation |
| `isEdge(shape)` | Detects edges via BeginX/BeginY/EndX/EndY cells |
| `getShapes()` / `getConnects()` / `getLayers()` | Page content accessors |
| `getPageDimensions()` / `getPageScale()` / `getDrawingScale()` | Page metrics |
**VsdxShape** (extends Shape) — Wrapper for VSDX shape elements with master/theme resolution.
| Method | Purpose |
|--------|---------|
| `constructor(page, shape, vertex, masters, master, model)` | Resolves master, calculates rotation, applies theme, processes geometry |
| `getTextLabel()` | Returns text content with HTML formatting |
| `getStyleFromShape()` | Returns map of draw.io style properties |
| `getOriginPoint(parentHeight, convertCoords)` | Converts VSDX coordinates to mxGraph (flips Y axis) |
| `getDimensions()` | Returns shape width and height |
| `getGeomList()` | Returns mxVsdxGeometryList path definition |
| `getHyperlink()` | Extracts page links and external links |
| `getProperties()` | Returns custom shape properties array |
| `getControlPoints(parentHeight)` | Returns NURBS control points for curved edges |
| `setThemeAndVariant(theme, variantClr, variantStl)` | Applies theme colors and style variant |
**Shape** (base class) — Wraps VSDX shape XML element with style/text/geometry parsing.
| Method | Purpose |
|--------|---------|
| `constructor(shape, model)` | Parses Cell/Section elements, extracts text and geometry |
| `getValue(cellElem, defaultValue)` | Gets cell value with formula handling |
| `getCellElement(name)` | Looks up Cell by N attribute |
| `getScreenNumericalValue(cellElem, defaultValue)` | Gets coordinate in screen units |
| `getStyleFromShape()` | Returns fill/line/text style properties |
| `getTextLabel()` | Returns formatted text content |
**mxVsdxTheme** — OOXML color theme parser.
| Method | Purpose |
|--------|---------|
| `constructor(themeElem)` | Parses a:clrScheme, a:fontScheme, a:fmtScheme |
| `getThemeColor(index, tint, shade)` | Resolves theme color with tint/shade modifications |
**Geometry Row hierarchy** — Path operations for shape outlines:
| Row Type | Parameters | Purpose |
|----------|-----------|---------|
| `MoveTo` | x, y | Start new subpath |
| `LineTo` | x, y | Line segment |
| `ArcTo` | x, y, a (radius) | Elliptical arc |
| `Ellipse` | x, y, a, b, c, d | Complete ellipse |
| `EllipticalArcTo` | x, y, a, b, c, d | Elliptical arc with rotation |
| `NURBSTo` | x, y, a, b, c, d, e | NURBS curve |
| `PolylineTo` | x, y, a | Series of line segments |
| `RelCubBezTo` | x, y, a, b, c, d | Cubic Bezier (relative) |
| `RelQuadBezTo` | x, y, a, b | Quadratic Bezier (relative) |
| `RelLineTo` | x, y | Relative line |
| `RelMoveTo` | x, y | Relative move |
| `RelEllipticalArcTo` | x, y, a, b, c, d | Relative elliptical arc |
| `SplineStart` | x, y, a, b, c, d | Spline definition start |
| `SplineKnot` | x, y, a | Spline knot point |
| `InfiniteLine` | x, y, a, b | Infinite line through two points |
| `DelRow` | index | Row deletion marker |
---
### VsdxExport.js
**Pattern**: Closure-based module. Constructor `VsdxExport(editorUi)` defines all functions as closures with shared state.
#### Functions (all internal closures)
| Function | Purpose |
|----------|---------|
| `exportCurrentDiagrams(currentPageOnly)` | Main entry point: collects pages, builds ZIP, triggers download |
| `createVsdxSkeleton(zip, pageCount)` | Creates complete static VSDX directory structure and template files |
| `getCellVsdxId(cellId)` | Maps mxGraph cell IDs → sequential VSDX shape IDs |
| `getGraphAttributes(graph)` | Extracts page properties (dimensions, grid, scale) |
| `applyMxCellStyle(state, shape, xmlDoc)` | Converts mxGraph styles to VSDX Cell elements (fill, line, font, text) |
| `createShape(id, geo, layerIndex, xmlDoc, parentHeight, isChild)` | Creates VSDX Shape element with XForm geometry |
| `createEdge(cell, layerIndex, graph, xmlDoc, parentHeight, isChild)` | Creates edge Shape with connector master and waypoints |
| `convertMxCell2Shape(cell, layerIndex, graph, xmlDoc, parentHeight, parentGeo, isChild)` | Main dispatcher: routes to createShape/createEdge, handles groups |
| `convertMxModel2Page(graph, modelAttrib)` | Converts entire mxGraph to PageContents XML |
| `addPagesXML(zip, pages, pageLayers, modelsAttr)` | Creates pages.xml and pages.xml.rels in ZIP |
| `addImagesRels(zip, pIndex)` | Creates relationship files for embedded images |
| `writeXmlDoc2Zip(zip, name, xmlDoc, noHeader)` | Serializes XML document into ZIP file entry |
| `createCellElem(name, val, xmlDoc, formula)` | Creates VSDX `<Cell>` element |
| `createCellElemScaled(name, val, xmlDoc, formula)` | Creates `<Cell>` with CONVERSION_FACTOR scaling |
| `createRow(type, index, x, y, xmlDoc)` | Creates geometry `<Row>` element |
| `getStyleColor(color)` | Normalizes color to VSDX format |
| `getArrowType(arrow, isFilled)` | Maps draw.io arrow name to VSDX arrow ID |
| `getArrowSize(size)` | Maps draw.io arrow size to VSDX arrow size value |
| `collectLayers(graph, diagramName)` | Extracts layer definitions from graph |
| `exportPage(page)` | Exports a single page (called in sequence) |
#### Constants
```javascript
CONVERSION_FACTOR = 40 * 2.54 // = 101.6 (screen coordinates per cm × cm per inch)
PAGES_TYPE = "http://schemas.microsoft.com/visio/2010/relationships/page"
RELS_XMLNS = "http://schemas.openxmlformats.org/package/2006/relationships"
XMLNS = "http://schemas.microsoft.com/office/visio/2012/main"
XMLNS_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships"
// Arrow type mapping: "drawioType|filled" → VSDX arrow ID
ARROWS_MAP = {
"none|1": 0, "none|0": 0,
"open|1": 1, "open|0": 1,
"block|1": 4, "block|0": 14,
"classic|1": 5, "classic|0": 17,
"oval|1": 10, "oval|0": 20,
"diamond|1": 11, "diamond|0": 22,
"blockThin|1": 2, "blockThin|0": 15,
"dash|1": 23, "dash|0": 23,
"ERone|1": 24, "ERmandOne|1": 25,
"ERmany|1": 27, "ERoneToMany|1": 28,
"ERzeroToMany|1": 29, "ERzeroToOne|1": 30,
"openAsync|1": 9, "openAsync|0": 9
}
```
---
### mxVsdxCanvas2D.js
**Inheritance**: `mxAbstractCanvas2D` → `mxVsdxCanvas2D` (via `mxUtils.extend`)
Intercepts mxGraph shape rendering calls and converts them to VSDX geometry XML instead of drawing to screen.
#### Methods
| Method | Signature | Purpose |
|--------|-----------|---------|
| `init(zip)` | `(JSZip)` | Initialize for new VSDX file |
| `onFilesLoaded()` | `()` | Hook called after pending files finish loading |
| `newShape(shape, cellState, xmlDoc)` | `(XMLElement, mxCellState, XMLDocument)` | Start capturing geometry for a vertex |
| `newEdge(shape, cellState, xmlDoc)` | `(XMLElement, mxCellState, XMLDocument)` | Start capturing geometry for an edge |
| `endShape()` | `()` | Finalize current shape (flush foreign data) |
| `newPage()` | `()` | Reset image list for new page |
| `getShapeType()` | → `string` | Returns captured shape type |
| `getShapeGeo()` | → `XMLElement` | Returns captured geometry section |
| `createGeoSec()` | `()` | Creates new Geometry Section element |
| `createElt(name)` | `(string)` → `XMLElement` | Creates namespaced XML element |
| `createCellElemScaled(name, val, formula)` | `(string, number, string?)` | Creates Cell with CONVERSION_FACTOR scaling |
| `createCellElem(name, val, formula)` | `(string, number, string?)` | Creates Cell element |
| `createRowScaled(type, ix, x, y, ...)` | `(string, number, ...)` | Creates geometry Row with scaled coordinates |
| `createRowRel(type, ix, x, y, ...)` | `(string, number, ...)` | Creates relative geometry Row |
| `begin()` | `()` | Start new path |
| `rect(x, y, w, h)` | `(number × 4)` | Rectangle via MoveTo/LineTo sequence |
| `roundrect(x, y, w, h, dx, dy)` | `(number × 6)` | Rounded rectangle with ArcTo corners |
| `ellipse(x, y, w, h)` | `(number × 4)` | Ellipse geometry row |
| `moveTo(x, y)` | `(number × 2)` | MoveTo geometry row |
| `lineTo(x, y)` | `(number × 2)` | LineTo geometry row |
| `quadTo(x1, y1, x2, y2)` | `(number × 4)` | Quadratic Bezier → RelQuadBezTo |
| `curveTo(x1, y1, x2, y2, x3, y3)` | `(number × 6)` | Cubic Bezier → RelCubBezTo |
| `close()` | `()` | Close path (implicit LineTo back to start) |
| `image(x, y, w, h, src, aspect, flipH, flipV)` | `(number × 4, string, boolean × 3)` | Embed image: handles SVG→PNG, BMP→PNG conversion |
| `text(x, y, w, h, str, align, valign, wrap, format, overflow, clip, rotation, dir)` | `(number × 4, string, ...)` | Text with HTML parsing → VSDX Paragraph/Character/Text sections |
| `convertSvg2Png(svgData, w, h, isBase64, callback)` | `(string, number × 2, boolean, Function)` | Renders SVG on canvas, exports PNG |
| `addForeignData(type, index)` | `(string, number)` | Creates ForeignData element for embedded images |
| `rotate(theta, flipH, flipV, cx, cy)` | `(number, boolean × 2, number × 2)` | Captures rotation state |
| `stroke()` / `fill()` / `fillAndStroke()` | `()` | No-ops (geometry captured via path methods) |
---
### bmpDecoder.js
Standalone BMP image format decoder. No dependencies on other module files.
#### Constructor
```javascript
BmpDecoder(buffer, is_with_alpha)
// buffer: Uint8Array containing BMP file data
// is_with_alpha: Boolean for alpha channel support
```
#### Methods
| Method | Purpose |
|--------|---------|
| `parseHeader()` | Extracts file size, dimensions, bit depth, compression, palette |
| `parseBGR()` | Routes to bit-depth specific decoder |
| `bit1()` | 1-bit monochrome (2-color palette lookup) |
| `bit4()` | 4-bit 16-color (palette lookup) |
| `bit8()` | 8-bit 256-color (palette lookup) |
| `bit15()` | 15-bit RGB 5:5:5 |
| `bit16()` | 16-bit RGB 5:6:5 (partial support) |
| `bit24()` | 24-bit BGR → RGBA |
| `bit32()` | 32-bit BGRA → RGBA |
| `getData()` | Returns Uint8ClampedArray of RGBA pixel data |
---
## Import Flow (VSDX → draw.io)
### Phase 1: ZIP Extraction
```
mxVsdxCodec.decodeVsdx(file, callback)
→ JSZip.loadAsync(file)
→ For each entry in ZIP:
.xml/.rels → parseXml() → docData[path]
(handles UTF-8 BOM, UTF-16LE fallback, entity fixing)
.emf → POST to EMF_CONVERT_URL → PNG base64 → mediaData[path]
(chunked: window.EMF_CHUNK_SIZE = 10, retries: 3)
.bmp → BmpDecoder → canvas → JPEG base64 → mediaData[path]
other media → base64 encode → mediaData[path]
```
### Phase 2: Model Initialization
```
allDone()
→ importNodes(document.xml) // Resolve OPC relationships recursively
→ new mxVsdxModel(doc, docData, mediaData)
├── initStylesheets() // Parse StyleSheet elements
├── initThemes() // Load theme1.xml, theme2.xml, ...
├── initMasters() // Load masters/masters.xml
└── initPages() // Load pages/pages.xml, link backgrounds
```
### Phase 3: Page Import (per page)
```
For each page in model.getPages():
createMxGraph() // New Graph with VSDX-specific config
graph.getModel().beginUpdate()
importPage(page, graph, root):
Pass 1 — Vertices: // addShape() → addVertex()/addGroup()
- Resolve master shape template
- Apply theme + QuickStyle colors
- Convert VSDX geometry to draw.io stencil
- Convert coordinates (flip Y axis)
- Create vertex cells
- Extract hyperlinks and custom properties
- Map layer membership to tags
Pass 2 — Connected edges: // addConnectedEdge()
- Look up source/target in vertexMap
- Create edge cells with graph.insertEdge()
- Apply line style, arrows, routing
- Process special geometry (line jumps, NURBS)
Pass 3 — Unconnected edges: // addUnconnectedEdge()
- Standalone lines with waypoints
Pass 4 — Layers: // Layer tag finalization
- Set hidden layer visibility
graph.getModel().endUpdate()
scaleGraph(graph, pageScale/drawingScale)
postImportPage(page, graph) // Async image cropping
sanitiseGraph(graph)
processPage(graph, page) // Encode → compress → <diagram> XML
```
### Phase 4: Output
```
Wrap all <diagram> elements in:
<?xml version="1.0" encoding="UTF-8"?><mxfile>...</mxfile>
→ callback(xmlString)
```
---
## Export Flow (draw.io → VSDX)
```
VsdxExport(editorUi).exportCurrentDiagrams(currentPageOnly)
│
├── Collect pages to export
├── createVsdxSkeleton(zip, pageCount) // Template VSDX structure
│
├── For each page:
│ ├── getGraphAttributes(graph) // Page dimensions, grid, scale
│ ├── collectLayers(graph) // Layer definitions
│ ├── convertMxModel2Page(graph, attrs)
│ │ ├── Get all cells from model
│ │ ├── For each cell:
│ │ │ convertMxCell2Shape(cell, ...)
│ │ │ ├── Vertex: render via mxVsdxCanvas2D → createShape()
│ │ │ ├── Edge: createEdge() with arrow mapping
│ │ │ └── Group: recursive processing
│ │ └── Build PageContents XML tree
│ └── addImagesRels(zip, pageIndex)
│
├── addPagesXML(zip, pages, layers, attrs) // pages.xml + relationships
└── JSZip.generateAsync({type: "blob"}) // → .vsdx download
```
---
## VSDX File Format (as understood by this code)
A VSDX file is a ZIP archive with this structure:
```
[Content_Types].xml ← MIME type mappings
_rels/.rels ← Package relationships
docProps/
app.xml ← Application metadata
core.xml ← Document metadata (creator, dates)
custom.xml ← Custom properties
visio/
document.xml ← Root document: settings, colors, fonts, stylesheets
document.xml.rels ← Relationships to pages, masters, themes
windows.xml ← Application window state
pages/
pages.xml ← Page listing with names, IDs, background refs
pages.xml.rels ← Relationships to individual page files
page1.xml ← PageContents: shapes, connects
page2.xml
_rels/
page1.xml.rels ← Per-page relationships (images)
masters/
masters.xml ← Master shape listing
master1.xml ← MasterContents: template shapes
_rels/
masters.xml.rels
theme/
theme1.xml ← OOXML color/font/effect theme
media/
image1.png ← Embedded images
image2.jpg
```
---
## Coordinate System Conversion
| | VSDX | draw.io |
|---|------|---------|
| **Origin** | Bottom-left | Top-left |
| **Y direction** | Up (+) | Down (+) |
| **Units** | Inches (default) | Pixels |
| **Conversion** | `mxGraph_Y = pageHeight - vsdx_Y` | |
| **Scale factor** | `CONVERSION_FACTOR = 101.6` (40 × 2.54) | |
---
## Style Property Mapping
### Fill
| VSDX | draw.io |
|------|---------|
| FillForegnd | fillColor |
| FillBkgnd / FillGradient | gradientColor |
| FillForegndTrans | opacity |
| FillPattern (0) | fillColor=none |
### Line
| VSDX | draw.io |
|------|---------|
| LineColor | strokeColor |
| LineWeight | strokeWidth |
| LinePattern | dashed (+ dashPattern) |
| BeginArrow | startArrow |
| EndArrow | endArrow |
| BeginArrowSize / EndArrowSize | startSize / endSize |
### Text
| VSDX | draw.io |
|------|---------|
| Char.Font | fontFamily |
| Char.Size | fontSize |
| Char.Color | fontColor |
| Char.Style (bold bit) | bold=1 |
| Char.Style (italic bit) | italic=1 |
| Char.Style (underline bit) | underline=1 |
| Para.HorzAlign | align (left/center/right) |
| VerticalAlign | verticalAlign (top/middle/bottom) |
### Shape Type Detection (Import)
- **Vertex**: No BeginX/BeginY/EndX/EndY cells
- **Edge**: Has BeginX/BeginY/EndX/EndY cells
- **Group**: Has `<Shapes>` child element containing sub-shapes
---
## Theme System
VSDX uses OOXML themes with a QuickStyle overlay:
```
Shape cells:
ThemeIndex → Which color scheme (0-11)
VariationColorIndex → Color variant
VariationStyleIndex → Style variant
QuickStyleFillColor → Theme fill color override
QuickStyleFontColor → Theme font color override
QuickStyleLineColor → Theme line color override
Theme provides:
12 accent colors (accent1-6, dark1-2, light1-2, hyperlink, followed-hyperlink)
Fill style definitions (NoFill, SolidFill, GradFill)
Line style definitions
Font definitions (major/minor)
```
Color resolution: `getThemeColor(index, tint, shade)` applies tint (lighten) or shade (darken) transformations to the base theme color.
---
## Master Shape Resolution
```
Instance shape in page
├── Master attribute → lookup mxVsdxMaster by ID
│ └── Contains geometry, default style, connection points
├── MasterShape attribute → specific sub-shape within master
└── Instance overrides master properties (cells override master cells)
```
Master shapes provide template geometry and styling. Instance shapes inherit from their master and can override individual properties.
---
## Dependencies
### Internal (draw.io)
- **mxGraph library**: mxAbstractCanvas2D, mxUtils, mxConstants, mxCell, mxGeometry, mxRectangle, mxPoint, mxCellState, mxCodec, mxEventSource
- **Graph class**: Extended mxGraph used by draw.io (for insertVertex, insertEdge, etc.)
- **EditorUi/App**: Application instance for file operations
### External Libraries
- **JSZip**: ZIP file creation and extraction
- **pako**: zlib compression/decompression (for compressed ForeignData in shapes)
- **DOMPurify**: HTML sanitization (optional, for text processing)
### Browser APIs
- Canvas 2D Context (SVG → PNG rendering)
- XMLHttpRequest (image fetching, EMF conversion)
- DOMParser / mxUtils.parseXml (XML parsing)
- FileReader (Blob → base64 for EMF conversion)
- Typed Arrays (Uint8Array, Uint8ClampedArray, DataView)
---
## Known Limitations and Issues
### Import Limitations
- **Layer model mismatch**: VSDX layers are virtual groupings where parts of a group can belong to different layers. draw.io cannot represent this — layers are mapped to tags instead.
- **MoveTo inside edge paths**: Not supported. Edge geometry assumes a single continuous path.
- **Connection constraint rotation**: Incomplete support for rotated connection points (fromPart/toPart).
- **Theme interpretation**: Gradient fills, effects, and variant styles are "best efforts" interpretations of the VSDX spec.
- **Edge groups**: Groups containing edges may produce suboptimal results — hard to detect edges that should be vertices when groups have children.
- **HTML text**: Complex HTML formatting is only partially preserved.
- **EMF images**: Require server-side conversion (EMF_CONVERT_URL). Without server, EMF images are lost.
- **Charset**: Full charset support is incomplete; UTF-16LE has a basic decoder, other encodings may fail.
- **Extremely large txtPinX/Y values**: Can cause browser hangs during import.
- **HTML `</li>` tag placement**: May appear after font/formatting tags instead of before them.
### Export Limitations
- **SVG shapes**: Converted to raster PNG rather than native Visio vector shapes.
- **Gradient fills**: Approximated as solid colors.
- **Image deduplication**: Not implemented — each image creates a separate media file.
- **Shape clipping**: Overflow handling may differ from mxGraph rendering.
- **Text position**: Approximate for rotated labels.
- **Connector arrows**: Limited arrow type mappings (see ARROWS_MAP).
- **Deep group nesting**: May cause geometry inaccuracies.
- **Image crop accuracy**: Minor width/height differences possible.
### BMP Decoder
- **RGB565 16-bit**: Not fully implemented.
- **RLE compression**: Not supported (uncompressed BMP only).
- **Orientation**: Assumes bottom-up (standard Windows BMP).
### Code Quality Notes
- `importer.js` is **JSweet-transpiled** from Java — patterns like `__extends`, verbose namespace nesting, and `_$LI$()` static initializers are transpiler artifacts.
- JSweet has a **field initialization ordering bug** where defaults execute before `super()` — workarounds exist in VsdxShape and Shape constructors.
---
## Key Data Structures (Import)
```javascript
// Vertex mapping: tracks created cells for edge connection
vertexMap = { ShapePageId(pageId, shapeId): mxCell }
// Edge shapes pending connection processing
edgeShapeMap = { ShapePageId(pageId, edgeId): VsdxShape }
// Original VSDX shape references
vertexShapeMap = { ShapePageId(pageId, shapeId): VsdxShape }
// Parent cells for edges in groups
parentsMap = { ShapePageId(pageId, edgeId): mxCell }
// Layer names indexed by position
layerNames = ["Layer1", "Layer2", ...]
```
---
## Key Data Structures (Export)
```javascript
// Cell ID → sequential VSDX shape ID mapping
idsMap = { "mxCellId": 1, "mxCellId2": 2, ... }
idsCounter = 1 // next available ID
```