summaryrefslogtreecommitdiffhomepage
path: root/packages/web/src/components/DiffView.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'packages/web/src/components/DiffView.tsx')
-rw-r--r--packages/web/src/components/DiffView.tsx73
1 files changed, 73 insertions, 0 deletions
diff --git a/packages/web/src/components/DiffView.tsx b/packages/web/src/components/DiffView.tsx
new file mode 100644
index 000000000..44feef140
--- /dev/null
+++ b/packages/web/src/components/DiffView.tsx
@@ -0,0 +1,73 @@
+import { type Component, createSignal, onMount } from "solid-js"
+import { diffLines } from "diff"
+import CodeBlock from "./CodeBlock"
+import styles from "./diffview.module.css"
+
+type DiffRow = {
+ left: string
+ right: string
+ type: "added" | "removed" | "unchanged"
+}
+
+interface DiffViewProps {
+ oldCode: string
+ newCode: string
+ lang?: string
+ class?: string
+}
+
+const DiffView: Component<DiffViewProps> = (props) => {
+ const [rows, setRows] = createSignal<DiffRow[]>([])
+
+ onMount(() => {
+ const chunks = diffLines(props.oldCode, props.newCode)
+ const diffRows: DiffRow[] = []
+
+ for (const chunk of chunks) {
+ const lines = chunk.value.split(/\r?\n/)
+ if (lines.at(-1) === "") lines.pop()
+
+ for (const line of lines) {
+ diffRows.push({
+ left: chunk.removed ? line : chunk.added ? "" : line,
+ right: chunk.added ? line : chunk.removed ? "" : line,
+ type: chunk.added
+ ? "added"
+ : chunk.removed
+ ? "removed"
+ : "unchanged",
+ })
+ }
+ }
+
+ setRows(diffRows)
+ })
+
+ return (
+ <div class={`${styles.diff} ${props.class ?? ""}`}>
+ <div class={styles.column}>
+ {rows().map((r) => (
+ <CodeBlock
+ code={r.left}
+ lang={props.lang}
+ data-section="cell"
+ data-diff-type={r.type === "removed" ? "removed" : ""}
+ />
+ ))}
+ </div>
+
+ <div class={styles.column}>
+ {rows().map((r) => (
+ <CodeBlock
+ code={r.right}
+ lang={props.lang}
+ data-section="cell"
+ data-diff-type={r.type === "added" ? "added" : ""}
+ />
+ ))}
+ </div>
+ </div>
+ )
+}
+
+export default DiffView