| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- // Package renderer provides rendering functionality for sequence diagrams
- package renderer
- import (
- "fmt"
- "strings"
- "mermaid-go/pkg/ast"
- )
- // SequenceRenderer renders sequence diagrams back to mermaid syntax
- type SequenceRenderer struct{}
- // NewSequenceRenderer creates a new sequence renderer
- func NewSequenceRenderer() *SequenceRenderer {
- return &SequenceRenderer{}
- }
- // Render renders a sequence diagram to mermaid syntax
- func (r *SequenceRenderer) Render(diagram *ast.SequenceDiagram) (string, error) {
- var builder strings.Builder
- // Start with diagram declaration
- builder.WriteString("sequenceDiagram\n")
- // Add title if present
- if diagram.Title != nil {
- builder.WriteString(fmt.Sprintf(" title %s\n", *diagram.Title))
- }
- // Render participants
- for _, participant := range diagram.Participants {
- builder.WriteString(" ")
- builder.WriteString(string(participant.Type))
- builder.WriteString(" ")
- builder.WriteString(participant.ID)
- if participant.Name != participant.ID {
- builder.WriteString(" as ")
- if strings.Contains(participant.Name, " ") {
- builder.WriteString(fmt.Sprintf("\"%s\"", participant.Name))
- } else {
- builder.WriteString(participant.Name)
- }
- }
- builder.WriteString("\n")
- }
- // Render boxes
- for _, box := range diagram.Boxes {
- builder.WriteString(" box ")
- if strings.Contains(box.Name, " ") {
- builder.WriteString(fmt.Sprintf("\"%s\"", box.Name))
- } else {
- builder.WriteString(box.Name)
- }
- if box.Color != nil {
- builder.WriteString(" ")
- builder.WriteString(*box.Color)
- }
- for _, participant := range box.Participants {
- builder.WriteString(" ")
- builder.WriteString(participant)
- }
- builder.WriteString("\n end\n")
- }
- // Render activations
- for _, activation := range diagram.Activations {
- builder.WriteString(" ")
- builder.WriteString(string(activation.Type))
- builder.WriteString(" ")
- builder.WriteString(activation.Actor)
- builder.WriteString("\n")
- }
- // Render messages
- for _, message := range diagram.Messages {
- builder.WriteString(" ")
- builder.WriteString(message.From)
- builder.WriteString(" ")
- builder.WriteString(string(message.Type))
- builder.WriteString(" ")
- builder.WriteString(message.To)
- if message.Message != "" {
- builder.WriteString(" : ")
- builder.WriteString(message.Message)
- }
- builder.WriteString("\n")
- }
- // Render notes
- for _, note := range diagram.Notes {
- builder.WriteString(" Note ")
- builder.WriteString(string(note.Placement))
- builder.WriteString(" ")
- builder.WriteString(note.Actor)
- builder.WriteString(" : ")
- builder.WriteString(note.Message)
- builder.WriteString("\n")
- }
- // Render loops
- for _, loop := range diagram.Loops {
- builder.WriteString(" loop ")
- builder.WriteString(loop.Label)
- builder.WriteString("\n")
- for _, message := range loop.Messages {
- builder.WriteString(" ")
- builder.WriteString(message.From)
- builder.WriteString(" ")
- builder.WriteString(string(message.Type))
- builder.WriteString(" ")
- builder.WriteString(message.To)
- if message.Message != "" {
- builder.WriteString(" : ")
- builder.WriteString(message.Message)
- }
- builder.WriteString("\n")
- }
- builder.WriteString(" end\n")
- }
- // Render alts
- for _, alt := range diagram.Alts {
- builder.WriteString(" alt ")
- builder.WriteString(alt.Label)
- builder.WriteString("\n")
- for _, message := range alt.IfMessages {
- builder.WriteString(" ")
- builder.WriteString(message.From)
- builder.WriteString(" ")
- builder.WriteString(string(message.Type))
- builder.WriteString(" ")
- builder.WriteString(message.To)
- if message.Message != "" {
- builder.WriteString(" : ")
- builder.WriteString(message.Message)
- }
- builder.WriteString("\n")
- }
- if len(alt.ElseMessages) > 0 {
- builder.WriteString(" else\n")
- for _, message := range alt.ElseMessages {
- builder.WriteString(" ")
- builder.WriteString(message.From)
- builder.WriteString(" ")
- builder.WriteString(string(message.Type))
- builder.WriteString(" ")
- builder.WriteString(message.To)
- if message.Message != "" {
- builder.WriteString(" : ")
- builder.WriteString(message.Message)
- }
- builder.WriteString("\n")
- }
- }
- builder.WriteString(" end\n")
- }
- // Render opts
- for _, opt := range diagram.Opts {
- builder.WriteString(" opt ")
- builder.WriteString(opt.Label)
- builder.WriteString("\n")
- for _, message := range opt.Messages {
- builder.WriteString(" ")
- builder.WriteString(message.From)
- builder.WriteString(" ")
- builder.WriteString(string(message.Type))
- builder.WriteString(" ")
- builder.WriteString(message.To)
- if message.Message != "" {
- builder.WriteString(" : ")
- builder.WriteString(message.Message)
- }
- builder.WriteString("\n")
- }
- builder.WriteString(" end\n")
- }
- // Render pars
- for _, par := range diagram.Pars {
- builder.WriteString(" par")
- for i, section := range par.Sections {
- if i == 0 {
- // First section starts with par
- builder.WriteString("\n")
- } else {
- // Subsequent sections start with and
- builder.WriteString(" and")
- if section.Label != nil {
- builder.WriteString(" ")
- builder.WriteString(*section.Label)
- }
- builder.WriteString("\n")
- }
- for _, message := range section.Messages {
- builder.WriteString(" ")
- builder.WriteString(message.From)
- builder.WriteString(" ")
- builder.WriteString(string(message.Type))
- builder.WriteString(" ")
- builder.WriteString(message.To)
- if message.Message != "" {
- builder.WriteString(" : ")
- builder.WriteString(message.Message)
- }
- builder.WriteString("\n")
- }
- }
- builder.WriteString(" end\n")
- }
- // Render rects
- for _, rect := range diagram.Rects {
- builder.WriteString(" rect")
- if rect.Color != nil {
- builder.WriteString(" ")
- builder.WriteString(*rect.Color)
- }
- builder.WriteString("\n")
- for _, message := range rect.Messages {
- builder.WriteString(" ")
- builder.WriteString(message.From)
- builder.WriteString(" ")
- builder.WriteString(string(message.Type))
- builder.WriteString(" ")
- builder.WriteString(message.To)
- if message.Message != "" {
- builder.WriteString(" : ")
- builder.WriteString(message.Message)
- }
- builder.WriteString("\n")
- }
- builder.WriteString(" end\n")
- }
- // Render criticals
- for _, critical := range diagram.Criticals {
- builder.WriteString(" critical")
- if critical.Label != "" {
- builder.WriteString(" ")
- builder.WriteString(critical.Label)
- }
- builder.WriteString("\n")
- // Render critical messages
- for _, message := range critical.Messages {
- builder.WriteString(" ")
- builder.WriteString(message.From)
- builder.WriteString(" ")
- builder.WriteString(string(message.Type))
- builder.WriteString(" ")
- builder.WriteString(message.To)
- if message.Message != "" {
- builder.WriteString(" : ")
- builder.WriteString(message.Message)
- }
- builder.WriteString("\n")
- }
- // Render options
- for _, option := range critical.Options {
- builder.WriteString(" option")
- if option.Label != "" {
- builder.WriteString(" ")
- builder.WriteString(option.Label)
- }
- builder.WriteString("\n")
- for _, message := range option.Messages {
- builder.WriteString(" ")
- builder.WriteString(message.From)
- builder.WriteString(" ")
- builder.WriteString(string(message.Type))
- builder.WriteString(" ")
- builder.WriteString(message.To)
- if message.Message != "" {
- builder.WriteString(" : ")
- builder.WriteString(message.Message)
- }
- builder.WriteString("\n")
- }
- }
- builder.WriteString(" end\n")
- }
- // Render breaks
- for _, breakBlock := range diagram.Breaks {
- builder.WriteString(" break")
- if breakBlock.Label != "" {
- builder.WriteString(" ")
- builder.WriteString(breakBlock.Label)
- }
- builder.WriteString("\n")
- for _, message := range breakBlock.Messages {
- builder.WriteString(" ")
- builder.WriteString(message.From)
- builder.WriteString(" ")
- builder.WriteString(string(message.Type))
- builder.WriteString(" ")
- builder.WriteString(message.To)
- if message.Message != "" {
- builder.WriteString(" : ")
- builder.WriteString(message.Message)
- }
- builder.WriteString("\n")
- }
- builder.WriteString(" end\n")
- }
- return builder.String(), nil
- }
|