57 lines
1.8 KiB
TypeScript
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");
|
|
}
|