Sort attributes before applying the diff - fixes #3402

This commit is contained in:
Tobias Hößl 2017-09-16 14:03:45 +02:00
parent c4a25637d6
commit da8f825d42
2 changed files with 29 additions and 12 deletions

View File

@ -625,21 +625,30 @@ angular.module('OpenSlidesApp.motions.diff', ['OpenSlidesApp.motions.lineNumberi
*/
this._normalizeHtmlForDiff = function (html) {
// Convert all HTML tags to uppercase, but leave the values of attributes unchanged
// All attributes and CSS class names are sorted alphabetically
html = html.replace(/<(\/?[a-z]*)( [^>]*)?>/ig, function (html, tag, attributes) {
var tagNormalized = tag.toUpperCase();
if (attributes === undefined) {
attributes = "";
}
attributes = attributes.replace(/( [^"'=]*)(= *((["'])(.*?)\4))?/gi, function (attr, attrName, attrRest, attrRest2, quot, attrValue) {
var attrNormalized = attrName.toUpperCase();
if (attrRest !== undefined) {
if (attrNormalized === ' CLASS') {
attrValue = attrValue.split(' ').sort().join(' ');
var attributesList = [],
attributesMatcher = /( [^"'=]*)(= *((["'])(.*?)\4))?/gi,
match;
do {
match = attributesMatcher.exec(attributes);
if (match) {
var attrNormalized = match[1].toUpperCase(),
attrValue = match[5];
if (match[2] !== undefined) {
if (attrNormalized === ' CLASS') {
attrValue = attrValue.split(' ').sort().join(' ');
}
attrNormalized += "=" + match[4] + attrValue + match[4];
}
attrNormalized += "=" + quot + attrValue + quot;
attributesList.push(attrNormalized);
}
return attrNormalized;
});
} while (match);
attributes = attributesList.sort().join('');
return "<" + tagNormalized + attributes + ">";
});

View File

@ -5,10 +5,10 @@ describe('linenumbering', function () {
var diffService, baseHtml1, baseHtmlDom1, baseHtml2, baseHtmlDom2, baseHtml3, baseHtmlDom3,
brMarkup = function (no) {
return '<br class="os-line-break">' +
'<span class="line-number-' + no + ' os-line-number" data-line-number="' + no + '" contenteditable="false">&nbsp;</span>';
'<span class="line-number-' + no + ' os-line-number" contenteditable="false" data-line-number="' + no + '">&nbsp;</span>';
},
noMarkup = function (no) {
return '<span class="line-number-' + no + ' os-line-number" data-line-number="' + no + '" contenteditable="false">&nbsp;</span>';
return '<span class="line-number-' + no + ' os-line-number" contenteditable="false" data-line-number="' + no + '">&nbsp;</span>';
};
beforeEach(inject(function (_diffService_, _lineNumberingService_) {
@ -374,12 +374,12 @@ describe('linenumbering', function () {
expect(normalized).toBe('The <STRONG>brown</STRONG> fox')
});
it('uppercases the names of html attributes, but not the values', function () {
it('uppercases the names of html attributes, but not the values, and sort the attributes', function () {
var unnormalized = 'This is our cool <a href="https://www.openslides.de/">home page</a> - have a look! ' +
'<input type="checkbox" checked title=\'A title with "s\'>',
normalized = diffService._normalizeHtmlForDiff(unnormalized);
expect(normalized).toBe('This is our cool <A HREF="https://www.openslides.de/">home page</A> - have a look! ' +
'<INPUT TYPE="checkbox" CHECKED TITLE=\'A title with "s\'>')
'<INPUT CHECKED TITLE=\'A title with "s\' TYPE="checkbox">')
});
it('strips unnecessary spaces', function () {
@ -569,6 +569,14 @@ describe('linenumbering', function () {
expect(diff).toBe('<p>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 <del>gubergren </del>bla, no sea takimata sanctus est Lorem ipsum dolor <ins>gubergren </ins>sit amet.</p>');
});
it('works with style-tags in spans', function () {
var before = '<p class="os-split-before os-split-after"><span class="os-line-number line-number-4" data-line-number="4" contenteditable="false">&nbsp;</span><span style="color: #0000ff;" class="os-split-before os-split-after">sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing </span></p>',
after = '<p class="os-split-after os-split-before"><span class="os-split-after os-split-before" style="color: #0000ff;">sanctus est Lorem ipsum dolor sit amet. Test Lorem ipsum dolor sit amet, consetetur sadipscing </span></p>';
var diff = diffService.diff(before, after);
expect(diff).toBe('<p class="os-split-after os-split-before"><span class="line-number-4 os-line-number" contenteditable="false" data-line-number="4">&nbsp;</span><span class="os-split-after os-split-before" style="color: #0000ff;">sanctus est Lorem ipsum dolor sit amet. <ins>Test </ins>Lorem ipsum dolor sit amet, consetetur sadipscing </span></p>');
});
});
describe('ignoring line numbers', function () {