@littledragon_wxl/drawio-style-graph 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -0
- package/LICENSE +21 -0
- package/README.md +175 -0
- package/README_zh.md +171 -0
- package/SKILL.md +419 -0
- package/data/SHAPE-INDEX-NOTICE.md +17 -0
- package/data/lobe-icons.json +878 -0
- package/data/shape-index.json.gz +0 -0
- package/package.json +43 -0
- package/references/autolayout.md +125 -0
- package/references/diagram-types.md +83 -0
- package/references/shapes.md +151 -0
- package/references/style-application-guide.md +120 -0
- package/references/style-diagram-matrix.md +159 -0
- package/references/style-extraction.md +255 -0
- package/references/style-presets.md +110 -0
- package/references/styles/style-1-flat-icon.md +79 -0
- package/references/styles/style-2-dark-terminal.md +80 -0
- package/references/styles/style-3-blueprint.md +84 -0
- package/references/styles/style-4-notion-clean.md +78 -0
- package/references/styles/style-5-glassmorphism.md +85 -0
- package/references/styles/style-6-claude-official.md +84 -0
- package/references/styles/style-7-openai.md +94 -0
- package/references/styles/style-8-dark-luxury.md +109 -0
- package/references/troubleshooting.md +63 -0
- package/scripts/aiicons.py +201 -0
- package/scripts/autolayout.py +341 -0
- package/scripts/encode_drawio_url.py +58 -0
- package/scripts/goimports.py +141 -0
- package/scripts/jsimports.py +162 -0
- package/scripts/pyclasses.py +156 -0
- package/scripts/pyimports.py +153 -0
- package/scripts/repair_png.py +37 -0
- package/scripts/rustimports.py +203 -0
- package/scripts/shapesearch.py +162 -0
- package/scripts/validate.py +137 -0
- package/styles/built-in/corporate.json +49 -0
- package/styles/built-in/default.json +49 -0
- package/styles/built-in/handdrawn.json +49 -0
- package/styles/schema-drawio.json +112 -0
- package/styles/schema.json +213 -0
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@littledragon_wxl/drawio-style-graph",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Generate .drawio diagrams with 8 professional visual styles. Self-contained — no external skill dependencies.",
|
|
5
|
+
"main": "SKILL.md",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"drawio",
|
|
8
|
+
"diagram",
|
|
9
|
+
"flowchart",
|
|
10
|
+
"architecture",
|
|
11
|
+
"visualization",
|
|
12
|
+
"uml",
|
|
13
|
+
"svg",
|
|
14
|
+
"style-preset",
|
|
15
|
+
"skill",
|
|
16
|
+
"claude-code"
|
|
17
|
+
],
|
|
18
|
+
"author": "littledragon_wxl",
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/Littledragon-wxl/drawio-style-graph.git"
|
|
23
|
+
},
|
|
24
|
+
"bugs": {
|
|
25
|
+
"url": "https://github.com/Littledragon-wxl/drawio-style-graph/issues"
|
|
26
|
+
},
|
|
27
|
+
"homepage": "https://github.com/Littledragon-wxl/drawio-style-graph#readme",
|
|
28
|
+
"files": [
|
|
29
|
+
"SKILL.md",
|
|
30
|
+
"README.md",
|
|
31
|
+
"README_zh.md",
|
|
32
|
+
"LICENSE",
|
|
33
|
+
"CHANGELOG.md",
|
|
34
|
+
"scripts/",
|
|
35
|
+
"data/",
|
|
36
|
+
"references/",
|
|
37
|
+
"styles/"
|
|
38
|
+
],
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=14.0.0"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# Auto-layout (Graphviz)
|
|
2
|
+
|
|
3
|
+
Read this when a diagram is **large or layout-heavy** — dependency/call graphs, code/module structure, or roughly **more than ~15 nodes** — where hand-placing `x`/`y` coordinates is slow, error-prone, and overlap-prone.
|
|
4
|
+
|
|
5
|
+
Instead of computing coordinates by hand in the Generate step, describe the graph as JSON and let `scripts/autolayout.py` place the nodes and route the edges with Graphviz, then continue the normal workflow (Export draft → Self-check → …) on the produced `.drawio`.
|
|
6
|
+
|
|
7
|
+
For small or carefully-styled diagrams, keep hand-placing — auto-layout trades fine control for scale.
|
|
8
|
+
|
|
9
|
+
## Dependency
|
|
10
|
+
|
|
11
|
+
Requires Graphviz `dot` on PATH:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# macOS
|
|
15
|
+
brew install graphviz
|
|
16
|
+
# Debian/Ubuntu
|
|
17
|
+
sudo apt install graphviz
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The script exits with a clear message if `dot` is missing — fall back to hand-placed coordinates in that case.
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
python3 <this-skill-dir>/scripts/autolayout.py graph.json -o diagram.drawio
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
It prints `wrote diagram.drawio (N nodes, M edges)` to stderr and writes a normal `.drawio` file. From there, continue at the **Export draft** step of the main workflow (preview PNG with `--width 2000`, self-check, review loop, final export with `-e` + `repair_png.py`).
|
|
29
|
+
|
|
30
|
+
## Input format
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"direction": "TB",
|
|
35
|
+
"nodes": [
|
|
36
|
+
{"id": "client", "label": "Web Client", "style": "rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;"},
|
|
37
|
+
{"id": "gw", "label": "API Gateway", "group": "edge", "groupLabel": "Edge tier"},
|
|
38
|
+
{"id": "db", "label": "User DB", "style": "shape=cylinder3;whiteSpace=wrap;html=1;", "width": 120, "height": 80, "group": "data"}
|
|
39
|
+
],
|
|
40
|
+
"edges": [
|
|
41
|
+
{"source": "client", "target": "gw", "label": "HTTPS"},
|
|
42
|
+
{"source": "gw", "target": "db"}
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Fields**
|
|
48
|
+
|
|
49
|
+
| Field | Required | Default | Notes |
|
|
50
|
+
|---|---|---|---|
|
|
51
|
+
| `direction` | no | `TB` | `TB` (top→bottom) or `LR` (left→right) — the layout rank direction |
|
|
52
|
+
| `nodes[].id` | **yes** | — | Unique; must not be `0` or `1` (reserved for draw.io root cells) |
|
|
53
|
+
| `nodes[].label` | no | the `id` | Display text; auto XML-escaped |
|
|
54
|
+
| `nodes[].style` | no | group colour, else blue | Any draw.io style string — reuse the role/shape styles from `diagram-types.md` and the active preset. A styleless node is tinted by its group (see **Containers / grouping**); an explicit style always wins |
|
|
55
|
+
| `nodes[].width` / `height` | no | `120` / `60` | Pixels; dot lays out at this real size |
|
|
56
|
+
| `nodes[].group` | no | none | Group key, or a `/`-delimited path (`"core/db"`) for **nested** containers — nodes sharing a path are boxed together (see **Containers / grouping**) |
|
|
57
|
+
| `nodes[].groupLabel` | no | last path segment | Title shown on the node's deepest container (first node with the path wins) |
|
|
58
|
+
| `edges[].source` / `target` | **yes** | — | Must match node ids |
|
|
59
|
+
| `edges[].label` | no | empty | Edge text |
|
|
60
|
+
|
|
61
|
+
## How it places things
|
|
62
|
+
|
|
63
|
+
- Node positions come from `dot` (hierarchical layered layout), converted to draw.io pixels and snapped to the grid (multiples of 10).
|
|
64
|
+
- Edges use `splines=ortho`: dot's orthogonal route is replayed as draw.io waypoints, so edges go **around** nodes instead of through them.
|
|
65
|
+
- Apply the active style preset by setting each node's `style` to the preset's role/shape values before calling the script — the script does not know about presets.
|
|
66
|
+
|
|
67
|
+
## Containers / grouping
|
|
68
|
+
|
|
69
|
+
Give nodes a `group` key and the script wraps each group in a labeled container (a dashed box with the group title at top) and tells dot to keep that group's nodes together via a Graphviz cluster. Grouped nodes become children of their container (`parent="<container>"`, relative coordinates); ungrouped nodes stay at the top level. This turns a flat hairball into a "boxes of related modules" architecture view.
|
|
70
|
+
|
|
71
|
+
**Nesting.** A `group` value with `/` separators builds nested containers: `"core/db"` puts the node inside a `db` box that itself sits inside a `core` box. Every path prefix becomes a container, so an arbitrarily deep package tree maps to nested boxes. A node can also sit *directly* in a parent box (`group: "core"`) alongside a sibling sub-box (`group: "core/db"`).
|
|
72
|
+
|
|
73
|
+
- **Colour by group.** Each top-level group is assigned a colour from the skill's own palette (`styles/built-in/default.json`, cycled in role order: blue → green → orange → purple → yellow → red → grey). A node with no `style` of its own is tinted with its group's colour, and the container's border + title match — so related modules read as a coloured cluster instead of monochrome boxes. A node that carries its own `style` (e.g. from an applied preset) is left untouched. Pass `--mono` to turn colouring off (dashed grey boxes, default-blue nodes — the previous look). Ungrouped graphs are unaffected.
|
|
74
|
+
- Each container box is the bounding box of its members and child boxes plus a uniform padding. The dot cluster margin is set to that same padding, so each box equals dot's cluster box — which dot keeps non-overlapping at **any nesting depth**.
|
|
75
|
+
- The title sits in the top padding (`verticalAlign=top`); the box title is the path's last segment, or a member's `groupLabel`.
|
|
76
|
+
- Containers are visual only (no edges of their own). Edges still connect node→node and route across containers normally.
|
|
77
|
+
- If a container's top padding would cross the page origin, the whole diagram is shifted so nothing lands at a negative coordinate.
|
|
78
|
+
|
|
79
|
+
## Validate before previewing
|
|
80
|
+
|
|
81
|
+
`scripts/validate.py` is a deterministic structural linter — run it on the produced `.drawio` before the (slower, vision-based) self-check:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
python3 <this-skill-dir>/scripts/validate.py diagram.drawio
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
It catches dangling edge endpoints, duplicate/reserved ids, broken parent references (errors), plus off-grid/negative geometry and overlapping sibling nodes (warnings) — without launching draw.io. Exit status is non-zero on any error (or any warning with `--strict`), so it can gate the workflow. Auto-layout output should always pass clean; a failure means a malformed input graph (e.g. an edge referencing a missing node id).
|
|
88
|
+
|
|
89
|
+
## Importers — visualize code structure
|
|
90
|
+
|
|
91
|
+
Bundled importers turn a codebase into a graph JSON ready for autolayout, so "visualize this project" is a two-step pipeline:
|
|
92
|
+
|
|
93
|
+
| Language | Script | Node = | Edge = |
|
|
94
|
+
|---|---|---|---|
|
|
95
|
+
| Python | `scripts/pyimports.py <dir>` | module / package (`ast`) | intra-project `import` / `from` |
|
|
96
|
+
| JS / TS | `scripts/jsimports.py <dir>` | source file (`.ts/.tsx/.js/.jsx/.mjs/.cjs`) | resolved relative `import`/`export from`/`require()`/`import()` |
|
|
97
|
+
| Go | `scripts/goimports.py <dir>` | package (directory, via `go.mod`) | intra-module package import |
|
|
98
|
+
| Rust | `scripts/rustimports.py <dir>` | module (`.rs` file / `mod`) | intra-crate `use crate::` / `super::` / `self::` |
|
|
99
|
+
| Python (classes) | `scripts/pyclasses.py <dir>` | class (`ast`) | subclass → base (inheritance) |
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
python3 <this-skill-dir>/scripts/pyimports.py myproject -o graph.json
|
|
103
|
+
python3 <this-skill-dir>/scripts/autolayout.py graph.json -o diagram.drawio
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Each keeps only **intra-project** edges (third-party/stdlib imports are ignored), shortens node labels (drops the shared package/module/directory prefix; ids stay fully qualified), and shares the same flags: `--direction TB|LR` (default `TB`), `--group`, `--no-reduce`.
|
|
107
|
+
|
|
108
|
+
- **Python** (`pyimports.py`): if the directory is itself a package (`__init__.py` present), module names are package-qualified so the project's own absolute imports resolve; nested subpackages (`pkg.sub.mod`) are handled.
|
|
109
|
+
- **JS/TS** (`jsimports.py`): resolution is path-based (tries the source extensions and directory `index` files); `node_modules` and bare specifiers are skipped. Scanning is regex-based, not a full parser.
|
|
110
|
+
- **Go** (`goimports.py`): reads the `module` path from `go.mod`; each directory of `.go` files is one package; `*_test.go` and `vendor/` are skipped.
|
|
111
|
+
- **Rust** (`rustimports.py`): each `.rs` file is a module (`mod.rs`/`main.rs`/`lib.rs` name the enclosing module); edges come from `use` paths rooted at `crate::`/`super::`/`self::` (brace groups expanded). `std`/external crates and `target/` are skipped. Regex-based — inline `mod { … }` blocks aren't split out, and 2015-edition bare intra-crate paths aren't resolved.
|
|
112
|
+
- **Python classes** (`pyclasses.py`): a finer granularity — one node per class, edges from each subclass to the project base classes it extends, so the result is an auto-generated class hierarchy. Bases are matched by name (preferring the same module); external bases (`object`, third-party) are ignored. With `--group`, classes are boxed by their module, so a deep package tree nests naturally. Inheritance only — function-level call graphs are out of scope (static call resolution in Python is unreliable).
|
|
113
|
+
|
|
114
|
+
**Density reduction is on by default** — this is the key to a readable result. Real import graphs are dense (asyncio: 33 modules / ~149 edges); without reduction they render as a hairball. Every importer applies **transitive reduction** (Graphviz `tred` — drops edges already implied by a longer path), which on asyncio cuts ~149 edges to ~46 and turns the hairball into a clean, traceable diagram. Pass `--no-reduce` to keep every edge.
|
|
115
|
+
|
|
116
|
+
**`--group`** assigns each node a container by its sub-package / directory path, so autolayout boxes related modules together — nested when the path has depth (see **Containers / grouping**). The fastest way to turn a large code graph into a tiered architecture view.
|
|
117
|
+
|
|
118
|
+
For any other language, produce the same graph JSON from any analyzer (e.g. `dependency-cruiser` for richer JS/TS resolution, `go-callvis` for Go call graphs) and feed it to autolayout the same way.
|
|
119
|
+
|
|
120
|
+
## Limitations
|
|
121
|
+
|
|
122
|
+
- **Placement is topological, not semantic** — dot minimises edge crossings, which may put a node in a different column than you'd choose by hand. Re-export with the other `direction`, or hand-tune the produced XML afterwards (it's a normal `.drawio`).
|
|
123
|
+
- **Import edges are static** — `pyimports`/`jsimports`/`goimports` read static import statements (not dynamic `importlib`, runtime `require`, or reflection); `pyclasses` resolves inheritance only, not method-level calls.
|
|
124
|
+
- **Parallel edges** between the same `(source, target)` pair share one route.
|
|
125
|
+
- **Containers don't add edges** — `group`/nesting only boxes nodes for layout; edges remain node→node. For hand-built swimlane/architecture containers with their own connections, see SKILL.md "Containers and groups".
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Diagram Type Presets
|
|
2
|
+
|
|
3
|
+
When the user requests a specific diagram type, apply the matching preset below for shapes, styles, and layout conventions. These presets set **structural** style keywords (e.g. ERD's `shape=table;childLayout=tableLayout`); a user style preset (see `references/style-presets.md`) layers color/font/edge/extras on top.
|
|
4
|
+
|
|
5
|
+
Read this file when:
|
|
6
|
+
- The user names one of these diagram types (ERD, UML class, sequence, architecture, ML/DL model, flowchart)
|
|
7
|
+
- You're choosing shape vocabulary or layout direction for a new diagram
|
|
8
|
+
|
|
9
|
+
## ERD (Entity-Relationship Diagram)
|
|
10
|
+
|
|
11
|
+
| Element | Style | Notes |
|
|
12
|
+
|---------|-------|-------|
|
|
13
|
+
| Table | `shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;strokeColor=#6c8ebf;fillColor=#dae8fc;` | Each table is a container |
|
|
14
|
+
| Row (column) | `shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;fontSize=12;` | Child of table, `parent=tableId` |
|
|
15
|
+
| PK column | Bold text: `fontStyle=1` on the row | Mark with `PK` prefix or key icon |
|
|
16
|
+
| FK relationship | Dashed edge: `dashed=1;endArrow=ERmandOne;startArrow=ERmandOne;` | Use ER notation arrows |
|
|
17
|
+
| Layout | TB, tables spaced 300px apart | Group related tables vertically |
|
|
18
|
+
|
|
19
|
+
## UML Class Diagram
|
|
20
|
+
|
|
21
|
+
| Element | Style | Notes |
|
|
22
|
+
|---------|-------|-------|
|
|
23
|
+
| Class box | `swimlane;fontStyle=1;align=center;startSize=26;html=1;` | 3-section: title / attributes / methods |
|
|
24
|
+
| Separator | `line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=10;rotatable=0;labelPosition=left;points=[];portConstraint=eastwest;` | Between sections |
|
|
25
|
+
| Inheritance | `endArrow=block;endFill=0;` | Hollow triangle arrow |
|
|
26
|
+
| Implementation | `endArrow=block;endFill=0;dashed=1;` | Dashed + hollow triangle |
|
|
27
|
+
| Composition | `endArrow=diamondThin;endFill=1;` | Filled diamond |
|
|
28
|
+
| Aggregation | `endArrow=diamondThin;endFill=0;` | Hollow diamond |
|
|
29
|
+
| Layout | TB, classes 250px apart | Interfaces above implementations |
|
|
30
|
+
|
|
31
|
+
## Sequence Diagram
|
|
32
|
+
|
|
33
|
+
| Element | Style | Notes |
|
|
34
|
+
|---------|-------|-------|
|
|
35
|
+
| Actor/Object | `shape=umlLifeline;perimeter=lifelinePerimeter;whiteSpace=wrap;html=1;container=1;collapsible=0;recursiveResize=0;outlineConnect=0;portConstraint=eastwest;` | Lifeline with dashed vertical line |
|
|
36
|
+
| Sync message | `html=1;verticalAlign=bottom;endArrow=block;` | Solid line, filled arrowhead |
|
|
37
|
+
| Async message | `html=1;verticalAlign=bottom;endArrow=open;dashed=1;` | Dashed line, open arrowhead |
|
|
38
|
+
| Return message | `html=1;verticalAlign=bottom;endArrow=open;dashed=1;strokeColor=#999999;` | Grey dashed |
|
|
39
|
+
| Activation box | `shape=umlFrame;whiteSpace=wrap;` on the lifeline | Narrow rectangle on lifeline |
|
|
40
|
+
| Layout | LR, lifelines spaced 200px apart | Time flows top to bottom |
|
|
41
|
+
|
|
42
|
+
## Architecture Diagram
|
|
43
|
+
|
|
44
|
+
| Element | Style | Notes |
|
|
45
|
+
|---------|-------|-------|
|
|
46
|
+
| Layer/tier | `swimlane;startSize=30;` | Containers for grouping: Client / API / Service / Data |
|
|
47
|
+
| Service | `rounded=1;whiteSpace=wrap;html=1;` + tier color | Use color palette by tier |
|
|
48
|
+
| Database | `shape=cylinder3;whiteSpace=wrap;html=1;` | Green palette |
|
|
49
|
+
| Queue/Bus | `rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;` | Yellow — place centrally for hub pattern |
|
|
50
|
+
| Gateway/LB | `shape=mxgraph.aws4.resourceIcon;` or `rounded=1;` with orange | Orange palette |
|
|
51
|
+
| External | `rounded=1;dashed=1;fillColor=#f5f5f5;strokeColor=#666666;` | Dashed border for external systems |
|
|
52
|
+
| Layout | TB or LR by tier count; ≥4 tiers → TB | Hub nodes centered |
|
|
53
|
+
|
|
54
|
+
## ML / Deep Learning Model Diagram
|
|
55
|
+
|
|
56
|
+
For neural network architecture diagrams — ideal for papers targeting NeurIPS, ICML, ICLR.
|
|
57
|
+
|
|
58
|
+
| Element | Style | Notes |
|
|
59
|
+
|---------|-------|-------|
|
|
60
|
+
| Layer block | `rounded=1;whiteSpace=wrap;html=1;` + type color | Main building block |
|
|
61
|
+
| Input/Output | `fillColor=#d5e8d4;strokeColor=#82b366;` | Green |
|
|
62
|
+
| Conv / Pooling | `fillColor=#dae8fc;strokeColor=#6c8ebf;` | Blue |
|
|
63
|
+
| Attention / Transformer | `fillColor=#e1d5e7;strokeColor=#9673a6;` | Purple |
|
|
64
|
+
| RNN / LSTM / GRU | `fillColor=#fff2cc;strokeColor=#d6b656;` | Yellow |
|
|
65
|
+
| FC / Linear | `fillColor=#ffe6cc;strokeColor=#d79b00;` | Orange |
|
|
66
|
+
| Loss / Activation | `fillColor=#f8cecc;strokeColor=#b85450;` | Red/Pink |
|
|
67
|
+
| Skip connection | `dashed=1;endArrow=block;curved=1;` | Dashed curved arrow |
|
|
68
|
+
| Tensor shape label | Add shape annotation as secondary label: `value="Conv2D
(B, 64, 32, 32)"` | Use `
` for multi-line |
|
|
69
|
+
| Layout | TB (data flows top→bottom), layers 150px apart | Group encoder/decoder as swimlanes |
|
|
70
|
+
|
|
71
|
+
**Tensor shape convention:** annotate each layer with input/output tensor dimensions in `(B, C, H, W)` or `(B, T, D)` format. Place dimensions as the second line of the label using `
`.
|
|
72
|
+
|
|
73
|
+
## Flowchart (enhanced)
|
|
74
|
+
|
|
75
|
+
| Element | Style | Notes |
|
|
76
|
+
|---------|-------|-------|
|
|
77
|
+
| Start/End | `ellipse;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;` | Green oval |
|
|
78
|
+
| Process | `rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;` | Blue rectangle |
|
|
79
|
+
| Decision | `rhombus;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;` | Yellow diamond |
|
|
80
|
+
| I/O | `shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;` | Orange parallelogram |
|
|
81
|
+
| Subprocess | `rounded=0;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;` + double border | Purple |
|
|
82
|
+
| Yes/No labels | `value="Yes"` / `value="No"` on decision edges | Always label decision branches |
|
|
83
|
+
| Layout | TB, 200px vertical gap | Decisions branch LR, merge back to center |
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# Shape vocabulary & search
|
|
2
|
+
|
|
3
|
+
Read this when a diagram needs a **specific shape** — a cloud-provider icon
|
|
4
|
+
(AWS/Azure/GCP), a network/Cisco/Kubernetes symbol, a UML/BPMN/ER element, an
|
|
5
|
+
electrical or P&ID part — or any time you'd otherwise *guess* a `style=` string.
|
|
6
|
+
|
|
7
|
+
There are two ways to get a style:
|
|
8
|
+
|
|
9
|
+
1. **Search the official shape index** (`scripts/shapesearch.py`) — 10,446 real
|
|
10
|
+
draw.io palette shapes with their exact `style`, `w`, `h`. Use this for
|
|
11
|
+
branded/vendor icons and anything non-trivial. **Always prefer a searched
|
|
12
|
+
style over a hand-written `shape=mxgraph.*` guess** — guessed stencil names
|
|
13
|
+
silently render as a blank box if the name is wrong.
|
|
14
|
+
2. **The cheatsheet below** — the common built-in shapes whose style strings are
|
|
15
|
+
short and stable enough to write by hand (rectangles, flowchart symbols,
|
|
16
|
+
UML primitives, containers, edges).
|
|
17
|
+
|
|
18
|
+
## Searching shapes
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
python3 <this-skill-dir>/scripts/shapesearch.py "aws lambda" --limit 5
|
|
22
|
+
python3 <this-skill-dir>/scripts/shapesearch.py "uml actor" --json
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
- Query is space-separated keywords; matching is tag-based with Soundex
|
|
26
|
+
fuzziness and `camelCase`/`digit` splitting (`"pid2valve"` → `pid valve`).
|
|
27
|
+
- Prints each match as `Title (WxH)` followed by its full `style=` string. With
|
|
28
|
+
`--json`, emits `[{style,w,h,title}]` for programmatic use.
|
|
29
|
+
- Copy the `style` verbatim into an `mxCell`, and use the reported `w`/`h` as the
|
|
30
|
+
`mxGeometry` width/height (vendor icons are drawn at a fixed aspect ratio).
|
|
31
|
+
- Results are ranked by tag relevance, with shapes whose **title** contains the
|
|
32
|
+
query terms bubbled to the top of each score tier. Ranking is still a
|
|
33
|
+
heuristic, though, and many shapes share a title (three `Lambda` variants:
|
|
34
|
+
`aws3`/`aws4`/`aws3d`) — so run with `--limit 5` and pick the row whose title
|
|
35
|
+
and size match what you actually want rather than blindly taking #1.
|
|
36
|
+
|
|
37
|
+
```xml
|
|
38
|
+
<mxCell id="2" value="Lambda" style="<paste the searched style here>" vertex="1" parent="1">
|
|
39
|
+
<mxGeometry x="40" y="40" width="78" height="78" as="geometry"/>
|
|
40
|
+
</mxCell>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Covered libraries: AWS (`aws3`/`aws4`), Azure, GCP, Cisco, Kubernetes, UML,
|
|
44
|
+
BPMN, ER, electrical, P&ID, mockup/wireframe, flowchart, network, and the
|
|
45
|
+
general/basic sets. The bundled index (`data/shape-index.json.gz`) is the
|
|
46
|
+
upstream draw.io shape data — see `data/SHAPE-INDEX-NOTICE.md` for attribution.
|
|
47
|
+
|
|
48
|
+
## AI / LLM brand logos
|
|
49
|
+
|
|
50
|
+
draw.io's bundled libraries have **no** modern AI/LLM brand logos, so an "LLM app
|
|
51
|
+
architecture" otherwise renders as generic boxes. `scripts/aiicons.py` resolves a
|
|
52
|
+
brand name (OpenAI, Claude, Gemini, Mistral, Llama, HuggingFace, Ollama,
|
|
53
|
+
LangChain, …321 brands) to a draw.io `image` style backed by the
|
|
54
|
+
[lobe-icons](https://github.com/lobehub/lobe-icons) set (MIT).
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
python3 <this-skill-dir>/scripts/aiicons.py "claude" --json # CDN reference
|
|
58
|
+
python3 <this-skill-dir>/scripts/aiicons.py "openai" --embed # self-contained
|
|
59
|
+
python3 <this-skill-dir>/scripts/aiicons.py --list # all brands
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
- Picks the `-color` variant when it exists, else the mono logo (e.g. OpenAI is
|
|
63
|
+
mono-only). Returns a square `image` style; use the reported `--size` (default
|
|
64
|
+
48) for both width and height.
|
|
65
|
+
- **Default references the icon by CDN URL** — the SVG lives on unpkg, not in
|
|
66
|
+
this repo, so **draw.io needs network access when the diagram is rendered or
|
|
67
|
+
opened**; an offline export draws a blank box. Pass `--embed` to fetch the SVG
|
|
68
|
+
once and inline it as a data URI (portable, renders offline, larger XML).
|
|
69
|
+
- Logos are trademarks of their respective owners, referenced for identification
|
|
70
|
+
only — the same basis on which draw.io ships AWS/Azure icons.
|
|
71
|
+
- **Data stores** common in RAG/LLM apps that lobe lacks (Qdrant, Redis,
|
|
72
|
+
Postgres, Mongo, Elasticsearch, Milvus, Supabase, Neo4j, ClickHouse, Kafka,
|
|
73
|
+
Snowflake, Databricks, …) resolve via the [simple-icons](https://simpleicons.org)
|
|
74
|
+
CDN (CC0) as an automatic fallback — same command, same output shape. A brand
|
|
75
|
+
in neither set has no logo; use a cylinder (`shape=cylinder3;`, see below) or
|
|
76
|
+
`scripts/shapesearch.py "<name> database"`.
|
|
77
|
+
|
|
78
|
+
## Cheatsheet — hand-writable styles
|
|
79
|
+
|
|
80
|
+
These are stable enough to write without searching. Combine with `whiteSpace=wrap;html=1;`.
|
|
81
|
+
|
|
82
|
+
### Common shapes (`shape=` keyword)
|
|
83
|
+
|
|
84
|
+
| Need | style |
|
|
85
|
+
|---|---|
|
|
86
|
+
| Rectangle / rounded box | `rounded=0;` / `rounded=1;` |
|
|
87
|
+
| Circle / ellipse | `ellipse;` (`aspect=fixed;` for a true circle) |
|
|
88
|
+
| Diamond (decision) | `rhombus;` |
|
|
89
|
+
| Cylinder (database) | `shape=cylinder3;` |
|
|
90
|
+
| Cloud | `cloud;` |
|
|
91
|
+
| Cube (3D) | `shape=cube;` |
|
|
92
|
+
| Sticky note | `shape=note;` |
|
|
93
|
+
| Document (curled bottom) | `shape=document;` |
|
|
94
|
+
| Folder | `shape=folder;` |
|
|
95
|
+
| Card (cut corner) | `shape=card;` |
|
|
96
|
+
| Process (double border) | `shape=process;` |
|
|
97
|
+
| Step / chevron | `shape=step;` |
|
|
98
|
+
| Parallelogram (I/O) | `shape=parallelogram;perimeter=parallelogramPerimeter;` |
|
|
99
|
+
| Trapezoid | `shape=trapezoid;perimeter=trapezoidPerimeter;` |
|
|
100
|
+
| Hexagon | `shape=hexagon;perimeter=hexagonPerimeter2;` |
|
|
101
|
+
| Manual input | `shape=manualInput;` |
|
|
102
|
+
| Data storage | `shape=dataStorage;` |
|
|
103
|
+
| Off-page connector | `shape=offPageConnector;` |
|
|
104
|
+
| Delay | `shape=delay;` |
|
|
105
|
+
| OR / XOR gate | `shape=or;` / `shape=xor;` |
|
|
106
|
+
| Block arrow | `shape=singleArrow;` / `shape=doubleArrow;` |
|
|
107
|
+
| Callout (speech bubble) | `shape=callout;` |
|
|
108
|
+
|
|
109
|
+
### UML primitives
|
|
110
|
+
|
|
111
|
+
| Element | style |
|
|
112
|
+
|---|---|
|
|
113
|
+
| Actor (stick figure) | `shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;` |
|
|
114
|
+
| Boundary | `shape=umlBoundary;` |
|
|
115
|
+
| Control | `shape=umlControl;` |
|
|
116
|
+
| Entity | `shape=umlEntity;` |
|
|
117
|
+
| Lifeline | `shape=umlLifeline;perimeter=lifelinePerimeter;container=1;` |
|
|
118
|
+
| Frame | `shape=umlFrame;` |
|
|
119
|
+
| Provided interface (lollipop) | `shape=lollipop;direction=south;` |
|
|
120
|
+
| Required interface | `shape=requires;direction=north;` |
|
|
121
|
+
| Component | `shape=component;` |
|
|
122
|
+
|
|
123
|
+
### Containers (parent-child; children use relative coords)
|
|
124
|
+
|
|
125
|
+
| Type | style | When |
|
|
126
|
+
|---|---|---|
|
|
127
|
+
| Invisible group | `group;pointerEvents=0;` | No border, no own connections |
|
|
128
|
+
| Titled swimlane | `swimlane;startSize=30;` | Visible title bar / has connections |
|
|
129
|
+
| Any shape as container | append `container=1;pointerEvents=0;` | Box without own connections |
|
|
130
|
+
|
|
131
|
+
### Edges
|
|
132
|
+
|
|
133
|
+
| Need | add to style |
|
|
134
|
+
|---|---|
|
|
135
|
+
| Orthogonal routing | `edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;` |
|
|
136
|
+
| Curved | `curved=1;` |
|
|
137
|
+
| No arrowhead | `endArrow=none;` |
|
|
138
|
+
| Open/thin arrow | `endArrow=open;` / `endArrow=classicThin;` |
|
|
139
|
+
| Dashed | `dashed=1;` (pattern via `dashPattern=8 8;`) |
|
|
140
|
+
| Flow animation | `flowAnimation=1;` |
|
|
141
|
+
| Label background | `labelBackgroundColor=#ffffff;` |
|
|
142
|
+
|
|
143
|
+
### Useful property knobs
|
|
144
|
+
|
|
145
|
+
- `fontStyle` is a bitmask: `1`=bold, `2`=italic, `4`=underline (add to combine: `3`=bold+italic).
|
|
146
|
+
- `direction=north|south|east|west` rotates a shape in 90° steps; `rotation=<deg>` for free rotation.
|
|
147
|
+
- `gradientColor=#RRGGBB;` + `gradientDirection=north;` for a gradient fill.
|
|
148
|
+
- `sketch=1;` gives a hand-drawn look (set globally via a style preset instead when possible).
|
|
149
|
+
|
|
150
|
+
For richer per-shape detail, the upstream source is jgraph/drawio-mcp's
|
|
151
|
+
`shared/style-reference.md` (Apache-2.0).
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Style Application Guide
|
|
2
|
+
|
|
3
|
+
How to apply a visual style to a draw.io diagram generation.
|
|
4
|
+
|
|
5
|
+
## Quick Reference: Style → Draw.io Tokens
|
|
6
|
+
|
|
7
|
+
When a style is selected, use these mappings to construct `mxCell` style strings:
|
|
8
|
+
|
|
9
|
+
### Step 1: Determine Role → Color
|
|
10
|
+
|
|
11
|
+
For each node, determine its semantic role, then look up the `(fillColor, strokeColor)` pair
|
|
12
|
+
from the selected style reference file:
|
|
13
|
+
|
|
14
|
+
| Role | Style Reference Key | Example Use |
|
|
15
|
+
|------|---------------------|-------------|
|
|
16
|
+
| Service / component | `primary` | API service, microservice, worker |
|
|
17
|
+
| Database / storage | `success` | PostgreSQL, Redis, S3, vector store |
|
|
18
|
+
| Queue / message bus | `warning` | Kafka, RabbitMQ, SQS |
|
|
19
|
+
| Gateway / API / LB | `accent` | API Gateway, Load Balancer, Proxy |
|
|
20
|
+
| Error / alert | `danger` | Error handler, monitoring alert |
|
|
21
|
+
| Security / auth | `secondary` | OAuth service, IAM, Vault |
|
|
22
|
+
| External system | `neutral` | Third-party API, external service |
|
|
23
|
+
|
|
24
|
+
### Step 2: Build Vertex Style String
|
|
25
|
+
|
|
26
|
+
Template:
|
|
27
|
+
```
|
|
28
|
+
{shape_keyword};whiteSpace=wrap;html=1;fillColor={fillColor};strokeColor={strokeColor};strokeWidth={strokeWidth};fontFamily={fontFamily};fontSize={fontSize};fontColor={fontColor};{extras}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Where each variable comes from the style reference:
|
|
32
|
+
|
|
33
|
+
| Variable | Style Reference Field |
|
|
34
|
+
|----------|----------------------|
|
|
35
|
+
| `shape_keyword` | "Shape Preferences" section (e.g., `rounded=1`) |
|
|
36
|
+
| `fillColor` | Role's fillColor from palette table |
|
|
37
|
+
| `strokeColor` | Role's strokeColor from palette table |
|
|
38
|
+
| `strokeWidth` | Extras section (default: 1.5) |
|
|
39
|
+
| `fontFamily` | Typography section |
|
|
40
|
+
| `fontSize` | Typography section (labels size) |
|
|
41
|
+
| `fontColor` | Typography section (primary text) |
|
|
42
|
+
| `extras` | Extras section (e.g., `glass=1;shadow=1;`) |
|
|
43
|
+
|
|
44
|
+
### Step 3: Build Edge Style String
|
|
45
|
+
|
|
46
|
+
Template:
|
|
47
|
+
```
|
|
48
|
+
edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;strokeColor={flowColor};strokeWidth={edgeWidth};{dashPattern};exitX={exitX};exitY={exitY};entryX={entryX};entryY={entryY};
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
| Variable | Source |
|
|
52
|
+
|----------|--------|
|
|
53
|
+
| `flowColor` | Edge Style section, pick by flow type |
|
|
54
|
+
| `edgeWidth` | Edge Style section or infer from strokeWidth |
|
|
55
|
+
| `dashPattern` | `dashed=1` if flow type says dashed |
|
|
56
|
+
| `exitX/Y`, `entryX/Y` | Routing rules (see SKILL.md) |
|
|
57
|
+
|
|
58
|
+
### Step 4: Set Page Background
|
|
59
|
+
|
|
60
|
+
For dark styles (2, 3, 5, 8), set the background on the mxGraphModel:
|
|
61
|
+
|
|
62
|
+
```xml
|
|
63
|
+
<mxGraphModel background="#0f0f1a">
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
For light styles (1, 4, 6, 7), use default or white:
|
|
67
|
+
```xml
|
|
68
|
+
<mxGraphModel background="#ffffff">
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Style-Specific Notes
|
|
72
|
+
|
|
73
|
+
### Style 1 (Flat Icon)
|
|
74
|
+
- Use `rounded=1` for all boxes
|
|
75
|
+
- Colorful palette — different fill for each role
|
|
76
|
+
- Default edge color: `#2563eb` (blue)
|
|
77
|
+
- Arrow semantics use different colors per flow type
|
|
78
|
+
|
|
79
|
+
### Style 2 (Dark Terminal)
|
|
80
|
+
- Always set `background="#0f0f1a"`
|
|
81
|
+
- Use monospace font for all text
|
|
82
|
+
- Add `shadow=1` on primary (AI/ML) nodes
|
|
83
|
+
- Edge colors match source node's theme
|
|
84
|
+
|
|
85
|
+
### Style 3 (Blueprint)
|
|
86
|
+
- Always set `background="#0a1628"`
|
|
87
|
+
- Use `rounded=0` (sharp corners)
|
|
88
|
+
- Monospace font, cyan-based text colors
|
|
89
|
+
- External nodes use `fillColor=none;dashed=1`
|
|
90
|
+
|
|
91
|
+
### Style 4 (Notion Clean)
|
|
92
|
+
- All standard nodes share `fillColor=#f9fafb;strokeColor=#e5e7eb`
|
|
93
|
+
- Only error nodes get pink tint
|
|
94
|
+
- Single arrow color: `#3b82f6`
|
|
95
|
+
- Uppercase type labels at 11px
|
|
96
|
+
|
|
97
|
+
### Style 5 (Glassmorphism)
|
|
98
|
+
- Always set `background="#0d1117"`
|
|
99
|
+
- Add `glass=1;shadow=1` to all vertex styles
|
|
100
|
+
- Edge colors match the source node's glow color bucket
|
|
101
|
+
- Semi-transparent look in draw.io
|
|
102
|
+
|
|
103
|
+
### Style 6 (Claude Official)
|
|
104
|
+
- All nodes share `strokeColor=#4a4a4a;strokeWidth=2.5`
|
|
105
|
+
- Warm teal/beige/blue/gray fill colors per role
|
|
106
|
+
- Consistent `#5a5a5a` for all arrows
|
|
107
|
+
- Bold 16px labels with `fontStyle=1`
|
|
108
|
+
|
|
109
|
+
### Style 7 (OpenAI Official)
|
|
110
|
+
- Almost all nodes: `fillColor=#ffffff;strokeColor=#e5e5e5`
|
|
111
|
+
- Thin borders: `strokeWidth=1.5`
|
|
112
|
+
- Color only in edges: `#10a37f` (green), `#71717a` (gray)
|
|
113
|
+
- No shadows, no decorations
|
|
114
|
+
|
|
115
|
+
### Style 8 (Dark Luxury)
|
|
116
|
+
- Always set `background="#0a0a0a"`
|
|
117
|
+
- All nodes: `fillColor=#111111` with colored stroke per bucket
|
|
118
|
+
- Dual font: serif for titles, sans-serif for nodes
|
|
119
|
+
- Gold edges (`#d4a574`) for primary flows
|
|
120
|
+
- 6 semantic buckets with distinct stroke colors
|