From a4e46e6e18140afbf376ef3baa26aa5e90c27d94 Mon Sep 17 00:00:00 2001
From: Jay V <air@live.ca>
Date: Fri, 30 May 2025 13:58:32 -0400
Subject: share page diff

---
 app/packages/web/src/components/DiffView.tsx | 66 ++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)
 create mode 100644 app/packages/web/src/components/DiffView.tsx

(limited to 'app/packages/web/src/components/DiffView.tsx')

diff --git a/app/packages/web/src/components/DiffView.tsx b/app/packages/web/src/components/DiffView.tsx
new file mode 100644
index 000000000..443fc6f47
--- /dev/null
+++ b/app/packages/web/src/components/DiffView.tsx
@@ -0,0 +1,66 @@
+import { type Component, createSignal, onMount } from "solid-js"
+import { diffLines, type Change } 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[] = []
+
+    chunks.forEach((chunk: Change) => {
+      const lines = chunk.value.split(/\r?\n/)
+      if (lines.at(-1) === "") lines.pop()
+
+      lines.forEach((line) => {
+        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 ?? ""}`}>
+      {rows().map((r) => (
+        <div data-section="row">
+          <CodeBlock
+            code={r.left}
+            lang={props.lang}
+            data-section="cell"
+            data-diff-type={r.type === "removed" ? "removed" : ""}
+          />
+          <CodeBlock
+            code={r.right}
+            lang={props.lang}
+            data-section="cell"
+            data-diff-type={r.type === "added" ? "added" : ""}
+          />
+        </div>
+      ))}
+    </div>
+  )
+}
+
+export default DiffView
-- 
cgit v1.2.3

