Spaces:
Sleeping
Sleeping
| 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; | |