@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
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# Style-to-Diagram-Type Adaptation Guide
|
|
2
|
+
|
|
3
|
+
How each visual style performs for each diagram type in draw.io.
|
|
4
|
+
|
|
5
|
+
## Architecture Diagram
|
|
6
|
+
|
|
7
|
+
| Style | Suitability | Notes |
|
|
8
|
+
|-------|-------------|-------|
|
|
9
|
+
| 1 Flat Icon | ★★★★★ | Default choice. Colorful node fills, clear layering with swimlanes |
|
|
10
|
+
| 2 Dark Terminal | ★★★★★ | Popular for dev blogs. Colored borders on dark background |
|
|
11
|
+
| 3 Blueprint | ★★★★★ | Perfect for formal architecture docs. Cyan-on-navy with grid feel |
|
|
12
|
+
| 4 Notion Clean | ★★★★ | Minimal, works for inline docs. Minimal color variation |
|
|
13
|
+
| 5 Glassmorphism | ★★★★ | Striking for presentations. `glass=1` + `shadow=1` |
|
|
14
|
+
| 6 Claude Official | ★★★★ | Warm aesthetic. Thick 2.5px borders, teal/beige palette |
|
|
15
|
+
| 7 OpenAI Official | ★★★★ | Clean, precise. White-on-white with minimal gray borders |
|
|
16
|
+
| 8 Dark Luxury | ★★★★★ | Premium editorial. Gold-on-black layers, 6 semantic color buckets |
|
|
17
|
+
|
|
18
|
+
## Class Diagram / ER Diagram
|
|
19
|
+
|
|
20
|
+
| Style | Suitability | Notes |
|
|
21
|
+
|-------|-------------|-------|
|
|
22
|
+
| 1 Flat Icon | ★★★★ | Colored headers per entity/class category |
|
|
23
|
+
| 2 Dark Terminal | ★★★★ | High contrast for code-like diagrams. Use lighter text |
|
|
24
|
+
| 3 Blueprint | ★★★★★ | Best for formal UML documentation. Monospace font, cyan strokes |
|
|
25
|
+
| 4 Notion Clean | ★★★★★ | Clean, minimal. Ideal for Notion/confluence embedded ERDs |
|
|
26
|
+
| 5 Glassmorphism | ★★ | Glass effects distract from structural content. Use with caution |
|
|
27
|
+
| 6 Claude Official | ★★★★★ | Warm, readable. Thick borders on class boxes |
|
|
28
|
+
| 7 OpenAI Official | ★★★★★ | Minimal aesthetic matches UML precision |
|
|
29
|
+
| 8 Dark Luxury | ★★★ | Non-standard dark background for UML. Use only for premium editorial |
|
|
30
|
+
|
|
31
|
+
## Sequence Diagram
|
|
32
|
+
|
|
33
|
+
| Style | Suitability | Notes |
|
|
34
|
+
|-------|-------------|-------|
|
|
35
|
+
| 1 Flat Icon | ★★★★ | Clear lifelines. Activation boxes visible |
|
|
36
|
+
| 2 Dark Terminal | ★★★★ | Good for dev articles. Dashed lifelines visible on dark bg |
|
|
37
|
+
| 3 Blueprint | ★★★★★ | Formal, technical documentation. Use cyan lifelines |
|
|
38
|
+
| 4 Notion Clean | ★★★★★ | Best for Notion-embedded sequence diagrams |
|
|
39
|
+
| 5 Glassmorphism | ★★ | Glass effects make lifelines hard to read |
|
|
40
|
+
| 6 Claude Official | ★★★★ | Warm contrast. Thick message arrows |
|
|
41
|
+
| 7 OpenAI Official | ★★★★★ | Minimal, precise. Ideal for API docs |
|
|
42
|
+
| 8 Dark Luxury | ★★★★ | Gold primary arrows. Dramatic contrast for dev blogs |
|
|
43
|
+
|
|
44
|
+
## Flowchart / Process Flow
|
|
45
|
+
|
|
46
|
+
| Style | Suitability | Notes |
|
|
47
|
+
|-------|-------------|-------|
|
|
48
|
+
| 1 Flat Icon | ★★★★★ | Default. Colorful decision diamonds (yellow), process boxes (blue) |
|
|
49
|
+
| 2 Dark Terminal | ★★★★ | Works well for dev workflow diagrams |
|
|
50
|
+
| 3 Blueprint | ★★★★ | Formal process documentation. Sharp corners |
|
|
51
|
+
| 4 Notion Clean | ★★★★ | Clean for SOPs and inline docs |
|
|
52
|
+
| 5 Glassmorphism | ★★★★ | Striking for product demos |
|
|
53
|
+
| 6 Claude Official | ★★★★ | Warm aesthetic for presentations |
|
|
54
|
+
| 7 OpenAI Official | ★★★★ | Clean and minimal |
|
|
55
|
+
| 8 Dark Luxury | ★★★★ | Gold decision diamonds. Premium process docs |
|
|
56
|
+
|
|
57
|
+
## Mind Map / Concept Map
|
|
58
|
+
|
|
59
|
+
| Style | Suitability | Notes |
|
|
60
|
+
|-------|-------------|-------|
|
|
61
|
+
| 1 Flat Icon | ★★★★★ | Colorful branches, engaging |
|
|
62
|
+
| 2 Dark Terminal | ★★★★ | Neon-like branches on dark bg |
|
|
63
|
+
| 3 Blueprint | ★★ | Blueprint grid conflicts with radial layout |
|
|
64
|
+
| 4 Notion Clean | ★★★★★ | Ideal for brainstorming |
|
|
65
|
+
| 5 Glassmorphism | ★★★★★ | Stunning visual for presentations |
|
|
66
|
+
| 6 Claude Official | ★★★★ | Warm, readable |
|
|
67
|
+
| 7 OpenAI Official | ★★★★ | Clean and minimal |
|
|
68
|
+
| 8 Dark Luxury | ★★★★★ | Gold accent branches on black. Standout in presentations |
|
|
69
|
+
|
|
70
|
+
## Data Flow Diagram
|
|
71
|
+
|
|
72
|
+
| Style | Suitability | Notes |
|
|
73
|
+
|-------|-------------|-------|
|
|
74
|
+
| 1 Flat Icon | ★★★★★ | Color-coded arrows by data type |
|
|
75
|
+
| 2 Dark Terminal | ★★★★★ | Glowing data paths on dark bg |
|
|
76
|
+
| 3 Blueprint | ★★★★★ | Formal data flow documentation |
|
|
77
|
+
| 4 Notion Clean | ★★★★ | Minimal, clean. Use blue arrows only |
|
|
78
|
+
| 5 Glassmorphism | ★★ | Distracts from flow semantics |
|
|
79
|
+
| 6 Claude Official | ★★★★ | Readable. Consistent dark gray arrows |
|
|
80
|
+
| 7 OpenAI Official | ★★★★ | Precise, minimal |
|
|
81
|
+
| 8 Dark Luxury | ★★★★★ | Color-coded data paths (gold, mint, amber). Data engineering |
|
|
82
|
+
|
|
83
|
+
## Agent / Memory Architecture
|
|
84
|
+
|
|
85
|
+
| Style | Suitability | Notes |
|
|
86
|
+
|-------|-------------|-------|
|
|
87
|
+
| 1 Flat Icon | ★★★★★ | Colorful layers, engaging |
|
|
88
|
+
| 2 Dark Terminal | ★★★★★ | Popular for AI/ML blog posts. Purple AI glow |
|
|
89
|
+
| 3 Blueprint | ★★★★ | Formal AI system documentation |
|
|
90
|
+
| 4 Notion Clean | ★★★★ | Clean for AI research notes |
|
|
91
|
+
| 5 Glassmorphism | ★★★★★ | Stunning for AI product presentations |
|
|
92
|
+
| 6 Claude Official | ★★★★★ | Anthropic AI aesthetic. Teal-green agent boxes |
|
|
93
|
+
| 7 OpenAI Official | ★★★★★ | OpenAI aesthetic. Brand green accents |
|
|
94
|
+
| 8 Dark Luxury | ★★★★★ | Best for premium AI system docs. Gold on deep black |
|
|
95
|
+
|
|
96
|
+
## Network Topology
|
|
97
|
+
|
|
98
|
+
| Style | Suitability | Notes |
|
|
99
|
+
|-------|-------------|-------|
|
|
100
|
+
| 1 Flat Icon | ★★★★★ | Colorful device shapes |
|
|
101
|
+
| 2 Dark Terminal | ★★★★★ | Cyberpunk-style network maps |
|
|
102
|
+
| 3 Blueprint | ★★★★★ | Ideal for infrastructure docs |
|
|
103
|
+
| 4 Notion Clean | ★★★★ | Clean for IT documentation |
|
|
104
|
+
| 5 Glassmorphism | ★★★★ | Striking for presentations |
|
|
105
|
+
| 6 Claude Official | ★★★★ | Professional network diagrams |
|
|
106
|
+
| 7 OpenAI Official | ★★★★ | Clean infrastructure diagrams |
|
|
107
|
+
| 8 Dark Luxury | ★★★★★ | Deep black classic. Gold topology lines |
|
|
108
|
+
|
|
109
|
+
## Use Case Diagram
|
|
110
|
+
|
|
111
|
+
| Style | Suitability | Notes |
|
|
112
|
+
|-------|-------------|-------|
|
|
113
|
+
| 1 Flat Icon | ★★★★ | Colorful use case ellipses |
|
|
114
|
+
| 2 Dark Terminal | ★★ | Stick figures less visible on dark bg |
|
|
115
|
+
| 3 Blueprint | ★★★★★ | Classic UML aesthetic |
|
|
116
|
+
| 4 Notion Clean | ★★★★★ | Perfect for product requirement docs |
|
|
117
|
+
| 5 Glassmorphism | ★★ | Unnecessary visual noise |
|
|
118
|
+
| 6 Claude Official | ★★★★★ | Warm, professional |
|
|
119
|
+
| 7 OpenAI Official | ★★★★★ | Clean, precise UML |
|
|
120
|
+
| 8 Dark Luxury | ★★★ | Stick figures less visible on deep black |
|
|
121
|
+
|
|
122
|
+
## State Machine Diagram
|
|
123
|
+
|
|
124
|
+
| Style | Suitability | Notes |
|
|
125
|
+
|-------|-------------|-------|
|
|
126
|
+
| 1 Flat Icon | ★★★★ | Colorful states |
|
|
127
|
+
| 2 Dark Terminal | ★★★★ | Glowing states and transitions |
|
|
128
|
+
| 3 Blueprint | ★★★★★ | Best for formal UML state machines |
|
|
129
|
+
| 4 Notion Clean | ★★★★★ | Clean for documentation |
|
|
130
|
+
| 5 Glassmorphism | ★★ | Distracts from state transitions |
|
|
131
|
+
| 6 Claude Official | ★★★★ | Readable |
|
|
132
|
+
| 7 OpenAI Official | ★★★★★ | Minimal, precise |
|
|
133
|
+
| 8 Dark Luxury | ★★★★ | High contrast for state transitions |
|
|
134
|
+
|
|
135
|
+
## Comparison / Feature Matrix
|
|
136
|
+
|
|
137
|
+
| Style | Suitability | Notes |
|
|
138
|
+
|-------|-------------|-------|
|
|
139
|
+
| 1 Flat Icon | ★★★★★ | Color-coded cells |
|
|
140
|
+
| 2 Dark Terminal | ★★★★ | Works for dev tool comparisons |
|
|
141
|
+
| 3 Blueprint | ★★ | Grid conflicts with table layout |
|
|
142
|
+
| 4 Notion Clean | ★★★★★ | Perfect for Notion-embedded tables |
|
|
143
|
+
| 5 Glassmorphism | ★★ | Distracts from tabular data |
|
|
144
|
+
| 6 Claude Official | ★★★★★ | Clean, warm |
|
|
145
|
+
| 7 OpenAI Official | ★★★★★ | Minimal, precise |
|
|
146
|
+
| 8 Dark Luxury | ★★★ | Dark bg non-standard for tables |
|
|
147
|
+
|
|
148
|
+
## Timeline / Gantt
|
|
149
|
+
|
|
150
|
+
| Style | Suitability | Notes |
|
|
151
|
+
|-------|-------------|-------|
|
|
152
|
+
| 1 Flat Icon | ★★★★★ | Colorful bars by category |
|
|
153
|
+
| 2 Dark Terminal | ★★★★ | Works for dev roadmaps |
|
|
154
|
+
| 3 Blueprint | ★★★★ | Formal project plans |
|
|
155
|
+
| 4 Notion Clean | ★★★★★ | Ideal for Notion project docs |
|
|
156
|
+
| 5 Glassmorphism | ★★★★ | Striking for keynote presentations |
|
|
157
|
+
| 6 Claude Official | ★★★★ | Warm, professional |
|
|
158
|
+
| 7 OpenAI Official | ★★★★ | Clean timeline |
|
|
159
|
+
| 8 Dark Luxury | ★★★★ | Premium project roadmaps |
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
# Style Extraction — agent reference
|
|
2
|
+
|
|
3
|
+
Loaded on demand by `SKILL.md` when the user asks to learn a style ("learn my style from `<path>` as `<name>`") or when the agent needs to render a sample after extraction.
|
|
4
|
+
|
|
5
|
+
## Sample diagram (for approval render)
|
|
6
|
+
|
|
7
|
+
After extracting a candidate preset, render this seven-node sample using the candidate's palette/shapes/fonts/edges. Each role appears exactly once; six edges, one dashed, exercise `edges.arrow`, `edges.style`, and `edges.dashedFor`.
|
|
8
|
+
|
|
9
|
+
**Layout (TB):**
|
|
10
|
+
- Row 1 (y=40): `gateway` centered at x=340
|
|
11
|
+
- Row 2 (y=180): `security` (x=80), `service` (x=340), `queue` (x=600)
|
|
12
|
+
- Row 3 (y=340): `database` (x=80), `external` (x=340), `error` (x=600)
|
|
13
|
+
|
|
14
|
+
**Template — substitute `{{...}}` placeholders from the candidate preset.**
|
|
15
|
+
|
|
16
|
+
The vertex style for role `R` is built as:
|
|
17
|
+
`<shapes[R]>;whiteSpace=wrap;html=1;fillColor=<palette[roles[R]].fillColor>;strokeColor=<palette[roles[R]].strokeColor>;fontFamily=<font.fontFamily>;fontSize=<font.fontSize>`
|
|
18
|
+
- If `extras.sketch=true`, append `;sketch=1` to every vertex style AND every edge style.
|
|
19
|
+
- If `extras.globalStrokeWidth !== 1` (i.e., any value other than the drawio default of 1, including `0.5`), append `;strokeWidth=<n>` to every vertex style AND every edge style.
|
|
20
|
+
|
|
21
|
+
The edge style is built as:
|
|
22
|
+
`<edges.style>;<edges.arrow>`
|
|
23
|
+
- Per-edge routing keys (`exitX/entryX/...`) are added as literals below.
|
|
24
|
+
- Edge 15 exercises `edges.dashedFor`:
|
|
25
|
+
- If `edges.dashedFor` is **non-empty**, use its first entry as the edge's `value` (label) AND append `;dashed=1` to the edge style.
|
|
26
|
+
- If `edges.dashedFor` is empty (`[]`), use the label `cross-call` and do NOT append `;dashed=1` — the preset has no dashed convention, so the sample must not fake one.
|
|
27
|
+
|
|
28
|
+
**Placeholder expansion (applied when filling the XML):**
|
|
29
|
+
- `{{VSTYLE:<role>}}` expands to the vertex-style formula above with `R = <role>`. Write the result as a literal string; do not URL-encode.
|
|
30
|
+
- `{{ESTYLE}}` expands to the edge-style formula above.
|
|
31
|
+
- `{{EDGE15_LABEL}}` and `{{EDGE15_DASH}}` follow the Edge-15 rule above.
|
|
32
|
+
|
|
33
|
+
```xml
|
|
34
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
35
|
+
<mxfile host="drawio" version="26.0.0">
|
|
36
|
+
<diagram name="Preset Sample">
|
|
37
|
+
<mxGraphModel>
|
|
38
|
+
<root>
|
|
39
|
+
<mxCell id="0" />
|
|
40
|
+
<mxCell id="1" parent="0" />
|
|
41
|
+
|
|
42
|
+
<!-- Row 1: gateway -->
|
|
43
|
+
<mxCell id="2" value="Gateway" style="{{VSTYLE:gateway}}" vertex="1" parent="1">
|
|
44
|
+
<mxGeometry x="340" y="40" width="160" height="60" as="geometry" />
|
|
45
|
+
</mxCell>
|
|
46
|
+
|
|
47
|
+
<!-- Row 2: security | service | queue -->
|
|
48
|
+
<mxCell id="3" value="Auth" style="{{VSTYLE:security}}" vertex="1" parent="1">
|
|
49
|
+
<mxGeometry x="80" y="180" width="160" height="60" as="geometry" />
|
|
50
|
+
</mxCell>
|
|
51
|
+
<mxCell id="4" value="Service" style="{{VSTYLE:service}}" vertex="1" parent="1">
|
|
52
|
+
<mxGeometry x="340" y="180" width="160" height="60" as="geometry" />
|
|
53
|
+
</mxCell>
|
|
54
|
+
<mxCell id="5" value="Queue" style="{{VSTYLE:queue}}" vertex="1" parent="1">
|
|
55
|
+
<mxGeometry x="600" y="180" width="160" height="60" as="geometry" />
|
|
56
|
+
</mxCell>
|
|
57
|
+
|
|
58
|
+
<!-- Row 3: database | external | error -->
|
|
59
|
+
<mxCell id="6" value="Database" style="{{VSTYLE:database}}" vertex="1" parent="1">
|
|
60
|
+
<mxGeometry x="80" y="340" width="160" height="70" as="geometry" />
|
|
61
|
+
</mxCell>
|
|
62
|
+
<mxCell id="7" value="External API" style="{{VSTYLE:external}}" vertex="1" parent="1">
|
|
63
|
+
<mxGeometry x="340" y="340" width="160" height="60" as="geometry" />
|
|
64
|
+
</mxCell>
|
|
65
|
+
<mxCell id="8" value="Error Sink" style="{{VSTYLE:error}}" vertex="1" parent="1">
|
|
66
|
+
<mxGeometry x="600" y="340" width="160" height="60" as="geometry" />
|
|
67
|
+
</mxCell>
|
|
68
|
+
|
|
69
|
+
<!-- Edges -->
|
|
70
|
+
<mxCell id="10" value="" style="{{ESTYLE}};exitX=0.25;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0" edge="1" parent="1" source="2" target="3">
|
|
71
|
+
<mxGeometry relative="1" as="geometry" />
|
|
72
|
+
</mxCell>
|
|
73
|
+
<mxCell id="11" value="" style="{{ESTYLE}};exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0" edge="1" parent="1" source="2" target="4">
|
|
74
|
+
<mxGeometry relative="1" as="geometry" />
|
|
75
|
+
</mxCell>
|
|
76
|
+
<mxCell id="12" value="" style="{{ESTYLE}};exitX=0.75;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0" edge="1" parent="1" source="2" target="5">
|
|
77
|
+
<mxGeometry relative="1" as="geometry" />
|
|
78
|
+
</mxCell>
|
|
79
|
+
<mxCell id="13" value="" style="{{ESTYLE}};exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0" edge="1" parent="1" source="4" target="7">
|
|
80
|
+
<mxGeometry relative="1" as="geometry" />
|
|
81
|
+
</mxCell>
|
|
82
|
+
<mxCell id="14" value="" style="{{ESTYLE}};exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0" edge="1" parent="1" source="4" target="6">
|
|
83
|
+
<mxGeometry relative="1" as="geometry" />
|
|
84
|
+
</mxCell>
|
|
85
|
+
<mxCell id="15" value="{{EDGE15_LABEL}}" style="{{ESTYLE}}{{EDGE15_DASH}};exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0" edge="1" parent="1" source="4" target="8">
|
|
86
|
+
<mxGeometry relative="1" as="geometry" />
|
|
87
|
+
</mxCell>
|
|
88
|
+
|
|
89
|
+
</root>
|
|
90
|
+
</mxGraphModel>
|
|
91
|
+
</diagram>
|
|
92
|
+
</mxfile>
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Rendering the sample
|
|
96
|
+
|
|
97
|
+
1. Write the filled XML to `/tmp/drawio-preset-<name>.drawio`.
|
|
98
|
+
2. Run the same `drawio -x -f png -e -s 2 -o <preset-name>-sample.png <tmp>.drawio` command the main workflow uses (substitute the binary name you resolved in SKILL.md Step 1 if it isn't `drawio`).
|
|
99
|
+
3. Repair the IEND chunk: `python3 <this-skill-dir>/scripts/repair_png.py <preset-name>-sample.png` — the `-e` flag truncates the PNG the same way the main workflow's step 7 does, so the sample needs the same fix to be readable.
|
|
100
|
+
4. Save the PNG as `./preset-<name>-sample.png` (the user's working directory).
|
|
101
|
+
5. Show the user: preset summary table + PNG path + provenance/confidence line.
|
|
102
|
+
|
|
103
|
+
### Approval loop
|
|
104
|
+
|
|
105
|
+
- "save" / "looks good" → write candidate to `~/.drawio-skill/styles/<name>.json`; delete tempfile and sample PNG.
|
|
106
|
+
- "change <field> to <value>" → edit the in-memory candidate; re-render; re-ask.
|
|
107
|
+
- "cancel" → delete tempfile and sample PNG; no save.
|
|
108
|
+
|
|
109
|
+
### If sample render fails (draw.io CLI missing / export error)
|
|
110
|
+
|
|
111
|
+
Still show the summary table and the provenance line. Note: *"Could not render sample PNG (CLI unavailable). Save anyway on your OK."* Do not block.
|
|
112
|
+
|
|
113
|
+
## XML extraction path
|
|
114
|
+
|
|
115
|
+
Input: a `.drawio` file path. Output: candidate preset JSON. Deterministic, no LLM inference.
|
|
116
|
+
|
|
117
|
+
### Steps
|
|
118
|
+
|
|
119
|
+
1. **Parse the file.** Read the XML, collect every `<mxCell>` with a `style=` attribute, split into vertices (`vertex="1"`) and edges (`edge="1"`).
|
|
120
|
+
2. **Tokenize each `style=` string** on `;`. Each element is either `key=value` or a bare keyword (e.g., `rhombus`, `ellipse`, `rounded=1`).
|
|
121
|
+
3. **Extract palette.** For every vertex, take the `(fillColor, strokeColor)` pair (skip vertices with neither). Count frequency. Keep the top ≤7 pairs.
|
|
122
|
+
4. **Extract shape vocabulary + role mapping.** For each vertex determine a shape class by precedence:
|
|
123
|
+
`cylinder3 > ellipse > rhombus > swimlane > rounded=1 > rounded=0`.
|
|
124
|
+
Then infer the semantic role from the vertex's shape class and its `value` (label) attribute. **Evaluate the rules below in order; first match wins.**
|
|
125
|
+
- `cylinder3` → `database`
|
|
126
|
+
- `rhombus` → `decision`
|
|
127
|
+
- `swimlane` → `container`
|
|
128
|
+
- `dashed=1` present + **grey-family fill** (hex where the R, G, and B channels all fall within ±16 of each other, i.e., near-achromatic) → `external`
|
|
129
|
+
- label matches `/queue|bus|kafka|rabbit/i` → `queue`
|
|
130
|
+
- label matches `/gateway|api|lb|load/i` → `gateway`
|
|
131
|
+
- label matches `/auth|login|jwt|oauth/i` → `security`
|
|
132
|
+
- label matches `/error|fail|alert/i` → `error`
|
|
133
|
+
- everything else → `service`
|
|
134
|
+
|
|
135
|
+
For each **role that has a canonical palette slot** — `service`, `database`, `queue`, `gateway`, `error`, `external`, `security` — the most frequent `(role, color-pair)` mapping wins. The pair goes into the role's canonical palette slot:
|
|
136
|
+
`service→primary, database→success, queue→warning, gateway→accent, error→danger, external→neutral, security→secondary`.
|
|
137
|
+
Set `roles[role]` to that slot name.
|
|
138
|
+
|
|
139
|
+
**Decision and container shapes do not get a `roles[...]` entry** — they are recorded only in `shapes.decision` and `shapes.container`. Any color pairs observed on decision/container vertices still participate in the palette (they can fill leftover slots) but are not tied to a semantic role.
|
|
140
|
+
|
|
141
|
+
Leftover color pairs (not claimed by any role-slot mapping) fill remaining empty palette slots in descending-frequency order.
|
|
142
|
+
|
|
143
|
+
Record the shape class string used per role in `shapes[role]`. The six named shape keys are `service`, `database`, `queue`, `decision`, `external`, `container` — `gateway`, `error`, and `security` roles inherit `shapes.service` and do not get their own `shapes[...]` entry. Example: `shapes.database = "shape=cylinder3"`.
|
|
144
|
+
|
|
145
|
+
5. **Extract fonts.** Compute modal `fontFamily` and `fontSize` across vertices; emit them as `font.fontFamily` and `font.fontSize`. Also track `fontStyle` per vertex as a **working variable** (not an output field — the schema has no top-level `font.fontStyle`). If a distinguishable subset of vertices uses a larger `fontSize` combined with `fontStyle=1` (bold), treat that subset as titles: set `font.titleFontSize` to their modal size and `font.titleBold: true`. Otherwise omit both title fields.
|
|
146
|
+
|
|
147
|
+
6. **Extract edge defaults.** Take the modal edge style string, but strip these per-edge coordinate keys before counting: `entryX`, `entryY`, `exitX`, `exitY`, `entryDx`, `entryDy`, `exitDx`, `exitDy`. Record arrow style from `endArrow`/`endFill` separately in `edges.arrow`.
|
|
148
|
+
If any edges have `dashed=1`, collect their `value` (label) attributes. If ≥2 share a common token (e.g., all are labeled "async" or "optional"), add that token to `edges.dashedFor`.
|
|
149
|
+
|
|
150
|
+
7. **Extract extras.** `sketch=1` seen on any vertex or edge → `extras.sketch = true`. Modal `strokeWidth` across vertices → `extras.globalStrokeWidth` (default `1`).
|
|
151
|
+
|
|
152
|
+
8. **Set provenance.**
|
|
153
|
+
```json
|
|
154
|
+
{
|
|
155
|
+
"source": { "type": "xml", "path": "<input absolute path>", "extracted_at": "YYYY-MM-DD" },
|
|
156
|
+
"confidence": "high"
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### XML edge cases
|
|
161
|
+
|
|
162
|
+
| Situation | Behavior |
|
|
163
|
+
|---|---|
|
|
164
|
+
| Source has <3 distinct color pairs | Leave unfilled slots as `null`. Downgrade `confidence` to `"medium"`. Summary warns the user. |
|
|
165
|
+
| Source has >7 color pairs | Keep the top 7 by frequency. Summary warns that some colors were dropped. |
|
|
166
|
+
| Non-standard `shape=` keywords (e.g., `shape=mxgraph.aws4.*`) | These do not match the Step 4 precedence ladder, so the vertex falls through to `rounded=0` for shape-class purposes. Iconography is lost; color, label, and edge style are still captured. Role inference still runs via the label-regex rules. Summary notes: *"Non-standard shape library detected — iconography not preserved in preset (color and label captured)."* |
|
|
167
|
+
| Non-English labels | The English-keyword regexes in step 4 will mostly miss; most vertices collapse to `service`. Palette/shapes/font/edges still captured correctly (they don't depend on label text). `confidence` stays `"high"`. Summary notes: *"Role labels not in English — `service`/`database`/`decision`/`container`/`external` inferred from shape class; other roles not mapped."* |
|
|
168
|
+
| File has no `<mxCell vertex="1">` at all | Stop. Refuse to save. Message: *"Nothing to learn from — source file has no shapes."* |
|
|
169
|
+
|
|
170
|
+
## Image extraction path
|
|
171
|
+
|
|
172
|
+
Input: path to a PNG/JPG (or any vision-readable image format). Output: candidate preset JSON. Inference-based; `confidence: "medium"` at best.
|
|
173
|
+
|
|
174
|
+
**Prerequisite:** the agent's vision capability must be available (same mechanism the main workflow's self-check uses). If vision is not available, stop and tell the user:
|
|
175
|
+
*"Image-based learning needs a vision-enabled model (Claude Sonnet or Opus). Re-run on such a model, or provide the `.drawio` source file instead."*
|
|
176
|
+
|
|
177
|
+
### Steps
|
|
178
|
+
|
|
179
|
+
1. **Read the image.** Use the agent's vision input — the same path the main workflow's step 5 uses to read exported PNGs during self-check.
|
|
180
|
+
|
|
181
|
+
2. **Extract palette by visual inspection.** Identify distinct fill-color regions on shape bodies.
|
|
182
|
+
|
|
183
|
+
For each distinct fill:
|
|
184
|
+
- `fillColor` — quantize each RGB channel to the nearest multiple of 16. If the resulting HSL lightness is below 0.75, raise it to 0.85 (keep hue and saturation; set L=0.85; HSL→RGB round-trip). Emit as `#RRGGBB`. Drawio-standard pastels occupy L≈0.85–0.96; below 0.75 reads as "too dark for a fill color" and this step lifts it back into that range.
|
|
185
|
+
- `strokeColor` — read the matching border. If unreadable, derive from fill by darkening ~25% (match HSL, drop L by 0.25).
|
|
186
|
+
|
|
187
|
+
Map each `(fillColor, strokeColor)` pair to a named slot using this decision order:
|
|
188
|
+
|
|
189
|
+
1. **Grey check first.** If the fill has R, G, and B channels all within ±16 of each other (same definition as the XML path's grey-family rule), OR HSL saturation < 0.20, classify as `neutral`. This check wins regardless of hue angle.
|
|
190
|
+
2. **Hue band otherwise.** Use these explicit HSL hue ranges:
|
|
191
|
+
- 180°–260° → `primary` (blue)
|
|
192
|
+
- 80°–170° → `success` (green)
|
|
193
|
+
- 45°–65° → `warning` (yellow)
|
|
194
|
+
- 20°–44° → `accent` (orange)
|
|
195
|
+
- 0°–19° or 320°–360° → `danger` (red/pink)
|
|
196
|
+
- 260°–320° → `secondary` (purple)
|
|
197
|
+
3. **No band matched** (gap regions at 65°–80° or 170°–180°) → spill to the nearest band by angular distance.
|
|
198
|
+
|
|
199
|
+
**Collision rule.** If ≥2 distinct fills land in the same slot, sort them by total pixel area covered in the image (descending). The largest keeps the canonical slot. Remaining fills spill to the **nearest empty slot** measured by hue-band angular distance — first to adjacent bands on either side, then farther out. If every slot is already filled, drop the extras and warn in the summary.
|
|
200
|
+
|
|
201
|
+
3. **Extract shape vocabulary.** Classify every visible shape by silhouette:
|
|
202
|
+
- rounded rectangle → `rounded=1`
|
|
203
|
+
- sharp rectangle → `rounded=0`
|
|
204
|
+
- circle / oval → `ellipse`
|
|
205
|
+
- diamond → `rhombus`
|
|
206
|
+
- cylinder (rectangle with curved top/bottom) → `shape=cylinder3`
|
|
207
|
+
- titled container (header bar + nested children inside) → `swimlane;startSize=30`
|
|
208
|
+
- dashed-bordered rectangle → `rounded=1;dashed=1`
|
|
209
|
+
|
|
210
|
+
Role assignment uses the **same label-text + shape rules as the XML path step 4**. Visible labels are read via vision.
|
|
211
|
+
|
|
212
|
+
4. **Extract fonts.** Best-effort. Distinguishable categories:
|
|
213
|
+
- clearly serif → `fontFamily: "Georgia"`
|
|
214
|
+
- clearly monospaced → `fontFamily: "Courier New"`
|
|
215
|
+
- otherwise → `fontFamily: "Helvetica"`
|
|
216
|
+
|
|
217
|
+
Size by relative appearance:
|
|
218
|
+
- small → `fontSize: 11`
|
|
219
|
+
- medium → `fontSize: 12`
|
|
220
|
+
- large → `fontSize: 14`
|
|
221
|
+
|
|
222
|
+
If titles/container headers are distinctly larger or bolder → set `titleFontSize` accordingly and `titleBold: true`.
|
|
223
|
+
|
|
224
|
+
5. **Extract edge defaults.**
|
|
225
|
+
- Right-angle orthogonal arrows → `edges.style = "edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1"`.
|
|
226
|
+
- Curved arrows → append `;curved=1` to `edges.style`.
|
|
227
|
+
- Filled triangle arrowheads → `edges.arrow = "endArrow=classic;endFill=1"`.
|
|
228
|
+
- Open V-shaped arrowheads → `edges.arrow = "endArrow=open;endFill=0"`.
|
|
229
|
+
- Any dashed arrows near labels like "optional", "async", "fallback", "secondary" → add those label tokens to `edges.dashedFor`.
|
|
230
|
+
|
|
231
|
+
6. **Extract extras.**
|
|
232
|
+
- Visibly hand-drawn / rough / sketch look (wavy strokes, uneven fills) → `extras.sketch = true`.
|
|
233
|
+
- Heavy strokes (clearly >1.5× normal) → `extras.globalStrokeWidth = 2`.
|
|
234
|
+
- Otherwise default: `extras = { "sketch": false, "globalStrokeWidth": 1 }`.
|
|
235
|
+
|
|
236
|
+
7. **Set provenance and confidence.**
|
|
237
|
+
```json
|
|
238
|
+
{
|
|
239
|
+
"source": { "type": "image", "path": "<input absolute path>", "extracted_at": "YYYY-MM-DD" },
|
|
240
|
+
"confidence": "medium"
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
Adjustments:
|
|
244
|
+
- <3 distinct shapes identifiable → `confidence: "low"`.
|
|
245
|
+
- Image path stays at `"medium"` by default. The only path to `"high"` is a strictly-verifiable signal: the source image was exported from drawio itself (recognizable drawio default chrome, grid, or a visible drawio watermark), **and** all seven palette slots are filled, **and** all seven roles are labeled. This preserves the semantic gap between inference-based (image) and parse-based (XML) provenance.
|
|
246
|
+
|
|
247
|
+
### Image edge cases
|
|
248
|
+
|
|
249
|
+
| Situation | Behavior |
|
|
250
|
+
|---|---|
|
|
251
|
+
| Vision unavailable | Stop as described above — do not fall back to guessing. |
|
|
252
|
+
| Image has <3 identifiable shapes | Continue; mark `confidence: "low"`; summary explicitly warns the user that the preset is a loose approximation. |
|
|
253
|
+
| Image has no visible labels | Role assignment collapses to shape-class only: cylinders → `database`, diamonds → `decision`, swimlanes → `container`, dashed-bordered rectangles with grey fill → `external`, everything else → `service`. Palette/font/edges still captured. Summary notes: *"No labels readable — semantic roles beyond shape-class not inferred."* |
|
|
254
|
+
| Two palette slots would land in the same hue family | Keep the more frequent one in its canonical slot; spill the other to the adjacent empty slot (rule in step 2). |
|
|
255
|
+
| Image has more than 7 distinct fills | Keep the 7 most area-covering fills per the Step 2 collision rule. Summary warns that some colors were dropped. |
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Style Presets — Learn, Apply, Manage
|
|
2
|
+
|
|
3
|
+
A **style preset** is a named JSON file capturing a user's visual preferences — palette, shape vocabulary, fonts, edge style. When a preset is active, it fully replaces the built-in conventions in SKILL.md's color/shape/edge tables.
|
|
4
|
+
|
|
5
|
+
Read this file when:
|
|
6
|
+
- The user asks to "learn", "save", "remember", or "extract" a style from a file
|
|
7
|
+
- The user wants to manage existing presets (list, set default, delete, rename)
|
|
8
|
+
- You've resolved an active preset in Step 0 and need the application rules
|
|
9
|
+
- You need to validate a preset file before loading it
|
|
10
|
+
|
|
11
|
+
## Locations and lookup order
|
|
12
|
+
|
|
13
|
+
1. `~/.drawio-skill/styles/<name>.json` — user presets (survive `git pull`).
|
|
14
|
+
2. `<this-skill-dir>/styles/built-in/<name>.json` — built-ins shipped with the skill (`default`, `corporate`, `handdrawn`).
|
|
15
|
+
|
|
16
|
+
A user preset shadows a built-in of the same name.
|
|
17
|
+
|
|
18
|
+
Only user presets can have `"default": true`. When the user says *"make `<built-in-name>` my default"*, copy the built-in JSON to `~/.drawio-skill/styles/<name>.json` first, then set `default: true` on the copy — leave the shipped built-in untouched.
|
|
19
|
+
|
|
20
|
+
**Name normalisation:** always lowercase the user-provided name before writing or looking up files (the preset schema enforces lowercase; uppercase names will fail validation).
|
|
21
|
+
|
|
22
|
+
## Applying a preset
|
|
23
|
+
|
|
24
|
+
When SKILL.md's Step 0 identified a preset, it fully replaces the built-in palette, shape keywords, edge defaults, and font for this diagram — do not mix values from the built-in color table.
|
|
25
|
+
|
|
26
|
+
**Color lookup.** For each role a shape plays (service / database / queue / gateway / error / external / security), resolve `preset.roles[role]` to a slot name, then `preset.palette[<slot>]` to the `(fillColor, strokeColor)` pair. If `roles[role]` is unset or the resolved slot is `null`, follow this fallback ladder:
|
|
27
|
+
|
|
28
|
+
1. Try the role's canonical slot (`service→primary`, `database→success`, `queue→warning`, `gateway→accent`, `error→danger`, `external→neutral`, `security→secondary`).
|
|
29
|
+
2. If that slot is also empty, pick the most-populated non-null slot in the preset.
|
|
30
|
+
3. Never reach into the built-in color table — the preset is authoritative.
|
|
31
|
+
|
|
32
|
+
**Decision and container shapes** are not in `preset.roles` — they have shape vocabulary (`preset.shapes.decision`, `preset.shapes.container`) but no role-to-slot mapping. Pick their colors as follows:
|
|
33
|
+
- **Decision** (rhombus) → use `preset.palette.warning` (the canonical yellow slot in the built-in conventions). If `warning` is empty, apply the slot-fallback ladder above starting from `warning`.
|
|
34
|
+
- **Container** (swimlane) → use the palette slot matching the tier/grouping the container represents (e.g. a "Services" tier container uses `primary`; a "Data" tier uses `success`). If no tier signal is available, default to `primary`.
|
|
35
|
+
|
|
36
|
+
**Shape keywords.** Use `preset.shapes[role]` as the **prefix** of the vertex style string (before `whiteSpace=wrap;html=1;...`). Example: for a database role, if `preset.shapes.database = "shape=cylinder3"`, the vertex style starts `shape=cylinder3;whiteSpace=wrap;html=1;fillColor=...`. The six named shape keys are `service`, `database`, `queue`, `decision`, `external`, `container`. Roles `gateway`, `error`, and `security` reuse `preset.shapes.service` unless the preset explicitly populates a key with their name.
|
|
37
|
+
|
|
38
|
+
**Edges.** Use `preset.edges.style` as the base edge style string. Append `preset.edges.arrow`. Per-edge routing keys (`exitX/exitY/entryX/entryY/...`) are still added by the usual routing rules in SKILL.md. If the flow between two shapes matches a token from `preset.edges.dashedFor` (either because the user's prompt used that word, or because one end of the edge plays a role whose typical relation is "optional"), append `;dashed=1` to the edge style.
|
|
39
|
+
|
|
40
|
+
**Fonts.** Append `fontFamily=<preset.font.fontFamily>;fontSize=<preset.font.fontSize>` to every vertex style. Container headers and swimlane titles additionally get `fontSize=<preset.font.titleFontSize>;fontStyle=1` when `preset.font.titleBold` is `true`.
|
|
41
|
+
|
|
42
|
+
**Extras.**
|
|
43
|
+
- `preset.extras.sketch === true` → append `sketch=1` to every vertex style and every edge style.
|
|
44
|
+
- `preset.extras.globalStrokeWidth !== 1` (any value other than the drawio default of 1, including `0.5`) → append `strokeWidth=<n>` to every vertex style and every edge style.
|
|
45
|
+
|
|
46
|
+
**Interaction with diagram-type presets** (ERD / UML / Sequence / ML / Flowchart). Diagram-type presets set structural style keywords that the user preset must preserve (e.g. ERD tables rely on `shape=table;startSize=30;container=1;childLayout=tableLayout;...`). The rule: keep the diagram-type preset's structural keywords, then layer the user preset's color / font / edge / extras on top. When a diagram-type preset hardcodes a color (`fillColor=#dae8fc`, etc.) that conflicts with the user preset, the user preset's color wins. Exception: `fillColor=none` is structural — do not replace it with a palette color.
|
|
47
|
+
|
|
48
|
+
## Learn flow
|
|
49
|
+
|
|
50
|
+
**Triggers:** "learn my style from `<path>` as `<name>`", "save this as `<name>` style", "remember this style as `<name>`".
|
|
51
|
+
|
|
52
|
+
**Dispatch by file extension:**
|
|
53
|
+
- `.drawio`, `.xml` → XML path
|
|
54
|
+
- `.png`, `.jpg`, `.jpeg`, `.svg` (rasterized flat image) → image path
|
|
55
|
+
|
|
56
|
+
**Steps:**
|
|
57
|
+
|
|
58
|
+
1. **Load the extraction reference.** Read `references/style-extraction.md` into context.
|
|
59
|
+
2. **Extract** following the XML path or image path procedure in the reference.
|
|
60
|
+
3. **Normalize and build candidate.** Convert the user-provided preset name to lowercase. Use this normalized name for ALL file paths in this flow. Build the candidate preset JSON and write it to `/tmp/drawio-preset-<name>.json` (where `<name>` is the already-normalized name). Do **not** save to `~/.drawio-skill/styles/<name>.json` yet.
|
|
61
|
+
4. **Render a sample** using the sample-diagram skeleton in `references/style-extraction.md`, parameterized by the candidate preset. Export PNG to `./preset-<name>-sample.png` using the same `drawio -x -f png -e -s 2 -o ./preset-<name>-sample.png /tmp/drawio-preset-<name>.drawio` command the main workflow uses, then run `repair_png.py` on it (see the Rendering the sample steps in `style-extraction.md`).
|
|
62
|
+
5. **Show the user:**
|
|
63
|
+
- Preset summary table (palette hex values, shapes per role, font, edge style, extras).
|
|
64
|
+
- The sample PNG path (and embed the image if the environment supports it).
|
|
65
|
+
- Provenance line: `source.type`, `source.path`, `extracted_at`, `confidence`.
|
|
66
|
+
6. **Wait for approval:**
|
|
67
|
+
- "save" / "looks good" → write candidate to `~/.drawio-skill/styles/<name>.json`. Create `~/.drawio-skill/styles/` if it doesn't exist. Delete tempfile and sample PNG.
|
|
68
|
+
- "change `<field>` to `<value>`" → edit the in-memory candidate, re-render, re-ask.
|
|
69
|
+
- "cancel" / "abort" / "no" → delete tempfile and sample PNG; nothing saved.
|
|
70
|
+
|
|
71
|
+
**Error behavior:**
|
|
72
|
+
|
|
73
|
+
| Failure | Behavior |
|
|
74
|
+
|---|---|
|
|
75
|
+
| Source path does not exist | Stop; report path not found. |
|
|
76
|
+
| XML parse fails | Stop; report the parse error; suggest opening the file in drawio desktop to repair. |
|
|
77
|
+
| Image vision unavailable | Stop; tell user to re-run on a vision-capable model or provide the `.drawio` file. |
|
|
78
|
+
| Extraction yields 0 vertices / shapes | Stop; refuse to save. |
|
|
79
|
+
| Extraction yields <3 distinct color pairs | Continue; mark `confidence: "low"` (image) or `"medium"` (XML); warn in summary. |
|
|
80
|
+
| Preset name collides with existing user preset | Ask: overwrite, or pick a new name. |
|
|
81
|
+
| Preset name collides with a built-in preset | Save to user dir (shadows the built-in); warn once. |
|
|
82
|
+
| Sample render fails | Still show summary; note "could not render sample — saving on your OK anyway". Do not block. |
|
|
83
|
+
|
|
84
|
+
## Management operations
|
|
85
|
+
|
|
86
|
+
All operations are natural language — no slash commands.
|
|
87
|
+
|
|
88
|
+
*Apply name normalisation (lowercase) to all `<name>`, `<a>`, `<b>` arguments before any file operation.*
|
|
89
|
+
|
|
90
|
+
| User says | Agent does |
|
|
91
|
+
|---|---|
|
|
92
|
+
| "list my styles", "what styles do I have", "show me my style presets" | Read `~/.drawio-skill/styles/` and `<this-skill-dir>/styles/built-in/`. Print a table: `name`, `location` (user/built-in), `source.type`, `confidence`, `default` flag. Built-ins shadowed by a user preset are marked so. |
|
|
93
|
+
| "show my `<name>` style", "what's in `<name>`" | Print the preset JSON (pretty-printed) + a one-line summary (source, confidence, is-default). |
|
|
94
|
+
| "make `<name>` the default", "set `<name>` as default" | If `<name>` is a user preset: set `default: true` on it; clear `default` on any other user preset that had it; save both files. If `<name>` is a built-in: copy `<this-skill-dir>/styles/built-in/<name>.json` → `~/.drawio-skill/styles/<name>.json` first, then set `default: true` on the copy. Never mutate the shipped built-in. |
|
|
95
|
+
| "remove default", "unset default" | Clear `default: true` from whichever user preset has it. |
|
|
96
|
+
| "delete `<name>`", "remove `<name>`" | Confirm first. Then `rm ~/.drawio-skill/styles/<name>.json`. Refuse to delete files under `<this-skill-dir>/styles/built-in/` — suggest shadowing with a user preset of the same name. |
|
|
97
|
+
| "rename `<a>` to `<b>`" | `mv ~/.drawio-skill/styles/<a>.json ~/.drawio-skill/styles/<b>.json`, then update the `name` field inside. Fails if `<a>` is a built-in (offer to copy-then-rename instead). |
|
|
98
|
+
| "learn my style from `<path>` as `<name>`" | Dispatch to the Learn flow above. |
|
|
99
|
+
|
|
100
|
+
## Preset file validation
|
|
101
|
+
|
|
102
|
+
When loading any preset (for generation or management), do a lightweight structural check:
|
|
103
|
+
- Required top-level fields present (`name`, `version`, `palette`, `roles`, `shapes`, `font`, `edges`).
|
|
104
|
+
- `version === 1`.
|
|
105
|
+
- Every populated palette slot has both `fillColor` and `strokeColor` as `#RRGGBB`.
|
|
106
|
+
- `confidence` ∈ {`"low"`, `"medium"`, `"high"`} if present.
|
|
107
|
+
|
|
108
|
+
On validation failure:
|
|
109
|
+
- **During generation:** warn the user, fall back to built-in conventions for this one diagram, do not mutate the file.
|
|
110
|
+
- **During learn:** refuse to save the candidate; report which field failed.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Style 1: Flat Icon (Default)
|
|
2
|
+
|
|
3
|
+
Adapted from fireworks-tech-graph Style 1. Clean, colorful, draw.io-native aesthetic.
|
|
4
|
+
|
|
5
|
+
## Color Palette → Draw.io Mapping
|
|
6
|
+
|
|
7
|
+
| Role | fillColor | strokeColor | Use for |
|
|
8
|
+
|------|-----------|-------------|---------|
|
|
9
|
+
| primary (service) | `#eff6ff` | `#bfdbfe` | services, clients, main components |
|
|
10
|
+
| success (database) | `#f0fdf4` | `#bbf7d0` | databases, storage |
|
|
11
|
+
| warning (queue) | `#fff7ed` | `#fed7aa` | queues, decisions |
|
|
12
|
+
| accent (gateway/API) | `#faf5ff` | `#e9d5ff` | gateways, APIs, orchestration |
|
|
13
|
+
| danger (error) | `#fef2f2` | `#fecaca` | errors, alerts |
|
|
14
|
+
| secondary (security) | `#f0fdfa` | `#ccfbf1` | security, auth |
|
|
15
|
+
| neutral (external) | `#f9fafb` | `#e5e7eb` | external systems, neutral |
|
|
16
|
+
|
|
17
|
+
## Typography → Draw.io Mapping
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
fontFamily=Helvetica Neue,Helvetica,Arial,PingFang SC,Microsoft YaHei,SimHei,sans-serif
|
|
21
|
+
fontSize=14 (labels)
|
|
22
|
+
fontSize=12 (sub-labels)
|
|
23
|
+
fontSize=16 (titles)
|
|
24
|
+
fontStyle=1 (bold, for titles)
|
|
25
|
+
fontColor=#111827 (primary text)
|
|
26
|
+
fontColor=#6b7280 (secondary text)
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Shape Preferences
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
rounded=1 (rounded corners, 8px equivalent)
|
|
33
|
+
whiteSpace=wrap
|
|
34
|
+
html=1
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
For standard boxes: `rounded=1;whiteSpace=wrap;html=1;`
|
|
38
|
+
For databases: `shape=cylinder3;whiteSpace=wrap;html=1;`
|
|
39
|
+
For decisions: `rhombus;whiteSpace=wrap;html=1;`
|
|
40
|
+
For clouds: `cloud;whiteSpace=wrap;html=1;`
|
|
41
|
+
For documents: `shape=document;whiteSpace=wrap;html=1;`
|
|
42
|
+
|
|
43
|
+
## Edge Style → Draw.io Mapping
|
|
44
|
+
|
|
45
|
+
Base edge style:
|
|
46
|
+
```
|
|
47
|
+
edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Arrow colors (append to edge style):
|
|
51
|
+
| Flow Type | strokeColor | Additional |
|
|
52
|
+
|-----------|-------------|------------|
|
|
53
|
+
| Primary data flow | `#2563eb` | — |
|
|
54
|
+
| Secondary/alt | `#dc2626` | — |
|
|
55
|
+
| Data/retrieval | `#16a34a` | — |
|
|
56
|
+
| Async/event | `#9333ea` | `dashed=1` |
|
|
57
|
+
| Control/trigger | `#ea580c` | — |
|
|
58
|
+
|
|
59
|
+
## Extras
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
strokeWidth=1.5 (on all shapes)
|
|
63
|
+
sketch=0 (no sketch mode)
|
|
64
|
+
shadow=0 (no drop shadows)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Complete Vertex Style Template
|
|
68
|
+
|
|
69
|
+
For a service node (primary role):
|
|
70
|
+
```
|
|
71
|
+
rounded=1;whiteSpace=wrap;html=1;fillColor=#eff6ff;strokeColor=#bfdbfe;strokeWidth=1.5;fontFamily=Helvetica Neue,Helvetica,Arial,PingFang SC,Microsoft YaHei,SimHei,sans-serif;fontSize=14;fontColor=#111827;
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Complete Edge Style Template
|
|
75
|
+
|
|
76
|
+
For a primary data flow edge:
|
|
77
|
+
```
|
|
78
|
+
edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#2563eb;strokeWidth=1.5;
|
|
79
|
+
```
|