Добавлены mermaid диаграммы

This commit is contained in:
FrigaT
2025-12-25 12:59:20 +03:00
parent 9abf8daf90
commit 0dae811dd0
15 changed files with 1063 additions and 228 deletions

View File

@@ -0,0 +1,147 @@
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");
// main: print Start, then tasks/gateways, then End
var mainStart = diagram.Main.Nodes.Where(n => n.Type == BpmnNodeType.Start).ToList();
var mainTasks = diagram.Main.Nodes.Where(n => n.Type == BpmnNodeType.Task || n.Type == BpmnNodeType.Gateway).ToList();
var mainEnd = diagram.Main.Nodes.Where(n => n.Type == BpmnNodeType.End).ToList();
foreach (var node in mainStart)
{
var nid = SanitizeId(node.Id);
var label = Escape(node.Label);
sb.AppendLine($" {nid}((\"{label}\"))");
}
foreach (var node in mainTasks)
{
var nid = SanitizeId(node.Id);
var label = Escape(node.Label);
if (node.Type == BpmnNodeType.Gateway)
sb.AppendLine($" {nid}{{\"{label}\"}}");
else
sb.AppendLine($" {nid}[\"{label}\"]");
}
foreach (var node in mainEnd)
{
var nid = SanitizeId(node.Id);
var label = Escape(node.Label);
sb.AppendLine($" {nid}((\"{label}\"))");
}
sb.AppendLine();
// subprocesses as subgraphs: pool label, start, tasks/gateways, end
foreach (var proc in diagram.Subprocesses)
{
var procId = SanitizeId(proc.Id);
sb.AppendLine($" subgraph {procId} [\"{Escape(proc.Name)}\"]");
var startNodes = proc.Nodes.Where(n => n.Type == BpmnNodeType.Start).ToList();
var taskNodes = proc.Nodes.Where(n => n.Type == BpmnNodeType.Task || n.Type == BpmnNodeType.Gateway).ToList();
var endNodes = proc.Nodes.Where(n => n.Type == BpmnNodeType.End).ToList();
var poolNodes = proc.Nodes.Where(n => n.Type == BpmnNodeType.Subprocess).ToList();
// pool label nodes (usually first)
foreach (var node in poolNodes)
{
var nid = SanitizeId(node.Id);
var label = Escape(node.Label);
sb.AppendLine($" {nid}[\"{label}\"]");
}
foreach (var node in startNodes)
{
var nid = SanitizeId(node.Id);
var label = Escape(node.Label);
sb.AppendLine($" {nid}((\"{label}\"))");
}
foreach (var node in taskNodes)
{
var nid = SanitizeId(node.Id);
var label = Escape(node.Label);
if (node.Type == BpmnNodeType.Gateway)
sb.AppendLine($" {nid}{{\"{label}\"}}");
else
sb.AppendLine($" {nid}[\"{label}\"]");
}
foreach (var node in endNodes)
{
var nid = SanitizeId(node.Id);
var label = Escape(node.Label);
sb.AppendLine($" {nid}((\"{label}\"))");
}
// edges inside subprocess
foreach (var e in proc.Edges)
{
var from = SanitizeId(e.From);
var to = SanitizeId(e.To);
var arrow = e.Dashed ? "-.->" : "-->";
var lbl = string.IsNullOrWhiteSpace(e.Label) ? string.Empty : $" |{Escape(e.Label)}|";
sb.AppendLine($" {from} {arrow} {to}{lbl}");
}
sb.AppendLine(" end");
sb.AppendLine();
}
// main edges
foreach (var e in diagram.Main.Edges)
{
var from = SanitizeId(e.From);
var to = SanitizeId(e.To);
var arrow = e.Dashed ? "-.->" : "-->";
var lbl = string.IsNullOrWhiteSpace(e.Label) ? string.Empty : $" |{Escape(e.Label)}|";
sb.AppendLine($" {from} {arrow} {to}{lbl}");
}
return sb.ToString();
}
public static string RenderMarkdown(BpmnDiagram diagram)
{
var content = ToMermaidContent(diagram);
var sb = new StringBuilder();
sb.AppendLine("```mermaid");
sb.Append(content);
sb.AppendLine("```");
return sb.ToString();
}
public static string RenderHtml(BpmnDiagram diagram)
{
var content = ToMermaidContent(diagram);
var sb = new StringBuilder();
// Put raw mermaid text inside .mermaid container so mermaid.js can render it
sb.AppendLine("<div class=\"mermaid\">\n" + content + "\n</div>");
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();
}
}