export function Diff({ diff }: { diff: string }) { const lines = diff.replace(/\n+$/, "").split("\n"); return (
{lines.map((l, i) => { let cls = ""; if (l.startsWith("+++") || l.startsWith("---")) cls = "meta"; else if (l.startsWith("@@")) cls = "hunk"; else if (l.startsWith("+")) cls = "add"; else if (l.startsWith("-")) cls = "del"; return (
{l || " "}
); })}
); } /** Split a unified diff into its file header and hunks (at "@@" lines). */ export function splitHunks(diff: string): { header: string[]; hunks: string[][] } { const lines = diff.replace(/\n+$/, "").split("\n"); const header: string[] = []; const hunks: string[][] = []; for (const l of lines) { if (l.startsWith("@@")) hunks.push([l]); else if (hunks.length) hunks[hunks.length - 1].push(l); else header.push(l); } return { header, hunks }; } /** Diff with a checkbox per hunk (review a change piece by piece). */ export function HunkDiff({ diff, selected, onToggle }: { diff: string; selected: boolean[]; onToggle: (i: number) => void }) { const { header, hunks } = splitHunks(diff); return (
{header.map((l, i) => (
{l}
))} {hunks.map((h, i) => (
{h.slice(1).map((l, j) => (
{l || " "}
))}
))}
); }