Skip to content

Commit 58d1448

Browse files
committed
fix(ui): Critical Mermaid parser bugs - class/state diagram contamination
**Problems:** 1. Mindmap root showing 'root((Project))' instead of 'Project' 2. Class diagram contaminated with state diagram nodes (Idle, Loading) 3. Parser treating '-->' (state) as '--' (class association) **Root Causes:** 1. **Mindmap Parser Bug:** - Format: 'root((Project))' = node 'root' with label 'Project' in circle shape - Old code tried to strip parentheses from START of string - But 'root((Project))' starts with 'r' not '(' - Result: Label never extracted 2. **Class Diagram Parser Contamination:** - State diagrams use '-->' for transitions - Class diagrams use '--' for associations - Parser checked contains('--') which MATCHES '-->'! - Result: 'Idle --> Loading' parsed as class relationship - Created ghost nodes in class diagram **Solutions:** 1. **Mindmap Parser:** - Find first '(' and last ')' - Extract text between them - Strip remaining parentheses - Result: 'root((Project))' → 'Project' 2. **Class Diagram Parser:** - Check for '-->' explicitly - Only parse '--' if NOT part of '-->' - Result: State transitions no longer contaminate class diagrams **Files Modified:** - Sources/UserInterface/Chat/Mermaid/MermaidParser.swift (lines ~1000, ~630) **Testing:** ✅ Build: PASS ⏳ Mindmap: Should now show 'Project' not 'root((Project))' ⏳ Class Diagram: Should ONLY show Animal/Dog, NOT Idle/Loading ⏳ State Diagram: Needs investigation why not rendering **Impact:** This fixes cross-diagram contamination - each diagram type now parses correctly without picking up syntax from other types.
1 parent 0b0af2f commit 58d1448

1 file changed

Lines changed: 14 additions & 6 deletions

File tree

Sources/UserInterface/Chat/Mermaid/MermaidParser.swift

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -626,8 +626,11 @@ struct MermaidParser {
626626
}
627627
}
628628
// Parse relationship
629+
// Check for specific arrows first to avoid false matches
630+
// (e.g., "-->" in state diagrams vs "--" in class diagrams)
629631
else if line.contains("<|--") || line.contains("*--") || line.contains("o--") ||
630-
line.contains("--") || line.contains("..>") || line.contains("..|>") {
632+
line.contains("..>") || line.contains("..|>") ||
633+
(line.contains("--") && !line.contains("-->")) {
631634
if let relationship = parseClassRelationship(line, classMap: &classMap, classes: &classes) {
632635
relationships.append(relationship)
633636
}
@@ -993,13 +996,18 @@ struct MermaidParser {
993996
return .unsupported(code)
994997
}
995998

996-
// Parse root node (remove parentheses if present)
997-
// Handle formats: "root", "root(text)", "root((text))"
999+
// Parse root node (remove shape indicators)
1000+
// Mindmap format: "root((text))" or "id(text)" or just "text"
9981001
var rootLabel = rootLine.trimmingCharacters(in: .whitespaces)
9991002

1000-
// Remove surrounding parentheses (single or double)
1001-
while rootLabel.hasPrefix("(") && rootLabel.hasSuffix(")") {
1002-
rootLabel = String(rootLabel.dropFirst().dropLast()).trimmingCharacters(in: .whitespaces)
1003+
// Extract text from parentheses: "root((Project))" -> "Project"
1004+
if let openParen = rootLabel.firstIndex(of: "("),
1005+
let closeParen = rootLabel.lastIndex(of: ")") {
1006+
let labelStart = rootLabel.index(after: openParen)
1007+
let labelEnd = closeParen
1008+
rootLabel = String(rootLabel[labelStart..<labelEnd])
1009+
.trimmingCharacters(in: CharacterSet(charactersIn: "()"))
1010+
.trimmingCharacters(in: .whitespaces)
10031011
}
10041012

10051013
// Parse hierarchy - build list of (label, level) pairs

0 commit comments

Comments
 (0)