Files
diagrams-drawio/references/rules-style.md
oleg-lukasonokandClaude Fable 5 77655d1d97 Restructure to skill-manager conventions
- Move the TypeScript project under scripts/ (src, tsconfig,
  package.json, pnpm lockfile/workspace, canonical .gitignore);
  drop the npm package-lock
- Add scripts/Taskfile.yml aggregator plus .scripts modules
  (loggers, base, cli) with build, run, and validate tasks
- Move the six SKILL-*.md docs into references/ with kebab names
  and extract the connector-routing sections from SKILL.md into
  references/routing-best-practices.md (SKILL.md 666 -> ~310 lines)
- Add license/metadata/compatibility frontmatter, an Available
  scripts section, and update all CLI paths in README and references

skill-manager validate: 13/13 passed, 0 warnings.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 15:20:26 +03:00

72 lines
5.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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)