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