From f6ed3cbd6dfd3456a93ad80c42d7e18948b197ef Mon Sep 17 00:00:00 2001 From: Haileyesus Date: Thu, 12 Feb 2026 20:53:34 +0300 Subject: [PATCH] refactor(calculateDiff): optimize LCS algorithm for improved diff calculation --- .../chat/utils/messageTransforms.ts | 47 +++++++++++++------ 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/src/components/chat/utils/messageTransforms.ts b/src/components/chat/utils/messageTransforms.ts index 2aee588..7093081 100644 --- a/src/components/chat/utils/messageTransforms.ts +++ b/src/components/chat/utils/messageTransforms.ts @@ -29,35 +29,54 @@ export const calculateDiff = (oldStr: string, newStr: string): DiffLine[] => { const oldLines = oldStr.split('\n'); const newLines = newStr.split('\n'); + // Use LCS alignment so insertions/deletions don't cascade into a full-file "changed" diff. + const lcsTable: number[][] = Array.from({ length: oldLines.length + 1 }, () => + new Array(newLines.length + 1).fill(0), + ); + for (let oldIndex = oldLines.length - 1; oldIndex >= 0; oldIndex -= 1) { + for (let newIndex = newLines.length - 1; newIndex >= 0; newIndex -= 1) { + if (oldLines[oldIndex] === newLines[newIndex]) { + lcsTable[oldIndex][newIndex] = lcsTable[oldIndex + 1][newIndex + 1] + 1; + } else { + lcsTable[oldIndex][newIndex] = Math.max( + lcsTable[oldIndex + 1][newIndex], + lcsTable[oldIndex][newIndex + 1], + ); + } + } + } + const diffLines: DiffLine[] = []; let oldIndex = 0; let newIndex = 0; - while (oldIndex < oldLines.length || newIndex < newLines.length) { + while (oldIndex < oldLines.length && newIndex < newLines.length) { const oldLine = oldLines[oldIndex]; const newLine = newLines[newIndex]; - if (oldIndex >= oldLines.length) { - diffLines.push({ type: 'added', content: newLine, lineNum: newIndex + 1 }); - newIndex += 1; - continue; - } - - if (newIndex >= newLines.length) { - diffLines.push({ type: 'removed', content: oldLine, lineNum: oldIndex + 1 }); - oldIndex += 1; - continue; - } - if (oldLine === newLine) { oldIndex += 1; newIndex += 1; continue; } - diffLines.push({ type: 'removed', content: oldLine, lineNum: oldIndex + 1 }); + if (lcsTable[oldIndex + 1][newIndex] >= lcsTable[oldIndex][newIndex + 1]) { + diffLines.push({ type: 'removed', content: oldLine, lineNum: oldIndex + 1 }); + oldIndex += 1; + continue; + } + diffLines.push({ type: 'added', content: newLine, lineNum: newIndex + 1 }); + newIndex += 1; + } + + while (oldIndex < oldLines.length) { + diffLines.push({ type: 'removed', content: oldLines[oldIndex], lineNum: oldIndex + 1 }); oldIndex += 1; + } + + while (newIndex < newLines.length) { + diffLines.push({ type: 'added', content: newLines[newIndex], lineNum: newIndex + 1 }); newIndex += 1; }