import { useMemo } from 'react'; import { highlightLines } from '@renderer/utils/syntaxHighlighter'; import { diffLines } from 'diff'; import type { FileChangeSummary, SnippetDiff } from '@shared/types/review'; // ============================================================================= // Types // ============================================================================= interface ReviewDiffContentProps { file: FileChangeSummary; } interface DiffLine { type: 'added' | 'removed' | 'unchanged'; html: string; } // ============================================================================= // Helpers // ============================================================================= /** Build highlighted diff lines by mapping diff parts onto pre-highlighted old/new lines. */ function buildHighlightedDiffLines(snippet: SnippetDiff, fileName: string): DiffLine[] { const isFullNew = snippet.type === 'write-new' || snippet.type === 'write-update'; const oldCode = isFullNew ? '' : snippet.oldString; const diffResult = diffLines(oldCode, snippet.newString); const oldHighlighted = highlightLines(oldCode, fileName); const newHighlighted = highlightLines(snippet.newString, fileName); const result: DiffLine[] = []; let oldIdx = 0; let newIdx = 0; for (const part of diffResult) { const lineCount = part.value.replace(/\n$/, '').split('\n').length; for (let i = 0; i < lineCount; i++) { if (part.removed) { result.push({ type: 'removed', html: oldHighlighted[oldIdx++] ?? '', }); } else if (part.added) { result.push({ type: 'added', html: newHighlighted[newIdx++] ?? '', }); } else { result.push({ type: 'unchanged', html: oldHighlighted[oldIdx++] ?? '', }); newIdx++; } } } return result; } // ============================================================================= // SnippetDiffView // ============================================================================= const SnippetDiffView = ({ snippet, index, fileName, }: { snippet: SnippetDiff; index: number; fileName: string; }) => { const lines = useMemo(() => buildHighlightedDiffLines(snippet, fileName), [snippet, fileName]); const toolLabel = snippet.type === 'write-new' ? 'New file' : snippet.type === 'write-update' ? 'Full rewrite' : snippet.type === 'multi-edit' ? 'Multi-edit' : 'Edit'; return (