summaryrefslogtreecommitdiffhomepage
path: root/app/packages/web/src/components/DiffView.tsx
diff options
context:
space:
mode:
authorJay V <[email protected]>2025-05-30 13:58:32 -0400
committerJay V <[email protected]>2025-05-30 13:58:34 -0400
commita4e46e6e18140afbf376ef3baa26aa5e90c27d94 (patch)
tree5024cfe0c94f650b95183a2781ba05dbeee6506b /app/packages/web/src/components/DiffView.tsx
parent680d52016c69887c331dbbb37de7109158ee9020 (diff)
downloadopencode-a4e46e6e18140afbf376ef3baa26aa5e90c27d94.tar.gz
opencode-a4e46e6e18140afbf376ef3baa26aa5e90c27d94.zip
share page diff
Diffstat (limited to 'app/packages/web/src/components/DiffView.tsx')
-rw-r--r--app/packages/web/src/components/DiffView.tsx66
1 files changed, 66 insertions, 0 deletions
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