-
-
Save Szandor72/56b0966e8e6a712335904ce048848359 to your computer and use it in GitHub Desktop.
diff javascript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Array.prototype.rotate = function(n){ | |
var len = this.length, | |
res = new Array(this.length); | |
if (n % len === 0) return this.slice(); | |
else for (var i = 0; i < len; i++) res[i] = this[(i + (len + n % len)) % len]; | |
return res; | |
}; | |
String.prototype.diff = function(s,p){ // p -> precision factor | |
function getMatchingSubstring(s,l,m){ // returns the first matching substring in-between the two strings | |
var i = 0, | |
slen = s.length, | |
match = false, | |
o = {fis:slen, mtc:m, sbs:""}; // temporary object used to construct the cd (change data) object | |
while (i < slen ) { | |
l[i] === s[i] ? match ? o.sbs += s[i] // o.sbs holds the matching substring itsef | |
: (match = true, o.fis = i, o.sbs = s[i]) | |
: match && (i = slen); // stop after the first found substring | |
++i; | |
} | |
return o; | |
} | |
function getChanges(t,s,m){ | |
var isThisLonger = t.length >= s.length ? true : false, | |
[longer,shorter] = isThisLonger ? [t,s] : [s,t], // assignment of longer and shorter by es6 destructuring | |
bi = 0; // base index designating the index of first mismacthing character in both strings | |
while (shorter[bi] === longer[bi] && bi < shorter.length) ++bi; // make bi the index of first mismatching character | |
longer = longer.split("").slice(bi); // as the longer string will be rotated it is converted into array | |
shorter = shorter.slice(bi); // shorter and longer now starts from the first mismatching character | |
var len = longer.length, // length of the longer string | |
cd = {fis: shorter.length, // the index of matching string in the shorter string | |
fil: len, // the index of matching string in the longer string | |
sbs: "", // the matching substring itself | |
mtc: m + s.slice(0,bi)}, // if exists mtc holds the matching string at the front | |
sub = {sbs:""}; // returned substring per 1 character rotation of the longer string | |
if (shorter !== "") { | |
for (var rc = 0; rc < len && sub.sbs.length < p; rc++){ // rc -> rotate count, p -> precision factor | |
sub = getMatchingSubstring(shorter, longer.rotate(rc), cd.mtc); // rotate longer string 1 char and get substring | |
sub.fil = rc < len - sub.fis ? sub.fis + rc // mismatch is longer than the mismatch in short | |
: sub.fis - len + rc; // mismatch is shorter than the mismatch in short | |
sub.sbs.length > cd.sbs.length && (cd = sub); // only keep the one with the longest substring. | |
} | |
} | |
// insert the mismatching delete subsrt and insert substr to the cd object and attach the previous substring | |
[cd.del, cd.ins] = isThisLonger ? [longer.slice(0,cd.fil).join(""), shorter.slice(0,cd.fis)] | |
: [shorter.slice(0,cd.fis), longer.slice(0,cd.fil).join("")]; | |
return cd.del.indexOf(" ") == -1 || | |
cd.ins.indexOf(" ") == -1 || | |
cd.del === "" || | |
cd.ins === "" || | |
cd.sbs === "" ? cd : getChanges(cd.del, cd.ins, cd.mtc); | |
} | |
var changeData = getChanges(this,s,""), | |
nextS = s.slice(changeData.mtc.length + changeData.ins.length + changeData.sbs.length), // remaining part of "s" | |
nextThis = this.slice(changeData.mtc.length + changeData.del.length + changeData.sbs.length), // remaining part of "this" | |
result = ""; // the glorious result | |
changeData.del.length > 0 && (changeData.del = '<span class = "deleted">' + changeData.del + '</span>'); | |
changeData.ins.length > 0 && (changeData.ins = '<span class = "inserted">' + changeData.ins + '</span>'); | |
result = changeData.mtc + changeData.del + changeData.ins + changeData.sbs; | |
result += (nextThis !== "" || nextS !== "") ? nextThis.diff(nextS,p) : ""; | |
return result; | |
}; | |
textOld.oninput = function(e){textNew.innerText = this.value}; | |
textNew.onfocus = function(e){this.select()}; | |
myButton.onclick = function(e){ | |
var sr = "", | |
so = textOld.value, | |
sn = textNew.value, | |
ts = 0, | |
te = 0; | |
ts = performance.now(); | |
sr = so.diff(sn,+precision.value); | |
te = performance.now(); | |
textdiff.innerHTML = sr; | |
perfdiff.textContent = "Diffing the above texts took " + (te-ts) + "msecs"; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment