Add drawio-main skill (renamed from drawio-main-v1)
Draw.io diagram generation and analysis skill: mandatory layout and style rules, XML reference, negative-space companion diagrams, and the drawio-tools TypeScript CLI with 12 analysis/validation actions. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
# drawio-main — Style Rules
|
||||
|
||||
Visual appearance and sizing rules for draw.io diagrams generated by this skill.
|
||||
These rules are **MANDATORY** — apply them when generating any diagram.
|
||||
|
||||
---
|
||||
|
||||
## General style rules — MANDATORY
|
||||
|
||||
- **All child shapes within the same swimlane must have the same height** — never mix different heights within one swimlane layer/row
|
||||
- **Rectangles must never use rounding** — always set `rounded=0` on rectangle shapes
|
||||
- Prefer dimensions divisible by 40; wrap non-divisible vendor icons in a grid-aligned container
|
||||
- **The space between sibling shapes of the same level (same swimlane, same row) must be divisible by 40px** — use 40px as the minimum gap. If a swimlane row has shapes of width W and gap G, the step between shape origins = W + G where G ≥ 40 and G mod 40 = 0.
|
||||
- **Swimlane `startSize` (header height) must be divisible by 40** — use `startSize=40`
|
||||
- **Swimlane body height (total − startSize) must be divisible by 40** — so total height = 40 + N×40 = a multiple of 40
|
||||
- Example: `startSize=40`, body=80 → total=120 ✓; body=160 → total=200 ✓
|
||||
- Use ≤ 3 primary color families; create hierarchy with shades
|
||||
- Use dashed connectors only for semantically distinct flows (async, backup, admin)
|
||||
- Shape size is driven by **content**, not routing — typically 80–160px tall per label line
|
||||
|
||||
---
|
||||
|
||||
## Connector routing rules — MANDATORY
|
||||
|
||||
- **All outgoing connectors from the same shape must share a single exit point** — never let multiple connectors leave a shape at different X/Y coordinates. Pick one exit side (top/bottom/left/right) and one coordinate on that side; all outgoing connectors use it as their first waypoint.
|
||||
- **All incoming connectors to the same shape must share a single entry point** — never let multiple connectors enter a shape at different X/Y coordinates. Pick one entry side and one coordinate; all incoming connectors use it as their last waypoint before the shape.
|
||||
- **Connectors must never attach at a shape corner** — the exit/entry point must lie on the middle of a side: top-center, bottom-center, left-center, or right-center. A point that is simultaneously on both an X-edge (left or right) AND a Y-edge (top or bottom) of the shape bounding box is a corner and is forbidden. Use the midpoint of the chosen side: `x_mid = (x1+x2)/2` for top/bottom sides, `y_mid = (y1+y2)/2` for left/right sides.
|
||||
- These rules ensure a clean "bus-bar" fan-out/fan-in pattern and prevent connectors from diverging at their source or converging at their target at different positions, which creates visual clutter and increases crossing risk.
|
||||
- Exception: shapes with only a single outgoing or single incoming connector — the single-port rule trivially holds. The corner rule still applies.
|
||||
- When computing waypoints: use `page-negative-space-summary` to find free X corridors per row, then pick an exit/entry coordinate that lies within a free corridor at the next traversed level. This minimises connector-shape overlaps and connector crossings.
|
||||
- **Waypoints must never be closer than 20px to any shape** — the first waypoint after a shape exit must be at least 20px away from the shape's edge in the direction of travel (e.g., if exiting bottom at y=520, first waypoint y ≥ 540; if exiting right at x=1040, first waypoint x ≥ 1060). The last waypoint before a shape entry must likewise be at least 20px away from the shape's edge. This 20px clearance also applies to any waypoint relative to same-level sibling shapes the connector passes by — the waypoint must not come within 20px of any sibling shape's bounding box side it is adjacent to.
|
||||
|
||||
---
|
||||
|
||||
## Text-width estimation — negative space calculation
|
||||
|
||||
When computing negative space manually (e.g. for a negative-space diagram), **shape bounding boxes alone overestimate occupied space**. Text labels only occupy a sub-region within the shape bbox. Use the following formula to estimate the text rendering width:
|
||||
|
||||
```
|
||||
charWidth = fontSize × 0.6 // avg glyph width for proportional fonts
|
||||
rawWidth = longestLineChrCount × charWidth
|
||||
padding = fontSize × 1.0 // horizontal padding (~0.5em each side)
|
||||
textWidth = rawWidth + padding
|
||||
|
||||
fontStyle modifiers (draw.io flags):
|
||||
bit 0 (value 1) = bold → charWidth × 1.10
|
||||
bit 1 (value 2) = italic → charWidth × 1.05
|
||||
|
||||
textXMin = clamp(shapeCenterX − textWidth/2, shape.xMin, shape.xMax)
|
||||
textXMax = clamp(shapeCenterX + textWidth/2, shape.xMin, shape.xMax)
|
||||
```
|
||||
|
||||
**When to apply:**
|
||||
- Swimlane headers (`startSize=40` band): the header text is centered in the full zone width. Use text region for occupied X, flanks are free negative space.
|
||||
- Large container shapes whose children don't fill the full width.
|
||||
- Any shape where `textWidth < shapeWidth` — the flanks inside the bbox are free.
|
||||
|
||||
**Example — zone headers at fontSize=12 bold (fontStyle=1), center x=660, zone x=80..1240:**
|
||||
|
||||
| Label | chars | charWidth | rawWidth | padding | textWidth | textXMin | textXMax | flank each side |
|
||||
|---|---|---|---|---|---|---|---|---|
|
||||
| "Client Layer" | 12 | 7.9 | 95 | 12 | 107 | 607 | 713 | ~527pt |
|
||||
| "API Gateway / Edge Layer" | 24 | 7.9 | 190 | 12 | 202 | 559 | 761 | ~479pt |
|
||||
| "Core Microservices" | 18 | 7.9 | 143 | 12 | 155 | 583 | 737 | ~503pt |
|
||||
| "Messaging / Event Bus" | 21 | 7.9 | 166 | 12 | 178 | 571 | 749 | ~491pt |
|
||||
| "Data Layer" | 10 | 7.9 | 79 | 12 | 91 | 615 | 705 | ~535pt |
|
||||
|
||||
**The `page-negative-space-summary` action now outputs these fields per shape:**
|
||||
- `textXMin`, `textXMax`, `textWidth` — estimated text rendering region
|
||||
- `textFlankLeft`, `textFlankRight` — free space flanking text inside bbox
|
||||
- `rows[].textAwareFreeCorridors` — free corridors computed using text regions (wider than bbox-based corridors)
|
||||
Reference in New Issue
Block a user