Source importers: lstat before open so FIFOs no longer hang the directory walk; replace the quadratic Rust macro regex with a linear scan. Three-way sync: report page add/add and delete-vs-modify as conflicts instead of silently overwriting or resurrecting; canonical comparison so key order is not a change; the sync action withholds output and fails on conflicts unless --force. Story publishing escapes <, >, & and U+2028/9 inside the embedded JSON. Views: drop parentId of unselected containers, re-layout instead of manual geometry, validate before serialising; flatten() merges identical nodes repeated across pages so C4 output works with every analysis action. Dark theme edge labels get a background; tube-map corridors sit above the stations; C4 containers keep the swimlane style and orphan relationships land on the matching page; router keeps container header bands as obstacles; sequence self-messages loop on one side. Docs: SKILL.md lists all 23 CLI actions and how each capability family is invoked, task wrappers for query/test/what-if/doctor, capability tables and --page scope corrected, maintenance snippet uses the real synchronous action signature, duplicated rule bullets moved to the rule references, coverage matrix wording made verifiable. Co-Authored-By: Claude Code <noreply@anthropic.com>
206 lines
8.3 KiB
Markdown
206 lines
8.3 KiB
Markdown
# diagrams-drawio
|
||
|
||
TypeScript tools for deterministic Diagram IR-to-Draw.io generation, loss-aware round trips, transactional editing, semantic analysis, synchronization, offline publishing, and visual verification.
|
||
|
||
Built with TypeScript using [`@maxgraph/core`](https://github.com/maxGraph/maxGraph) — the official TypeScript successor to mxGraph (the library draw.io is built on) — for accurate XML parsing and absolute coordinate resolution.
|
||
|
||
## Stack
|
||
|
||
| Concern | Choice |
|
||
|---|---|
|
||
| Language | TypeScript (ESM, `NodeNext`) |
|
||
| Package manager | pnpm |
|
||
| XML / model parsing | `@maxgraph/core` v0.23 |
|
||
| Node.js DOM polyfill | `jsdom` |
|
||
| `<mxfile>` decoding | `pako` (base64 + deflate) |
|
||
| Output | YAML (via `js-yaml`) |
|
||
|
||
## Install
|
||
|
||
```bash
|
||
cd scripts
|
||
pnpm install --frozen-lockfile
|
||
```
|
||
|
||
## Build
|
||
|
||
```bash
|
||
cd scripts
|
||
task build # or: pnpm run build
|
||
# compiled output → scripts/dist/
|
||
```
|
||
|
||
## Usage
|
||
|
||
```bash
|
||
cd scripts
|
||
task run -- --file="diagram.drawio" --action=<action> [--page <index>]
|
||
# or directly:
|
||
node dist/cli/commands.js --file diagram.drawio --action <action> [--page <index>]
|
||
|
||
# Build from semantic YAML/JSON Diagram IR:
|
||
node dist/cli/commands.js --action build --file architecture.yaml --output architecture.drawio
|
||
|
||
# Loss-aware import and transactional edit:
|
||
node dist/cli/commands.js --action import --file architecture.drawio --output architecture.yaml
|
||
node dist/cli/commands.js --action edit --file architecture.yaml --spec ../examples/edit-batch.yaml --output edited.drawio
|
||
```
|
||
|
||
Output is always YAML to stdout.
|
||
|
||
## Actions
|
||
|
||
### Authoring
|
||
|
||
#### `build`
|
||
|
||
Validates a versioned YAML Diagram IR and emits deterministic native Draw.io XML.
|
||
|
||
- **v1 remains supported** for single-page linear diagrams.
|
||
- **v2** adds multiple pages, containers and semantic kinds, explicit geometry, edge waypoints, provenance/properties/extensions, and typed layout options.
|
||
- `linear`, `layered`, `tree`, `grid`, and `manual` layouts are supported. Layered/tree layouts use deterministic dependency-aware placement.
|
||
- Generated connectors receive deterministic obstacle-aware orthogonal waypoints when a clear route is available.
|
||
- Duplicate/reserved IDs, invalid dimensions, unknown parents, and unknown edge endpoints fail before output is written.
|
||
|
||
See `examples/platform-v2.yaml` and `schemas/diagram-ir-v2.schema.json`.
|
||
|
||
---
|
||
|
||
### Semantic lifecycle
|
||
|
||
| Action | Purpose | Key options |
|
||
|---|---|---|
|
||
| `import` | Loss-aware Draw.io to Diagram IR v2 | `--output model.yaml|json` |
|
||
| `edit` | Atomic stable-ID edit batch | `--spec`, `--output`, `--dry-run` |
|
||
| `views` | Linked executive/system/deployment/dataflow/security views | `--views`, `--output` |
|
||
| `query` | Kind/property filtering and deterministic shortest paths | `--kind`, `--property`, `--from`, `--to` |
|
||
| `test` | Seven built-in architecture policies | `--spec`, `--strict` |
|
||
| `what-if` | Failure propagation with isolation boundaries | `--fail` |
|
||
| `sync` | Three-way synchronization preserving manual presentation | `--base`, `--spec`, `--output`, `--prune`, `--dry-run` |
|
||
| `story` | Self-contained accessible offline HTML | `--output`, optional `--fail` |
|
||
| `doctor` | Report optional backend availability without launching it | no `--file` required |
|
||
|
||
Commands fail closed on ambiguous identities, invalid view/policy names, input/output aliases, and malformed operations. See [`references/semantic-lifecycle.md`](references/semantic-lifecycle.md) for complete contracts and examples.
|
||
|
||
---
|
||
|
||
### Native service libraries
|
||
|
||
The combined package also exposes tested TypeScript service APIs for capabilities that are not registered as CLI actions:
|
||
|
||
| Family | Implemented native services |
|
||
|---|---|
|
||
| Safe source importers | Python, JavaScript/TypeScript, Go, Rust, Terraform, Kubernetes, Docker Compose, SQL, OpenAPI, and CI job DAG subsets |
|
||
| Toolbox | Five themes, generic offline shape search, Mermaid and Markdown reverse transforms, semantic diff, strict relabeling, and accessible metric heatmaps |
|
||
| Specialized profiles | C4, sequence, tube map, executive compression, runbook HTML, timelapse, and dependency-ordered build-up |
|
||
|
||
These are conservative, bounded service contracts rather than claims of complete language parsers or peer-compatible command-line interfaces. See [`references/agents365-capability-coverage.md`](references/agents365-capability-coverage.md) for the strict 42-tool comparison and remaining gaps.
|
||
|
||
---
|
||
|
||
### Inventory
|
||
|
||
#### `summary`
|
||
|
||
Parses **all pages (tabs)** in the `.drawio` file and returns a full inventory of shapes and edges per page. Delegates per-page data to the same logic as `page-summary`.
|
||
|
||
**Output:** `pageCount`, `pages[]` (each page has the same structure as `page-summary`)
|
||
|
||
---
|
||
|
||
#### `page-summary`
|
||
|
||
Parses a **single page**. Use `--page <index>` (0-based, default `0`).
|
||
|
||
**Output:** `pageCount`, `pageIndex`, `pageName`, `page` (width/height), `summary` (shapeCount, edgeCount, contentRight, contentBottom), `shapes[]`, `edges[]`
|
||
|
||
---
|
||
|
||
#### `page-hierarchy`
|
||
|
||
Reads `parentId` from each shape and builds a **recursive containment tree**:
|
||
- Depth 0 — layers / top-level containers (direct children of the canvas)
|
||
- Depth 1 — subsystems / groups inside a layer
|
||
- Depth 2+ — leaf components and nested elements
|
||
|
||
**Output:** `summary` (totalShapes, maxDepth, depthCounts), `tree[]` (recursive: id, label, depth, childCount, children[])
|
||
|
||
---
|
||
|
||
#### `page-connectors-summary`
|
||
|
||
Returns a summary of all **connectors (edges)** on the page, classified by type and connectivity.
|
||
|
||
Connector types: `directed` (both endpoints connected), `partial` (one missing), `floating` (both missing)
|
||
|
||
**Output:** `summary` (total, directed, partial, floating, labelled, unlabelled, withWaypoints, straight), `connectors[]` (id, label, sourceId, sourceLabel, targetId, targetLabel, waypointCount, type)
|
||
|
||
---
|
||
|
||
### Validation
|
||
|
||
#### `quality`
|
||
|
||
Runs objective visual-quality checks across every page: page clipping, likely text overflow, placeholder text, external image URLs, palette spread, page density, and edge density. Findings have explicit `error` or `warning` severity; the action never invents a minimum defect count.
|
||
|
||
**Output:** `summary` (pages, shapes, edges, errors, warnings), `issues[]`
|
||
|
||
---
|
||
|
||
#### `page-connectors-validation`
|
||
|
||
Detects two categories of layout defects on the first page:
|
||
1. **Connector-shape overlaps** — a connector segment passes through a shape it is not connected to
|
||
2. **Connector crossings** — two connectors intersect at an interior point
|
||
|
||
Uses 2 px tolerance. **Output:** `summary` (connectorShapeOverlaps, connectorCrossings, totalIssues), `issues[]`
|
||
|
||
---
|
||
|
||
#### `page-labels-validation`
|
||
|
||
Validates shape labels and flags:
|
||
1. **empty_label** — shape has no label (whitespace counts as empty)
|
||
2. **duplicate_label** — two or more shapes share the same label
|
||
3. **long_label** — label exceeds 80 characters
|
||
|
||
Edges/connectors are excluded. **Output:** `config` (maxLabelLength), `summary` (emptyLabels, duplicateLabels, longLabels, totalIssues), `issues[]`
|
||
|
||
---
|
||
|
||
#### `page-shape-bbox-validation`
|
||
|
||
Detects shapes whose **bounding boxes overlap** each other. Parent-child containment is intentional and is **not** flagged. Uses 2 px tolerance.
|
||
|
||
**Output:** `summary` (totalShapes, overlappingPairs), `issues[]` (shapeAId, shapeALabel, shapeBId, shapeBLabel, overlapX, overlapY)
|
||
|
||
---
|
||
|
||
#### `page-orphans`
|
||
|
||
Finds disconnected elements:
|
||
1. **isolated_shape** — shape with no edges connected to it
|
||
2. **dangling_connector** — edge missing its source and/or target shape
|
||
|
||
**Output:** `summary` (isolatedShapes, danglingConnectors, totalIssues), `issues[]`
|
||
|
||
---
|
||
|
||
### Layout
|
||
|
||
#### `page-recommendations`
|
||
|
||
Computes the bounding box of all shapes and recommends the smallest standard landscape page size that fits with an 80 px margin (first page).
|
||
|
||
Standard sizes: A4 (1169×827), A3 (1654×1169), A2 (2339×1654), A1 (3307×2339). Falls back to custom rounded size.
|
||
|
||
**Output:** `currentPage` (width, height, orientation), `contentBbox`, `required` (min size needed), `recommendedPage` (name, width, height), `checks` (contentFitsCurrentPage, hasAdequateMargin, isLandscape)
|
||
|
||
---
|
||
|
||
## Supported file formats
|
||
|
||
- Bare `<mxGraphModel>` XML files
|
||
- `<mxfile><diagram>…</diagram></mxfile>` wrappers (draw.io desktop format, base64+deflate encoded, multi-page supported)
|
||
- Loss-aware semantic import preserves unknown wrapper/page/model XML in explicit `$drawio` envelopes for deterministic round trips
|