Esanders has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/62352


Change subject: Use a smarter comparison of annotations when creating 
open/close tags
......................................................................

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

Currently we just compare by store index, but a bold annotation
with data-parsoid attributes set should merge with a new clean bold
annotation. Similar rules apply to link annotations.

Bug: 48110
Change-Id: I93586919002c78732228e08b134e67e1a94f8ad7
---
M modules/ve/dm/annotations/ve.dm.LinkAnnotation.js
M modules/ve/dm/annotations/ve.dm.MWExternalLinkAnnotation.js
M modules/ve/dm/annotations/ve.dm.MWInternalLinkAnnotation.js
M modules/ve/dm/annotations/ve.dm.TextStyleAnnotation.js
M modules/ve/dm/ve.dm.Annotation.js
M modules/ve/dm/ve.dm.AnnotationSet.js
M modules/ve/dm/ve.dm.Converter.js
7 files changed, 76 insertions(+), 14 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor 
refs/changes/52/62352/1

diff --git a/modules/ve/dm/annotations/ve.dm.LinkAnnotation.js 
b/modules/ve/dm/annotations/ve.dm.LinkAnnotation.js
index 571f202..28bdd6c 100644
--- a/modules/ve/dm/annotations/ve.dm.LinkAnnotation.js
+++ b/modules/ve/dm/annotations/ve.dm.LinkAnnotation.js
@@ -45,6 +45,15 @@
        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 );
diff --git a/modules/ve/dm/annotations/ve.dm.MWExternalLinkAnnotation.js 
b/modules/ve/dm/annotations/ve.dm.MWExternalLinkAnnotation.js
index 4ee505e..e7cb8b8 100644
--- a/modules/ve/dm/annotations/ve.dm.MWExternalLinkAnnotation.js
+++ b/modules/ve/dm/annotations/ve.dm.MWExternalLinkAnnotation.js
@@ -50,6 +50,16 @@
        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 );
diff --git a/modules/ve/dm/annotations/ve.dm.MWInternalLinkAnnotation.js 
b/modules/ve/dm/annotations/ve.dm.MWInternalLinkAnnotation.js
index b803bf2..c837de8 100644
--- a/modules/ve/dm/annotations/ve.dm.MWInternalLinkAnnotation.js
+++ b/modules/ve/dm/annotations/ve.dm.MWInternalLinkAnnotation.js
@@ -67,6 +67,15 @@
        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 );
diff --git a/modules/ve/dm/annotations/ve.dm.TextStyleAnnotation.js 
b/modules/ve/dm/annotations/ve.dm.TextStyleAnnotation.js
index 15fd0d7..4989bd7 100644
--- a/modules/ve/dm/annotations/ve.dm.TextStyleAnnotation.js
+++ b/modules/ve/dm/annotations/ve.dm.TextStyleAnnotation.js
@@ -65,6 +65,11 @@
        return [ doc.createElement( nodeNames[dataElement.type.substring( 10 )] 
) ];
 };
 
+/* Methods */
+
+ve.dm.TextStyleAnnotation.prototype.getComparableObject = function () {
+       return { 'type': this.getType() };
+};
 
 /* Registration */
 
diff --git a/modules/ve/dm/ve.dm.Annotation.js 
b/modules/ve/dm/ve.dm.Annotation.js
index b75fa60..b308e26 100644
--- a/modules/ve/dm/ve.dm.Annotation.js
+++ b/modules/ve/dm/ve.dm.Annotation.js
@@ -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.prototype.getDomElements = function ( doc ) {
        return this.constructor.static.toDomElements( this.element, doc || 
document );
 };
+
+/**
+ * Get an object which defines an annotation.
+ *
+ * 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()
+       };
+};
diff --git a/modules/ve/dm/ve.dm.AnnotationSet.js 
b/modules/ve/dm/ve.dm.AnnotationSet.js
index 929c0fd..793dac2 100644
--- a/modules/ve/dm/ve.dm.AnnotationSet.js
+++ b/modules/ve/dm/ve.dm.AnnotationSet.js
@@ -111,7 +111,7 @@
  * 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;
@@ -221,6 +221,24 @@
 };
 
 /**
+ * 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.
  *
  * This is equivalent to (but more efficient than) `!this.filter( .. 
).isEmpty()`.
@@ -229,7 +247,7 @@
  *
  * @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 );
diff --git a/modules/ve/dm/ve.dm.Converter.js b/modules/ve/dm/ve.dm.Converter.js
index 44b2774..a290251 100644
--- a/modules/ve/dm/ve.dm.Converter.js
+++ b/modules/ve/dm/ve.dm.Converter.js
@@ -63,17 +63,15 @@
  * @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 @@
                // 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 );

-- 
To view, visit https://gerrit.wikimedia.org/r/62352
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I93586919002c78732228e08b134e67e1a94f8ad7
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Esanders <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to