Esanders has uploaded a new change for review.

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

Change subject: Factor out class <-> attribute mappings from BlockImageNode
......................................................................

Factor out class <-> attribute mappings from BlockImageNode

Create a mixin with functionality to extract attributes from classes
and vice-versa.

Change-Id: I4fc42e1468a9f0860c7c13e73967204bdf5ad78d
---
M VisualEditor.php
M modules/ve-mw/dm/nodes/ve.dm.MWBlockImageNode.js
A modules/ve-mw/dm/nodes/ve.dm.MWClassAttributeNode.js
3 files changed, 123 insertions(+), 72 deletions(-)


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

diff --git a/VisualEditor.php b/VisualEditor.php
index bc2c6c4..d21b244 100644
--- a/VisualEditor.php
+++ b/VisualEditor.php
@@ -699,6 +699,8 @@
                        // dm
                        'modules/ve-mw/dm/ve.dm.MW.js',
 
+                       'modules/ve-mw/dm/nodes/ve.dm.MWClassAttributeNode.js',
+
                        'modules/ve-mw/dm/nodes/ve.dm.MWEntityNode.js',
                        'modules/ve-mw/dm/nodes/ve.dm.MWExtensionNode.js',
 
diff --git a/modules/ve-mw/dm/nodes/ve.dm.MWBlockImageNode.js 
b/modules/ve-mw/dm/nodes/ve.dm.MWBlockImageNode.js
index f86cb8c..4a2ae65 100644
--- a/modules/ve-mw/dm/nodes/ve.dm.MWBlockImageNode.js
+++ b/modules/ve-mw/dm/nodes/ve.dm.MWBlockImageNode.js
@@ -11,6 +11,7 @@
  * @class
  * @extends ve.dm.BranchNode
  * @mixins ve.dm.MWImageNode
+ * @mixins ve.dm.MWClassAttributeNode
  *
  * @constructor
  * @param {Object} [element] Reference to element in linear model
@@ -22,6 +23,7 @@
 
        // Mixin constructors
        ve.dm.MWImageNode.call( this );
+       ve.dm.MWClassAttributeNode.call( this );
 };
 
 /* Inheritance */
@@ -32,6 +34,8 @@
 OO.mixinClass( ve.dm.MWBlockImageNode, ve.dm.GeneratedContentNode );
 
 OO.mixinClass( ve.dm.MWBlockImageNode, ve.dm.MWImageNode );
+
+OO.mixinClass( ve.dm.MWBlockImageNode, ve.dm.MWClassAttributeNode );
 
 /* Static Properties */
 
@@ -60,6 +64,15 @@
        return ve.getObjectKeys( this.rdfaToType );
 };
 
+ve.dm.MWBlockImageNode.static.classAttributes = {
+       'mw-image-border': { borderImage: true },
+       'mw-halign-left': { align: 'left' },
+       'mw-halign-right': { align: 'right' },
+       'mw-halign-center': { align: 'center' },
+       'mw-halign-none': { align: 'none' },
+       'mw-default-size': { defaultSize: true }
+};
+
 ve.dm.MWBlockImageNode.static.toDataElement = function ( domElements, 
converter ) {
        var dataElement, newDimensions,
                $figure = $( domElements[0] ),
@@ -67,15 +80,13 @@
                $imgWrapper = $figure.children( 'a, span' ).eq( 0 ),
                $img = $imgWrapper.children( 'img' ).eq( 0 ),
                $caption = $figure.children( 'figcaption' ).eq( 0 ),
+               classAttr = $figure.attr( 'class' ),
                typeofAttr = $figure.attr( 'typeof' ),
-               classes = $figure.attr( 'class' ),
-               recognizedClasses = [],
                attributes = {
                        type: this.rdfaToType[typeofAttr],
                        href: $imgWrapper.attr( 'href' ) || '',
                        src: $img.attr( 'src' ),
-                       resource: $img.attr( 'resource' ),
-                       originalClasses: classes
+                       resource: $img.attr( 'resource' )
                },
                width = $img.attr( 'width' ),
                height = $img.attr( 'height' ),
@@ -85,40 +96,15 @@
                attributes.alt = altText;
        }
 
-       // Extract individual classes
-       classes = typeof classes === 'string' ? classes.trim().split( /\s+/ ) : 
[];
+       this.setClassAttributes( attributes, classAttr );
 
-       // Deal with border flag
-       if ( classes.indexOf( 'mw-image-border' ) !== -1 ) {
-               attributes.borderImage = true;
-               recognizedClasses.push( 'mw-image-border' );
-       }
-
-       // Horizontal alignment
-       if ( classes.indexOf( 'mw-halign-left' ) !== -1 ) {
-               attributes.align = 'left';
-               recognizedClasses.push( 'mw-halign-left' );
-       } else if ( classes.indexOf( 'mw-halign-right' ) !== -1 ) {
-               attributes.align = 'right';
-               recognizedClasses.push( 'mw-halign-right' );
-       } else if ( classes.indexOf( 'mw-halign-center' ) !== -1 ) {
-               attributes.align = 'center';
-               recognizedClasses.push( 'mw-halign-center' );
-       } else if ( classes.indexOf( 'mw-halign-none' ) !== -1 ) {
-               attributes.align = 'none';
-               recognizedClasses.push( 'mw-halign-none' );
-       } else {
-               attributes.align = 'default';
-       }
+       attributes.align = attributes.align || 'default';
 
        attributes.width = width !== undefined && width !== '' ? Number( width 
) : null;
        attributes.height = height !== undefined && height !== '' ? Number( 
height ) : null;
 
        // Default-size
-       if ( classes.indexOf( 'mw-default-size' ) !== -1 ) {
-               // Flag as default size
-               attributes.defaultSize = true;
-               recognizedClasses.push( 'mw-default-size' );
+       if ( attributes.defaultSize ) {
                // Force wiki-default size for thumb and frameless
                if (
                        attributes.type === 'thumb' ||
@@ -140,9 +126,6 @@
                        }
                }
        }
-
-       // Store unrecognized classes so we can restore them on the way out
-       attributes.unrecognizedClasses = OO.simpleArrayDifference( classes, 
recognizedClasses );
 
        dataElement = { type: this.name, attributes: attributes };
 
@@ -172,8 +155,7 @@
                imgWrapper = doc.createElement( dataElement.attributes.href !== 
'' ? 'a' : 'span' ),
                img = doc.createElement( 'img' ),
                wrapper = doc.createElement( 'div' ),
-               classes = [],
-               originalClasses = dataElement.attributes.originalClasses,
+               classAttr = this.getClassAttrFromAttributes( 
dataElement.attributes ),
                captionData = data.slice( 1, -1 );
 
        if ( !this.typeToRdfa ) {
@@ -185,43 +167,11 @@
 
        // Type
        figure.setAttribute( 'typeof', 
this.typeToRdfa[dataElement.attributes.type] );
-       if ( dataElement.attributes.borderImage === true ) {
-               classes.push( 'mw-image-border' );
+
+       if ( classAttr ) {
+               figure.className = classAttr;
        }
 
-       // Apply classes if size is default
-       if ( dataElement.attributes.defaultSize === true ) {
-               classes.push( 'mw-default-size' );
-       }
-
-       // Horizontal alignment
-       switch ( dataElement.attributes.align ) {
-               case 'left':
-                       classes.push( 'mw-halign-left' );
-                       break;
-               case 'right':
-                       classes.push( 'mw-halign-right' );
-                       break;
-               case 'center':
-                       classes.push( 'mw-halign-center' );
-                       break;
-               case 'none':
-                       classes.push( 'mw-halign-none' );
-                       break;
-       }
-
-       if ( dataElement.attributes.unrecognizedClasses ) {
-               classes = OO.simpleArrayUnion( classes, 
dataElement.attributes.unrecognizedClasses );
-       }
-
-       if (
-               originalClasses &&
-               ve.compare( originalClasses.trim().split( /\s+/ ).sort(), 
classes.sort() )
-       ) {
-               figure.className = originalClasses;
-       } else if ( classes.length > 0 ) {
-               figure.className = classes.join( ' ' );
-       }
        if ( dataElement.attributes.href !== '' ) {
                imgWrapper.setAttribute( 'href', dataElement.attributes.href );
        }
diff --git a/modules/ve-mw/dm/nodes/ve.dm.MWClassAttributeNode.js 
b/modules/ve-mw/dm/nodes/ve.dm.MWClassAttributeNode.js
new file mode 100644
index 0000000..6ca247f
--- /dev/null
+++ b/modules/ve-mw/dm/nodes/ve.dm.MWClassAttributeNode.js
@@ -0,0 +1,99 @@
+/*!
+ * VisualEditor DataModel MWClassAttribute class.
+ *
+ * @copyright 2011-2014 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+/**
+ * DataModel MediaWiki class-attribute node.
+ *
+ * Used for nodes which use classes to store attributes.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ */
+ve.dm.MWClassAttributeNode = function VeDmMWImageNode() {
+};
+
+/* Inheritance */
+
+OO.initClass( ve.dm.MWClassAttributeNode );
+
+/* Static methods */
+
+/**
+ * Mapping from class names to attributes
+ *
+ * e.g. { alignLeft: { align: 'left' } } sets the align attribute to 'left'
+ * if the element has the class 'alignLeft'
+ *
+ * @type {Object}
+ */
+ve.dm.MWClassAttributeNode.static.classAttributes = {};
+
+/**
+ * Set attributes from a class attribute
+ *
+ * Unrecognized classes are also preserved.
+ *
+ * @param {Object} attributes Attributes object to modify
+ * @param {string|null} classAttr Class attribute from an element
+ */
+ve.dm.MWClassAttributeNode.static.setClassAttributes = function ( attributes, 
classAttr ) {
+       var className,
+               recognizedClasses = [],
+               classes = classAttr ? classAttr.trim().split( /\s+/ ) : [];
+
+       for ( className in this.classAttributes ) {
+               if ( ve.indexOf( className, classes ) !== -1 ) {
+                       attributes = ve.extendObject( attributes, 
this.classAttributes[className] );
+                       recognizedClasses.push( className );
+               }
+       }
+       attributes.originalClasses = classAttr;
+       attributes.unrecognizedClasses = OO.simpleArrayDifference( classes, 
recognizedClasses );
+};
+
+/**
+ * Get class attribute from element attributes
+ *
+ * @param {Object} elementAttributes Element attributes
+ * @return {string|null} Class name, or null if no classes to set
+ */
+ve.dm.MWClassAttributeNode.static.getClassAttrFromAttributes = function ( 
attributes ) {
+       var className, key, classAttributeSet, hasClass,
+               classes = [];
+
+       for ( className in this.classAttributes ) {
+               classAttributeSet = this.classAttributes[className];
+               hasClass = true;
+               for ( key in classAttributeSet ) {
+                       if ( attributes[key] !== classAttributeSet[key] ) {
+                               hasClass = false;
+                               break;
+                       }
+               }
+               if ( hasClass ) {
+                       classes.push( className );
+               }
+       }
+
+       if ( attributes.unrecognizedClasses ) {
+               classes = OO.simpleArrayUnion( classes, 
attributes.unrecognizedClasses );
+       }
+
+       // If no meaningful change in classes, preserve order
+       if (
+               attributes.originalClasses &&
+               ve.compare( attributes.originalClasses.trim().split( /\s+/ 
).sort(), classes.sort() )
+       ) {
+               return attributes.originalClasses;
+       } else if ( classes.length > 0 ) {
+               return classes.join( ' ' );
+       }
+
+       return null;
+};

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I4fc42e1468a9f0860c7c13e73967204bdf5ad78d
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