Merge pull request #3096 from CatoTH/Issue3077-highlight-inline-diff
Add an explicit line highlighting function for the diff
This commit is contained in:
commit
42cf987aed
@ -331,7 +331,7 @@ angular.module('OpenSlidesApp.motions', [
|
||||
text = '';
|
||||
for (var i = 0; i < changes.length; i++) {
|
||||
text += this.getTextBetweenChangeRecommendations(versionId, (i === 0 ? null : changes[i - 1]), changes[i], highlight);
|
||||
text += changes[i].getDiff(this, versionId);
|
||||
text += changes[i].getDiff(this, versionId, highlight);
|
||||
}
|
||||
text += this.getTextRemainderAfterLastChangeRecommendation(versionId, changes);
|
||||
break;
|
||||
@ -740,7 +740,13 @@ angular.module('OpenSlidesApp.motions', [
|
||||
oldText = data.outerContextStart + data.innerContextStart +
|
||||
data.html + data.innerContextEnd + data.outerContextEnd;
|
||||
|
||||
return diffService.diff(oldText, this.text, lineLength, this.line_from);
|
||||
var diff = diffService.diff(oldText, this.text, lineLength, this.line_from);
|
||||
|
||||
if (highlight > 0) {
|
||||
diff = lineNumberingService.highlightLine(diff, highlight);
|
||||
}
|
||||
|
||||
return diff;
|
||||
},
|
||||
getType: function(original_full_html) {
|
||||
return this.type;
|
||||
|
@ -71,6 +71,32 @@ angular.module('OpenSlidesApp.motions.lineNumbering', [])
|
||||
return isLineNumber;
|
||||
};
|
||||
|
||||
this._getLineNumberNode = function(fragment, lineNumber) {
|
||||
return fragment.querySelector('.os-line-number.line-number-' + lineNumber);
|
||||
};
|
||||
|
||||
this._htmlToFragment = function(html) {
|
||||
var fragment = document.createDocumentFragment(),
|
||||
div = document.createElement('DIV');
|
||||
div.innerHTML = html;
|
||||
while (div.childElementCount) {
|
||||
var child = div.childNodes[0];
|
||||
div.removeChild(child);
|
||||
fragment.appendChild(child);
|
||||
}
|
||||
return fragment;
|
||||
};
|
||||
|
||||
this._fragmentToHtml = function(fragment) {
|
||||
var div = document.createElement('DIV');
|
||||
while (fragment.firstChild) {
|
||||
var child = fragment.firstChild;
|
||||
fragment.removeChild(child);
|
||||
div.appendChild(child);
|
||||
}
|
||||
return div.innerHTML;
|
||||
};
|
||||
|
||||
this._createLineBreak = function () {
|
||||
var br = document.createElement('br');
|
||||
br.setAttribute('class', 'os-line-break');
|
||||
@ -413,6 +439,15 @@ angular.module('OpenSlidesApp.motions.lineNumbering', [])
|
||||
return this._insertLineNumbersToNode(root, lineLength, highlight);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} html
|
||||
* @param {number} lineLength
|
||||
* @param {string} highlight - optional
|
||||
* @param {function} callback
|
||||
* @param {number} firstLine
|
||||
* @returns {string}
|
||||
*/
|
||||
this.insertLineNumbers = function (html, lineLength, highlight, callback, firstLine) {
|
||||
var newHtml, newRoot;
|
||||
|
||||
@ -438,12 +473,81 @@ angular.module('OpenSlidesApp.motions.lineNumbering', [])
|
||||
return newHtml;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} html
|
||||
* @returns {string}
|
||||
*/
|
||||
this.stripLineNumbers = function (html) {
|
||||
var root = document.createElement('div');
|
||||
root.innerHTML = html;
|
||||
this._stripLineNumbers(root);
|
||||
return root.innerHTML;
|
||||
};
|
||||
|
||||
/**
|
||||
* Traverses up the DOM tree until it finds a node with a nextSibling, then returns that sibling
|
||||
*
|
||||
* @param node
|
||||
* @private
|
||||
*/
|
||||
this._findNextAuntNode = function(node) {
|
||||
if (node.nextSibling) {
|
||||
return node.nextSibling;
|
||||
} else if (node.parentNode) {
|
||||
return this._findNextAuntNode(node.parentNode);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
this._highlightUntilNextLine = function(lineNumberNode) {
|
||||
var currentNode = lineNumberNode,
|
||||
foundNextLineNumber = false;
|
||||
|
||||
do {
|
||||
var wasHighlighted = false;
|
||||
if (currentNode.nodeType === TEXT_NODE) {
|
||||
var node = document.createElement('span');
|
||||
node.setAttribute('class', 'highlight');
|
||||
node.innerHTML = currentNode.nodeValue;
|
||||
currentNode.parentNode.insertBefore(node, currentNode);
|
||||
currentNode.parentNode.removeChild(currentNode);
|
||||
currentNode = node;
|
||||
wasHighlighted = true;
|
||||
} else {
|
||||
wasHighlighted = false;
|
||||
}
|
||||
|
||||
if (currentNode.childNodes.length > 0 && !this._isOsLineNumberNode(currentNode) && !wasHighlighted) {
|
||||
currentNode = currentNode.childNodes[0];
|
||||
} else if (currentNode.nextSibling) {
|
||||
currentNode = currentNode.nextSibling;
|
||||
} else {
|
||||
currentNode = this._findNextAuntNode(currentNode);
|
||||
}
|
||||
|
||||
if (this._isOsLineNumberNode(currentNode)) {
|
||||
foundNextLineNumber = true;
|
||||
}
|
||||
} while (!foundNextLineNumber && currentNode !== null);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} html
|
||||
* @param {number} lineNumber
|
||||
* @return {string}
|
||||
*/
|
||||
this.highlightLine = function (html, lineNumber) {
|
||||
var fragment = this._htmlToFragment(html),
|
||||
lineNumberNode = this._getLineNumberNode(fragment, lineNumber);
|
||||
|
||||
if (lineNumberNode) {
|
||||
this._highlightUntilNextLine(lineNumberNode);
|
||||
html = this._fragmentToHtml(fragment);
|
||||
}
|
||||
|
||||
return html;
|
||||
};
|
||||
}
|
||||
]);
|
||||
|
||||
|
@ -286,4 +286,42 @@ describe('linenumbering', function () {
|
||||
expect(outHtml).toBe("<ul>\n\n<li>" + noMarkup(1) + "Point 1</li>\n\n</ul>");
|
||||
});
|
||||
});
|
||||
|
||||
describe('line highlighting', function() {
|
||||
it('highlights a simple line', function () {
|
||||
var inHtml = lineNumberingService.insertLineNumbers("<span>Lorem ipsum dolorsit amet</span>", 5);
|
||||
var highlighted = lineNumberingService.highlightLine(inHtml, 2);
|
||||
expect(highlighted).toBe(noMarkup(1) + '<span>Lorem ' + brMarkup(2) + '<span class="highlight">ipsum </span>' + brMarkup(3) + 'dolor' + brMarkup(4) + 'sit ' + brMarkup(5) + 'amet</span>');
|
||||
});
|
||||
|
||||
it('highlights a simple line with formattings', function () {
|
||||
var inHtml = lineNumberingService.insertLineNumbers("<span>Lorem ipsum <strong>dolorsit amet Lorem</strong><em> ipsum dolorsit amet</em> Lorem ipsum dolorsit amet</span>", 20);
|
||||
expect(inHtml).toBe(noMarkup(1) + '<span>Lorem ipsum <strong>dolorsit ' +
|
||||
brMarkup(2) + 'amet Lorem</strong><em> ipsum ' +
|
||||
brMarkup(3) + 'dolorsit amet</em> Lorem ' + brMarkup(4) + 'ipsum dolorsit amet</span>');
|
||||
|
||||
var highlighted = lineNumberingService.highlightLine(inHtml, 2);
|
||||
expect(highlighted).toBe(noMarkup(1) + '<span>Lorem ipsum <strong>dolorsit ' +
|
||||
brMarkup(2) + '<span class="highlight">amet Lorem</span></strong><em><span class="highlight"> ipsum </span>' +
|
||||
brMarkup(3) + 'dolorsit amet</em> Lorem ' + brMarkup(4) + 'ipsum dolorsit amet</span>');
|
||||
});
|
||||
|
||||
it('highlights the last line', function () {
|
||||
var inHtml = lineNumberingService.insertLineNumbers("<span>Lorem ipsum dolorsit amet</span>", 5);
|
||||
var highlighted = lineNumberingService.highlightLine(inHtml, 5);
|
||||
expect(highlighted).toBe(noMarkup(1) + '<span>Lorem ' + brMarkup(2) + 'ipsum ' + brMarkup(3) + 'dolor' + brMarkup(4) + 'sit ' + brMarkup(5) + '<span class="highlight">amet</span></span>');
|
||||
});
|
||||
|
||||
it('highlights the first line', function () {
|
||||
var inHtml = lineNumberingService.insertLineNumbers("<span>Lorem ipsum dolorsit amet</span>", 5);
|
||||
var highlighted = lineNumberingService.highlightLine(inHtml, 1);
|
||||
expect(highlighted).toBe(noMarkup(1) + '<span><span class="highlight">Lorem </span>' + brMarkup(2) + 'ipsum ' + brMarkup(3) + 'dolor' + brMarkup(4) + 'sit ' + brMarkup(5) + 'amet</span>');
|
||||
});
|
||||
|
||||
it('does not change the string if the line number is not found', function () {
|
||||
var inHtml = lineNumberingService.insertLineNumbers("<span>Lorem ipsum dolorsit amet</span>", 5);
|
||||
var highlighted = lineNumberingService.highlightLine(inHtml, 8);
|
||||
expect(highlighted).toBe(noMarkup(1) + '<span>Lorem ' + brMarkup(2) + 'ipsum ' + brMarkup(3) + 'dolor' + brMarkup(4) + 'sit ' + brMarkup(5) + 'amet</span>');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user