diff --git a/README.md b/README.md index 6830b39..7990d98 100644 --- a/README.md +++ b/README.md @@ -119,6 +119,12 @@ g := dot.NewGraph(dot.Directed) fmt.Println(dot.MermaidGraph(g, dot.MermaidTopToBottom)) ``` +### subgraphs in mermaid + +```mermaid +flowchart LR;n8-->n3;subgraph one;n2("a1");n3("a2");n2-->n3;end;subgraph three;n8("c1");n9("c2");n8-->n9;end;subgraph two;n5("b1");n6("b2");n5-->n6;end; +``` + ## extensions See also package `dot/dotx` for types that can help in constructing complex graphs. diff --git a/mermaid.go b/mermaid.go index ba694f4..fc5e163 100644 --- a/mermaid.go +++ b/mermaid.go @@ -60,6 +60,17 @@ func diagram(g *Graph, diagramType string, orientation int) string { sb.WriteString("TD") } writeEnd(sb) + diagramGraph(g, sb) + for _, id := range g.sortedSubgraphsKeys() { + each := g.subgraphs[id] + fmt.Fprintf(sb, "subgraph %s;\n", id) + diagramGraph(each, sb) + fmt.Fprintln(sb, "end;") + } + return sb.String() +} + +func diagramGraph(g *Graph, sb *strings.Builder) { // graph nodes for _, key := range g.sortedNodesKeys() { nodeShape := MermaidShapeRound @@ -92,7 +103,6 @@ func diagram(g *Graph, diagramType string, orientation int) string { } } } - return sb.String() } func writeEnd(sb *strings.Builder) { diff --git a/mermaid_test.go b/mermaid_test.go index e965836..7e4f1a0 100644 --- a/mermaid_test.go +++ b/mermaid_test.go @@ -79,3 +79,21 @@ func TestUndirectedMermaid(t *testing.T) { t.Errorf("got [%v]:%T want [%v]:%T", got, got, want, want) } } + +// example from https://mermaid.js.org/syntax/flowchart.html +// note that c1 and a2 are nodes created in their subgraphs to make the diagram match with the example. +func TestMermaidSubgraph(t *testing.T) { + di := NewGraph(Directed) + sub1 := di.Subgraph("one") + sub1.Node("a1").Edge(sub1.Node("a2")) + sub2 := di.Subgraph("two") + sub2.Node("b1").Edge(sub2.Node("b2")) + sub3 := di.Subgraph("three") + sub3.Node("c1").Edge(sub3.Node("c2")) + + sub3.Node("c1").Edge(sub1.Node("a2")) + mf := MermaidFlowchart(di, MermaidLeftToRight) + if got, want := flatten(mf), `flowchart LR;n8-->n3;subgraph one;n2("a1");n3("a2");n2-->n3;end;subgraph three;n8("c1");n9("c2");n8-->n9;end;subgraph two;n5("b1");n6("b2");n5-->n6;end;`; got != want { + t.Errorf("got [%[1]v:%[1]T] want [%[2]v:%[2]T]", got, want) + } +}