50 lines
2.2 KiB
JavaScript
50 lines
2.2 KiB
JavaScript
import { structuredPatch } from 'diff';
|
|
/**
|
|
* Creates a smart diff that returns full content when changes exceed threshold.
|
|
*
|
|
* When more than `threshold` (default 50%) of lines have changed, showing a diff
|
|
* is not useful - we return the full new content instead.
|
|
*/
|
|
export function createSmartDiff(options) {
|
|
const { oldContent, newContent, threshold = 0.5, label = 'content' } = options;
|
|
const patch = structuredPatch(label, label, oldContent, newContent, 'previous', 'current', {
|
|
context: 3,
|
|
});
|
|
// Count added and removed lines
|
|
let addedLines = 0;
|
|
let removedLines = 0;
|
|
for (const hunk of patch.hunks) {
|
|
for (const line of hunk.lines) {
|
|
if (line.startsWith('+')) {
|
|
addedLines++;
|
|
}
|
|
else if (line.startsWith('-')) {
|
|
removedLines++;
|
|
}
|
|
}
|
|
}
|
|
// No changes - return full content
|
|
if (addedLines === 0 && removedLines === 0) {
|
|
return { type: 'no-change', content: newContent };
|
|
}
|
|
// Calculate change ratio: use max(added, removed) since a replacement counts as both
|
|
// This ensures the ratio stays in 0-100% range
|
|
const oldLineCount = oldContent.split('\n').length;
|
|
const newLineCount = newContent.split('\n').length;
|
|
const maxLines = Math.max(oldLineCount, newLineCount, 1); // Avoid division by zero
|
|
const changedLines = Math.max(addedLines, removedLines);
|
|
const changeRatio = Math.min(changedLines / maxLines, 1); // Cap at 100%
|
|
// Build unified diff string from structured patch
|
|
const diffLines = [`--- ${label} (previous)`, `+++ ${label} (current)`];
|
|
for (const hunk of patch.hunks) {
|
|
diffLines.push(`@@ -${hunk.oldStart},${hunk.oldLines} +${hunk.newStart},${hunk.newLines} @@`);
|
|
diffLines.push(...hunk.lines);
|
|
}
|
|
const diffString = diffLines.join('\n');
|
|
// Return full content if changes exceed threshold OR if diff is longer than full content
|
|
if (changeRatio >= threshold || diffString.length >= newContent.length) {
|
|
return { type: 'full', content: newContent };
|
|
}
|
|
return { type: 'diff', content: diffString };
|
|
}
|
|
//# sourceMappingURL=diff-utils.js.map
|