jenkins-bot has submitted this change and it was merged.

Change subject: Support for inline images
......................................................................


Support for inline images

Handles typeof mw:Image and mw:Image/Frameless

Change-Id: Ie2fbd4a3e12fb6faa4ab8e6dd0aa8d1334ff6498
---
M modules/ve/ce/nodes/ve.ce.MWInlineImageNode.js
M modules/ve/dm/nodes/ve.dm.MWBlockImageNode.js
M modules/ve/dm/nodes/ve.dm.MWInlineImageNode.js
M modules/ve/test/dm/ve.dm.example.js
4 files changed, 174 insertions(+), 51 deletions(-)

Approvals:
  Catrope: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/modules/ve/ce/nodes/ve.ce.MWInlineImageNode.js 
b/modules/ve/ce/nodes/ve.ce.MWInlineImageNode.js
index 163c17d..bded49d 100644
--- a/modules/ve/ce/nodes/ve.ce.MWInlineImageNode.js
+++ b/modules/ve/ce/nodes/ve.ce.MWInlineImageNode.js
@@ -9,31 +9,52 @@
  * ContentEditable MediaWiki image node.
  *
  * @class
- * @extends ve.ce.ImageNode
+ * @extends ve.ce.LeafNode
  *
  * @constructor
  * @param {ve.dm.MWInlineImageNode} model Model to observe
  * @param {Object} [config] Config options
  */
- ve.ce.MWInlineImageNode = function VeCeMWInlineImageNode( model, config ) {
+ve.ce.MWInlineImageNode = function VeCeMWInlineImageNode( model, config ) {
+       var valign;
+
        // Parent constructor
-       ve.ce.ImageNode.call( this, model, config );
+       ve.ce.LeafNode.call( this, model, config );
 
-       // Properties
-       this.$ = this.$$( '<' + ( model.getAttribute( 'isLinked' ) ? 'a' : 
'span' ) + '>' );
+       if ( this.model.getAttribute( 'isLinked' ) ) {
+               this.$ = this.$$( '<a>' ).addClass( 'image' );
+               this.$image = this.$$( '<img>' ).appendTo( this.$ );
+       } else {
+               this.$ = this.$$( '<img>' );
+               this.$image = this.$;
+       }
 
-       // Initialization
-       this.$
-               .attr( 'contenteditable', false )
-               .addClass( 've-ce-mwInlineImageNode' )
-               .append( this.$image )
-               .data( 'view', this.$image.data( 'view' ) );
-       this.onUpdate();
+       // Mixin constructors
+       ve.ce.ProtectedNode.call( this );
+       ve.ce.FocusableNode.call( this );
+
+       this.$image
+               .attr( 'src', this.model.getAttribute( 'src' ) )
+               .attr( 'width', this.model.getAttribute( 'width' ) )
+               .attr( 'height', this.model.getAttribute( 'height' ) );
+
+       if ( this.model.getAttribute( 'border' ) ) {
+               this.$image.addClass( 'thumbborder' );
+       }
+
+       valign = this.model.getAttribute( 'valign' );
+       if ( valign !== 'default' ) {
+               this.$image.css( 'vertical-align', valign );
+       }
 };
 
 /* Inheritance */
 
-ve.inheritClass( ve.ce.MWInlineImageNode, ve.ce.ImageNode );
+ve.inheritClass( ve.ce.MWInlineImageNode, ve.ce.LeafNode );
+
+ve.mixinClass( ve.ce.MWInlineImageNode, ve.ce.ProtectedNode );
+
+ve.mixinClass( ve.ce.MWInlineImageNode, ve.ce.FocusableNode );
 
 /* Static Properties */
 
diff --git a/modules/ve/dm/nodes/ve.dm.MWBlockImageNode.js 
b/modules/ve/dm/nodes/ve.dm.MWBlockImageNode.js
index ed39504..36d53cf 100644
--- a/modules/ve/dm/nodes/ve.dm.MWBlockImageNode.js
+++ b/modules/ve/dm/nodes/ve.dm.MWBlockImageNode.js
@@ -33,7 +33,7 @@
 ve.dm.MWBlockImageNode.static.childNodeTypes = [ 'mwImageCaption' ];
 
 // Match typeof="mw:Image/Thumb" and typeof="mw:Image/Frame"
-ve.dm.MWBlockImageNode.static.matchRdfaTypes = [ /mw:Image\/(Thumb|Frame)/ ];
+ve.dm.MWBlockImageNode.static.matchRdfaTypes = [ /^mw:Image\/(Thumb|Frame)$/ ];
 
 ve.dm.MWBlockImageNode.static.toDataElement = function ( domElements, 
converter ) {
        var $figure = $( domElements[0] ),
diff --git a/modules/ve/dm/nodes/ve.dm.MWInlineImageNode.js 
b/modules/ve/dm/nodes/ve.dm.MWInlineImageNode.js
index 48e1915..8d18920 100644
--- a/modules/ve/dm/nodes/ve.dm.MWInlineImageNode.js
+++ b/modules/ve/dm/nodes/ve.dm.MWInlineImageNode.js
@@ -9,48 +9,143 @@
  * DataModel MediaWiki image node.
  *
  * @class
- * @extends ve.dm.ImageNode
+ * @extends ve.dm.LeafNode
  * @constructor
  * @param {number} [length] Length of content data in document
  * @param {Object} [element] Reference to element in linear model
  */
 ve.dm.MWInlineImageNode = function VeDmMWInlineImageNode( length, element ) {
-       ve.dm.ImageNode.call( this, 0, element );
+       ve.dm.LeafNode.call( this, 0, element );
 };
 
 /* Inheritance */
 
-ve.inheritClass( ve.dm.MWInlineImageNode, ve.dm.ImageNode );
+ve.inheritClass( ve.dm.MWInlineImageNode, ve.dm.LeafNode );
 
 /* Static Properties */
 
+ve.dm.MWInlineImageNode.static.isContent = true;
+
 ve.dm.MWInlineImageNode.static.name = 'mwInlineImage';
+
+ve.dm.MWInlineImageNode.static.storeHtmlAttributes = {
+       'blacklist': [ 'typeof', 'class', 'src', 'resource', 'width', 'height', 
'href' ]
+};
 
 ve.dm.MWInlineImageNode.static.matchTagNames = null;
 
-// TODO: Develop better method to test for generated content
-ve.dm.MWInlineImageNode.static.generatedContent = true;
-
-ve.dm.MWInlineImageNode.static.matchRdfaTypes = [ 'mw:Image' ];
+ve.dm.MWInlineImageNode.static.matchRdfaTypes = [
+       'mw:Image',
+       'mw:Image/Frameless'
+];
 
 ve.dm.MWInlineImageNode.static.toDataElement = function ( domElements ) {
-       var children = Array.prototype.slice.call( domElements[0].children, 0 ),
-               parentResult = ve.dm.ImageNode.static.toDataElement.apply(
-                       this, [ children ].concat( Array.prototype.slice.call( 
arguments, 1 ) )
-               );
-       return ve.extendObject( true, parentResult, {
-               'type': 'mwInlineImage',
-               'attributes': {
-                       'isLinked': domElements[0].nodeName.toLowerCase() === 
'a'
-               }
-       } );
+       var $span = $( domElements[0] ),
+               $firstChild = $span.children().first(), // could be <span> or 
<a>
+               $img = $firstChild.children().first(),
+               typeofAttr = $span.attr( 'typeof' ),
+               classes = $span.attr( 'class' ),
+               attributes = {
+                       src: $img.attr( 'src' ),
+                       resource: $img.attr( 'resource' )
+               },
+               width = $img.attr( 'width' ),
+               height = $img.attr( 'height' );
+
+       attributes.width = width !== undefined && width !== '' ? Number( width 
) : null;
+       attributes.height = height !== undefined && height !== '' ? Number( 
height ) : null;
+
+       attributes.isLinked = $firstChild.is( 'a' );
+       if ( attributes.isLinked ) {
+               attributes.href = $firstChild.attr( 'href' );
+       }
+
+       // Extract individual classes
+       classes = typeof classes === 'string' ?
+               classes.replace( /\s{2,}/g, ' ' ).split( ' ' ) : [];
+
+       // Type
+       switch ( typeofAttr ) {
+               case 'mw:Image':
+                       attributes.type = 'inline';
+                       break;
+               case 'mw:Image/Frameless':
+                       attributes.type = 'frameless';
+                       break;
+       }
+
+       // Vertical alignment
+       if ( classes.indexOf( 'mw-valign-middle' ) !== -1 ) {
+               attributes.valign = 'middle';
+       } else if ( classes.indexOf( 'mw-valign-baseline' ) !== -1 ) {
+               attributes.valign = 'baseline';
+       } else if ( classes.indexOf( 'mw-valign-sub' ) !== -1 ) {
+               attributes.valign = 'sub';
+       } else if ( classes.indexOf( 'mw-valign-super' ) !== -1 ) {
+               attributes.valign = 'super';
+       } else if ( classes.indexOf( 'mw-valign-top' ) !== -1 ) {
+               attributes.valign = 'top';
+       } else if ( classes.indexOf( 'mw-valign-text-top' ) !== -1 ) {
+               attributes.valign = 'text-top';
+       } else if ( classes.indexOf( 'mw-valign-bottom' ) !== -1 ) {
+               attributes.valign = 'bottom';
+       } else if ( classes.indexOf( 'mw-valign-text-bottom' ) !== -1 ) {
+               attributes.valign = 'text-bottom';
+       } else {
+               attributes.valign = 'default';
+       }
+
+       // Border
+       if ( classes.indexOf( 'mw-image-border' ) !== -1 ) {
+               attributes.border = true;
+       }
+
+       // Default-size
+       if ( classes.indexOf( 'mw-default-size' ) !== -1 ) {
+               attributes.defaultSize = true;
+       }
+       return { 'type': 'mwInlineImage', 'attributes': attributes };
 };
 
-ve.dm.MWInlineImageNode.static.toDomElements = function ( dataElement, doc ) {
-       var wrapper = doc.createElement( dataElement.attributes.isLinked ? 'a' 
: 'span' ),
-               imageDomElement = ve.dm.ImageNode.static.toDomElements.apply( 
this, arguments )[0];
-       wrapper.appendChild( imageDomElement );
-       return [ wrapper ];
+ve.dm.MWInlineImageNode.static.toDomElements = function ( data, doc ) {
+       var span = doc.createElement( 'span' ),
+               img = doc.createElement( 'img' ),
+               firstChild;
+
+       ve.setDomAttributes( img, data.attributes, [ 'src', 'width', 'height', 
'resource' ] );
+
+       switch ( data.attributes.type  ) {
+               case 'inline':
+                       span.setAttribute( 'typeof', 'mw:Image' );
+                       break;
+               case 'frameless':
+                       span.setAttribute( 'typeof', 'mw:Image/Frameless' );
+                       break;
+       }
+
+       if ( data.attributes.defaultSize ) {
+               span.className += ' mw-default-size';
+       }
+
+       if ( data.attributes.border ) {
+               span.className += ' mw-image-border';
+       }
+
+       if ( data.attributes.valign && data.attributes.valign !== 'default' ) {
+               span.className += ' mw-image-' + data.attributes.valign;
+       }
+
+       if ( data.attributes.isLinked ) {
+               firstChild = doc.createElement( 'a' );
+               firstChild.setAttribute( 'href', data.attributes.href );
+       } else {
+               firstChild = doc.createElement( 'span' );
+       }
+
+       span.appendChild( firstChild );
+       firstChild.appendChild( img );
+
+       return [ span ];
 };
 
 /* Registration */
diff --git a/modules/ve/test/dm/ve.dm.example.js 
b/modules/ve/test/dm/ve.dm.example.js
index 10adede..b06e956 100644
--- a/modules/ve/test/dm/ve.dm.example.js
+++ b/modules/ve/test/dm/ve.dm.example.js
@@ -908,7 +908,7 @@
        }
 };
 
-ve.dm.example.MWInlineImageHtml = '<a rel="mw:Image" href="./File:Wiki.png" 
data-parsoid="{&quot;tsr&quot;:[158,216],&quot;src&quot;:&quot;[[Image:Wiki.png|500px|thumb|center|Example
 wiki 
file]]&quot;,&quot;optNames&quot;:{&quot;width&quot;:&quot;$1px&quot;},&quot;dsr&quot;:[158,216,null,null]}"><img
 height="" width="500" 
src="/index.php?title=Special:FilePath/Wiki.png&amp;width=500" 
alt="Wiki.png"></a>';
+ve.dm.example.MWInlineImageHtml = '<span typeof="mw:Image" 
data-parsoid="{&quot;tsr&quot;:[0,24],&quot;optList&quot;:[{&quot;ck&quot;:&quot;width&quot;,&quot;ak&quot;:&quot;500px&quot;}],&quot;cacheKey&quot;:&quot;[[Image:Wiki.png|500px]]&quot;,&quot;img&quot;:{&quot;h&quot;:155,&quot;w&quot;:135,&quot;wdset&quot;:true},&quot;dsr&quot;:[0,24,null,null]}"><a
 href="./File:Wiki.png" 
data-parsoid="{&quot;a&quot;:{&quot;href&quot;:&quot;./File:Wiki.png&quot;}}"><img
 resource="./File:Wiki.png" 
src="http://upload.wikimedia.org/wikipedia/en/b/bc/Wiki.png"; height="155" 
width="135" 
data-parsoid="{&quot;a&quot;:{&quot;resource&quot;:&quot;./File:Wiki.png&quot;,&quot;width&quot;:&quot;135&quot;},&quot;sa&quot;:{&quot;resource&quot;:&quot;Image:Wiki.png&quot;,&quot;width&quot;:&quot;500&quot;}}"></a></span>';
 ve.dm.example.MWTemplate = {
        'blockSpan':         '<span about="#mwt1" typeof="mw:Transclusion" 
data-mw="{&quot;id&quot;:&quot;mwt1&quot;,&quot;target&quot;:{&quot;wt&quot;:&quot;Test&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;Hello,
 world!&quot;}}}" 
data-parsoid="{&quot;tsr&quot;:[18,40],&quot;src&quot;:&quot;{{Test|Hello, 
world!}}&quot;,&quot;dsr&quot;:[18,40,null,null]}"></span>',
        'blockSpanModified': '<span about="#mwt1" typeof="mw:Transclusion" 
data-mw="{&quot;id&quot;:&quot;mwt1&quot;,&quot;target&quot;:{&quot;wt&quot;:&quot;Test&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;Hello,
 globe!&quot;}}}" 
data-parsoid="{&quot;tsr&quot;:[18,40],&quot;src&quot;:&quot;{{Test|Hello, 
world!}}&quot;,&quot;dsr&quot;:[18,40,null,null]}"></span>',
@@ -1090,28 +1090,35 @@
                        {
                                'type': 'mwInlineImage',
                                'attributes': {
-                                       'src': 
'/index.php?title=Special:FilePath/Wiki.png&width=500',
-                                       'width': 500,
-                                       'height': null,
-                                       'isLinked': true
+                                       'src': 
'http://upload.wikimedia.org/wikipedia/en/b/bc/Wiki.png',
+                                       'href': './File:Wiki.png',
+                                       'width': 135,
+                                       'height': 155,
+                                       'isLinked': true,
+                                       'valign': 'default',
+                                       'resource': './File:Wiki.png',
+                                       'type': 'inline'
                                },
                                'htmlAttributes': [
                                        {
-                                               'keys': [ 'rel', 'href', 
'data-parsoid' ],
+                                               'keys': [ 'data-parsoid' ],
                                                'values': {
-                                                       'data-parsoid': 
'{"tsr":[158,216],"src":"[[Image:Wiki.png|500px|thumb|center|Example wiki 
file]]","optNames":{"width":"$1px"},"dsr":[158,216,null,null]}',
-                                                       'href': 
'./File:Wiki.png',
-                                                       'rel': 'mw:Image'
+                                                       'data-parsoid': 
'{\"tsr\":[0,24],\"optList\":[{\"ck\":\"width\",\"ak\":\"500px\"}],\"cacheKey\":\"[[Image:Wiki.png|500px]]\",\"img\":{\"h\":155,\"w\":135,\"wdset\":true},\"dsr\":[0,24,null,null]}'
                                                },
                                                'children': [
                                                        {
-                                                               'keys': [ 
'height', 'width', 'src', 'alt' ],
+                                                               'keys': [ 
'data-parsoid' ],
                                                                'values': {
-                                                                       'alt': 
'Wiki.png',
-                                                                       
'height': '',
-                                                                       'src': 
'/index.php?title=Special:FilePath/Wiki.png&width=500',
-                                                                       
'width': '500'
-                                                               }
+                                                                       
'data-parsoid': '{\"a\":{\"href\":\"./File:Wiki.png\"}}'
+                                                               },
+                                                               'children': [
+                                                                       {
+                                                                               
'keys': [ 'data-parsoid' ],
+                                                                               
'values': {
+                                                                               
        'data-parsoid': 
'{\"a\":{\"resource\":\"./File:Wiki.png\",\"width\":\"135\"},\"sa\":{\"resource\":\"Image:Wiki.png\",\"width\":\"500\"}}'
+                                                                               
}
+                                                                       }
+                                                               ]
                                                        }
                                                ]
                                        }

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

Gerrit-MessageType: merged
Gerrit-Change-Id: Ie2fbd4a3e12fb6faa4ab8e6dd0aa8d1334ff6498
Gerrit-PatchSet: 6
Gerrit-Project: mediawiki/extensions/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Inez <[email protected]>
Gerrit-Reviewer: Catrope <[email protected]>
Gerrit-Reviewer: jenkins-bot

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

Reply via email to