From bc8739f017192a88156d2a7983c2b3d1632b23a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Ho=CC=88=C3=9Fl?= Date: Sat, 27 Apr 2019 17:49:21 +0200 Subject: [PATCH] Diff-Bugfix: Insertions/Deletions beyond paragraph boundaries --- .../app/core/ui-services/diff.service.spec.ts | 16 ++++++ .../src/app/core/ui-services/diff.service.ts | 56 ++++++++++++++++--- 2 files changed, 64 insertions(+), 8 deletions(-) diff --git a/client/src/app/core/ui-services/diff.service.spec.ts b/client/src/app/core/ui-services/diff.service.spec.ts index 48a0e4bcc..186f007d8 100644 --- a/client/src/app/core/ui-services/diff.service.spec.ts +++ b/client/src/app/core/ui-services/diff.service.spec.ts @@ -886,6 +886,22 @@ describe('DiffService', () => { } )); + it('detects inline insertions exceeding block paragraphs', inject([DiffService], (service: DiffService) => { + const before = + '

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.

', + after = + '

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. Insertion 1

\n' + + '

Insertion 2 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.

'; + + const diff = service.diff(before, after); + + 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. Insertion 1

\n' + + '

Insertion 2 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.

' + ); + })); + it('does not lose formattings when multiple lines are deleted', inject( [DiffService], (service: DiffService) => { diff --git a/client/src/app/core/ui-services/diff.service.ts b/client/src/app/core/ui-services/diff.service.ts index f565fd2f7..1cc637550 100644 --- a/client/src/app/core/ui-services/diff.service.ts +++ b/client/src/app/core/ui-services/diff.service.ts @@ -2001,14 +2001,6 @@ export class DiffService { } ); - // deleted text

inserted.

=> deleted tetinserted.

- diffUnnormalized = diffUnnormalized.replace( - /([^<]*)<\/(p|div|blockquote|li)><\/del>([^<]*)<\/\2><\/ins>\s*$/gi, - (whole: string, deleted: string, tag: string, inserted: string): string => { - return '' + deleted + '' + inserted + ''; - } - ); - // If larger inserted HTML text contains block elements, we separate the inserted text into // inline elements and "insert"-class-based block elements. // ...
...
...
=> ...
...
... @@ -2026,6 +2018,54 @@ export class DiffService { } ); + // deleted text

inserted.

=> deleted tetinserted.

+ diffUnnormalized = diffUnnormalized.replace( + /([^<]*)<\/(p|div|blockquote|li)><\/del>([^<]*)<\/\2>(\s*)<\/ins>/gi, + (whole: string, deleted: string, tag: string, inserted: string, white: string): string => { + return '' + deleted + '' + inserted + '' + white; + } + ); + + // ...

... => ...

... + diffUnnormalized = diffUnnormalized.replace( + /<(ins|del)>([\s\S]*?)<\/(p|div|blockquote|li)>\s*<(p|div|blockquote|li)([^>]*)>([\s\S]*?)<\/\1>/gi, + ( + whole: string, + insDel: string, + content1: string, + blockEnd: string, + blockStart: string, + blockAttrs: string, + content2: string + ): string => { + if (this.isValidInlineHtml(content1) && this.isValidInlineHtml(content2)) { + return ( + '<' + + insDel + + '>' + + content1 + + '' + + '<' + + blockStart + + blockAttrs + + '><' + + insDel + + '>' + + content2 + + '' + ); + } else { + return whole; + } + } + ); + // Cleanup leftovers from the operation above, when -tags ore -tags are left // around block tags. It should be safe to remove them and just leave the whitespaces. diffUnnormalized = diffUnnormalized.replace(