mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-04-20 15:36:16 -04:00
prepare to async: trivial reformatting
This change is only cosmetic. Its aim is do make it easier to understand the async changes that are going to be merged later on. It was extracted from the original work from Ray Bellis. To verify that nothing has changed, you can run the following command on each file touched by this commit: npm install uglify-es diff --unified <(uglify-js --beautify bracketize <BEFORE.js>) <(uglify-js --beautify bracketize <AFTER.js>) This is a complete script that does the same automatically (works from a mercurial clone): ```bash #!/usr/bin/env bash set -eu REVISION=<THIS_REVISION> PARENT_REV=$(hg identify --rev "${REVISION}" --template '{p1rev}') FILE_LIST=$(hg status --no-status --change ${REVISION}) UGLIFYJS="node_modules/uglify-es/bin/uglifyjs" for FILE_NAME in ${FILE_LIST[@]}; do echo "Checking ${FILE_NAME}" diff --unified \ <("${UGLIFYJS}" --beautify bracketize <(hg cat --rev "${PARENT_REV}" "${FILE_NAME}")) \ <("${UGLIFYJS}" --beautify bracketize <(hg cat --rev "${REVISION}" "${FILE_NAME}")) done ```
This commit is contained in:
parent
cc23bd18a4
commit
9497ee734f
33 changed files with 2706 additions and 2943 deletions
|
@ -1,336 +1,348 @@
|
|||
var Changeset = require("../../static/js/Changeset");
|
||||
var async = require("async");
|
||||
var exportHtml = require('./ExportHtml');
|
||||
|
||||
function PadDiff (pad, fromRev, toRev){
|
||||
//check parameters
|
||||
if(!pad || !pad.id || !pad.atext || !pad.pool)
|
||||
{
|
||||
|
||||
function PadDiff (pad, fromRev, toRev) {
|
||||
// check parameters
|
||||
if (!pad || !pad.id || !pad.atext || !pad.pool) {
|
||||
throw new Error('Invalid pad');
|
||||
}
|
||||
|
||||
|
||||
var range = pad.getValidRevisionRange(fromRev, toRev);
|
||||
if(!range) { throw new Error('Invalid revision range.' +
|
||||
if (!range) {
|
||||
throw new Error('Invalid revision range.' +
|
||||
' startRev: ' + fromRev +
|
||||
' endRev: ' + toRev); }
|
||||
|
||||
' endRev: ' + toRev);
|
||||
}
|
||||
|
||||
this._pad = pad;
|
||||
this._fromRev = range.startRev;
|
||||
this._toRev = range.endRev;
|
||||
this._html = null;
|
||||
this._authors = [];
|
||||
}
|
||||
|
||||
PadDiff.prototype._isClearAuthorship = function(changeset){
|
||||
//unpack
|
||||
|
||||
PadDiff.prototype._isClearAuthorship = function(changeset) {
|
||||
// unpack
|
||||
var unpacked = Changeset.unpack(changeset);
|
||||
|
||||
//check if there is nothing in the charBank
|
||||
if(unpacked.charBank !== "")
|
||||
|
||||
// check if there is nothing in the charBank
|
||||
if (unpacked.charBank !== "") {
|
||||
return false;
|
||||
|
||||
//check if oldLength == newLength
|
||||
if(unpacked.oldLen !== unpacked.newLen)
|
||||
}
|
||||
|
||||
// check if oldLength == newLength
|
||||
if (unpacked.oldLen !== unpacked.newLen) {
|
||||
return false;
|
||||
|
||||
//lets iterator over the operators
|
||||
}
|
||||
|
||||
// lets iterator over the operators
|
||||
var iterator = Changeset.opIterator(unpacked.ops);
|
||||
|
||||
//get the first operator, this should be a clear operator
|
||||
|
||||
// get the first operator, this should be a clear operator
|
||||
var clearOperator = iterator.next();
|
||||
|
||||
//check if there is only one operator
|
||||
if(iterator.hasNext() === true)
|
||||
|
||||
// check if there is only one operator
|
||||
if (iterator.hasNext() === true) {
|
||||
return false;
|
||||
|
||||
//check if this operator doesn't change text
|
||||
if(clearOperator.opcode !== "=")
|
||||
}
|
||||
|
||||
// check if this operator doesn't change text
|
||||
if (clearOperator.opcode !== "=") {
|
||||
return false;
|
||||
|
||||
//check that this operator applys to the complete text
|
||||
//if the text ends with a new line, its exactly one character less, else it has the same length
|
||||
if(clearOperator.chars !== unpacked.oldLen-1 && clearOperator.chars !== unpacked.oldLen)
|
||||
}
|
||||
|
||||
// check that this operator applys to the complete text
|
||||
// if the text ends with a new line, its exactly one character less, else it has the same length
|
||||
if (clearOperator.chars !== unpacked.oldLen-1 && clearOperator.chars !== unpacked.oldLen) {
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
var attributes = [];
|
||||
Changeset.eachAttribNumber(changeset, function(attrNum){
|
||||
Changeset.eachAttribNumber(changeset, function(attrNum) {
|
||||
attributes.push(attrNum);
|
||||
});
|
||||
|
||||
//check that this changeset uses only one attribute
|
||||
if(attributes.length !== 1)
|
||||
|
||||
// check that this changeset uses only one attribute
|
||||
if (attributes.length !== 1) {
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
var appliedAttribute = this._pad.pool.getAttrib(attributes[0]);
|
||||
|
||||
//check if the applied attribute is an anonymous author attribute
|
||||
if(appliedAttribute[0] !== "author" || appliedAttribute[1] !== "")
|
||||
|
||||
// check if the applied attribute is an anonymous author attribute
|
||||
if (appliedAttribute[0] !== "author" || appliedAttribute[1] !== "") {
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
PadDiff.prototype._createClearAuthorship = function(rev, callback){
|
||||
|
||||
PadDiff.prototype._createClearAuthorship = function(rev, callback) {
|
||||
var self = this;
|
||||
this._pad.getInternalRevisionAText(rev, function(err, atext){
|
||||
if(err){
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
//build clearAuthorship changeset
|
||||
this._pad.getInternalRevisionAText(rev, function(err, atext) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
// build clearAuthorship changeset
|
||||
var builder = Changeset.builder(atext.text.length);
|
||||
builder.keepText(atext.text, [['author','']], self._pad.pool);
|
||||
var changeset = builder.toString();
|
||||
|
||||
|
||||
callback(null, changeset);
|
||||
});
|
||||
};
|
||||
|
||||
PadDiff.prototype._createClearStartAtext = function(rev, callback){
|
||||
|
||||
PadDiff.prototype._createClearStartAtext = function(rev, callback) {
|
||||
var self = this;
|
||||
|
||||
//get the atext of this revision
|
||||
this._pad.getInternalRevisionAText(rev, function(err, atext){
|
||||
if(err){
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
//create the clearAuthorship changeset
|
||||
self._createClearAuthorship(rev, function(err, changeset){
|
||||
if(err){
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
try {
|
||||
//apply the clearAuthorship changeset
|
||||
var newAText = Changeset.applyToAText(changeset, atext, self._pad.pool);
|
||||
} catch(err) {
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
callback(null, newAText);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
PadDiff.prototype._getChangesetsInBulk = function(startRev, count, callback) {
|
||||
var self = this;
|
||||
|
||||
//find out which revisions we need
|
||||
var revisions = [];
|
||||
for(var i=startRev;i<(startRev+count) && i<=this._pad.head;i++){
|
||||
revisions.push(i);
|
||||
}
|
||||
|
||||
var changesets = [], authors = [];
|
||||
|
||||
//get all needed revisions
|
||||
async.forEach(revisions, function(rev, callback){
|
||||
self._pad.getRevision(rev, function(err, revision){
|
||||
if(err){
|
||||
|
||||
// get the atext of this revision
|
||||
this._pad.getInternalRevisionAText(rev, function(err, atext) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
// create the clearAuthorship changeset
|
||||
self._createClearAuthorship(rev, function(err, changeset) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
// apply the clearAuthorship changeset
|
||||
var newAText = Changeset.applyToAText(changeset, atext, self._pad.pool);
|
||||
} catch(err) {
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
callback(null, newAText);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
PadDiff.prototype._getChangesetsInBulk = function(startRev, count, callback) {
|
||||
var self = this;
|
||||
|
||||
// find out which revisions we need
|
||||
var revisions = [];
|
||||
for (var i = startRev; i < (startRev + count) && i <= this._pad.head; i++) {
|
||||
revisions.push(i);
|
||||
}
|
||||
|
||||
var changesets = [], authors = [];
|
||||
|
||||
// get all needed revisions
|
||||
async.forEach(revisions, function(rev, callback) {
|
||||
self._pad.getRevision(rev, function(err, revision) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
var arrayNum = rev-startRev;
|
||||
|
||||
|
||||
changesets[arrayNum] = revision.changeset;
|
||||
authors[arrayNum] = revision.meta.author;
|
||||
|
||||
|
||||
callback();
|
||||
});
|
||||
}, function(err){
|
||||
},
|
||||
function(err) {
|
||||
callback(err, changesets, authors);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
PadDiff.prototype._addAuthors = function(authors) {
|
||||
var self = this;
|
||||
//add to array if not in the array
|
||||
authors.forEach(function(author){
|
||||
if(self._authors.indexOf(author) == -1){
|
||||
|
||||
// add to array if not in the array
|
||||
authors.forEach(function(author) {
|
||||
if (self._authors.indexOf(author) == -1) {
|
||||
self._authors.push(author);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
PadDiff.prototype._createDiffAtext = function(callback) {
|
||||
var self = this;
|
||||
var bulkSize = 100;
|
||||
|
||||
//get the cleaned startAText
|
||||
self._createClearStartAtext(self._fromRev, function(err, atext){
|
||||
if(err) { return callback(err); }
|
||||
|
||||
|
||||
// get the cleaned startAText
|
||||
self._createClearStartAtext(self._fromRev, function(err, atext) {
|
||||
if (err) { return callback(err); }
|
||||
|
||||
var superChangeset = null;
|
||||
|
||||
|
||||
var rev = self._fromRev + 1;
|
||||
|
||||
//async while loop
|
||||
|
||||
// async while loop
|
||||
async.whilst(
|
||||
//loop condition
|
||||
// loop condition
|
||||
function () { return rev <= self._toRev; },
|
||||
|
||||
//loop body
|
||||
|
||||
// loop body
|
||||
function (callback) {
|
||||
//get the bulk
|
||||
self._getChangesetsInBulk(rev,bulkSize,function(err, changesets, authors){
|
||||
// get the bulk
|
||||
self._getChangesetsInBulk(rev,bulkSize,function(err, changesets, authors) {
|
||||
var addedAuthors = [];
|
||||
|
||||
//run trough all changesets
|
||||
for(var i=0;i<changesets.length && (rev+i)<=self._toRev;i++){
|
||||
|
||||
// run trough all changesets
|
||||
for (var i = 0; i < changesets.length && (rev + i) <= self._toRev; i++) {
|
||||
var changeset = changesets[i];
|
||||
|
||||
//skip clearAuthorship Changesets
|
||||
if(self._isClearAuthorship(changeset)){
|
||||
|
||||
// skip clearAuthorship Changesets
|
||||
if (self._isClearAuthorship(changeset)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
changeset = self._extendChangesetWithAuthor(changeset, authors[i], self._pad.pool);
|
||||
|
||||
//add this author to the authorarray
|
||||
|
||||
// add this author to the authorarray
|
||||
addedAuthors.push(authors[i]);
|
||||
|
||||
//compose it with the superChangset
|
||||
if(superChangeset === null){
|
||||
|
||||
// compose it with the superChangset
|
||||
if (superChangeset === null) {
|
||||
superChangeset = changeset;
|
||||
} else {
|
||||
} else {
|
||||
superChangeset = Changeset.composeWithDeletions(superChangeset, changeset, self._pad.pool);
|
||||
}
|
||||
}
|
||||
|
||||
//add the authors to the PadDiff authorArray
|
||||
|
||||
// add the authors to the PadDiff authorArray
|
||||
self._addAuthors(addedAuthors);
|
||||
|
||||
//lets continue with the next bulk
|
||||
|
||||
// lets continue with the next bulk
|
||||
rev += bulkSize;
|
||||
callback();
|
||||
});
|
||||
},
|
||||
|
||||
//after the loop has ended
|
||||
|
||||
// after the loop has ended
|
||||
function (err) {
|
||||
//if there are only clearAuthorship changesets, we don't get a superChangeset, so we can skip this step
|
||||
if(superChangeset){
|
||||
// if there are only clearAuthorship changesets, we don't get a superChangeset, so we can skip this step
|
||||
if (superChangeset) {
|
||||
var deletionChangeset = self._createDeletionChangeset(superChangeset,atext,self._pad.pool);
|
||||
|
||||
|
||||
try {
|
||||
//apply the superChangeset, which includes all addings
|
||||
atext = Changeset.applyToAText(superChangeset,atext,self._pad.pool);
|
||||
//apply the deletionChangeset, which adds a deletions
|
||||
atext = Changeset.applyToAText(deletionChangeset,atext,self._pad.pool);
|
||||
// apply the superChangeset, which includes all addings
|
||||
atext = Changeset.applyToAText(superChangeset, atext, self._pad.pool);
|
||||
// apply the deletionChangeset, which adds a deletions
|
||||
atext = Changeset.applyToAText(deletionChangeset, atext, self._pad.pool);
|
||||
} catch(err) {
|
||||
return callback(err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
callback(err, atext);
|
||||
}
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
PadDiff.prototype.getHtml = function(callback){
|
||||
//cache the html
|
||||
if(this._html != null){
|
||||
|
||||
PadDiff.prototype.getHtml = function(callback) {
|
||||
// cache the html
|
||||
if (this._html != null) {
|
||||
return callback(null, this._html);
|
||||
}
|
||||
|
||||
|
||||
var self = this;
|
||||
var atext, html, authorColors;
|
||||
|
||||
|
||||
async.series([
|
||||
//get the diff atext
|
||||
function(callback){
|
||||
self._createDiffAtext(function(err, _atext){
|
||||
if(err){
|
||||
// get the diff atext
|
||||
function(callback) {
|
||||
self._createDiffAtext(function(err, _atext) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
|
||||
atext = _atext;
|
||||
callback();
|
||||
});
|
||||
},
|
||||
//get the authorColor table
|
||||
function(callback){
|
||||
self._pad.getAllAuthorColors(function(err, _authorColors){
|
||||
if(err){
|
||||
|
||||
// get the authorColor table
|
||||
function(callback) {
|
||||
self._pad.getAllAuthorColors(function(err, _authorColors) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
|
||||
authorColors = _authorColors;
|
||||
callback();
|
||||
});
|
||||
},
|
||||
//convert the atext to html
|
||||
function(callback){
|
||||
|
||||
// convert the atext to html
|
||||
function(callback) {
|
||||
html = exportHtml.getHTMLFromAtext(self._pad, atext, authorColors);
|
||||
self._html = html;
|
||||
callback();
|
||||
}
|
||||
], function(err){
|
||||
],
|
||||
function(err) {
|
||||
callback(err, html);
|
||||
});
|
||||
};
|
||||
|
||||
PadDiff.prototype.getAuthors = function(callback){
|
||||
|
||||
PadDiff.prototype.getAuthors = function(callback) {
|
||||
var self = this;
|
||||
|
||||
//check if html was already produced, if not produce it, this generates the author array at the same time
|
||||
if(self._html == null){
|
||||
self.getHtml(function(err){
|
||||
if(err){
|
||||
|
||||
// check if html was already produced, if not produce it, this generates the author array at the same time
|
||||
if (self._html == null) {
|
||||
self.getHtml(function(err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
|
||||
callback(null, self._authors);
|
||||
});
|
||||
} else {
|
||||
callback(null, self._authors);
|
||||
}
|
||||
};
|
||||
|
||||
PadDiff.prototype._extendChangesetWithAuthor = function(changeset, author, apool) {
|
||||
//unpack
|
||||
var unpacked = Changeset.unpack(changeset);
|
||||
|
||||
|
||||
PadDiff.prototype._extendChangesetWithAuthor = function(changeset, author, apool) {
|
||||
// unpack
|
||||
var unpacked = Changeset.unpack(changeset);
|
||||
|
||||
var iterator = Changeset.opIterator(unpacked.ops);
|
||||
var assem = Changeset.opAssembler();
|
||||
|
||||
//create deleted attribs
|
||||
|
||||
// create deleted attribs
|
||||
var authorAttrib = apool.putAttrib(["author", author || ""]);
|
||||
var deletedAttrib = apool.putAttrib(["removed", true]);
|
||||
var attribs = "*" + Changeset.numToString(authorAttrib) + "*" + Changeset.numToString(deletedAttrib);
|
||||
|
||||
//iteratore over the operators of the changeset
|
||||
while(iterator.hasNext()){
|
||||
|
||||
// iteratore over the operators of the changeset
|
||||
while(iterator.hasNext()) {
|
||||
var operator = iterator.next();
|
||||
|
||||
//this is a delete operator, extend it with the author
|
||||
if(operator.opcode === "-"){
|
||||
|
||||
if (operator.opcode === "-") {
|
||||
// this is a delete operator, extend it with the author
|
||||
operator.attribs = attribs;
|
||||
}
|
||||
//this is operator changes only attributes, let's mark which author did that
|
||||
else if(operator.opcode === "=" && operator.attribs){
|
||||
} else if (operator.opcode === "=" && operator.attribs) {
|
||||
// this is operator changes only attributes, let's mark which author did that
|
||||
operator.attribs+="*"+Changeset.numToString(authorAttrib);
|
||||
}
|
||||
|
||||
//append the new operator to our assembler
|
||||
|
||||
// append the new operator to our assembler
|
||||
assem.append(operator);
|
||||
}
|
||||
|
||||
//return the modified changeset
|
||||
|
||||
// return the modified changeset
|
||||
return Changeset.pack(unpacked.oldLen, unpacked.newLen, assem.toString(), unpacked.charBank);
|
||||
};
|
||||
|
||||
//this method is 80% like Changeset.inverse. I just changed so instead of reverting, it adds deletions and attribute changes to to the atext.
|
||||
|
||||
// this method is 80% like Changeset.inverse. I just changed so instead of reverting, it adds deletions and attribute changes to to the atext.
|
||||
PadDiff.prototype._createDeletionChangeset = function(cs, startAText, apool) {
|
||||
var lines = Changeset.splitTextLines(startAText.text);
|
||||
var alines = Changeset.splitAttributionLines(startAText.attribs, startAText.text);
|
||||
|
||||
|
||||
// lines and alines are what the exports is meant to apply to.
|
||||
// They may be arrays or objects with .get(i) and .length methods.
|
||||
// They include final newlines on lines.
|
||||
|
||||
|
||||
function lines_get(idx) {
|
||||
if (lines.get) {
|
||||
return lines.get(idx);
|
||||
|
@ -338,7 +350,7 @@ PadDiff.prototype._createDeletionChangeset = function(cs, startAText, apool) {
|
|||
return lines[idx];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function alines_get(idx) {
|
||||
if (alines.get) {
|
||||
return alines.get(idx);
|
||||
|
@ -346,19 +358,19 @@ PadDiff.prototype._createDeletionChangeset = function(cs, startAText, apool) {
|
|||
return alines[idx];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var curLine = 0;
|
||||
var curChar = 0;
|
||||
var curLineOpIter = null;
|
||||
var curLineOpIterLine;
|
||||
var curLineNextOp = Changeset.newOp('+');
|
||||
|
||||
|
||||
var unpacked = Changeset.unpack(cs);
|
||||
var csIter = Changeset.opIterator(unpacked.ops);
|
||||
var builder = Changeset.builder(unpacked.newLen);
|
||||
|
||||
|
||||
function consumeAttribRuns(numChars, func /*(len, attribs, endsLine)*/ ) {
|
||||
|
||||
|
||||
if ((!curLineOpIter) || (curLineOpIterLine != curLine)) {
|
||||
// create curLineOpIter and advance it to curChar
|
||||
curLineOpIter = Changeset.opIterator(alines_get(curLine));
|
||||
|
@ -375,7 +387,7 @@ PadDiff.prototype._createDeletionChangeset = function(cs, startAText, apool) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
while (numChars > 0) {
|
||||
if ((!curLineNextOp.chars) && (!curLineOpIter.hasNext())) {
|
||||
curLine++;
|
||||
|
@ -384,22 +396,25 @@ PadDiff.prototype._createDeletionChangeset = function(cs, startAText, apool) {
|
|||
curLineNextOp.chars = 0;
|
||||
curLineOpIter = Changeset.opIterator(alines_get(curLine));
|
||||
}
|
||||
|
||||
if (!curLineNextOp.chars) {
|
||||
curLineOpIter.next(curLineNextOp);
|
||||
}
|
||||
|
||||
var charsToUse = Math.min(numChars, curLineNextOp.chars);
|
||||
|
||||
func(charsToUse, curLineNextOp.attribs, charsToUse == curLineNextOp.chars && curLineNextOp.lines > 0);
|
||||
numChars -= charsToUse;
|
||||
curLineNextOp.chars -= charsToUse;
|
||||
curChar += charsToUse;
|
||||
}
|
||||
|
||||
|
||||
if ((!curLineNextOp.chars) && (!curLineOpIter.hasNext())) {
|
||||
curLine++;
|
||||
curChar = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function skip(N, L) {
|
||||
if (L) {
|
||||
curLine += L;
|
||||
|
@ -412,27 +427,29 @@ PadDiff.prototype._createDeletionChangeset = function(cs, startAText, apool) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function nextText(numChars) {
|
||||
var len = 0;
|
||||
var assem = Changeset.stringAssembler();
|
||||
var firstString = lines_get(curLine).substring(curChar);
|
||||
len += firstString.length;
|
||||
assem.append(firstString);
|
||||
|
||||
|
||||
var lineNum = curLine + 1;
|
||||
|
||||
while (len < numChars) {
|
||||
var nextString = lines_get(lineNum);
|
||||
len += nextString.length;
|
||||
assem.append(nextString);
|
||||
lineNum++;
|
||||
}
|
||||
|
||||
|
||||
return assem.toString().substring(0, numChars);
|
||||
}
|
||||
|
||||
|
||||
function cachedStrFunc(func) {
|
||||
var cache = {};
|
||||
|
||||
return function (s) {
|
||||
if (!cache[s]) {
|
||||
cache[s] = func(s);
|
||||
|
@ -440,57 +457,59 @@ PadDiff.prototype._createDeletionChangeset = function(cs, startAText, apool) {
|
|||
return cache[s];
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
var attribKeys = [];
|
||||
var attribValues = [];
|
||||
|
||||
//iterate over all operators of this changeset
|
||||
|
||||
// iterate over all operators of this changeset
|
||||
while (csIter.hasNext()) {
|
||||
var csOp = csIter.next();
|
||||
|
||||
if (csOp.opcode == '=') {
|
||||
|
||||
if (csOp.opcode == '=') {
|
||||
var textBank = nextText(csOp.chars);
|
||||
|
||||
|
||||
// decide if this equal operator is an attribution change or not. We can see this by checkinf if attribs is set.
|
||||
// If the text this operator applies to is only a star, than this is a false positive and should be ignored
|
||||
if (csOp.attribs && textBank != "*") {
|
||||
var deletedAttrib = apool.putAttrib(["removed", true]);
|
||||
var authorAttrib = apool.putAttrib(["author", ""]);
|
||||
|
||||
|
||||
attribKeys.length = 0;
|
||||
attribValues.length = 0;
|
||||
Changeset.eachAttribNumber(csOp.attribs, function (n) {
|
||||
attribKeys.push(apool.getAttribKey(n));
|
||||
attribValues.push(apool.getAttribValue(n));
|
||||
|
||||
if(apool.getAttribKey(n) === "author"){
|
||||
|
||||
if (apool.getAttribKey(n) === "author") {
|
||||
authorAttrib = n;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
var undoBackToAttribs = cachedStrFunc(function (attribs) {
|
||||
var backAttribs = [];
|
||||
for (var i = 0; i < attribKeys.length; i++) {
|
||||
var appliedKey = attribKeys[i];
|
||||
var appliedValue = attribValues[i];
|
||||
var oldValue = Changeset.attribsAttributeValue(attribs, appliedKey, apool);
|
||||
|
||||
if (appliedValue != oldValue) {
|
||||
backAttribs.push([appliedKey, oldValue]);
|
||||
}
|
||||
}
|
||||
|
||||
return Changeset.makeAttribsString('=', backAttribs, apool);
|
||||
});
|
||||
|
||||
|
||||
var oldAttribsAddition = "*" + Changeset.numToString(deletedAttrib) + "*" + Changeset.numToString(authorAttrib);
|
||||
|
||||
|
||||
var textLeftToProcess = textBank;
|
||||
|
||||
while(textLeftToProcess.length > 0){
|
||||
//process till the next line break or process only one line break
|
||||
|
||||
while(textLeftToProcess.length > 0) {
|
||||
// process till the next line break or process only one line break
|
||||
var lengthToProcess = textLeftToProcess.indexOf("\n");
|
||||
var lineBreak = false;
|
||||
switch(lengthToProcess){
|
||||
case -1:
|
||||
switch(lengthToProcess) {
|
||||
case -1:
|
||||
lengthToProcess=textLeftToProcess.length;
|
||||
break;
|
||||
case 0:
|
||||
|
@ -498,27 +517,28 @@ PadDiff.prototype._createDeletionChangeset = function(cs, startAText, apool) {
|
|||
lengthToProcess=1;
|
||||
break;
|
||||
}
|
||||
|
||||
//get the text we want to procceed in this step
|
||||
|
||||
// get the text we want to procceed in this step
|
||||
var processText = textLeftToProcess.substr(0, lengthToProcess);
|
||||
|
||||
textLeftToProcess = textLeftToProcess.substr(lengthToProcess);
|
||||
|
||||
if(lineBreak){
|
||||
builder.keep(1, 1); //just skip linebreaks, don't do a insert + keep for a linebreak
|
||||
|
||||
//consume the attributes of this linebreak
|
||||
consumeAttribRuns(1, function(){});
|
||||
|
||||
if (lineBreak) {
|
||||
builder.keep(1, 1); // just skip linebreaks, don't do a insert + keep for a linebreak
|
||||
|
||||
// consume the attributes of this linebreak
|
||||
consumeAttribRuns(1, function() {});
|
||||
} else {
|
||||
//add the old text via an insert, but add a deletion attribute + the author attribute of the author who deleted it
|
||||
// add the old text via an insert, but add a deletion attribute + the author attribute of the author who deleted it
|
||||
var textBankIndex = 0;
|
||||
consumeAttribRuns(lengthToProcess, function (len, attribs, endsLine) {
|
||||
//get the old attributes back
|
||||
// get the old attributes back
|
||||
var attribs = (undoBackToAttribs(attribs) || "") + oldAttribsAddition;
|
||||
|
||||
|
||||
builder.insert(processText.substr(textBankIndex, len), attribs);
|
||||
textBankIndex += len;
|
||||
});
|
||||
|
||||
|
||||
builder.keep(lengthToProcess, 0);
|
||||
}
|
||||
}
|
||||
|
@ -531,16 +551,16 @@ PadDiff.prototype._createDeletionChangeset = function(cs, startAText, apool) {
|
|||
} else if (csOp.opcode == '-') {
|
||||
var textBank = nextText(csOp.chars);
|
||||
var textBankIndex = 0;
|
||||
|
||||
|
||||
consumeAttribRuns(csOp.chars, function (len, attribs, endsLine) {
|
||||
builder.insert(textBank.substr(textBankIndex, len), attribs + csOp.attribs);
|
||||
textBankIndex += len;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return Changeset.checkRep(builder.toString());
|
||||
};
|
||||
|
||||
//export the constructor
|
||||
|
||||
// export the constructor
|
||||
module.exports = PadDiff;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue