UNPKG

@ckeditor/ckeditor5-image

Version:

Image feature for CKEditor 5.

108 lines (107 loc) 4.81 kB
/** * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved. * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ import { Command } from 'ckeditor5/src/core'; /** * The image style command. It is used to apply {@link module:image/imageconfig~ImageStyleConfig#options image style option} * to a selected image. * * **Note**: Executing this command may change the image model element if the desired style requires an image of a different * type. See {@link module:image/imagestyle/imagestylecommand~ImageStyleCommand#execute} to learn more. */ export default class ImageStyleCommand extends Command { /** * Creates an instance of the image style command. When executed, the command applies one of * {@link module:image/imageconfig~ImageStyleConfig#options style options} to the currently selected image. * * @param editor The editor instance. * @param styles The style options that this command supports. */ constructor(editor, styles) { super(editor); this._defaultStyles = { imageBlock: false, imageInline: false }; this._styles = new Map(styles.map(style => { if (style.isDefault) { for (const modelElementName of style.modelElements) { this._defaultStyles[modelElementName] = style.name; } } return [style.name, style]; })); } /** * @inheritDoc */ refresh() { const editor = this.editor; const imageUtils = editor.plugins.get('ImageUtils'); const element = imageUtils.getClosestSelectedImageElement(this.editor.model.document.selection); this.isEnabled = !!element; if (!this.isEnabled) { this.value = false; } else if (element.hasAttribute('imageStyle')) { this.value = element.getAttribute('imageStyle'); } else { this.value = this._defaultStyles[element.name]; } } /** * Executes the command and applies the style to the currently selected image: * * ```ts * editor.execute( 'imageStyle', { value: 'side' } ); * ``` * * **Note**: Executing this command may change the image model element if the desired style requires an image * of a different type. Learn more about {@link module:image/imageconfig~ImageStyleOptionDefinition#modelElements model element} * configuration for the style option. * * @param options.value The name of the style (as configured in {@link module:image/imageconfig~ImageStyleConfig#options}). * @param options.setImageSizes Specifies whether the image `width` and `height` attributes should be set automatically. * The default is `true`. * @fires execute */ execute(options = {}) { const editor = this.editor; const model = editor.model; const imageUtils = editor.plugins.get('ImageUtils'); model.change(writer => { const requestedStyle = options.value; const { setImageSizes = true } = options; let imageElement = imageUtils.getClosestSelectedImageElement(model.document.selection); // Change the image type if a style requires it. if (requestedStyle && this.shouldConvertImageType(requestedStyle, imageElement)) { this.editor.execute(imageUtils.isBlockImage(imageElement) ? 'imageTypeInline' : 'imageTypeBlock', { setImageSizes }); // Update the imageElement to the newly created image. imageElement = imageUtils.getClosestSelectedImageElement(model.document.selection); } // Default style means that there is no `imageStyle` attribute in the model. // https://github.com/ckeditor/ckeditor5-image/issues/147 if (!requestedStyle || this._styles.get(requestedStyle).isDefault) { writer.removeAttribute('imageStyle', imageElement); } else { writer.setAttribute('imageStyle', requestedStyle, imageElement); } if (setImageSizes) { imageUtils.setImageNaturalSizeAttributes(imageElement); } }); } /** * Returns `true` if requested style change would trigger the image type change. * * @param requestedStyle The name of the style (as configured in {@link module:image/imageconfig~ImageStyleConfig#options}). * @param imageElement The image model element. */ shouldConvertImageType(requestedStyle, imageElement) { const supportedTypes = this._styles.get(requestedStyle).modelElements; return !supportedTypes.includes(imageElement.name); } }