using System.Text; namespace SQLLinter.Infrastructure.Diagram; public static class MermaidRenderer { public static string ToMermaidContent(BpmnDiagram diagram) { var sb = new StringBuilder(); sb.AppendLine("flowchart TB"); // ----------------------------------------- // Рендер каждого процесса как subgraph // ----------------------------------------- foreach (var proc in diagram.Processes) { var procId = SanitizeId(proc.Id); sb.AppendLine($" subgraph {procId} [\"{Escape(proc.Name)}\"]"); sb.AppendLine(" direction TB"); foreach (var node in proc.Nodes) { var nid = SanitizeId(node.Id); var label = Escape(node.Label); label = node.Type switch { BpmnNodeType.Start => $@"((""{label}""))", BpmnNodeType.Task => $@"[""{label}""]", BpmnNodeType.Subprocess => $@"[[""{label}""]]", BpmnNodeType.Gateway => $@"{{""{label}""}}", BpmnNodeType.Hexagon => $@"{{{{""{label}""}}}}", BpmnNodeType.End => $@"((""{label}""))", _ => $@">""{label}""]" }; sb.AppendLine($" {nid}{label}"); } // Edges внутри процесса foreach (var e in proc.Edges) { var from = SanitizeId(e.From); var to = SanitizeId(e.To); var arrow = e.ArrowType switch { BpmnArrowType.Dashed => "-.->", _ => "-->", }; var lbl = string.IsNullOrWhiteSpace(e.Label) ? string.Empty : $" |{Escape(e.Label)}|"; sb.AppendLine($" {from} {arrow}{lbl} {to}"); } sb.AppendLine(" end"); sb.AppendLine(); } // ----------------------------------------- // Рендер глобальных связей между процессами // ----------------------------------------- foreach (var e in diagram.GlobalEdges) { var from = SanitizeId(e.From); var to = SanitizeId(e.To); var arrow = e.ArrowType switch { BpmnArrowType.Dashed => "-.->", _ => "-->", }; var lbl = string.IsNullOrWhiteSpace(e.Label) ? string.Empty : $" |{Escape(e.Label)}|"; sb.AppendLine($" {from} {arrow}{lbl} {to}"); } return sb.ToString(); } private static string Escape(string s) { if (s == null) return string.Empty; return s.Replace("\"", "\\\"").Replace("\n", " ").Replace("\r", " "); } private static string SanitizeId(string s) { if (string.IsNullOrEmpty(s)) return "id"; var sb = new StringBuilder(); foreach (var ch in s) { if (char.IsLetterOrDigit(ch)) sb.Append(ch); else sb.Append('_'); } return sb.ToString(); } }