DEV Community

nchika
nchika

Posted on

simple mermaid builder in golang: support ER/sequence diagram, pie chart

Markdown with mermaid

I previously introduced the nao1215/markdown package as a markdown builder for the Go language (previously it was go-spectest/markdown, but the Owner has changed). What syntax do you want when writing markdown? I thought it was important to support mermaid. When we write design documents, we should be able to write not only text but also sequence diagrams and ER diagrams.

I decided to support some mermaid syntax in the markdown package. This article introduces that.

Mermaid sequence diagram syntax

Sample code

package main

import (
    "os"

    "github.com/nao1215/markdown"
    "github.com/nao1215/mermaid/sequence"
)

//go:generate go run main.go

func main() {
    diagram := sequence.NewDiagram(io.Discard).
        Participant("Sophia").
        Participant("David").
        Participant("Subaru").
        LF().
        SyncRequest("Sophia", "David", "Please wake up Subaru").
        SyncResponse("David", "Sophia", "OK").
        LF().
        LoopStart("until Subaru wake up").
        SyncRequest("David", "Subaru", "Wake up!").
        SyncResponse("Subaru", "David", "zzz").
        SyncRequest("David", "Subaru", "Hey!!!").
        BreakStart("if Subaru wake up").
        SyncResponse("Subaru", "David", "......").
        BreakEnd().
        LoopEnd().
        LF().
        SyncResponse("David", "Sophia", "wake up, wake up").
        String()

    markdown.NewMarkdown(os.Stdout).
        H2("Sequence Diagram").
        CodeBlocks(markdown.SyntaxHighlightMermaid, diagram).
        Build()
}
Enter fullscreen mode Exit fullscreen mode

Generated markdown with sequence diagram

## Sequence Diagram


```mermaid
sequenceDiagram
    participant Sophia
    participant David
    participant Subaru

    Sophia->>David: Please wake up Subaru
    David-->>Sophia: OK

    loop until Subaru wake up
    David->>Subaru: Wake up!
    Subaru-->>David: zzz
    David->>Subaru: Hey!!!
    break if Subaru wake up
    Subaru-->>David: ......
    end
    end

    David-->>Sophia: wake up, wake up
```

Sequence diagram preview

Mermaid entity relationsip diagram syntax

Sample code

package main

import (
    "os"

    "github.com/nao1215/markdown"
    "github.com/nao1215/markdown/mermaid/er"
)

//go:generate go run main.go

func main() {
    f, err := os.Create("generated.md")
    if err != nil {
        panic(err)
    }

    teachers := er.NewEntity(
        "teachers",
        []*er.Attribute{
            {
                Type:         "int",
                Name:         "id",
                IsPrimaryKey: true,
                IsForeignKey: false,
                IsUniqueKey:  true,
                Comment:      "Teacher ID",
            },
            {
                Type:         "string",
                Name:         "name",
                IsPrimaryKey: false,
                IsForeignKey: false,
                IsUniqueKey:  false,
                Comment:      "Teacher Name",
            },
        },
    )
    students := er.NewEntity(
        "students",
        []*er.Attribute{
            {
                Type:         "int",
                Name:         "id",
                IsPrimaryKey: true,
                IsForeignKey: false,
                IsUniqueKey:  true,
                Comment:      "Student ID",
            },
            {
                Type:         "string",
                Name:         "name",
                IsPrimaryKey: false,
                IsForeignKey: false,
                IsUniqueKey:  false,
                Comment:      "Student Name",
            },
            {
                Type:         "int",
                Name:         "teacher_id",
                IsPrimaryKey: false,
                IsForeignKey: true,
                IsUniqueKey:  true,
                Comment:      "Teacher ID",
            },
        },
    )
    schools := er.NewEntity(
        "schools",
        []*er.Attribute{
            {
                Type:         "int",
                Name:         "id",
                IsPrimaryKey: true,
                IsForeignKey: false,
                IsUniqueKey:  true,
                Comment:      "School ID",
            },
            {
                Type:         "string",
                Name:         "name",
                IsPrimaryKey: false,
                IsForeignKey: false,
                IsUniqueKey:  false,
                Comment:      "School Name",
            },
            {
                Type:         "int",
                Name:         "teacher_id",
                IsPrimaryKey: false,
                IsForeignKey: true,
                IsUniqueKey:  true,
                Comment:      "Teacher ID",
            },
        },
    )

    erString := er.NewDiagram(f).
        Relationship(
            teachers,
            students,
            er.ExactlyOneRelationship, // "||"
            er.ZeroToMoreRelationship, // "}o"
            er.Identifying,            // "--"
            "Teacher has many students",
        ).
        Relationship(
            teachers,
            schools,
            er.OneToMoreRelationship,  // "|}"
            er.ExactlyOneRelationship, // "||"
            er.NonIdentifying,         // ".."
            "School has many teachers",
        ).
        String()

    err = markdown.NewMarkdown(f).
        H2("Entity Relationship Diagram").
        CodeBlocks(markdown.SyntaxHighlightMermaid, erString).
        Build()

    if err != nil {
        panic(err)
    }
}
Enter fullscreen mode Exit fullscreen mode

Generated markdown with entity relationship diagram

## Entity Relationship Diagram


```mermaid
erDiagram
    teachers ||--o{ students : "Teacher has many students"
    teachers }|..|| schools : "School has many teachers"
    schools {
        int id PK,UK "School ID"
        string name  "School Name"
        int teacher_id FK,UK "Teacher ID"
    }
    students {
        int id PK,UK "Student ID"
        string name  "Student Name"
        int teacher_id FK,UK "Teacher ID"
    }
    teachers {
        int id PK,UK "Teacher ID"
        string name  "Teacher Name"
    }
```

ER_Diagram_preview

Mermaid pie chart syntax

Sample code

package main

import (
    "io"
    "os"

    "github.com/nao1215/markdown"
    "github.com/nao1215/markdown/mermaid/piechart"
)

//go:generate go run main.go

func main() {
    f, err := os.Create("generated.md")
    if err != nil {
        panic(err)
    }

    chart := piechart.NewPieChart(
        io.Discard,
        piechart.WithTitle("mermaid pie chart builder"),
        piechart.WithShowData(true),
    ).
        LabelAndIntValue("A", 10).
        LabelAndFloatValue("B", 20.1).
        LabelAndIntValue("C", 30).
        String()

    err = markdown.NewMarkdown(f).
        H2("Pie Chart").
        CodeBlocks(markdown.SyntaxHighlightMermaid, chart).
        Build()

    if err != nil {
        panic(err)
    }
}
Enter fullscreen mode Exit fullscreen mode

Generated markdown with pie chart diagram

## Pie Chart


```mermaid
%%{init: {"pie": {"textPosition": 0.75}, "themeVariables": {"pieOuterStrokeWidth": "5px"}} }%%
pie showData
    title mermaid pie chart builder
    "A" : 10
    "B" : 20.100000
    "C" : 30
```


Pie_Chart_Preview

Next work

This new markdown package, which incorporates Mermaid support, enables a more diverse range of expressions when writing design documents, including sequence diagrams, ER diagrams, and more, alongside traditional text.

In the future, I will continue to develop to support more Mermaid syntax. If you're interested, please try using the nao1215/markdown package.

Thank you for reading this article.

Top comments (7)

Collapse
 
ccoveille profile image
Christophe Colombier

Great, I love mermaid graphs

How does your project differs from github.com/emicklei/dot ?

Collapse
 
nchika profile image
nchika

Supported mermaid syntaxes are different.

emicklei/dot supports Graph and Flowchart. nao1215/markdown supports ER diagrams, sequence diagrams and pie charts.

Collapse
 
ccoveille profile image
Christophe Colombier

Do you plan supporting graph and flowchart ? That's the ones I use the most

Thread Thread
 
nchika profile image
nchika

I intend to expand the supported mermaid syntax when requests are added to GitHub Issues.

I don't think I will voluntarily increase the support range much, because the current functionality of the markdown package meets my own use cases.

Thread Thread
 
nchika profile image
nchika • Edited
Thread Thread
 
ccoveille profile image
Christophe Colombier

Wow, thanks

Collapse
 
cmelgarejo profile image
Christian Melgarejo

Wake up!
zzz
....
A R I S E