Merge pull request #3236 from CatoTH/Issue3226-WhitespacesDisturbingLineExtraction

Bugfix: whitespaces were disturbing line extraction - fixes #3226
This commit is contained in:
Norman Jäckel 2017-05-08 13:06:13 +02:00 committed by GitHub
commit db1d087aa0
2 changed files with 31 additions and 10 deletions

View File

@ -32,6 +32,18 @@ angular.module('OpenSlidesApp.motions.diff', ['OpenSlidesApp.motions.lineNumberi
return context; return context;
}; };
this._isFirstNonemptyChild = function(node, child) {
for (var i = 0; i < node.childNodes.length; i++) {
if (node.childNodes[i] === child) {
return true;
}
if (node.childNodes[i].nodeType !== TEXT_NODE || node.childNodes[i].nodeValue.match(/\S/)) {
return false;
}
}
return false;
};
// Adds elements like <OS-LINEBREAK class="os-line-number line-number-23" data-line-number="23"/> // Adds elements like <OS-LINEBREAK class="os-line-number line-number-23" data-line-number="23"/>
this._insertInternalLineMarkers = function(fragment) { this._insertInternalLineMarkers = function(fragment) {
if (fragment.querySelectorAll('OS-LINEBREAK').length > 0) { if (fragment.querySelectorAll('OS-LINEBREAK').length > 0) {
@ -43,7 +55,8 @@ angular.module('OpenSlidesApp.motions.diff', ['OpenSlidesApp.motions.lineNumberi
for (var i = 0; i < lineNumbers.length; i++) { for (var i = 0; i < lineNumbers.length; i++) {
var insertBefore = lineNumbers[i]; var insertBefore = lineNumbers[i];
while (insertBefore.parentNode.nodeType != DOCUMENT_FRAGMENT_NODE && insertBefore.parentNode.childNodes[0] == insertBefore) { while (insertBefore.parentNode.nodeType !== DOCUMENT_FRAGMENT_NODE &&
this._isFirstNonemptyChild(insertBefore.parentNode, insertBefore)) {
insertBefore = insertBefore.parentNode; insertBefore = insertBefore.parentNode;
} }
lineMarker = document.createElement('OS-LINEBREAK'); lineMarker = document.createElement('OS-LINEBREAK');
@ -384,10 +397,10 @@ angular.module('OpenSlidesApp.motions.diff', ['OpenSlidesApp.motions.lineNumberi
var found = false; var found = false;
for (var i = 0; i < fromChildTraceRel.length && !found; i++) { for (var i = 0; i < fromChildTraceRel.length && !found; i++) {
if (fromChildTraceRel[i].nodeName == 'OS-LINEBREAK') { if (fromChildTraceRel[i].nodeName === 'OS-LINEBREAK') {
found = true; found = true;
} else { } else {
if (fromChildTraceRel[i].nodeName == 'OL') { if (fromChildTraceRel[i].nodeName === 'OL') {
fakeOl = fromChildTraceRel[i].cloneNode(false); fakeOl = fromChildTraceRel[i].cloneNode(false);
fakeOl.setAttribute('start', this._isWithinNthLIOfOL(fromChildTraceRel[i], fromLineNode)); fakeOl.setAttribute('start', this._isWithinNthLIOfOL(fromChildTraceRel[i], fromLineNode));
innerContextStart += this._serializeTag(fakeOl); innerContextStart += this._serializeTag(fakeOl);
@ -398,7 +411,7 @@ angular.module('OpenSlidesApp.motions.diff', ['OpenSlidesApp.motions.lineNumberi
} }
found = false; found = false;
for (i = 0; i < toChildTraceRel.length && !found; i++) { for (i = 0; i < toChildTraceRel.length && !found; i++) {
if (toChildTraceRel[i].nodeName == 'OS-LINEBREAK') { if (toChildTraceRel[i].nodeName === 'OS-LINEBREAK') {
found = true; found = true;
} else { } else {
innerContextEnd = '</' + toChildTraceRel[i].nodeName + '>' + innerContextEnd; innerContextEnd = '</' + toChildTraceRel[i].nodeName + '>' + innerContextEnd;
@ -407,11 +420,11 @@ angular.module('OpenSlidesApp.motions.diff', ['OpenSlidesApp.motions.lineNumberi
found = false; found = false;
for (i = 0; i < ancestor.childNodes.length; i++) { for (i = 0; i < ancestor.childNodes.length; i++) {
if (ancestor.childNodes[i] == fromChildTraceRel[0]) { if (ancestor.childNodes[i] === fromChildTraceRel[0]) {
found = true; found = true;
fromChildTraceRel.shift(); fromChildTraceRel.shift();
htmlOut += this._serializePartialDomFromChild(ancestor.childNodes[i], fromChildTraceRel, true); htmlOut += this._serializePartialDomFromChild(ancestor.childNodes[i], fromChildTraceRel, true);
} else if (ancestor.childNodes[i] == toChildTraceRel[0]) { } else if (ancestor.childNodes[i] === toChildTraceRel[0]) {
found = false; found = false;
toChildTraceRel.shift(); toChildTraceRel.shift();
htmlOut += this._serializePartialDomToChild(ancestor.childNodes[i], toChildTraceRel, true); htmlOut += this._serializePartialDomToChild(ancestor.childNodes[i], toChildTraceRel, true);
@ -422,7 +435,7 @@ angular.module('OpenSlidesApp.motions.diff', ['OpenSlidesApp.motions.lineNumberi
currNode = ancestor; currNode = ancestor;
while (currNode.parentNode) { while (currNode.parentNode) {
if (currNode.nodeName == 'OL') { if (currNode.nodeName === 'OL') {
fakeOl = currNode.cloneNode(false); fakeOl = currNode.cloneNode(false);
fakeOl.setAttribute('start', this._isWithinNthLIOfOL(currNode, fromLineNode)); fakeOl.setAttribute('start', this._isWithinNthLIOfOL(currNode, fromLineNode));
outerContextStart = this._serializeTag(fakeOl) + outerContextStart; outerContextStart = this._serializeTag(fakeOl) + outerContextStart;

View File

@ -144,6 +144,14 @@ describe('linenumbering', function () {
expect(diff.followingHtmlStartSnippet).toBe('<UL class="ul-class"><LI class="li-class"><UL>'); expect(diff.followingHtmlStartSnippet).toBe('<UL class="ul-class"><LI class="li-class"><UL>');
}); });
it('extracts a single line right before a UL/LI', function () {
// Test case for https://github.com/OpenSlides/OpenSlides/issues/3226
var html = "<p>A line</p><p>Another line</p>\n<ul>\t<li>A list item</li>\t<li>Yet another item</li></ul>";
html = lineNumberingService.insertLineNumbers(html, 80);
var diff = diffService.extractRangeByLineNumbers(html, 2, 3, true);
expect(diff.html).toBe("<P>Another line</P>\n");
});
it('extracts lines from a more complex example', function () { it('extracts lines from a more complex example', function () {
var diff = diffService.extractRangeByLineNumbers(baseHtml2, 6, 11); var diff = diffService.extractRangeByLineNumbers(baseHtml2, 6, 11);
@ -172,7 +180,7 @@ describe('linenumbering', function () {
}); });
it('preserves the numbering of OLs (1)', function () { it('preserves the numbering of OLs (1)', function () {
var diff = diffService.extractRangeByLineNumbers(baseHtml3, 5, 7, true); var diff = diffService.extractRangeByLineNumbers(baseHtml3, 5, 7);
expect(diff.html).toBe('<LI>Line 3.3</LI></OL></LI><LI> Line 4</LI></OL>'); expect(diff.html).toBe('<LI>Line 3.3</LI></OL></LI><LI> Line 4</LI></OL>');
expect(diff.ancestor.nodeName).toBe('#document-fragment'); expect(diff.ancestor.nodeName).toBe('#document-fragment');
@ -182,7 +190,7 @@ describe('linenumbering', function () {
}); });
it('preserves the numbering of OLs (2)', function () { it('preserves the numbering of OLs (2)', function () {
var diff = diffService.extractRangeByLineNumbers(baseHtml3, 3, 5, true); var diff = diffService.extractRangeByLineNumbers(baseHtml3, 3, 5);
expect(diff.html).toBe('<LI><OL><LI>Line 3.1</LI><LI>Line 3.2</LI>'); expect(diff.html).toBe('<LI><OL><LI>Line 3.1</LI><LI>Line 3.2</LI>');
expect(diff.ancestor.nodeName).toBe('OL'); expect(diff.ancestor.nodeName).toBe('OL');
@ -192,7 +200,7 @@ describe('linenumbering', function () {
it('escapes text resembling HTML-Tags', function () { it('escapes text resembling HTML-Tags', function () {
var inHtml = '<h2>' + noMarkup(1) + 'Looks like a &lt;p&gt; tag &lt;/p&gt;</h2><p>' + noMarkup(2) + 'Another line</p>'; var inHtml = '<h2>' + noMarkup(1) + 'Looks like a &lt;p&gt; tag &lt;/p&gt;</h2><p>' + noMarkup(2) + 'Another line</p>';
var diff = diffService.extractRangeByLineNumbers(inHtml, 1, 2, true); var diff = diffService.extractRangeByLineNumbers(inHtml, 1, 2);
expect(diff.html).toBe('<H2>Looks like a &lt;p&gt; tag &lt;/p&gt;</H2>'); expect(diff.html).toBe('<H2>Looks like a &lt;p&gt; tag &lt;/p&gt;</H2>');
}); });
}); });