File size: 2,620 Bytes
aea470f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import { memo } from "react";
interface DiffBlockProps { content: string }

interface DiffLine {
  type: "add" | "remove" | "context" | "header";
  content: string;
}

function parseDiff(raw: string): DiffLine[] {
  return raw.split("\n").map(line => {
    if (line.startsWith("+++") || line.startsWith("---") || line.startsWith("@@")) return { type: "header" as const, content: line };
    if (line.startsWith("+")) return { type: "add" as const, content: line.slice(1) };
    if (line.startsWith("-")) return { type: "remove" as const, content: line.slice(1) };
    return { type: "context" as const, content: line.startsWith(" ") ? line.slice(1) : line };
  });
}

const DiffBlock = memo(function DiffBlock({ content }: DiffBlockProps) {
  const lines = parseDiff(content);
  const adds = lines.filter(l => l.type === "add").length;
  const removes = lines.filter(l => l.type === "remove").length;

  return (
    <div style={{ background: "#0d0d18", border: "1px solid #1e1e2e", borderRadius: 10, marginBottom: "0.6em", overflow: "hidden" }}>
      <div style={{ display: "flex", alignItems: "center", gap: 8, padding: "0.4rem 0.85rem", background: "#0a0a14", borderBottom: "1px solid #1e1e2e" }}>
        <span style={{ fontSize: "0.78rem", color: "#6b6b7b", fontWeight: 600 }}>Diff</span>
        <span style={{ fontSize: "0.7rem", color: "#22c55e" }}>+{adds}</span>
        <span style={{ fontSize: "0.7rem", color: "#ef4444" }}>-{removes}</span>
      </div>
      <div style={{ overflowX: "auto" }}>
        <table style={{ width: "100%", borderCollapse: "collapse", fontFamily: "ui-monospace, monospace", fontSize: "0.78rem", lineHeight: 1.5 }}>
          <tbody>
            {lines.map((line, i) => {
              const bg = line.type === "add" ? "rgba(34,197,94,0.08)" : line.type === "remove" ? "rgba(239,68,68,0.08)" : line.type === "header" ? "rgba(79,142,247,0.06)" : "transparent";
              const color = line.type === "add" ? "#86efac" : line.type === "remove" ? "#fca5a5" : line.type === "header" ? "#7aadff" : "#c0c0d0";
              const prefix = line.type === "add" ? "+" : line.type === "remove" ? "−" : line.type === "header" ? "" : " ";
              return (
                <tr key={i} style={{ background: bg }}>
                  <td style={{ width: 16, paddingLeft: 8, color, userSelect: "none", opacity: 0.8 }}>{prefix}</td>
                  <td style={{ padding: "0 8px 0 4px", color, whiteSpace: "pre" }}>{line.content}</td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
    </div>
  );
}
);
export default DiffBlock;