Esanders has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/367921 )

Change subject: Abstract definition of type equality when comparing inline nodes
......................................................................

Abstract definition of type equality when comparing inline nodes

Bug: T166801
Change-Id: I0f24d9d81b5491a8f09bc59e5f544f99751fd506
---
M src/dm/ve.dm.Model.js
M src/dm/ve.dm.VisualDiff.js
M src/ve.DiffMatchPatch.js
M tests/ui/ve.ui.DiffElement.test.js
4 files changed, 67 insertions(+), 8 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor 
refs/changes/21/367921/1

diff --git a/src/dm/ve.dm.Model.js b/src/dm/ve.dm.Model.js
index 007e3ba..399f5c0 100644
--- a/src/dm/ve.dm.Model.js
+++ b/src/dm/ve.dm.Model.js
@@ -280,6 +280,20 @@
        }
 };
 
+/**
+ * Check if this element is of the same type as another element for the 
purposes of diffing.
+ *
+ * Elements which aren't of the same type will always be shown as removal and 
an insertion,
+ * whereas comarable elements will be shown as an attribute change.
+ *
+ * @param {Object} element This element
+ * @param {Object} other Another element
+ * @return {boolean} Elements are of a comparable type
+ */
+ve.dm.Model.static.isDiffComparable = function ( element, other ) {
+       return element.type === other.type;
+};
+
 /* Methods */
 
 /**
@@ -417,3 +431,7 @@
 ve.dm.Model.prototype.getHashObject = function () {
        return this.constructor.static.getHashObject( this.element );
 };
+
+ve.dm.Model.prototype.isDiffComparable = function ( other ) {
+       return this.constructor.static.isDiffComparable( this.element, 
other.element );
+};
diff --git a/src/dm/ve.dm.VisualDiff.js b/src/dm/ve.dm.VisualDiff.js
index c6e2806..8104d02 100644
--- a/src/dm/ve.dm.VisualDiff.js
+++ b/src/dm/ve.dm.VisualDiff.js
@@ -163,7 +163,7 @@
 ve.dm.VisualDiff.prototype.compareDocChildren = function ( oldDocChild, 
newDocChild ) {
        var i, ilen, oldData, newData, oldStore, newStore;
 
-       if ( oldDocChild.length !== newDocChild.length || oldDocChild.type !== 
newDocChild.type ) {
+       if ( oldDocChild.length !== newDocChild.length || 
!oldDocChild.isDiffComparable( newDocChild ) ) {
                return false;
        }
 
@@ -327,7 +327,7 @@
                        if ( !oldNode.canContainContent() && 
!newNode.canContainContent() ) {
 
                                // There is no content change
-                               replacement = oldNode.type !== newNode.type;
+                               replacement = !oldNode.isDiffComparable( 
newNode );
                                diffInfo[ i ] = {
                                        linearDiff: null,
                                        replacement: replacement,
@@ -362,7 +362,7 @@
 
                        // If we got this far, they are both CBNs
                        } else {
-                               replacement = oldNode.type !== newNode.type;
+                               replacement = !oldNode.isDiffComparable( 
newNode );
 
                                if ( !replacement && new Date().getTime() < 
this.endTime ) {
                                        linearDiff = 
this.linearDiffer.getCleanDiff(
diff --git a/src/ve.DiffMatchPatch.js b/src/ve.DiffMatchPatch.js
index 85339aa..1e67a97 100644
--- a/src/ve.DiffMatchPatch.js
+++ b/src/ve.DiffMatchPatch.js
@@ -141,12 +141,20 @@
                        remove = [],
                        insert = [];
 
-               function equalUnannotated( element, index, other ) {
+               function equalUnannotated( other, element, index ) {
                        return 
ve.dm.ElementLinearData.static.compareElementsUnannotated( element, other[ 
index ] );
                }
 
-               function equalElements( element, index, other ) {
-                       return element.type && other[ index ].type && 
element.type === other[ index ].type;
+               function equalElements( other, element, index ) {
+                       if ( !( element.type && other[ index ].type && 
element.type === other[ index ].type ) ) {
+                               return false;
+                       }
+                       if ( ve.dm.LinearData.static.isOpenElementData( element 
) ) {
+                               // Elements have equal types, do a comparison
+                               return ve.dm.modelRegistry.lookup( element.type 
).static.isDiffComparable( element, other[ index ] );
+                       } else {
+                               return true;
+                       }
                }
 
                function isWhitespace( element ) {
@@ -294,7 +302,7 @@
                                aData.length === bData.length &&
                                ( ( aAction === DIFF_DELETE && bAction === 
DIFF_INSERT ) || ( aAction === DIFF_INSERT && bAction === DIFF_DELETE ) )
                        ) {
-                               if ( aData.every( equalUnannotated.bind( bData 
) ) ) {
+                               if ( aData.every( equalUnannotated.bind( this, 
bData ) ) ) {
                                        aAnnotations = new 
ve.dm.ElementLinearData( store, aData ).getAnnotationsFromRange( new ve.Range( 
0, aData.length ), true );
                                        bAnnotations = new 
ve.dm.ElementLinearData( store, bData ).getAnnotationsFromRange( new ve.Range( 
0, bData.length ), true );
 
@@ -313,7 +321,7 @@
                                                cleanDiff[ i + 1 ][ 0 ] = 
bAction === DIFF_DELETE ? DIFF_CHANGE_DELETE : DIFF_CHANGE_INSERT;
                                        }
                                }
-                               if ( aData.every( equalElements.bind( bData ) ) 
) {
+                               if ( aData.every( equalElements.bind( this, 
bData ) ) ) {
                                        attributeChanges = [];
                                        // eslint-disable-next-line no-loop-func
                                        bData.forEach( function ( element, i ) {
diff --git a/tests/ui/ve.ui.DiffElement.test.js 
b/tests/ui/ve.ui.DiffElement.test.js
index 9622ba7..befa3d3 100644
--- a/tests/ui/ve.ui.DiffElement.test.js
+++ b/tests/ui/ve.ui.DiffElement.test.js
@@ -431,9 +431,42 @@
                                                        '<li><p>foo</p></li>' +
                                                '</ul>' +
                                        '</div>'
+                       },
+                       {
+                               msg: 'Inline widget with same type but not diff 
comparable is marked as a remove/insert',
+                               oldDoc: '<p>Foo bar baz<span 
rel="test:inlineWidget" data-name="FooWidget"></span></p>',
+                               newDoc: '<p>Foo bar baz<span 
rel="test:inlineWidget" data-name="BarWidget"></span></p>',
+                               expected:
+                                       '<div 
class="ve-ui-diffElement-doc-child-change">' +
+                                               '<p>Foo bar baz' +
+                                                       '<del 
data-diff-action="remove"><span rel="test:inlineWidget" 
data-name="FooWidget"></span></del>' +
+                                                       '<ins 
data-diff-action="insert"><span rel="test:inlineWidget" 
data-name="BarWidget"></span></ins>' +
+                                               '</p>' +
+                                       '</div>'
                        }
                ];
 
+       function InlineWidgetNode() {
+               InlineWidgetNode.super.apply( this, arguments );
+       }
+       OO.inheritClass( InlineWidgetNode, ve.dm.LeafNode );
+       InlineWidgetNode.static.name = 'testInlineWidget';
+       InlineWidgetNode.static.matchTagNames = [ 'span' ];
+       InlineWidgetNode.static.matchRdfaTypes = [ 'test:inlineWidget' ];
+       InlineWidgetNode.static.isContent = true;
+       InlineWidgetNode.static.toDataElement = function ( domElements ) {
+               return {
+                       type: this.name,
+                       attributes: {
+                               name: domElements[ 0 ].getAttribute( 
'data-name' )
+                       }
+               };
+       };
+       InlineWidgetNode.static.isDiffComparable = function ( element, other ) {
+               return element.attributes.name === other.attributes.name;
+       };
+       ve.dm.modelRegistry.register( InlineWidgetNode );
+
        for ( i = 0, len = cases.length; i < len; i++ ) {
                oldDoc = ve.dm.converter.getModelFromDom( 
ve.createDocumentFromHtml( cases[ i ].oldDoc ) );
                newDoc = ve.dm.converter.getModelFromDom( 
ve.createDocumentFromHtml( cases[ i ].newDoc ) );

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I0f24d9d81b5491a8f09bc59e5f544f99751fd506
Gerrit-PatchSet: 1
Gerrit-Project: VisualEditor/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Esanders <esand...@wikimedia.org>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to