@drunkcoding/agents-and-skills 0.0.44 → 0.0.46

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.
Files changed (107) hide show
  1. package/.claude-plugin/marketplace.json +2 -47
  2. package/README.md +3 -6
  3. package/package.json +4 -1
  4. package/plugins/multica-tool/.claude-plugin/plugin.json +1 -1
  5. package/plugins/multica-tool/scripts/lib.mjs +53 -4
  6. package/plugins/multica-tool/scripts/multica-export.mjs +170 -50
  7. package/plugins/multica-tool/scripts/multica-import.mjs +209 -27
  8. package/plugins/multica-tool/skills/export/SKILL.md +91 -22
  9. package/plugins/multica-tool/skills/import/SKILL.md +24 -9
  10. package/plugins/multica-tool/skills/sync/SKILL.md +1 -1
  11. package/plugins/plugin-validator/.claude-plugin/plugin.json +1 -1
  12. package/plugins/html-effectiveness/.claude-plugin/plugin.json +0 -17
  13. package/plugins/html-effectiveness/README.md +0 -28
  14. package/plugins/html-effectiveness/agents/report-builder.md +0 -66
  15. package/plugins/html-effectiveness/assets/base.css +0 -51
  16. package/plugins/html-effectiveness/assets/base.js +0 -11
  17. package/plugins/html-effectiveness/assets/charts.js +0 -1
  18. package/plugins/html-effectiveness/assets/components.css +0 -10
  19. package/plugins/html-effectiveness/commands/html-report.md +0 -13
  20. package/plugins/html-effectiveness/docs/template-gallery.md +0 -28
  21. package/plugins/html-effectiveness/package.json +0 -6
  22. package/plugins/html-effectiveness/scripts/_tmp.js +0 -37
  23. package/plugins/html-effectiveness/scripts/catalog.js +0 -47
  24. package/plugins/html-effectiveness/scripts/extract.js +0 -104
  25. package/plugins/html-effectiveness/scripts/mustache.js +0 -90
  26. package/plugins/html-effectiveness/scripts/render.js +0 -176
  27. package/plugins/html-effectiveness/skills/html-effectiveness/SKILL.md +0 -94
  28. package/plugins/html-effectiveness/templates/01-exploration-code-approaches.html.tmpl +0 -400
  29. package/plugins/html-effectiveness/templates/02-exploration-visual-designs.html.tmpl +0 -456
  30. package/plugins/html-effectiveness/templates/03-code-review-pr.html.tmpl +0 -581
  31. package/plugins/html-effectiveness/templates/04-code-understanding.html.tmpl +0 -443
  32. package/plugins/html-effectiveness/templates/05-design-system.html.tmpl +0 -578
  33. package/plugins/html-effectiveness/templates/06-component-variants.html.tmpl +0 -557
  34. package/plugins/html-effectiveness/templates/07-prototype-animation.html.tmpl +0 -417
  35. package/plugins/html-effectiveness/templates/08-prototype-interaction.html.tmpl +0 -363
  36. package/plugins/html-effectiveness/templates/09-slide-deck.html.tmpl +0 -535
  37. package/plugins/html-effectiveness/templates/10-svg-illustrations.html.tmpl +0 -444
  38. package/plugins/html-effectiveness/templates/11-status-report.html.tmpl +0 -152
  39. package/plugins/html-effectiveness/templates/12-incident-report.html.tmpl +0 -547
  40. package/plugins/html-effectiveness/templates/13-flowchart-diagram.html.tmpl +0 -361
  41. package/plugins/html-effectiveness/templates/14-research-feature-explainer.html.tmpl +0 -348
  42. package/plugins/html-effectiveness/templates/15-research-concept-explainer.html.tmpl +0 -334
  43. package/plugins/html-effectiveness/templates/16-implementation-plan.html.tmpl +0 -657
  44. package/plugins/html-effectiveness/templates/17-pr-writeup.html.tmpl +0 -553
  45. package/plugins/html-effectiveness/templates/18-editor-triage-board.html.tmpl +0 -541
  46. package/plugins/html-effectiveness/templates/19-editor-feature-flags.html.tmpl +0 -627
  47. package/plugins/html-effectiveness/templates/20-editor-prompt-tuner.html.tmpl +0 -687
  48. package/plugins/html-effectiveness/templates/manifest.json +0 -441
  49. package/plugins/team-share/.claude-plugin/plugin.json +0 -18
  50. package/plugins/team-share/README.md +0 -46
  51. package/plugins/team-share/agents/team-share.md +0 -53
  52. package/plugins/team-share/commands/team-share.md +0 -4
  53. package/plugins/team-share/skills/claude-config/SKILL.md +0 -143
  54. package/plugins/team-share/skills/codegraph-setup/SKILL.md +0 -81
  55. package/plugins/team-share/skills/understand-setup/SKILL.md +0 -115
  56. package/plugins/tech-graph/.claude-plugin/plugin.json +0 -17
  57. package/plugins/tech-graph/README.md +0 -66
  58. package/plugins/tech-graph/agents/tech-graph.md +0 -97
  59. package/plugins/tech-graph/commands/tech-graph.md +0 -13
  60. package/plugins/tech-graph/scripts/check-deps.sh +0 -55
  61. package/plugins/tech-graph/skills/tech-graph/LICENSE +0 -21
  62. package/plugins/tech-graph/skills/tech-graph/README.md +0 -555
  63. package/plugins/tech-graph/skills/tech-graph/README.zh.md +0 -514
  64. package/plugins/tech-graph/skills/tech-graph/SKILL.md +0 -263
  65. package/plugins/tech-graph/skills/tech-graph/agents/openai.yaml +0 -4
  66. package/plugins/tech-graph/skills/tech-graph/assets/samples/sample-style1-flat.png +0 -0
  67. package/plugins/tech-graph/skills/tech-graph/assets/samples/sample-style2-dark.png +0 -0
  68. package/plugins/tech-graph/skills/tech-graph/assets/samples/sample-style3-blueprint.png +0 -0
  69. package/plugins/tech-graph/skills/tech-graph/assets/samples/sample-style4-notion.png +0 -0
  70. package/plugins/tech-graph/skills/tech-graph/assets/samples/sample-style5-glass.png +0 -0
  71. package/plugins/tech-graph/skills/tech-graph/assets/samples/sample-style6-claude.png +0 -0
  72. package/plugins/tech-graph/skills/tech-graph/assets/samples/sample-style7-openai.png +0 -0
  73. package/plugins/tech-graph/skills/tech-graph/fixtures/agent-memory-types-style4.json +0 -181
  74. package/plugins/tech-graph/skills/tech-graph/fixtures/api-flow-style7.json +0 -40
  75. package/plugins/tech-graph/skills/tech-graph/fixtures/mem0-style1.json +0 -297
  76. package/plugins/tech-graph/skills/tech-graph/fixtures/microservices-style3.json +0 -64
  77. package/plugins/tech-graph/skills/tech-graph/fixtures/multi-agent-style5.json +0 -45
  78. package/plugins/tech-graph/skills/tech-graph/fixtures/system-architecture-style6.json +0 -48
  79. package/plugins/tech-graph/skills/tech-graph/fixtures/tool-call-style2.json +0 -182
  80. package/plugins/tech-graph/skills/tech-graph/package.json +0 -42
  81. package/plugins/tech-graph/skills/tech-graph/references/diagram-types.md +0 -171
  82. package/plugins/tech-graph/skills/tech-graph/references/icons.md +0 -406
  83. package/plugins/tech-graph/skills/tech-graph/references/style-1-flat-icon.md +0 -108
  84. package/plugins/tech-graph/skills/tech-graph/references/style-2-dark-terminal.md +0 -107
  85. package/plugins/tech-graph/skills/tech-graph/references/style-3-blueprint.md +0 -113
  86. package/plugins/tech-graph/skills/tech-graph/references/style-4-notion-clean.md +0 -95
  87. package/plugins/tech-graph/skills/tech-graph/references/style-5-glassmorphism.md +0 -125
  88. package/plugins/tech-graph/skills/tech-graph/references/style-6-claude-official.md +0 -209
  89. package/plugins/tech-graph/skills/tech-graph/references/style-7-openai.md +0 -215
  90. package/plugins/tech-graph/skills/tech-graph/references/style-diagram-matrix.md +0 -135
  91. package/plugins/tech-graph/skills/tech-graph/references/svg-layout-best-practices.md +0 -100
  92. package/plugins/tech-graph/skills/tech-graph/references/svg-to-png.md +0 -115
  93. package/plugins/tech-graph/skills/tech-graph/scripts/README.md +0 -269
  94. package/plugins/tech-graph/skills/tech-graph/scripts/generate-diagram.sh +0 -181
  95. package/plugins/tech-graph/skills/tech-graph/scripts/generate-from-template.py +0 -1587
  96. package/plugins/tech-graph/skills/tech-graph/scripts/test-all-styles.sh +0 -143
  97. package/plugins/tech-graph/skills/tech-graph/scripts/validate-svg.sh +0 -306
  98. package/plugins/tech-graph/skills/tech-graph/templates/agent-architecture.svg +0 -28
  99. package/plugins/tech-graph/skills/tech-graph/templates/architecture.svg +0 -23
  100. package/plugins/tech-graph/skills/tech-graph/templates/comparison-matrix.svg +0 -14
  101. package/plugins/tech-graph/skills/tech-graph/templates/data-flow.svg +0 -28
  102. package/plugins/tech-graph/skills/tech-graph/templates/er-diagram.svg +0 -21
  103. package/plugins/tech-graph/skills/tech-graph/templates/flowchart.svg +0 -21
  104. package/plugins/tech-graph/skills/tech-graph/templates/sequence.svg +0 -20
  105. package/plugins/tech-graph/skills/tech-graph/templates/state-machine.svg +0 -20
  106. package/plugins/tech-graph/skills/tech-graph/templates/timeline.svg +0 -19
  107. package/plugins/tech-graph/skills/tech-graph/templates/use-case.svg +0 -21
@@ -1,143 +0,0 @@
1
- #!/bin/bash
2
- # Batch Test Script
3
- # Renders regression fixtures, validates SVGs, and exports PNGs
4
-
5
- set -euo pipefail
6
-
7
- # Colors
8
- RED='\033[0;31m'
9
- GREEN='\033[0;32m'
10
- YELLOW='\033[1;33m'
11
- BLUE='\033[0;34m'
12
- NC='\033[0m'
13
-
14
- SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
15
- TEST_DIR="${SKILL_DIR}/test-output"
16
- TIMESTAMP=$(date +%Y%m%d_%H%M%S)
17
-
18
- echo -e "${BLUE}=== Fireworks Tech Graph - Batch Test ===${NC}"
19
- echo "Test directory: $TEST_DIR"
20
- echo "Timestamp: $TIMESTAMP"
21
- echo ""
22
-
23
- # Create test directory
24
- mkdir -p "$TEST_DIR"
25
-
26
- # Test configuration
27
- STYLES=(1 2 3 4 5 6 7)
28
- STYLE_NAMES=("Flat Icon" "Dark Terminal" "Blueprint" "Notion Clean" "Glassmorphism" "Claude Official" "OpenAI Official")
29
-
30
- # Summary counters
31
- TOTAL=0
32
- PASSED=0
33
- FAILED=0
34
-
35
- FIXTURES_DIR="${SKILL_DIR}/fixtures"
36
-
37
- echo -e "${BLUE}Testing all styles...${NC}"
38
- echo "----------------------------------------"
39
-
40
- for i in "${!STYLES[@]}"; do
41
- STYLE="${STYLES[$i]}"
42
- STYLE_NAME="${STYLE_NAMES[$i]}"
43
-
44
- echo -e "\n${YELLOW}Style $STYLE: $STYLE_NAME${NC}"
45
-
46
- # Check if style reference exists
47
- STYLE_FILE=$(find "${SKILL_DIR}/references" -maxdepth 1 -type f -name "style-${STYLE}-*.md" | head -n 1)
48
- if [ -z "${STYLE_FILE:-}" ] || [ ! -f "$STYLE_FILE" ]; then
49
- echo -e "${RED}✗ Style file not found: $STYLE_FILE${NC}"
50
- FAILED=$((FAILED + 1))
51
- TOTAL=$((TOTAL + 1))
52
- continue
53
- fi
54
-
55
- echo -e "${GREEN}✓ Style file found${NC}"
56
-
57
- if [ ! -d "$FIXTURES_DIR" ]; then
58
- echo -e "${YELLOW}⚠ Fixtures directory not found: $FIXTURES_DIR${NC}"
59
- continue
60
- fi
61
-
62
- FIXTURE_FILES=$(find "$FIXTURES_DIR" -maxdepth 1 -type f -name "*.json" | sort || true)
63
- MATCHED_FIXTURES=()
64
- for FIXTURE in $FIXTURE_FILES; do
65
- FIXTURE_STYLE=$(python3 - "$FIXTURE" <<'PY'
66
- import json
67
- import sys
68
- from pathlib import Path
69
- data = json.loads(Path(sys.argv[1]).read_text(encoding='utf-8'))
70
- print(data.get("style", ""))
71
- PY
72
- )
73
- if [ "$FIXTURE_STYLE" = "$STYLE" ]; then
74
- MATCHED_FIXTURES+=("$FIXTURE")
75
- fi
76
- done
77
-
78
- if [ "${#MATCHED_FIXTURES[@]}" -eq 0 ]; then
79
- echo -e "${YELLOW}⚠ No regression fixtures found for style $STYLE${NC}"
80
- continue
81
- fi
82
-
83
- # Render, validate, and export each fixture
84
- for FIXTURE in "${MATCHED_FIXTURES[@]}"; do
85
- BASENAME=$(basename "$FIXTURE" .json)
86
- SVG_FILE="${TEST_DIR}/${BASENAME}_${TIMESTAMP}.svg"
87
- PNG_FILE="${TEST_DIR}/${BASENAME}_${TIMESTAMP}.png"
88
- TEMPLATE_TYPE=$(python3 - "$FIXTURE" <<'PY'
89
- import json
90
- import sys
91
- from pathlib import Path
92
- data = json.loads(Path(sys.argv[1]).read_text(encoding='utf-8'))
93
- print(data.get("template_type", "architecture"))
94
- PY
95
- )
96
-
97
- echo -n " Rendering $BASENAME... "
98
- TOTAL=$((TOTAL + 1))
99
-
100
- if python3 "${SKILL_DIR}/scripts/generate-from-template.py" "$TEMPLATE_TYPE" "$SVG_FILE" "$(cat "$FIXTURE")" > /dev/null 2>&1 \
101
- && "${SKILL_DIR}/scripts/validate-svg.sh" "$SVG_FILE" > /dev/null 2>&1; then
102
- PNG_OK=false
103
- # Prefer cairosvg (best CSS support); fall back to rsvg-convert
104
- if python3 -c "import cairosvg" 2>/dev/null \
105
- && python3 -c "import cairosvg; cairosvg.svg2png(url='${SVG_FILE}', write_to='${PNG_FILE}', scale=2)" 2>/dev/null; then
106
- PNG_OK=true
107
- elif command -v rsvg-convert &> /dev/null \
108
- && rsvg-convert -w 1920 "$SVG_FILE" -o "$PNG_FILE" 2>/dev/null; then
109
- PNG_OK=true
110
- fi
111
- if [ "$PNG_OK" = true ]; then
112
- PNG_SIZE=$(du -h "$PNG_FILE" | cut -f1)
113
- echo -e "${GREEN}✓ Pass${NC} (${PNG_SIZE})"
114
- else
115
- echo -e "${GREEN}✓ Pass${NC}"
116
- fi
117
- PASSED=$((PASSED + 1))
118
- else
119
- echo -e "${RED}✗ Fail${NC}"
120
- FAILED=$((FAILED + 1))
121
- if [ -f "$SVG_FILE" ]; then
122
- "${SKILL_DIR}/scripts/validate-svg.sh" "$SVG_FILE" 2>&1 | grep -E "✗|Error" | sed 's/^/ /' || true
123
- fi
124
- fi
125
- done
126
- done
127
-
128
- # Print summary
129
- echo ""
130
- echo "========================================"
131
- echo -e "${BLUE}Test Summary${NC}"
132
- echo "----------------------------------------"
133
- echo "Total tests: $TOTAL"
134
- echo -e "${GREEN}Passed: $PASSED${NC}"
135
- echo -e "${RED}Failed: $FAILED${NC}"
136
-
137
- if [ "$FAILED" -eq 0 ]; then
138
- echo -e "\n${GREEN}✓ All tests passed!${NC}"
139
- exit 0
140
- else
141
- echo -e "\n${RED}✗ Some tests failed${NC}"
142
- exit 1
143
- fi
@@ -1,306 +0,0 @@
1
- #!/bin/bash
2
- # SVG Validation Script
3
- # Checks SVG syntax and reports detailed errors
4
-
5
- set -euo pipefail
6
-
7
- # Colors for output
8
- RED='\033[0;31m'
9
- GREEN='\033[0;32m'
10
- YELLOW='\033[1;33m'
11
- NC='\033[0m' # No Color
12
-
13
- if [ $# -eq 0 ]; then
14
- echo "Usage: $0 <svg-file>"
15
- exit 1
16
- fi
17
-
18
- SVG_FILE="$1"
19
-
20
- if [ ! -f "$SVG_FILE" ]; then
21
- echo -e "${RED}Error: File not found: $SVG_FILE${NC}"
22
- exit 1
23
- fi
24
-
25
- echo "Validating SVG: $SVG_FILE"
26
- echo "----------------------------------------"
27
-
28
- FAILURES=0
29
-
30
- # Check 0: XML syntax
31
- echo -n "Checking XML syntax... "
32
- if command -v xmllint &> /dev/null; then
33
- if xmllint --noout "$SVG_FILE" 2>/dev/null; then
34
- echo -e "${GREEN}✓ Pass${NC}"
35
- else
36
- echo -e "${RED}✗ Fail${NC}"
37
- xmllint --noout "$SVG_FILE" 2>&1 || true
38
- FAILURES=$((FAILURES + 1))
39
- fi
40
- else
41
- echo -e "${YELLOW}⚠ Skipped${NC} (xmllint not found)"
42
- fi
43
-
44
- # Check 1: Tag balance
45
- echo -n "Checking tag balance... "
46
- OPEN_TAGS=$( { grep -o '<[A-Za-z][A-Za-z0-9:-]*' "$SVG_FILE" || true; } | { grep -v '</' || true; } | wc -l | tr -d ' ' )
47
- SELF_CLOSING=$( { grep -o '/>' "$SVG_FILE" || true; } | wc -l | tr -d ' ' )
48
- CLOSE_TAGS=$( { grep -o '</[A-Za-z][A-Za-z0-9:-]*>' "$SVG_FILE" || true; } | wc -l | tr -d ' ' )
49
- TOTAL_CLOSE=$((SELF_CLOSING + CLOSE_TAGS))
50
-
51
- if [ "$OPEN_TAGS" -eq "$TOTAL_CLOSE" ]; then
52
- echo -e "${GREEN}✓ Pass${NC} (${OPEN_TAGS} tags)"
53
- else
54
- echo -e "${RED}✗ Fail${NC} (${OPEN_TAGS} open, ${TOTAL_CLOSE} close)"
55
- FAILURES=$((FAILURES + 1))
56
- fi
57
-
58
- # Check 2: Quote check
59
- echo -n "Checking attribute quotes... "
60
- UNQUOTED=$( { grep -oE '[a-z-]+=[^"'\''> ]' "$SVG_FILE" || true; } | wc -l | tr -d ' ' )
61
- if [ "$UNQUOTED" -eq 0 ]; then
62
- echo -e "${GREEN}✓ Pass${NC}"
63
- else
64
- echo -e "${RED}✗ Fail${NC} (${UNQUOTED} unquoted attributes)"
65
- grep -n -oE '[a-z-]+=[^"'\''> ]' "$SVG_FILE" | head -5 || true
66
- FAILURES=$((FAILURES + 1))
67
- fi
68
-
69
- # Check 3: Unescaped entities in text
70
- echo -n "Checking text entities... "
71
- SPECIAL=$(python3 - "$SVG_FILE" <<'PY'
72
- from pathlib import Path
73
- import re
74
- import sys
75
-
76
- text = Path(sys.argv[1]).read_text(encoding='utf-8')
77
- issues = 0
78
- for chunk in re.findall(r'>([^<]*)<', text, flags=re.S):
79
- cleaned = re.sub(r'&(amp|lt|gt|quot|apos);', '', chunk)
80
- if '&' in cleaned:
81
- issues += 1
82
- print(issues)
83
- PY
84
- )
85
- if [ "$SPECIAL" -eq 0 ]; then
86
- echo -e "${GREEN}✓ Pass${NC}"
87
- else
88
- echo -e "${YELLOW}⚠ Warning${NC} (${SPECIAL} potential unescaped entities)"
89
- fi
90
-
91
- # Check 4: Marker references
92
- echo -n "Checking marker references... "
93
- MARKER_REFS=$( { grep -oE 'marker-end="url\(#[^)]+\)"' "$SVG_FILE" || true; } | { grep -oE '#[^)]+' || true; } | tr -d '#' | sort -u )
94
- MARKER_DEFS=$( { grep -oE '<marker id="[^"]+"' "$SVG_FILE" || true; } | { grep -oE 'id="[^"]+"' || true; } | tr -d 'id="' | sort -u )
95
-
96
- MISSING=0
97
- for ref in $MARKER_REFS; do
98
- if ! echo "$MARKER_DEFS" | grep -q "^${ref}$"; then
99
- echo -e "${RED}✗ Missing marker: $ref${NC}"
100
- MISSING=$((MISSING + 1))
101
- fi
102
- done
103
-
104
- if [ "$MISSING" -eq 0 ]; then
105
- echo -e "${GREEN}✓ Pass${NC}"
106
- else
107
- echo -e "${RED}✗ Fail${NC} (${MISSING} missing markers)"
108
- FAILURES=$((FAILURES + 1))
109
- fi
110
-
111
- # Check 5: Arrow-component collision
112
- echo -n "Checking arrow collisions... "
113
- COLLISIONS=$(python3 - "$SVG_FILE" <<'PY'
114
- from pathlib import Path
115
- import re
116
- import sys
117
- import xml.etree.ElementTree as ET
118
-
119
- SVG_NS = {'svg': 'http://www.w3.org/2000/svg'}
120
-
121
- def strip(tag):
122
- return tag.split('}', 1)[-1]
123
-
124
- def to_float(value, default=0.0):
125
- try:
126
- return float(value)
127
- except (TypeError, ValueError):
128
- return default
129
-
130
- def is_container_rect(el):
131
- if el.get('stroke-dasharray'):
132
- return True
133
- width = to_float(el.get('width'))
134
- height = to_float(el.get('height'))
135
- if width > 700 or height > 500:
136
- return True
137
- if width < 70 or height < 30:
138
- return True
139
- return False
140
-
141
- def shape_bounds(el):
142
- tag = strip(el.tag)
143
- if tag == 'rect':
144
- if is_container_rect(el):
145
- return None
146
- x = to_float(el.get('x'))
147
- y = to_float(el.get('y'))
148
- w = to_float(el.get('width'))
149
- h = to_float(el.get('height'))
150
- return (x, y, x + w, y + h)
151
- if tag == 'circle':
152
- r = to_float(el.get('r'))
153
- if r < 20:
154
- return None
155
- cx = to_float(el.get('cx'))
156
- cy = to_float(el.get('cy'))
157
- return (cx - r, cy - r, cx + r, cy + r)
158
- if tag == 'ellipse':
159
- rx = to_float(el.get('rx'))
160
- ry = to_float(el.get('ry'))
161
- if rx < 20 or ry < 20:
162
- return None
163
- cx = to_float(el.get('cx'))
164
- cy = to_float(el.get('cy'))
165
- return (cx - rx, cy - ry, cx + rx, cy + ry)
166
- return None
167
-
168
- def parse_path_points(d):
169
- tokens = re.findall(r'[ML]|-?\d+(?:\.\d+)?', d or '')
170
- if not tokens:
171
- return []
172
- points = []
173
- command = None
174
- index = 0
175
- while index < len(tokens):
176
- token = tokens[index]
177
- if token in {'M', 'L'}:
178
- command = token
179
- index += 1
180
- continue
181
- if command not in {'M', 'L'} or index + 1 >= len(tokens):
182
- return []
183
- x = float(tokens[index])
184
- y = float(tokens[index + 1])
185
- points.append((x, y))
186
- index += 2
187
- return points
188
-
189
- def segment_hits_bounds(p1, p2, bounds):
190
- x1, y1 = p1
191
- x2, y2 = p2
192
- left, top, right, bottom = bounds
193
- eps = 1e-6
194
-
195
- if abs(y1 - y2) < eps:
196
- y = y1
197
- if not (top + eps < y < bottom - eps):
198
- return False
199
- seg_left = min(x1, x2)
200
- seg_right = max(x1, x2)
201
- overlap_left = max(seg_left, left)
202
- overlap_right = min(seg_right, right)
203
- if overlap_right - overlap_left <= eps:
204
- return False
205
- if abs(overlap_left - x1) < eps or abs(overlap_right - x2) < eps:
206
- return False
207
- if abs(overlap_left - x2) < eps or abs(overlap_right - x1) < eps:
208
- return False
209
- return True
210
-
211
- if abs(x1 - x2) < eps:
212
- x = x1
213
- if not (left + eps < x < right - eps):
214
- return False
215
- seg_top = min(y1, y2)
216
- seg_bottom = max(y1, y2)
217
- overlap_top = max(seg_top, top)
218
- overlap_bottom = min(seg_bottom, bottom)
219
- if overlap_bottom - overlap_top <= eps:
220
- return False
221
- if abs(overlap_top - y1) < eps or abs(overlap_bottom - y2) < eps:
222
- return False
223
- if abs(overlap_top - y2) < eps or abs(overlap_bottom - y1) < eps:
224
- return False
225
- return True
226
-
227
- return False
228
-
229
- root = ET.fromstring(Path(sys.argv[1]).read_text(encoding='utf-8'))
230
- obstacles = [bounds for element in root.iter() if (bounds := shape_bounds(element)) is not None]
231
-
232
- collisions = 0
233
- for element in root.iter():
234
- tag = strip(element.tag)
235
- if tag == 'line' and element.get('marker-end'):
236
- points = [
237
- (to_float(element.get('x1')), to_float(element.get('y1'))),
238
- (to_float(element.get('x2')), to_float(element.get('y2'))),
239
- ]
240
- elif tag == 'path' and element.get('marker-end'):
241
- points = parse_path_points(element.get('d'))
242
- else:
243
- continue
244
-
245
- for p1, p2 in zip(points, points[1:]):
246
- if any(segment_hits_bounds(p1, p2, bounds) for bounds in obstacles):
247
- collisions += 1
248
- break
249
-
250
- print(collisions)
251
- PY
252
- )
253
- if [ "$COLLISIONS" -eq 0 ]; then
254
- echo -e "${GREEN}✓ Pass${NC}"
255
- else
256
- echo -e "${RED}✗ Fail${NC} (${COLLISIONS} arrow path collision(s))"
257
- FAILURES=$((FAILURES + 1))
258
- fi
259
-
260
- # Check 6: Closing </svg> tag
261
- echo -n "Checking closing tag... "
262
- if grep -q '</svg>' "$SVG_FILE"; then
263
- echo -e "${GREEN}✓ Pass${NC}"
264
- else
265
- echo -e "${RED}✗ Fail${NC} (missing </svg>)"
266
- FAILURES=$((FAILURES + 1))
267
- fi
268
-
269
- # Check 7: render validation (cairosvg preferred, rsvg-convert fallback)
270
- echo -n "Running render validation... "
271
- RENDER_OK=false
272
- RENDER_TOOL=""
273
- RENDER_ERR=""
274
-
275
- if python3 -c "import cairosvg" 2>/dev/null; then
276
- RENDER_TOOL="cairosvg"
277
- if RENDER_ERR=$(python3 -c "import cairosvg; cairosvg.svg2png(url='${SVG_FILE}', write_to='/tmp/test-output.png')" 2>&1); then
278
- RENDER_OK=true
279
- fi
280
- elif command -v rsvg-convert &> /dev/null; then
281
- RENDER_TOOL="rsvg-convert"
282
- if RENDER_ERR=$(rsvg-convert "$SVG_FILE" -o /tmp/test-output.png 2>&1); then
283
- RENDER_OK=true
284
- fi
285
- fi
286
-
287
- if [ "$RENDER_OK" = true ]; then
288
- echo -e "${GREEN}✓ Pass${NC} (via ${RENDER_TOOL})"
289
- rm -f /tmp/test-output.png
290
- elif [ -n "$RENDER_TOOL" ]; then
291
- echo -e "${RED}✗ Fail${NC} (via ${RENDER_TOOL})"
292
- echo "${RENDER_TOOL} error:"
293
- echo "$RENDER_ERR"
294
- FAILURES=$((FAILURES + 1))
295
- else
296
- echo -e "${YELLOW}⚠ Skipped${NC} (no renderer found — install cairosvg: pip install cairosvg)"
297
- fi
298
-
299
- echo "----------------------------------------"
300
- if [ "$FAILURES" -eq 0 ]; then
301
- echo "Validation complete"
302
- exit 0
303
- fi
304
-
305
- echo -e "${RED}Validation failed (${FAILURES} error(s))${NC}"
306
- exit 1
@@ -1,28 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 700">
2
- <defs>
3
- <marker id="arrowBlue" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
4
- <polygon points="0 0, 10 3.5, 0 7" fill="#2563eb"/>
5
- </marker>
6
- <marker id="arrowPurple" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
7
- <polygon points="0 0, 10 3.5, 0 7" fill="#7c3aed"/>
8
- </marker>
9
- <marker id="arrowGreen" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
10
- <polygon points="0 0, 10 3.5, 0 7" fill="#059669"/>
11
- </marker>
12
- <marker id="arrowOrange" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
13
- <polygon points="0 0, 10 3.5, 0 7" fill="#ea580c"/>
14
- </marker>
15
- </defs>
16
- <style>
17
- text { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; }
18
- .title { font-size: 24px; font-weight: 700; fill: #1e293b; }
19
- .node-label { font-size: 16px; font-weight: 600; fill: #1e293b; }
20
- .sub-label { font-size: 13px; font-weight: 400; fill: #64748b; }
21
- .arrow-label { font-size: 12px; font-weight: 400; fill: #475569; }
22
- </style>
23
- <rect width="960" height="700" fill="#ffffff"/>
24
- <text x="480" y="60" text-anchor="middle" class="title">{{TITLE}}</text>
25
- <!-- NODES -->
26
- <!-- ARROWS -->
27
- <!-- LEGEND -->
28
- </svg>
@@ -1,23 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 700">
2
- <defs>
3
- <marker id="arrowBlue" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
4
- <polygon points="0 0, 10 3.5, 0 7" fill="#2563eb"/>
5
- </marker>
6
- <marker id="arrowGreen" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
7
- <polygon points="0 0, 10 3.5, 0 7" fill="#059669"/>
8
- </marker>
9
- </defs>
10
- <style>
11
- text { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; }
12
- .title { font-size: 24px; font-weight: 700; fill: #1e293b; }
13
- .layer-label { font-size: 16px; font-weight: 600; fill: #475569; }
14
- .node-label { font-size: 16px; font-weight: 600; fill: #1e293b; }
15
- .sub-label { font-size: 13px; font-weight: 400; fill: #64748b; }
16
- .arrow-label { font-size: 12px; font-weight: 400; fill: #475569; }
17
- </style>
18
- <rect width="960" height="700" fill="#ffffff"/>
19
- <text x="480" y="60" text-anchor="middle" class="title">{{TITLE}}</text>
20
- <!-- NODES -->
21
- <!-- ARROWS -->
22
- <!-- LEGEND -->
23
- </svg>
@@ -1,14 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 700">
2
- <style>
3
- text { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; }
4
- .title { font-size: 24px; font-weifill: #1e293b; }
5
- .header { font-size: 14px; font-weight: 600; fill: #1e293b; }
6
- .row-label { font-size: 13px; font-weight: 500; fill: #475569; }
7
- .cell-text { font-size: 13px; font-weight: 400; fill: #1e293b; }
8
- </style>
9
- <rect width="960" height="700" fill="#ffffff"/>
10
- <text x="480" y="60" text-anchor="middle" class="title">{{TITLE}}</text>
11
- <!-- HEADERS -->
12
- <!-- ROWS -->
13
- <!-- CELLS -->
14
- </svg>
@@ -1,28 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 700">
2
- <defs>
3
- <marker id="arrowBlue" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
4
- <polygon points="0 0, 10 3.5, 0 7" fill="#2563eb"/>
5
- </marker>
6
- <marker id="arrowPurple" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
7
- <polygon points="0 0, 10 3.5, 0 7" fill="#7c3aed"/>
8
- </marker>
9
- <marker id="arrowGreen" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
10
- <polygon points="0 0, 10 3.5, 0 7" fill="#059669"/>
11
- </marker>
12
- <marker id="arrowOrange" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
13
- <polygon points="0 0, 10 3.5, 0 7" fill="#ea580c"/>
14
- </marker>
15
- </defs>
16
- <style>
17
- text { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; }
18
- .title { font-size: 24px; font-weight: 700; fill: #1e293b; }
19
- .node-label { font-size: 16px; font-weight: 600; fill: #1e293b; }
20
- .sub-label { font-size: 13px; font-weight: 400; fill: #64748b; }
21
- .arrow-label { font-size: 12px; font-weight: 400; fill: #475569; }
22
- </style>
23
- <rect width="960" height="700" fill="#ffffff"/>
24
- <text x="480" y="60" text-anchor="middle" class="title">{{TITLE}}</text>
25
- <!-- NODES -->
26
- <!-- ARROWS -->
27
- <!-- LEGEND -->
28
- </svg>
@@ -1,21 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 700">
2
- <defs>
3
- <marker id="arrowBlue" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
4
- <polygon points="0 0, 10 3.5, 0 7" fill="#2563eb"/>
5
- </marker>
6
- </defs>
7
- <style>
8
- text { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; }
9
- .title { font-size: 24px; font-weight: 700; fill: #1e293b; }
10
- .entity-name { font-size: 15px; font-weight: 700; fill: #1e293b; }
11
- .attribute { font-size: 12px; font-weight: 400; fill: #475569; }
12
- .primary-key { font-size: 12px; font-weight: 600; fill: #1e293b; text-decoration: underline; }
13
- .relationship { font-size: 12px; font-weight: 500; fill: #64748b; }
14
- .cardinality { font-size: 11px; font-weight: 400; fill: #64748b; }
15
- </style>
16
- <rect width="960" height="700" fill="#ffffff"/>
17
- <text x="480" y="60" text-anchor="middle" class="title">{{TITLE}}</text>
18
- <!-- ENTITIES -->
19
- <!-- RELATIONSHIPS -->
20
- <!-- CARDINALITY -->
21
- </svg>
@@ -1,21 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 700">
2
- <defs>
3
- <marker id="arrowBlue" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
4
- <polygon points="0 0, 10 3.5, 0 7" fill="#2563eb"/>
5
- </marker>
6
- </defs>
7
- <style>
8
- text { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; }
9
- .title { font-size: 24px; font-weight: 700; fill: #1e293b; }
10
- .node-label { font-size: 14px; font-weight: 500; fill: #1e293b; }
11
- .decision-label { font-size: 13px; font-weight: 500; fill: #1e293b; }
12
- .arrow-label { font-size: 11px; font-weight: 400; fill: #475569; }
13
- </style>
14
- <rect width="960" height="700" fill="#ffffff"/>
15
- <text x="480" y="60" text-anchor="middle" class="title">{{TITLE}}</text>
16
- <!-- START -->
17
- <!-- PROCESSES -->
18
- <!-- DECISIONS -->
19
- <!-- ARROWS -->
20
- <!-- END -->
21
- </svg>
@@ -1,20 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 800">
2
- <defs>
3
- <marker id="arrowBlue" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
4
- <polygon points="0 0, 10 3.5, 0 7" fill="#2563eb"/>
5
- </marker>
6
- </defs>
7
- <style>
8
- text { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; }
9
- .title { font-size: 24px; font-weight: 700; fill: #1e293b; }
10
- .participant { font-size: 14px; font-weight: 600; fill: #1e293b; }
11
- .message { font-size: 12px; font-weight: 400; fill: #475569; }
12
- .lifeline { stroke: #cbd5e1; stroke-width: 1.5; stroke-dasharray: 5,3; }
13
- </style>
14
- <rect width="960" height="800" fill="#ffffff"/>
15
- <text x="480" y="60" text-anchor="middle" class="title">{{TITLE}}</text>
16
- <!-- PARTICIPANTS -->
17
- <!-- LIFELINES -->
18
- <!-- MESSAGES -->
19
- <!-- ACTIVATIONS -->
20
- </svg>
@@ -1,20 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 700">
2
- <defs>
3
- <marker id="arrowBlue" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
4
- <polygon points="0 0, 10 3.5, 0 7" fill="#2563eb"/>
5
- </marker>
6
- </defs>
7
- <style>
8
- text { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; }
9
- .title { font-size: 24px; font-weight: 700; fill: #1e293b; }
10
- .state-name { font-size: 14px; font-weight: 600; fill: #1e293b; }
11
- .state-activity { font-size: 11px; font-weight: 400; fill: #64748b; }
12
- . { font-size: 11px; font-weight: 400; fill: #475569; }
13
- </style>
14
- <rect width="960" height="700" fill="#ffffff"/>
15
- <text x="480" y="60" text-anchor="middle" class="title">{{TITLE}}</text>
16
- <!-- INITIAL_STATE -->
17
- <!-- STATES -->
18
- <!-- TRANSITIONS -->
19
- <!-- FINAL_STATE -->
20
- </svg>
@@ -1,19 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 400">
2
- <defs>
3
- <marker id="arrowBlue" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
4
- <polygon points="0 0, 10 3.5, 0 7" fill="#2563eb"/>
5
- </marker>
6
- </defs>
7
- <style>
8
- text { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; }
9
- .title { font-size: 24px; font-weight: 700; fill: #1e293b; }
10
- .period-label { font-size: 12px; font-weight: 500; fill: #475569; }
11
- .task-label { font-size: 13px; font-weight: 500; fill: #1e293b; }
12
- .milestone-label { font-size: 12px; font-weight: 600; fill: #1e293b; }
13
- </style>
14
- <rect width="1200" height="400" fill="#ffffff"/>
15
- <text x="600" y="50" text-anchor="middle" class="title">{{TITLE}}</text>
16
- <!-- TIME_AXIS -->
17
- <!-- TASKS -->
18
- <!-- MILESTONES -->
19
- </svg>
@@ -1,21 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 700">
2
- <defs>
3
- <marker id="arrowBlue" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
4
- <polygon points="0 0, 10 3.5, 0 7" fill="#2563eb"/>
5
- </marker>
6
- </defs>
7
- <style>
8
- text { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; }
9
- .title { font-size: 24px; font-weight: 700; fill: #1e293b; }
10
- .actor-label { font-size: 13px; font-weight: 600; fill: #1e293b; }
11
- .usecaseel { font-size: 13px; font-weight: 500; fill: #1e293b; }
12
- .system-label { font-size: 16px; font-weight: 600; fill: #475569; }
13
- .relationship { font-size: 11px; font-weight: 400; fill: #64748b; font-style: italic; }
14
- </style>
15
- <rect width="960" height="700" fill="#ffffff"/>
16
- <text x="480" y="60" text-anchor="middle" class="title">{{TITLE}}</text>
17
- <!-- SYSTEM_BOUNDARY -->
18
- <!-- ACTORS -->
19
- <!-- USECASES -->
20
- <!-- RELATIONSHIPS -->
21
- </svg>