import { useMemo } from "react"; import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; import { oneDark, oneLight } from "react-syntax-highlighter/dist/esm/styles/prism"; import type { DisplayBlock, DiffBlock, TodoBlock, BriefBlock, ShellBlock } from "shared/legacy-sdk"; import { cn } from "@/lib/utils"; import * as Diff from "diff"; function useIsDark(): boolean { return typeof document !== "undefined" && document.documentElement.classList.contains("dark"); } interface DiffBlockProps { block: DiffBlock; maxHeight?: string; } interface DiffPart { value: string; added?: boolean; removed?: boolean; } function renderDiffLine(parts: DiffPart[], type: "added" | "removed"): React.ReactNode { return parts.map((part, i) => { if (type === "removed") { if (part.added) return null; return ( {part.value} ); } else { if (part.removed) return null; return ( {part.value} ); } }); } // Extract diff computation to a pure function for memoization function computeDiffLines(oldText: string, newText: string): { oldLines: DiffPart[][]; newLines: DiffPart[][] } { const diffParts = Diff.diffWords(oldText, newText); const oldLines: DiffPart[][] = []; const newLines: DiffPart[][] = []; let currentOldLine: DiffPart[] = []; let currentNewLine: DiffPart[] = []; for (const part of diffParts) { const lines = part.value.split("\n"); lines.forEach((line, lineIndex) => { const isLastLine = lineIndex === lines.length - 1; const partForLine: DiffPart = { value: line, added: part.added, removed: part.removed, }; if (!part.added) { currentOldLine.push(partForLine); } if (!part.removed) { currentNewLine.push(partForLine); } if (!isLastLine) { if (!part.added) { oldLines.push(currentOldLine); currentOldLine = []; } if (!part.removed) { newLines.push(currentNewLine); currentNewLine = []; } } }); } if (currentOldLine.length > 0) oldLines.push(currentOldLine); if (currentNewLine.length > 0) newLines.push(currentNewLine); return { oldLines, newLines }; } export function DiffBlockView({ block, maxHeight = "max-h-40" }: DiffBlockProps) { const fileName = block.path.split("/").pop() || block.path; const hasOld = block.old_text.length > 0; const hasNew = block.new_text.length > 0; const { oldLines, newLines } = useMemo(() => computeDiffLines(block.old_text, block.new_text), [block.old_text, block.new_text]); return (