From 8650bc04019f153460462061b916c98558070e34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Ho=CC=88=C3=9Fl?= Date: Sat, 16 Sep 2017 17:09:40 +0200 Subject: [PATCH] Inline-Diff works when the first word in a paragraph is being replaced - fixes #3401 --- CHANGELOG | 5 ++-- openslides/motions/static/js/motions/diff.js | 26 ++++++++++++-------- tests/karma/motions/diff.service.test.js | 16 +++++++++--- 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index f0b162c9f..92b31043d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -21,7 +21,7 @@ Motions: - Fixed empty motion comment field in motion update form [#3194]. - Fixed error on category sort [#3318]. - Removed server side image to base64 transformation and - added local transformation [#3181] + added local transformation [#3181]. - Added support for export motions in a ZIP archive [#3189]. - Performance improvement for ZIP creation [#3251]. - Bugfix: Changing motion line length did not invalidate cache [#3202]. @@ -36,7 +36,8 @@ Motions: pdf/docx export [#3329]. - Added config value for pagenumber alignment in PDF [#3327]. - Bugfix: Several bugfixes regarding splitting list items in - change recommendations [#3288] + change recommendations [#3288]. +- Bugfix: Several bugfixes regarding diff version [#3407, #3408]. - Added inline Editing for motion reason [#3361]. - Added multiselect filter for motion comments [#3372]. - Added support for pinning personal notes to the window [#3360]. diff --git a/openslides/motions/static/js/motions/diff.js b/openslides/motions/static/js/motions/diff.js index 920ec857a..504ad90c5 100644 --- a/openslides/motions/static/js/motions/diff.js +++ b/openslides/motions/static/js/motions/diff.js @@ -1189,9 +1189,20 @@ angular.module('OpenSlidesApp.motions.diff', ['OpenSlidesApp.motions.lineNumberi var workaroundPrepend = ""; var str = this._diffString(workaroundPrepend + htmlOld, workaroundPrepend + htmlNew), - diffUnnormalized = str.replace(/^\s+/g, '').replace(/\s+$/g, '').replace(/ {2,}/g, ' ') - .replace(/<\/ins>/gi, '').replace(/<\/del>/gi, ''); + diffUnnormalized = str.replace(/^\s+/g, '').replace(/\s+$/g, '').replace(/ {2,}/g, ' '); + // Remove tags that only delete line numbers + // We need to do this before removing as done in one of the next statements + diffUnnormalized = diffUnnormalized.replace( + /((
<\/del>)?(]+os-line-number[^>]+?>)(\s|<\/?del>)*<\/span>)<\/del>/gi, + function(found,tag,br,span) { + return (br !== undefined ? br : '') + span + ' '; + } + ); + + diffUnnormalized = diffUnnormalized.replace(/<\/ins>/gi, '').replace(/<\/del>/gi, ''); + + // Move whitespaces around inserted P's out of the INS-tag diffUnnormalized = diffUnnormalized.replace( /(\s*)(]*)?>[\s\S]*?<\/p>)(\s*)<\/ins>/gim, function(match, whiteBefore, inner, tagInner, whiteAfter) { @@ -1205,6 +1216,8 @@ angular.module('OpenSlidesApp.motions.diff', ['OpenSlidesApp.motions.lineNumberi } ); + // If only a few characters of a word have changed, don't display this as a replacement of the whole word, + // but only of these specific characters diffUnnormalized = diffUnnormalized.replace(/([a-z0-9,_-]* ?)<\/del>([a-z0-9,_-]* ?)<\/ins>/gi, function (found, oldText, newText) { var foundDiff = false, commonStart = '', commonEnd = '', remainderOld = oldText, remainderNew = newText; @@ -1242,14 +1255,7 @@ angular.module('OpenSlidesApp.motions.diff', ['OpenSlidesApp.motions.lineNumberi return out; }); - // Remove tags that only delete line numbers - diffUnnormalized = diffUnnormalized.replace( - /((
)?]+os-line-number[^>]+?>\s*<\/span>)<\/del>/gi, - function(found,tag) { - return tag; - } - ); - + // Replace spaces in line numbers by   diffUnnormalized = diffUnnormalized.replace( /]+os-line-number[^>]+?>\s*<\/span>/gi, function(found) { diff --git a/tests/karma/motions/diff.service.test.js b/tests/karma/motions/diff.service.test.js index de5e65999..a8fcacb84 100644 --- a/tests/karma/motions/diff.service.test.js +++ b/tests/karma/motions/diff.service.test.js @@ -433,6 +433,14 @@ describe('linenumbering', function () { expect(diff).toBe('Test1 Test2 Test3 Test4 Test5 Test9Test1 Test6 Test7 Test8 Test9'); }); + it('does not result in separate paragraphs when only the first word has changed', function () { + var before = '

 Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor

', + after = '

Bla ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor

'; + var diff = diffService.diff(before, after); + + expect(diff).toBe('

 LoremBla ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor

'); + }); + it('merges multiple inserts and deletes', function () { var before = "Some additional text to circumvent the threshold Test1 Test2 Test3 Test4 Test5 Test9", after = "Some additional text to circumvent the threshold Test1 Test6 Test7 Test8 Test9"; @@ -538,10 +546,10 @@ describe('linenumbering', function () { brMarkup(14) + 'gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.

', after= '

Test

'; var diff = diffService.diff(before, after).toLowerCase(), - expected = '

' + - noMarkup(13).replace(/ /, "\u00A0") + 'diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd ' + - brMarkup(14).replace(/ /, "\u00A0") + 'gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.

' + - '

Test

'; + expected = '

' + + noMarkup(13) + 'diam voluptua. at vero eos et accusam et justo duo dolores et ea rebum. stet clita kasd ' + + brMarkup(14) + 'gubergren, no sea takimata sanctus est lorem ipsum dolor sit amet.' + + 'test

'; expect(diff).toBe(expected.toLowerCase()); });