mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-12-21 10:33:05 +00:00
79120fc16c
Parsoid added a class and, without it, we get selser complaining about wrappers being modified, similar to T214649. The "image" class is removed since Parsoid never added it (although it now has "mw-file-description" for a similar purpose) and the legacy parser doesn't apply it indiscriminately. It doesn't seem like VE supports editing the |link= media option; it just tries to roundtrip what's there and drops it on edit. The patch here works with that limitation. Galleries are found to drop href's, breaking selser, and should be fixed in a follow up. Bug: T292657 Bug: T303469 Change-Id: I92359048b42d32fe8a0f2cb79cd348cf5f2c56cc
153 lines
4.5 KiB
JavaScript
153 lines
4.5 KiB
JavaScript
/*!
|
|
* VisualEditor DataModel MWGalleryImageNode class.
|
|
*
|
|
* @copyright 2016 VisualEditor Team and others; see AUTHORS.txt
|
|
* @license The MIT License (MIT); see LICENSE.txt
|
|
*/
|
|
|
|
/**
|
|
* DataModel MediaWiki gallery image node.
|
|
*
|
|
* @class
|
|
* @extends ve.dm.BranchNode
|
|
*
|
|
* @constructor
|
|
* @param {Object} [element] Reference to element in linear model
|
|
* @param {ve.dm.Node[]} [children]
|
|
*/
|
|
ve.dm.MWGalleryImageNode = function VeDmMWGalleryImageNode() {
|
|
// Parent constructor
|
|
ve.dm.MWGalleryImageNode.super.apply( this, arguments );
|
|
};
|
|
|
|
/* Inheritance */
|
|
|
|
OO.inheritClass( ve.dm.MWGalleryImageNode, ve.dm.BranchNode );
|
|
|
|
/* Static members */
|
|
|
|
ve.dm.MWGalleryImageNode.static.name = 'mwGalleryImage';
|
|
|
|
ve.dm.MWGalleryImageNode.static.matchTagNames = [ 'li' ];
|
|
|
|
ve.dm.MWGalleryImageNode.static.childNodeTypes = [ 'mwGalleryImageCaption' ];
|
|
|
|
ve.dm.MWGalleryImageNode.static.matchFunction = function ( element ) {
|
|
var parentTypeof = ( element.parentNode && element.parentNode.getAttribute( 'typeof' ) ) || '';
|
|
return element.getAttribute( 'class' ) === 'gallerybox' &&
|
|
parentTypeof.trim().split( /\s+/ ).indexOf( 'mw:Extension/gallery' ) !== -1;
|
|
};
|
|
|
|
ve.dm.MWGalleryImageNode.static.parentNodeTypes = [ 'mwGallery' ];
|
|
|
|
ve.dm.MWGalleryImageNode.static.toDataElement = function ( domElements, converter ) {
|
|
// TODO: Improve handling of missing files. See 'isError' in MWBlockImageNode#toDataElement
|
|
var li = domElements[ 0 ];
|
|
var img = li.querySelector( 'img,audio,video,span[resource]' );
|
|
var figureInline = img.parentNode.parentNode;
|
|
|
|
// Get caption (may be missing for mode="packed-hover" galleries)
|
|
var captionNode = li.querySelector( '.gallerytext' );
|
|
if ( captionNode ) {
|
|
captionNode = captionNode.cloneNode( true );
|
|
// If showFilename is 'yes', the filename is also inside the caption, so throw this out
|
|
var filename = captionNode.querySelector( '.galleryfilename' );
|
|
if ( filename ) {
|
|
filename.remove();
|
|
}
|
|
}
|
|
|
|
var caption;
|
|
if ( captionNode ) {
|
|
caption = converter.getDataFromDomClean( captionNode, { type: 'mwGalleryImageCaption' } );
|
|
} else {
|
|
caption = [
|
|
{ type: 'mwGalleryImageCaption' },
|
|
{ type: 'paragraph', internal: { generated: 'wrapper' } },
|
|
{ type: '/paragraph' },
|
|
{ type: '/mwGalleryImageCaption' }
|
|
];
|
|
}
|
|
|
|
var dataElement = {
|
|
type: this.name,
|
|
attributes: {
|
|
resource: './' + mw.libs.ve.normalizeParsoidResourceName( img.getAttribute( 'resource' ) ),
|
|
altText: img.getAttribute( 'alt' ),
|
|
// 'src' for images, 'poster' for video/audio
|
|
src: img.getAttribute( 'src' ) || img.getAttribute( 'poster' ),
|
|
height: img.getAttribute( 'height' ),
|
|
width: img.getAttribute( 'width' ),
|
|
tagName: figureInline.nodeName.toLowerCase()
|
|
}
|
|
};
|
|
|
|
return [ dataElement ]
|
|
.concat( caption )
|
|
.concat( { type: '/' + this.name } );
|
|
};
|
|
|
|
ve.dm.MWGalleryImageNode.static.toDomElements = function ( data, doc ) {
|
|
// ImageNode:
|
|
// <li> li (gallerybox)
|
|
// <div> thumbDiv
|
|
// <span> innerDiv
|
|
// <a> a
|
|
// <img> img
|
|
var model = data,
|
|
li = doc.createElement( 'li' ),
|
|
thumbDiv = doc.createElement( 'div' ),
|
|
innerDiv = doc.createElement( model.attributes.tagName || 'span' ),
|
|
a = doc.createElement( 'a' ),
|
|
img = doc.createElement( 'img' ),
|
|
alt = model.attributes.altText;
|
|
|
|
li.classList.add( 'gallerybox' );
|
|
thumbDiv.classList.add( 'thumb' );
|
|
innerDiv.setAttribute( 'typeof', 'mw:Image' );
|
|
|
|
// TODO: Support editing the link
|
|
// FIXME: Dropping the href causes Parsoid to mark the node as wrapper modified,
|
|
// making the whole gallery subtree edited, preventing selser. When fixing,
|
|
// preserving the imgWrapperClassAttr, as in the MW*ImageNodes, will also be
|
|
// necessary.
|
|
// a.setAttribute( 'href', model.attributes.src );
|
|
|
|
img.setAttribute( 'resource', model.attributes.resource );
|
|
img.setAttribute( 'src', model.attributes.src );
|
|
if ( alt ) {
|
|
img.setAttribute( 'alt', alt );
|
|
}
|
|
|
|
a.appendChild( img );
|
|
innerDiv.appendChild( a );
|
|
thumbDiv.appendChild( innerDiv );
|
|
li.appendChild( thumbDiv );
|
|
|
|
return [ li ];
|
|
};
|
|
|
|
ve.dm.MWGalleryImageNode.static.describeChange = function ( key ) {
|
|
// These attributes are computed
|
|
if ( key === 'src' || key === 'width' || key === 'height' ) {
|
|
return null;
|
|
}
|
|
// Parent method
|
|
return ve.dm.MWGalleryImageNode.super.static.describeChange.apply( this, arguments );
|
|
};
|
|
|
|
/* Methods */
|
|
|
|
/**
|
|
* Get the image's caption node.
|
|
*
|
|
* @return {ve.dm.MWImageCaptionNode|null} Caption node, if present
|
|
*/
|
|
ve.dm.MWGalleryImageNode.prototype.getCaptionNode = function () {
|
|
return this.children.length > 0 ? this.children[ 0 ] : null;
|
|
};
|
|
|
|
/* Registration */
|
|
|
|
ve.dm.modelRegistry.register( ve.dm.MWGalleryImageNode );
|