Only use HTML attributes when comparing annotations for serialisation

The UI still needs a simplified version of annotation comparison
so it can clear/set annotations, whereas for serailisation we need
to compare selected HTML attributes (and once Parsoid is fixed,
compare all attributes).

Change-Id: I1a5521a3f51ea373a21cfbc9a007a2381c12f4fe
This commit is contained in:
Ed Sanders 2013-06-25 16:09:51 +01:00
parent d31918d145
commit 29d61dbea4
5 changed files with 52 additions and 12 deletions

View file

@ -52,8 +52,7 @@ ve.dm.LinkAnnotation.static.toDomElements = function ( dataElement, doc ) {
ve.dm.LinkAnnotation.prototype.getComparableObject = function () { ve.dm.LinkAnnotation.prototype.getComparableObject = function () {
return { return {
'type': this.getType(), 'type': this.getType(),
'href': this.getAttribute( 'href' ), 'href': this.getAttribute( 'href' )
'htmlAttributes': this.getComparableHtmlAttributes()
}; };
}; };

View file

@ -69,8 +69,7 @@ ve.dm.TextStyleAnnotation.static.toDomElements = function ( dataElement, doc ) {
ve.dm.TextStyleAnnotation.prototype.getComparableObject = function () { ve.dm.TextStyleAnnotation.prototype.getComparableObject = function () {
return { return {
'type': this.getType(), 'type': this.getType()
'htmlAttributes': this.getComparableHtmlAttributes()
}; };
}; };

View file

@ -79,13 +79,36 @@ ve.dm.Annotation.prototype.getComparableObject = function () {
* *
* This should be removed once similar annotation merging is handled correctly * This should be removed once similar annotation merging is handled correctly
* by Parsoid. * by Parsoid.
*
* @returns {Object} An object all HTML attributes except data-parsoid
*/ */
ve.dm.Annotation.prototype.getComparableHtmlAttributes = function () { ve.dm.Annotation.prototype.getComparableHtmlAttributes = function () {
var i, length, attributes = ve.copyArray( this.getHtmlAttributes() ); var comparableAttributes, attributes = this.getHtmlAttributes();
for ( i = 0, length = attributes.length; i < length; i++ ) {
if ( attributes[i].values ) { if ( attributes[0] ) {
delete attributes[i].values['data-parsoid']; comparableAttributes = ve.copyObject( attributes[0].values );
} delete comparableAttributes['data-parsoid'];
return comparableAttributes;
} else {
return {};
} }
return attributes; };
/**
* HACK: This method adds in HTML attributes so comparable objects aren't serialized
* together if they have different HTML attributes.
*
* This method needs to be different from getComparableObject which is
* still used for editing annotations.
*
* @returns {Object} An object containing a subset of the annotation's properties and HTML attributes
*/
ve.dm.Annotation.prototype.getComparableObjectForSerialization = function () {
var object = this.getComparableObject(),
htmlAttributes = this.getComparableHtmlAttributes();
if ( !ve.isEmptyObject( htmlAttributes ) ) {
object.htmlAttributes = htmlAttributes;
}
return object;
}; };

View file

@ -256,6 +256,25 @@ ve.dm.AnnotationSet.prototype.containsComparable = function ( annotation ) {
}, true ); }, true );
}; };
/**
* HACK: Check if the set contains an annotation comparable to the specified one
* for the purposes of serialization.
*
* This method uses getComparableObjectForSerialization which also includes
* HTML attributes.
*
* @param {ve.dm.Annotation} annotation Annotation to compare to
* @returns {boolean} At least one comprable annotation found
*/
ve.dm.AnnotationSet.prototype.containsComparableForSerialization = function ( annotation ) {
return this.filter( function ( a ) {
return ve.compare(
annotation.getComparableObjectForSerialization(),
a.getComparableObjectForSerialization()
);
}, true );
};
/** /**
* Check if the set contains at least one annotation where a given property matches a given filter. * Check if the set contains at least one annotation where a given property matches a given filter.
* *

View file

@ -74,7 +74,7 @@ ve.dm.Converter.openAndCloseAnnotations = function ( currentSet, targetSet, open
// Go through annotationStack from bottom to top (low to high), // Go through annotationStack from bottom to top (low to high),
// and find the first annotation that's not in annotations. // and find the first annotation that's not in annotations.
for ( i = 0, len = currentSet.getLength(); i < len; i++ ) { for ( i = 0, len = currentSet.getLength(); i < len; i++ ) {
if ( !targetSet.containsComparable( currentSet.get( i ) ) ) { if ( !targetSet.containsComparableForSerialization( currentSet.get( i ) ) ) {
startClosingAt = i; startClosingAt = i;
break; break;
} }
@ -92,7 +92,7 @@ ve.dm.Converter.openAndCloseAnnotations = function ( currentSet, targetSet, open
// Open annotations as needed // Open annotations as needed
for ( i = 0, len = targetSet.getLength(); i < len; i++ ) { for ( i = 0, len = targetSet.getLength(); i < len; i++ ) {
annotation = targetSet.get( i ); annotation = targetSet.get( i );
if ( !currentSet.containsComparable( annotation ) ) { if ( !currentSet.containsComparableForSerialization( annotation ) ) {
open( annotation ); open( annotation );
// Add to currentClone // Add to currentClone
currentSet.push( annotation ); currentSet.push( annotation );