/** * Code Review Engine - HTML Reporter * * Generate HTML format reports. */ import type { CodeIssue, ReportOptions, ReviewResult } from "../types.js"; export class HtmlReporter { /** * Generate HTML report */ generate(result: ReviewResult, options: ReportOptions): string { return ` Code Review Report - ${result.id}

Code Review Report

Review ID: ${result.id}

Generated: ${new Date(result.timestamp).toLocaleString()}

Duration: ${result.durationMs}ms

Files Reviewed

${result.stats.filesReviewed}

Lines Reviewed

${result.stats.linesReviewed}

Errors

${result.summary.errors}

Warnings

${result.summary.warnings}

Info

${result.summary.info}
${ result.issues.length > 0 ? result.issues .map((issue) => this.renderIssue(issue, options)) .join("\n") : `

No Issues Found

Your code passed all automated checks!

` }
`; } /** * Render a single issue */ private renderIssue(issue: CodeIssue, options: ReportOptions): string { const location = issue.file + (issue.line ? `:${issue.line}` : ""); return `
${issue.severity} ${issue.category}
${this.escapeHtml(issue.title)}
${this.escapeHtml(location)} ${issue.rule ? `• Rule: ${this.escapeHtml(issue.rule)}` : ""}
${this.escapeHtml(issue.message)}
${issue.code && options.includeCode !== false ? `
${this.escapeHtml(issue.code)}
` : ""} ${issue.suggestion && options.includeSuggestions !== false ? `
Suggestion: ${this.escapeHtml(issue.suggestion)}
` : ""}
`; } /** * Escape HTML */ private escapeHtml(text: string): string { return text .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); } }