diff options
Diffstat (limited to 'packages/web/src/components/DiffView.tsx')
| -rw-r--r-- | packages/web/src/components/DiffView.tsx | 73 |
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 |
