Diff-Bugfix: Insertions/Deletions beyond paragraph boundaries

This commit is contained in:
Tobias Hößl 2019-04-27 17:49:21 +02:00
parent 0675bdcf46
commit bc8739f017
No known key found for this signature in database
GPG Key ID: 1D780C7599C2D2A2
2 changed files with 64 additions and 8 deletions

View File

@ -886,6 +886,22 @@ describe('DiffService', () => {
}
));
it('detects inline insertions exceeding block paragraphs', inject([DiffService], (service: DiffService) => {
const before =
'<P>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</P>\n' +
'<P>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.</P>',
after =
'<P>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</P>\n' +
'<P>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.</P>';
const diff = service.diff(before, after);
expect(diff).toBe(
'<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.<ins> Insertion 1</ins></p>\n' +
'<p><ins>Insertion 2 </ins>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.</p>'
);
}));
it('does not lose formattings when multiple lines are deleted', inject(
[DiffService],
(service: DiffService) => {

View File

@ -2001,14 +2001,6 @@ export class DiffService {
}
);
// <del>deleted text</P></del><ins>inserted.</P></ins> => <del>deleted tet</del><ins>inserted.</ins></P>
diffUnnormalized = diffUnnormalized.replace(
/<del>([^<]*)<\/(p|div|blockquote|li)><\/del><ins>([^<]*)<\/\2><\/ins>\s*$/gi,
(whole: string, deleted: string, tag: string, inserted: string): string => {
return '<del>' + deleted + '</del><ins>' + inserted + '</ins></' + tag + '>';
}
);
// If larger inserted HTML text contains block elements, we separate the inserted text into
// inline <ins> elements and "insert"-class-based block elements.
// <ins>...<div>...</div>...</ins> => <ins>...</ins><div class="insert">...</div><ins>...</ins>
@ -2026,6 +2018,54 @@ export class DiffService {
}
);
// <del>deleted text</P></del><ins>inserted.</P></ins> => <del>deleted tet</del><ins>inserted.</ins></P>
diffUnnormalized = diffUnnormalized.replace(
/<del>([^<]*)<\/(p|div|blockquote|li)><\/del><ins>([^<]*)<\/\2>(\s*)<\/ins>/gi,
(whole: string, deleted: string, tag: string, inserted: string, white: string): string => {
return '<del>' + deleted + '</del><ins>' + inserted + '</ins></' + tag + '>' + white;
}
);
// <ins>...</p><p>...</ins> => <ins>...</ins></p><p><ins>...</ins>
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 +
'</' +
insDel +
'></' +
blockEnd +
'>' +
'<' +
blockStart +
blockAttrs +
'><' +
insDel +
'>' +
content2 +
'</' +
insDel +
'>'
);
} else {
return whole;
}
}
);
// Cleanup leftovers from the operation above, when <ins></ins>-tags ore <ins> </ins>-tags are left
// around block tags. It should be safe to remove them and just leave the whitespaces.
diffUnnormalized = diffUnnormalized.replace(