| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- // Package renderer provides rendering functionality for state diagrams
- package renderer
- import (
- "fmt"
- "strings"
- "mermaid-go/pkg/ast"
- )
- // StateRenderer renders state diagrams back to mermaid syntax
- type StateRenderer struct{}
- // NewStateRenderer creates a new state renderer
- func NewStateRenderer() *StateRenderer {
- return &StateRenderer{}
- }
- // Render renders a state diagram to mermaid syntax
- func (r *StateRenderer) Render(diagram *ast.StateDiagram) (string, error) {
- var builder strings.Builder
- // Start with diagram declaration
- builder.WriteString("stateDiagram-v2\n")
- // Add title if present
- if diagram.Title != nil {
- builder.WriteString(fmt.Sprintf(" title %s\n", *diagram.Title))
- }
- // Add direction if present
- if diagram.Direction != "" {
- builder.WriteString(fmt.Sprintf(" direction %s\n", diagram.Direction))
- }
- // Render states
- for _, state := range diagram.States {
- builder.WriteString(" state ")
- builder.WriteString(state.ID)
- // Add alias if different from ID
- if state.Label != state.ID {
- builder.WriteString(" as ")
- if strings.Contains(state.Label, " ") {
- builder.WriteString(fmt.Sprintf("\"%s\"", state.Label))
- } else {
- builder.WriteString(state.Label)
- }
- }
- // Add description or special type
- if state.Description != nil {
- builder.WriteString(" : ")
- builder.WriteString(*state.Description)
- } else {
- switch state.Type {
- case ast.StateTypeFork:
- builder.WriteString(" : <<fork>>")
- case ast.StateTypeJoin:
- builder.WriteString(" : <<join>>")
- case ast.StateTypeChoice:
- builder.WriteString(" : <<choice>>")
- case ast.StateTypeHistory:
- builder.WriteString(" : <<history>>")
- case ast.StateTypeDeepHistory:
- builder.WriteString(" : <<deepHistory>>")
- }
- }
- builder.WriteString("\n")
- // Render composite state body if it has sub-states
- if len(state.SubStates) > 0 {
- builder.WriteString(" state ")
- builder.WriteString(state.ID)
- builder.WriteString(" {\n")
- for _, subState := range state.SubStates {
- builder.WriteString(" state ")
- builder.WriteString(subState.ID)
- if subState.Label != subState.ID {
- builder.WriteString(" as ")
- builder.WriteString(subState.Label)
- }
- if subState.Description != nil {
- builder.WriteString(" : ")
- builder.WriteString(*subState.Description)
- }
- builder.WriteString("\n")
- }
- builder.WriteString(" }\n")
- }
- // Render note if present
- if state.Note != nil {
- builder.WriteString(" note ")
- builder.WriteString(string(state.Note.Position))
- builder.WriteString(" ")
- builder.WriteString(state.ID)
- builder.WriteString(" : ")
- builder.WriteString(state.Note.Text)
- builder.WriteString("\n")
- }
- // Render state actions
- if state.EntryAction != nil {
- builder.WriteString(" ")
- builder.WriteString(state.ID)
- builder.WriteString(" : entry ")
- builder.WriteString(*state.EntryAction)
- builder.WriteString("\n")
- }
- if state.ExitAction != nil {
- builder.WriteString(" ")
- builder.WriteString(state.ID)
- builder.WriteString(" : exit ")
- builder.WriteString(*state.ExitAction)
- builder.WriteString("\n")
- }
- if state.DoAction != nil {
- builder.WriteString(" ")
- builder.WriteString(state.ID)
- builder.WriteString(" : do ")
- builder.WriteString(*state.DoAction)
- builder.WriteString("\n")
- }
- }
- // Render transitions
- for _, transition := range diagram.Transitions {
- builder.WriteString(" ")
- builder.WriteString(transition.From)
- builder.WriteString(" --> ")
- builder.WriteString(transition.To)
- // Add transition decorations: label, [guard], /action
- var decorations []string
- if transition.Label != nil {
- decorations = append(decorations, *transition.Label)
- }
- if transition.Condition != nil {
- decorations = append(decorations, fmt.Sprintf("[%s]", *transition.Condition))
- }
- if transition.Action != nil {
- decorations = append(decorations, fmt.Sprintf("/%s", *transition.Action))
- }
- if len(decorations) > 0 {
- builder.WriteString(" : ")
- builder.WriteString(strings.Join(decorations, " "))
- }
- builder.WriteString("\n")
- }
- return builder.String(), nil
- }
|