diff --git a/openslides/motions/static/js/motions/diff.js b/openslides/motions/static/js/motions/diff.js
index 893332cbc..4e436c320 100644
--- a/openslides/motions/static/js/motions/diff.js
+++ b/openslides/motions/static/js/motions/diff.js
@@ -32,6 +32,18 @@ angular.module('OpenSlidesApp.motions.diff', ['OpenSlidesApp.motions.lineNumberi
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
this._insertInternalLineMarkers = function(fragment) {
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++) {
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;
}
lineMarker = document.createElement('OS-LINEBREAK');
@@ -384,10 +397,10 @@ angular.module('OpenSlidesApp.motions.diff', ['OpenSlidesApp.motions.lineNumberi
var found = false;
for (var i = 0; i < fromChildTraceRel.length && !found; i++) {
- if (fromChildTraceRel[i].nodeName == 'OS-LINEBREAK') {
+ if (fromChildTraceRel[i].nodeName === 'OS-LINEBREAK') {
found = true;
} else {
- if (fromChildTraceRel[i].nodeName == 'OL') {
+ if (fromChildTraceRel[i].nodeName === 'OL') {
fakeOl = fromChildTraceRel[i].cloneNode(false);
fakeOl.setAttribute('start', this._isWithinNthLIOfOL(fromChildTraceRel[i], fromLineNode));
innerContextStart += this._serializeTag(fakeOl);
@@ -398,7 +411,7 @@ angular.module('OpenSlidesApp.motions.diff', ['OpenSlidesApp.motions.lineNumberi
}
found = false;
for (i = 0; i < toChildTraceRel.length && !found; i++) {
- if (toChildTraceRel[i].nodeName == 'OS-LINEBREAK') {
+ if (toChildTraceRel[i].nodeName === 'OS-LINEBREAK') {
found = true;
} else {
innerContextEnd = '' + toChildTraceRel[i].nodeName + '>' + innerContextEnd;
@@ -407,11 +420,11 @@ angular.module('OpenSlidesApp.motions.diff', ['OpenSlidesApp.motions.lineNumberi
found = false;
for (i = 0; i < ancestor.childNodes.length; i++) {
- if (ancestor.childNodes[i] == fromChildTraceRel[0]) {
+ if (ancestor.childNodes[i] === fromChildTraceRel[0]) {
found = true;
fromChildTraceRel.shift();
htmlOut += this._serializePartialDomFromChild(ancestor.childNodes[i], fromChildTraceRel, true);
- } else if (ancestor.childNodes[i] == toChildTraceRel[0]) {
+ } else if (ancestor.childNodes[i] === toChildTraceRel[0]) {
found = false;
toChildTraceRel.shift();
htmlOut += this._serializePartialDomToChild(ancestor.childNodes[i], toChildTraceRel, true);
@@ -422,7 +435,7 @@ angular.module('OpenSlidesApp.motions.diff', ['OpenSlidesApp.motions.lineNumberi
currNode = ancestor;
while (currNode.parentNode) {
- if (currNode.nodeName == 'OL') {
+ if (currNode.nodeName === 'OL') {
fakeOl = currNode.cloneNode(false);
fakeOl.setAttribute('start', this._isWithinNthLIOfOL(currNode, fromLineNode));
outerContextStart = this._serializeTag(fakeOl) + outerContextStart;
diff --git a/tests/karma/motions/diff.service.test.js b/tests/karma/motions/diff.service.test.js
index 4ebcc68a2..4fadbc178 100644
--- a/tests/karma/motions/diff.service.test.js
+++ b/tests/karma/motions/diff.service.test.js
@@ -144,6 +144,14 @@ describe('linenumbering', function () {
expect(diff.followingHtmlStartSnippet).toBe('
');
});
+ it('extracts a single line right before a UL/LI', function () {
+ // Test case for https://github.com/OpenSlides/OpenSlides/issues/3226
+ var html = "A line
Another line
\n\t- A list item
\t- Yet another item
";
+ html = lineNumberingService.insertLineNumbers(html, 80);
+ var diff = diffService.extractRangeByLineNumbers(html, 2, 3, true);
+ expect(diff.html).toBe("Another line
\n");
+ });
+
it('extracts lines from a more complex example', function () {
var diff = diffService.extractRangeByLineNumbers(baseHtml2, 6, 11);
@@ -172,7 +180,7 @@ describe('linenumbering', 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('- Line 3.3
- Line 4
');
expect(diff.ancestor.nodeName).toBe('#document-fragment');
@@ -182,7 +190,7 @@ describe('linenumbering', 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('- Line 3.1
- Line 3.2
');
expect(diff.ancestor.nodeName).toBe('OL');
@@ -192,7 +200,7 @@ describe('linenumbering', function () {
it('escapes text resembling HTML-Tags', function () {
var inHtml = '' + noMarkup(1) + 'Looks like a <p> tag </p>
' + noMarkup(2) + 'Another line
';
- var diff = diffService.extractRangeByLineNumbers(inHtml, 1, 2, true);
+ var diff = diffService.extractRangeByLineNumbers(inHtml, 1, 2);
expect(diff.html).toBe('Looks like a <p> tag </p>
');
});
});