/**
* @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md.
*/
/**
* @module image/converters
*/
import ModelElement from '@ckeditor/ckeditor5-engine/src/model/element';
import { isImageWidget } from './utils';
/**
* Returns function that converts image view representation:
*
*
*
* to model representation:
*
*
*
* @returns {Function}
*/
export function viewToModelImage() {
return ( evt, data, consumable, conversionApi ) => {
const viewFigureElement = data.input;
// *** Step 1: Validate conversion.
// Check if figure element can be consumed.
if ( !consumable.test( viewFigureElement, { name: true, class: 'image' } ) ) {
return;
}
// Check if image element can be converted in current context.
if ( !conversionApi.schema.check( { name: 'image', inside: data.context, attributes: 'src' } ) ) {
return;
}
// Check if img element is placed inside figure element and can be consumed with `src` attribute.
const viewImg = viewFigureElement.getChild( 0 );
if ( !viewImg || viewImg.name != 'img' || !consumable.test( viewImg, { name: true, attribute: 'src' } ) ) {
return;
}
// *** Step2: Convert to model.
consumable.consume( viewFigureElement, { name: true, class: 'image' } );
consumable.consume( viewImg, { name: true, attribute: 'src' } );
// Create model element.
const modelImage = new ModelElement( 'image', {
src: viewImg.getAttribute( 'src' )
} );
// Convert `alt` attribute if present.
if ( consumable.consume( viewImg, { attribute: [ 'alt' ] } ) ) {
modelImage.setAttribute( 'alt', viewImg.getAttribute( 'alt' ) );
}
data.output = modelImage;
};
}
/**
* Returns model to view selection converter. This converter is applied after default selection conversion is made.
* It creates fake view selection when {@link module:engine/view/selection~Selection#getSelectedElement} returns instance
* of image widget.
*
* @param {Function} t {@link module:utils/locale~Locale#t Locale#t function} used to translate default fake selection's label.
* @returns {Function}
*/
export function modelToViewSelection( t ) {
return ( evt, data, consumable, conversionApi ) => {
const viewSelection = conversionApi.viewSelection;
const selectedElement = viewSelection.getSelectedElement();
if ( !selectedElement || !isImageWidget( selectedElement ) ) {
return;
}
let fakeSelectionLabel = t( 'image widget' );
const imgElement = selectedElement.getChild( 0 );
const altText = imgElement.getAttribute( 'alt' );
if ( altText ) {
fakeSelectionLabel = `${ altText } ${ fakeSelectionLabel }`;
}
viewSelection.setFake( true, { label: fakeSelectionLabel } );
};
}
/**
* Creates image attribute converter for provided model conversion dispatchers.
*
* @param {Array.} dispatchers
* @param {String} attributeName
*/
export function createImageAttributeConverter( dispatchers, attributeName ) {
for ( let dispatcher of dispatchers ) {
dispatcher.on( `addAttribute:${ attributeName }:image`, modelToViewAttributeConverter );
dispatcher.on( `changeAttribute:${ attributeName }:image`, modelToViewAttributeConverter );
dispatcher.on( `removeAttribute:${ attributeName }:image`, modelToViewAttributeConverter );
}
}
// Model to view image converter converting given attribute, and adding it to `img` element nested inside `figure` element.
//
// @private
function modelToViewAttributeConverter( evt, data, consumable, conversionApi ) {
const parts = evt.name.split( ':' );
const consumableType = parts[ 0 ] + ':' + parts[ 1 ];
if ( !consumable.consume( data.item, consumableType ) ) {
return;
}
const figure = conversionApi.mapper.toViewElement( data.item );
const img = figure.getChild( 0 );
if ( parts[ 0 ] == 'removeAttribute' ) {
img.removeAttribute( data.attributeKey );
} else {
img.setAttribute( data.attributeKey, data.attributeNewValue );
}
}