Files
wikiplus/components/diff-viewer.tsx
T
2026-01-24 16:52:19 -06:00

96 lines
2.6 KiB
TypeScript

'use client';
import { useMemo } from 'react';
import * as Diff from 'diff';
interface DiffViewerProps {
oldContent: string;
newContent: string;
}
interface DiffLine {
type: 'added' | 'removed' | 'unchanged';
content: string;
oldLineNum?: number;
newLineNum?: number;
}
export function DiffViewer({ oldContent, newContent }: DiffViewerProps) {
const diffLines = useMemo(() => {
const changes = Diff.diffLines(oldContent, newContent);
const lines: DiffLine[] = [];
let oldLineNum = 1;
let newLineNum = 1;
for (const change of changes) {
const changeLines = change.value.split('\n');
// Remove empty last line from split
if (changeLines[changeLines.length - 1] === '') {
changeLines.pop();
}
for (const line of changeLines) {
if (change.added) {
lines.push({
type: 'added',
content: line,
newLineNum: newLineNum++,
});
} else if (change.removed) {
lines.push({
type: 'removed',
content: line,
oldLineNum: oldLineNum++,
});
} else {
lines.push({
type: 'unchanged',
content: line,
oldLineNum: oldLineNum++,
newLineNum: newLineNum++,
});
}
}
}
return lines;
}, [oldContent, newContent]);
// Split into old and new columns
const oldLines = diffLines.filter(l => l.type !== 'added');
const newLines = diffLines.filter(l => l.type !== 'removed');
return (
<div className="diff-viewer">
<div className="diff-header">
<div className="diff-column-header">Previous Version</div>
<div className="diff-column-header">New Version</div>
</div>
<div className="diff-content">
<div className="diff-column diff-old">
{oldLines.map((line, i) => (
<div
key={i}
className={`diff-line ${line.type === 'removed' ? 'diff-removed' : ''}`}
>
<span className="diff-line-num">{line.oldLineNum || ''}</span>
<span className="diff-line-content">{line.content || '\u00A0'}</span>
</div>
))}
</div>
<div className="diff-column diff-new">
{newLines.map((line, i) => (
<div
key={i}
className={`diff-line ${line.type === 'added' ? 'diff-added' : ''}`}
>
<span className="diff-line-num">{line.newLineNum || ''}</span>
<span className="diff-line-content">{line.content || '\u00A0'}</span>
</div>
))}
</div>
</div>
</div>
);
}