blob: 531b7a0ec92039fbe8275baab66b03a0fedc6a01 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
export const DiffWrapper = {
/**
* @param {string} text1
* @param {string} text2
* @param {boolean=} cleanup
* @return {!Array.<!{0: number, 1: string}>}
*/
charDiff: function(text1, text2, cleanup) {
const differ = new diff_match_patch();
const diff = differ.diff_main(text1, text2);
if (cleanup) {
differ.diff_cleanupSemantic(diff);
}
return diff;
},
/**
* @param {!Array.<string>} lines1
* @param {!Array.<string>} lines2
* @return {!Diff.Diff.DiffArray}
*/
lineDiff: function(lines1, lines2) {
/** @type {!Common.CharacterIdMap<string>} */
const idMap = new Common.CharacterIdMap();
const text1 = lines1.map(line => idMap.toChar(line)).join('');
const text2 = lines2.map(line => idMap.toChar(line)).join('');
const diff = DiffWrapper.charDiff(text1, text2);
const lineDiff = [];
for (let i = 0; i < diff.length; i++) {
const lines = [];
for (let j = 0; j < diff[i][1].length; j++) {
lines.push(idMap.fromChar(diff[i][1][j]));
}
lineDiff.push({0: diff[i][0], 1: lines});
}
return lineDiff;
},
/**
* @param {!Diff.Diff.DiffArray} diff
* @return {!Array<!Array<number>>}
*/
convertToEditDiff: function(diff) {
const normalized = [];
let added = 0;
let removed = 0;
for (let i = 0; i < diff.length; ++i) {
const token = diff[i];
if (token[0] === Operation.Equal) {
flush();
normalized.push([Operation.Equal, token[1].length]);
} else if (token[0] === Operation.Delete) {
removed += token[1].length;
} else {
added += token[1].length;
}
}
flush();
return normalized;
function flush() {
if (added && removed) {
const min = Math.min(added, removed);
normalized.push([Operation.Edit, min]);
added -= min;
removed -= min;
}
if (added || removed) {
const balance = added - removed;
const type = balance < 0 ? Operation.Delete : Operation.Insert;
normalized.push([type, Math.abs(balance)]);
added = 0;
removed = 0;
}
}
}
};
/** @enum {number} */
export const Operation = {
Equal: 0,
Insert: 1,
Delete: -1,
Edit: 2
};
/* Legacy exported object */
self.Diff = self.Diff || {};
/* Legacy exported object */
Diff = Diff || {};
Diff.Diff = DiffWrapper;
/** @enum {number} */
Diff.Diff.Operation = Operation;
/** @typedef {!Array<!{0: !Diff.Diff.Operation, 1: !Array<string>}>} */
Diff.Diff.DiffArray;