Files
2026-07-11 14:56:10 +08:00

57 lines
1.8 KiB
TypeScript

import type { ConfigDiffView, DiffLine } from "../contracts/workspace";
export function computeLineDiff(previous: string, next: string): DiffLine[] {
const previousLines = previous.split("\n");
const nextLines = next.split("\n");
const m = previousLines.length;
const n = nextLines.length;
// classic LCS table; config files are small enough for O(m*n)
const lcs: number[][] = Array.from({ length: m + 1 }, () => new Array<number>(n + 1).fill(0));
for (let i = m - 1; i >= 0; i -= 1) {
for (let j = n - 1; j >= 0; j -= 1) {
lcs[i][j] = previousLines[i] === nextLines[j] ? lcs[i + 1][j + 1] + 1 : Math.max(lcs[i + 1][j], lcs[i][j + 1]);
}
}
const lines: DiffLine[] = [];
let i = 0;
let j = 0;
while (i < m && j < n) {
if (previousLines[i] === nextLines[j]) {
lines.push({ kind: "same", text: previousLines[i] });
i += 1;
j += 1;
} else if (lcs[i + 1][j] >= lcs[i][j + 1]) {
lines.push({ kind: "removed", text: previousLines[i] });
i += 1;
} else {
lines.push({ kind: "added", text: nextLines[j] });
j += 1;
}
}
while (i < m) {
lines.push({ kind: "removed", text: previousLines[i] });
i += 1;
}
while (j < n) {
lines.push({ kind: "added", text: nextLines[j] });
j += 1;
}
return lines;
}
export function buildConfigDiff(serverInstanceId: string, previous: string, next: string): ConfigDiffView {
const lines = computeLineDiff(previous, next);
const added = lines.filter((line) => line.kind === "added").length;
const removed = lines.filter((line) => line.kind === "removed").length;
return {
serverInstanceId,
summary: `+${added} / -${removed} 行变更`,
lines,
nextContent: next
};
}
export function diffHasChanges(diff: ConfigDiffView): boolean {
return diff.lines.some((line) => line.kind !== "same");
}