Merge "Use a smarter comparison of annotations when creating open/close tags"

This commit is contained in:
jenkins-bot 2013-05-06 18:52:30 +00:00 committed by Gerrit Code Review
commit bf0a227fd6
7 changed files with 76 additions and 14 deletions

View file

@ -45,6 +45,15 @@ ve.dm.LinkAnnotation.static.toDomElements = function ( dataElement, doc ) {
return [ domElement ];
};
/* Methods */
ve.dm.LinkAnnotation.prototype.getComparableObject = function () {
return {
'type': this.getType(),
'href': this.getAttribute( 'href' )
};
};
/* Registration */
ve.dm.modelRegistry.register( ve.dm.LinkAnnotation );

View file

@ -50,6 +50,16 @@ ve.dm.MWExternalLinkAnnotation.static.toDomElements = function ( dataElement ) {
return parentResult;
};
/* Methods */
ve.dm.MWExternalLinkAnnotation.prototype.getComparableObject = function () {
return {
'type': this.getType(),
'href': this.getAttribute( 'href' ),
'rel': this.getAttribute( 'rel' ) || 'mw:ExtLink'
};
};
/* Registration */
ve.dm.modelRegistry.register( ve.dm.MWExternalLinkAnnotation );

View file

@ -67,6 +67,15 @@ ve.dm.MWInternalLinkAnnotation.static.toDomElements = function ( dataElement, do
return [ domElement ];
};
/* Methods */
ve.dm.MWInternalLinkAnnotation.prototype.getComparableObject = function () {
return {
'type': this.getType(),
'title': this.getAttribute( 'title' )
};
};
/* Registration */
ve.dm.modelRegistry.register( ve.dm.MWInternalLinkAnnotation );

View file

@ -65,6 +65,11 @@ ve.dm.TextStyleAnnotation.static.toDomElements = function ( dataElement, doc ) {
return [ doc.createElement( nodeNames[dataElement.type.substring( 10 )] ) ];
};
/* Methods */
ve.dm.TextStyleAnnotation.prototype.getComparableObject = function () {
return { 'type': this.getType() };
};
/* Registration */

View file

@ -15,6 +15,7 @@
* only override static properties and functions.
*
* @class
* @extends {ve.dm.Model}
* @constructor
* @param {Object} element Linear model annotation
*/
@ -51,3 +52,17 @@ ve.dm.Annotation.static.enableAboutGrouping = false;
ve.dm.Annotation.prototype.getDomElements = function ( doc ) {
return this.constructor.static.toDomElements( this.element, doc || document );
};
/**
* Get an object containing comparable annotation properties.
*
* This is used by the converter to merge adjacent annotations.
*
* @returns {Object} An object containing a subset of the annotation's properties
*/
ve.dm.Annotation.prototype.getComparableObject = function () {
return {
'type': this.getType(),
'attributes': this.getAttributes()
};
};

View file

@ -111,7 +111,7 @@ ve.dm.AnnotationSet.prototype.getLength = function () {
* Check if the set is empty.
*
* @method
* @returns {boolean} True if the set is empty, false otherwise
* @returns {boolean} The set is empty
*/
ve.dm.AnnotationSet.prototype.isEmpty = function () {
return this.getLength() === 0;
@ -220,6 +220,24 @@ ve.dm.AnnotationSet.prototype.filter = function ( callback, returnBool ) {
return returnBool ? false : result;
};
/**
* Check if the set contains an annotation comparable to the specified one.
*
* getComparableObject is used to compare the annotations, and should return
* true if an annotation is found which is mergeable with the specified one.
*
* @param {ve.dm.Annotation} annotation Annotation to compare to
* @returns {boolean} At least one comprable annotation found
*/
ve.dm.AnnotationSet.prototype.containsComparable = function ( annotation ) {
return this.filter( function ( a ) {
return ve.compareObjects(
annotation.getComparableObject(),
a.getComparableObject()
);
}, true );
};
/**
* Check if the set contains at least one annotation where a given property matches a given filter.
*
@ -229,7 +247,7 @@ ve.dm.AnnotationSet.prototype.filter = function ( callback, returnBool ) {
*
* @method
* @param {Function} callback Function that takes an annotation and returns boolean true to include
* @returns {boolean} True if at least one annotation matches, false otherwise
* @returns {boolean} At least one matching annotation found
*/
ve.dm.AnnotationSet.prototype.containsMatching = function ( callback ) {
return this.filter( callback, true );

View file

@ -63,17 +63,15 @@ ve.dm.Converter.getDataContentFromText = function ( text, annotations ) {
* @param {ve.dm.AnnotationSet} currentSet The set of annotations currently opened. Will be modified.
* @param {ve.dm.AnnotationSet} targetSet The set of annotations we want to have.
* @param {Function} open Callback called when an annotation is opened. Passed a ve.dm.Annotation.
* @param {Function} close Callback called when an annotation is closed. Passed a ve.dm.Annotation.
* @param {Function} close Callback called when an annotation is closed.
*/
ve.dm.Converter.openAndCloseAnnotations = function ( currentSet, targetSet, open, close ) {
var i, len, arr, annotation, annotationIndex, startClosingAt;
var i, len, annotation, startClosingAt;
// Close annotations as needed
// Go through annotationStack from bottom to top (low to high),
// and find the first annotation that's not in annotations.
arr = currentSet.getIndexes();
for ( i = 0, len = arr.length; i < len; i++ ) {
annotationIndex = arr[i];
if ( !targetSet.containsIndex( annotationIndex ) ) {
for ( i = 0, len = currentSet.getLength(); i < len; i++ ) {
if ( !targetSet.containsComparable( currentSet.get( i ) ) ) {
startClosingAt = i;
break;
}
@ -82,18 +80,16 @@ ve.dm.Converter.openAndCloseAnnotations = function ( currentSet, targetSet, open
// Close all annotations from top to bottom (high to low)
// until we reach startClosingAt
for ( i = currentSet.getLength() - 1; i >= startClosingAt; i-- ) {
close( arr[i] );
close();
// Remove from currentClone
currentSet.removeAt( i );
}
}
// Open annotations as needed
arr = targetSet.getIndexes();
for ( i = 0, len = arr.length; i < len; i++ ) {
annotationIndex = arr[i];
if ( !currentSet.containsIndex( annotationIndex ) ) {
annotation = targetSet.getStore().value( annotationIndex );
for ( i = 0, len = targetSet.getLength(); i < len; i++ ) {
annotation = targetSet.get( i );
if ( !currentSet.containsComparable( annotation ) ) {
open( annotation );
// Add to currentClone
currentSet.push( annotation );