// Package renderer provides BPMN rendering package renderer import ( "fmt" "strings" "mermaid-go/pkg/ast" ) // BPMNRenderer implements BPMN rendering type BPMNRenderer struct{} // NewBPMNRenderer creates a new BPMN renderer func NewBPMNRenderer() *BPMNRenderer { return &BPMNRenderer{} } // Render renders a BPMN diagram to mermaid syntax func (r *BPMNRenderer) Render(diagram *ast.BPMNDiagram) (string, error) { var result strings.Builder // Start with bpmn declaration result.WriteString("bpmn\n") // Add title if present if diagram.Title != nil { result.WriteString(fmt.Sprintf(" title %s\n", *diagram.Title)) } // Render pools for _, pool := range diagram.Pools { result.WriteString(fmt.Sprintf(" pool %s", pool.ID)) if pool.Name != pool.ID { result.WriteString(fmt.Sprintf("[%s]", pool.Name)) } result.WriteString("\n") } // Render lanes for _, lane := range diagram.Lanes { result.WriteString(fmt.Sprintf(" lane %s", lane.ID)) if lane.Name != lane.ID { result.WriteString(fmt.Sprintf("[%s]", lane.Name)) } if lane.Pool != "" { result.WriteString(fmt.Sprintf(" in %s", lane.Pool)) } result.WriteString("\n") } // Render elements for _, element := range diagram.Elements { result.WriteString(fmt.Sprintf(" %s", element.ID)) if element.Name != element.ID { result.WriteString(fmt.Sprintf("[%s]", element.Name)) } // Add type information if not default if element.Type != ast.BPMNElementTask { result.WriteString(fmt.Sprintf("(%s)", string(element.Type))) } result.WriteString("\n") } // Render flows for _, flow := range diagram.Flows { result.WriteString(fmt.Sprintf(" %s ", flow.From)) // Render flow type switch flow.Type { case ast.BPMNFlowSequence: result.WriteString("-->") case ast.BPMNFlowMessage: result.WriteString("-.->") case ast.BPMNFlowAssociation: result.WriteString("-.->") default: result.WriteString("-->") } result.WriteString(fmt.Sprintf(" %s", flow.To)) // Add flow name if present if flow.Name != nil { result.WriteString(fmt.Sprintf(" : %s", *flow.Name)) } result.WriteString("\n") } return result.String(), nil }