state.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. // Package renderer provides rendering functionality for state diagrams
  2. package renderer
  3. import (
  4. "fmt"
  5. "strings"
  6. "mermaid-go/pkg/ast"
  7. )
  8. // StateRenderer renders state diagrams back to mermaid syntax
  9. type StateRenderer struct{}
  10. // NewStateRenderer creates a new state renderer
  11. func NewStateRenderer() *StateRenderer {
  12. return &StateRenderer{}
  13. }
  14. // Render renders a state diagram to mermaid syntax
  15. func (r *StateRenderer) Render(diagram *ast.StateDiagram) (string, error) {
  16. var builder strings.Builder
  17. // Start with diagram declaration
  18. builder.WriteString("stateDiagram-v2\n")
  19. // Add title if present
  20. if diagram.Title != nil {
  21. builder.WriteString(fmt.Sprintf(" title %s\n", *diagram.Title))
  22. }
  23. // Add direction if present
  24. if diagram.Direction != "" {
  25. builder.WriteString(fmt.Sprintf(" direction %s\n", diagram.Direction))
  26. }
  27. // Render states
  28. for _, state := range diagram.States {
  29. builder.WriteString(" state ")
  30. builder.WriteString(state.ID)
  31. // Add alias if different from ID
  32. if state.Label != state.ID {
  33. builder.WriteString(" as ")
  34. if strings.Contains(state.Label, " ") {
  35. builder.WriteString(fmt.Sprintf("\"%s\"", state.Label))
  36. } else {
  37. builder.WriteString(state.Label)
  38. }
  39. }
  40. // Add description or special type
  41. if state.Description != nil {
  42. builder.WriteString(" : ")
  43. builder.WriteString(*state.Description)
  44. } else {
  45. switch state.Type {
  46. case ast.StateTypeFork:
  47. builder.WriteString(" : <<fork>>")
  48. case ast.StateTypeJoin:
  49. builder.WriteString(" : <<join>>")
  50. case ast.StateTypeChoice:
  51. builder.WriteString(" : <<choice>>")
  52. case ast.StateTypeHistory:
  53. builder.WriteString(" : <<history>>")
  54. case ast.StateTypeDeepHistory:
  55. builder.WriteString(" : <<deepHistory>>")
  56. }
  57. }
  58. builder.WriteString("\n")
  59. // Render composite state body if it has sub-states
  60. if len(state.SubStates) > 0 {
  61. builder.WriteString(" state ")
  62. builder.WriteString(state.ID)
  63. builder.WriteString(" {\n")
  64. for _, subState := range state.SubStates {
  65. builder.WriteString(" state ")
  66. builder.WriteString(subState.ID)
  67. if subState.Label != subState.ID {
  68. builder.WriteString(" as ")
  69. builder.WriteString(subState.Label)
  70. }
  71. if subState.Description != nil {
  72. builder.WriteString(" : ")
  73. builder.WriteString(*subState.Description)
  74. }
  75. builder.WriteString("\n")
  76. }
  77. builder.WriteString(" }\n")
  78. }
  79. // Render note if present
  80. if state.Note != nil {
  81. builder.WriteString(" note ")
  82. builder.WriteString(string(state.Note.Position))
  83. builder.WriteString(" ")
  84. builder.WriteString(state.ID)
  85. builder.WriteString(" : ")
  86. builder.WriteString(state.Note.Text)
  87. builder.WriteString("\n")
  88. }
  89. }
  90. // Render transitions
  91. for _, transition := range diagram.Transitions {
  92. builder.WriteString(" ")
  93. // Handle start state
  94. if transition.From == "[*]" {
  95. builder.WriteString("[*]")
  96. } else {
  97. builder.WriteString(transition.From)
  98. }
  99. builder.WriteString(" --> ")
  100. // Handle end state
  101. if transition.To == "[*]" {
  102. builder.WriteString("[*]")
  103. } else {
  104. builder.WriteString(transition.To)
  105. }
  106. // Add label if present
  107. if transition.Label != nil {
  108. builder.WriteString(" : ")
  109. builder.WriteString(*transition.Label)
  110. }
  111. // Add condition if present
  112. if transition.Condition != nil {
  113. builder.WriteString(" [")
  114. builder.WriteString(*transition.Condition)
  115. builder.WriteString("]")
  116. }
  117. // Add action if present
  118. if transition.Action != nil {
  119. builder.WriteString(" / ")
  120. builder.WriteString(*transition.Action)
  121. }
  122. builder.WriteString("\n")
  123. }
  124. return builder.String(), nil
  125. }