package review import ( "fmt" "strings" ) // FormatMarkdown formats a ReviewResult into the markdown body for a Gitea review. func FormatMarkdown(result *ReviewResult, reviewerName string) string { return FormatMarkdownWithDisplay(result, reviewerName, reviewerName) } // GiteaEvent converts the verdict to the Gitea API event string. func GiteaEvent(verdict string) string { switch verdict { case "APPROVE": return "APPROVED" case "REQUEST_CHANGES": return "REQUEST_CHANGES" default: return "COMMENT" } } // FormatMarkdownWithDisplay formats a ReviewResult with separate display name and sentinel name. // Note: displayName is not HTML-escaped as Gitea sanitizes rendered Markdown. // Persona display names are controlled by repo owners (trusted input). // displayName is used for the header title, sentinelName is used for the cleanup sentinel. // If displayName is empty, sentinelName is used for both. func FormatMarkdownWithDisplay(result *ReviewResult, displayName, sentinelName string) string { var sb strings.Builder // Use display name for header, or fall back to sentinel name headerName := displayName if headerName == "" { headerName = sentinelName } if headerName != "" { title := CapitalizeFirst(headerName) sb.WriteString(fmt.Sprintf("# %s Review\n\n", title)) } sb.WriteString("## Summary\n\n") sb.WriteString(result.Summary) sb.WriteString("\n\n") if len(result.Findings) > 0 { sb.WriteString("## Findings\n\n") sb.WriteString("| # | Severity | File | Line | Finding |\n") sb.WriteString("|---|----------|------|------|--------|\n") for i, f := range result.Findings { sb.WriteString(fmt.Sprintf("| %d | [%s] | `%s` | %d | %s |\n", i+1, f.Severity, f.File, f.Line, f.Finding)) } sb.WriteString("\n") } sb.WriteString("## Recommendation\n\n") sb.WriteString(fmt.Sprintf("**%s** — %s\n", result.Verdict, result.Recommendation)) if sentinelName != "" { sb.WriteString(fmt.Sprintf("\n---\n*Review by %s*\n", headerName)) // Hidden sentinel for identifying this bot's reviews during cleanup sb.WriteString(fmt.Sprintf("\n\n", sentinelName)) } return sb.String() }