diff --git a/openslides/motions/static/js/motions/diff.js b/openslides/motions/static/js/motions/diff.js index e9b4bfc5b..d3c0491da 100644 --- a/openslides/motions/static/js/motions/diff.js +++ b/openslides/motions/static/js/motions/diff.js @@ -450,6 +450,32 @@ angular.module('OpenSlidesApp.motions.diff', ['OpenSlidesApp.motions.lineNumberi return ret; }; + /* + * This is a workardoun to prevent the last word of the inserted text from accidently being merged with the + * first word of the following line. + * + * This happens as trailing spaces in the change recommendation's text are frequently stripped, + * which is pretty nasty if the original text goes on after the affected line. So we insert a space + * if the original line ends with one. + */ + this._insertDanglingSpace = function(element) { + if (element.childNodes.length > 0) { + var lastChild = element.childNodes[element.childNodes.length - 1]; + if (lastChild.nodeType == TEXT_NODE && !lastChild.nodeValue.match(/[\S]/) && element.childNodes.length > 1) { + // If the text node only contains whitespaces, chances are high it's just space between block elmeents, + // like a line break between and + lastChild = element.childNodes[element.childNodes.length - 2]; + } + if (lastChild.nodeType == TEXT_NODE) { + if (lastChild.nodeValue === '' || lastChild.nodeValue.substr(-1) != ' ') { + lastChild.nodeValue += ' '; + } + } else { + this._insertDanglingSpace(lastChild); + } + } + }; + /* * This functions merges to arrays of nodes. The last element of nodes1 and the first element of nodes2 * are merged, if they are of the same type. @@ -583,6 +609,10 @@ angular.module('OpenSlidesApp.motions.diff', ['OpenSlidesApp.motions.lineNumberi followingFragment = this.htmlToFragment(followingHtml), newFragment = this.htmlToFragment(newHTML); + if (data.html.length > 0 && data.html.substr(-1) == ' ') { + this._insertDanglingSpace(newFragment); + } + var merged = this._replaceLinesMergeNodeArrays(previousFragment.childNodes, newFragment.childNodes); merged = this._replaceLinesMergeNodeArrays(merged, followingFragment.childNodes); diff --git a/tests/karma/motions/diff.service.test.js b/tests/karma/motions/diff.service.test.js index 1d7acc4cc..a11579a99 100644 --- a/tests/karma/motions/diff.service.test.js +++ b/tests/karma/motions/diff.service.test.js @@ -221,6 +221,22 @@ describe('linenumbering', function () { expect(merged).toBe('

Line 1 Line 2 Line 3
Line 4 Line
5

Replaced Line 10

Inserted Line 11 Line 11

'); }); + it('does not accidently merge two separate words', function() { + var merged = diffService.replaceLines(baseHtml1, '

Line 1INSERTION

', 1, 2), + containsError = merged.indexOf("Line 1INSERTIONLine 2"), + containsCorrectVersion = merged.indexOf("Line 1INSERTION Line 2"); + expect(containsError).toBe(-1); + expect(containsCorrectVersion).toBe(3); + }); + + it('does not accidently merge two separate words, even in lists', function() { + // The newlines between UL and LI are the problem here + var merged = diffService.replaceLines(baseHtml1, '', 6, 7), + containsError = merged.indexOf("Line 6InsertedLine 7"), + containsCorrectVersion = merged.indexOf("Line 6Inserted Line 7"); + expect(containsError).toBe(-1); + expect(containsCorrectVersion > 0).toBe(true); + }); }); describe('detecting the type of change', function() {