diffling
Version:
A versatile diff computation package, supporting various diff methods and line-by-line comparisons.
138 lines (137 loc) • 5.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.diffling = void 0;
const diff_1 = require("diff");
const getLines = (value) => {
if (value === "")
return [];
const lines = value.replace(/\n$/, "").split("\n");
return lines;
};
const getDiff = (original, modified) => {
const changes = (0, diff_1.diffChars)(original, modified);
const diffs = { left: [], right: [] };
changes.forEach((change) => {
var _a, _b, _c, _d;
const { added, removed, value } = change;
const diff = {};
if (added) {
diff.type = "added";
diff.value = value;
(_a = diffs.right) === null || _a === void 0 ? void 0 : _a.push(diff);
}
if (removed) {
diff.type = "removed";
diff.value = value;
(_b = diffs.left) === null || _b === void 0 ? void 0 : _b.push(diff);
}
if (!removed && !added) {
diff.type = "default";
diff.value = value;
(_c = diffs.right) === null || _c === void 0 ? void 0 : _c.push(diff);
(_d = diffs.left) === null || _d === void 0 ? void 0 : _d.push(diff);
}
return diff;
});
return diffs;
};
const getChanges = (original, modified) => {
if (typeof original === "string" && typeof modified === "string") {
return (0, diff_1.diffLines)(original, modified, {
newlineIsToken: false,
ignoreWhitespace: false,
ignoreCase: false,
});
}
return (0, diff_1.diffJson)(original, modified);
};
const diffling = (original, modified, offset = 0) => {
let changes = getChanges(original, modified);
let rightLineNumber = offset;
let leftLineNumber = offset;
let lineInformation = [];
let counter = 0;
const lineNumbers = [];
const ignoredIndexes = [];
const getLineInformation = (diffIndex, change, compareFirstLine) => {
const { value, added, removed } = change;
const lines = getLines(value);
return lines
.map((line, index) => {
var _a;
const left = {};
const right = {};
if (ignoredIndexes.includes(`${diffIndex}-${index}`) ||
(compareFirstLine && index !== 0)) {
return undefined;
}
if (added || removed) {
let hasChanged = true;
if (removed) {
leftLineNumber += 1;
left.lineNumber = leftLineNumber;
left.type = "removed";
left.value = line || " ";
const nextDiff = changes[diffIndex + 1];
if (nextDiff && nextDiff.added) {
const nextDiffLines = getLines(nextDiff.value)[index];
if (nextDiffLines) {
const change = {
value: nextDiffLines,
added: true,
removed: false,
};
const nextDiffLineInfo = getLineInformation(diffIndex, change, true);
const { value: rightValue, lineNumber, type, } = ((_a = nextDiffLineInfo[0]) === null || _a === void 0 ? void 0 : _a.right) || {};
ignoredIndexes.push(`${diffIndex + 1}-${index}`);
right.lineNumber = lineNumber;
if (left.value === rightValue) {
hasChanged = false;
right.type = "default";
left.type = "default";
right.value = rightValue;
}
else {
right.type = type;
const diff = getDiff(line, rightValue);
right.value = diff.right;
left.value = diff.left;
}
}
}
}
else {
rightLineNumber = rightLineNumber + 1;
right.lineNumber = rightLineNumber;
right.type = "added";
right.value = line;
}
if (hasChanged &&
!compareFirstLine &&
!lineNumbers.includes(counter)) {
lineNumbers.push(counter);
}
}
else {
left.lineNumber = leftLineNumber + 1;
left.type = "default";
left.value = line;
right.lineNumber = rightLineNumber + 1;
right.type = "default";
right.value = line;
}
if (!compareFirstLine)
counter += 1;
return { right, left };
})
.filter(Boolean);
};
changes.forEach((change, index) => {
lineInformation.push(...getLineInformation(index, change));
});
return {
lines: lineInformation,
diffs: lineNumbers,
};
};
exports.diffling = diffling;