From 023f3988758781512a2a0b3c9b5cefde339dacb5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tobias=20Ho=CC=88=C3=9Fl?=
Date: Mon, 22 Oct 2018 20:20:47 +0200
Subject: [PATCH] Diff Bugfix: inserted/deleted list items
---
CHANGELOG.rst | 13 ++++---
openslides/motions/static/js/motions/diff.js | 39 ++++++++++++++------
tests/karma/motions/diff.service.test.js | 18 ++++++++-
3 files changed, 51 insertions(+), 19 deletions(-)
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index e0c764797..eec45f75b 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -6,14 +6,17 @@ https://openslides.org/
Version 2.3.1 (unreleased)
==========================
+`Milestone `_
Bugfixes:
- - Fixed image browser in CKEditor plugin to show uploaded images.
- - Fixed sorting of users in dropdowns for speakers, submitters and candidates.
- - Fixed election ballot paper layout (more space required for global 'no').
- - Fixed missing output of special poll values (for motions and elections).
+ - Fixed image browser in CKEditor plugin to show uploaded images [#3889].
+ - Fixed sorting of users in dropdowns for speakers, submitters and candidates [#3932].
+ - Fixed election ballot paper layout (more space required for global 'no') [#3932].
+ - Fixed missing output of special poll values (for motions and elections) [#3932].
- Fixed amendment csv export (added missing submitters and recommendation, removed
- html tags for old and new text).
+ html tags for old and new text) [#3942].
+ - Fixed motion/amendment diff bug: does not delete a paragraph/list item
+ before an new one was inserted [#3943].
Version 2.3 (2018-09-20)
diff --git a/openslides/motions/static/js/motions/diff.js b/openslides/motions/static/js/motions/diff.js
index d6abfbf65..8600986e6 100644
--- a/openslides/motions/static/js/motions/diff.js
+++ b/openslides/motions/static/js/motions/diff.js
@@ -1545,6 +1545,33 @@ angular.module('OpenSlidesApp.motions.diff', ['OpenSlidesApp.motions.lineNumberi
}
);
+ // ... => ...
+ diffUnnormalized = diffUnnormalized.replace(
+ /<(ins|del)><(p|div|blockquote|li)([^>]*)>([\s\S]*)<\/\2><\/\1>/gi,
+ function(whole, insDel, block, blockArguments, content) {
+ // Prevent accidental matches like ...
......
+ if (content.match(/<(ins|del)>/gi)) {
+ return whole;
+ }
+
+ // Add the CSS-class to the existing "class"-attribute, or add one
+ var newArguments = blockArguments;
+ var modificationClass = (insDel.toLowerCase() === 'ins' ? 'insert' : 'delete');
+ if (newArguments.match(/class="/gi)) {
+ // class="someclass" => class="someclass insert"
+ newArguments = newArguments.replace(/(class\s*=\s*)(["'])([^\2]*)\2/gi,
+ function(classWhole, attr, para, content) {
+ return attr + para + content + ' ' + modificationClass + para;
+ }
+ );
+ } else {
+ newArguments += ' class="' + modificationClass + '"';
+ }
+
+ return '<' + block + newArguments + '>' + content + '' + block + '>';
+ }
+ );
+
if (diffUnnormalized.substr(0, workaroundPrepend.length) === workaroundPrepend) {
diffUnnormalized = diffUnnormalized.substring(workaroundPrepend.length);
@@ -1554,18 +1581,6 @@ angular.module('OpenSlidesApp.motions.diff', ['OpenSlidesApp.motions.lineNumberi
if (this._diffDetectBrokenDiffHtml(diffUnnormalized)) {
diff = this._diffParagraphs(htmlOld, htmlNew, lineLength, firstLineNumber);
} else {
- diffUnnormalized = diffUnnormalized.replace(/.*?(\n.*?)*<\/ins>/gi, function (found) {
- found = found.replace(/<(div|p|li)[^>]*>/gi, function(match) { return match + ''; });
- found = found.replace(/<\/(div|p|li)[^>]*>/gi, function(match) { return '' + match; });
- return found;
- });
- diffUnnormalized = diffUnnormalized.replace(/.*?(\n.*?)*<\/del>/gi, function (found) {
- found = found.replace(/<(div|p|li)[^>]*>/gi, function(match) { return match + ''; });
- found = found.replace(/<\/(div|p|li)[^>]*>/gi, function(match) { return '' + match; });
- return found;
- });
- diffUnnormalized = diffUnnormalized.replace(/^(.*)<\/p><\/del>$/gi, function(match, inner) { return "
" + inner + "
"; });
-
var node = document.createElement('div');
node.innerHTML = diffUnnormalized;
diff = node.innerHTML;
diff --git a/tests/karma/motions/diff.service.test.js b/tests/karma/motions/diff.service.test.js
index 5891aa047..0e32d88e1 100644
--- a/tests/karma/motions/diff.service.test.js
+++ b/tests/karma/motions/diff.service.test.js
@@ -563,7 +563,7 @@ describe('linenumbering', function () {
var before = "Ihr könnt ohne Sorge fortgehen.'Da meckerte die Alte und machte sich getrost auf den Weg.
",
after = "";
var diff = diffService.diff(before, after);
- expect(diff).toBe("Ihr könnt ohne Sorge fortgehen.'Da meckerte die Alte und machte sich getrost auf den Weg.
");
+ expect(diff).toBe("Ihr könnt ohne Sorge fortgehen.'Da meckerte die Alte und machte sich getrost auf den Weg.
");
});
it('does not repeat the last word (1)', function () {
@@ -661,7 +661,21 @@ describe('linenumbering', function () {
'Gegenüber
';
var diff = diffService.diff(inHtml, outHtml);
expect(diff).toBe('Test 123
wir strikt ab. lehnen wir ' + brMarkup(1486) + 'ab.
' + noMarkup(1487) + 'Gegenüber
')
- });
+ });
+
+ it('does not delete a paragraph before an inserted one', function () {
+ var inHtml = '- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
\n' +
+ '
',
+ outHtml = '\n' +
+ '- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
\n' +
+ '- At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
\n' +
+ '
';
+ var diff = diffService.diff(inHtml, outHtml);
+ expect(diff).toBe('' +
+ '- Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
' +
+ '- At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
' +
+ '
');
+ });
});
describe('ignoring line numbers', function () {