UNPKG

4.86 kBJavaScriptView Raw
1/**
2 * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
3 * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4 */
5
6/**
7 * @module image/imagestyle/imagestylecommand
8 */
9
10import { Command } from 'ckeditor5/src/core';
11
12/**
13 * The image style command. It is used to apply {@link module:image/imagestyle~ImageStyleConfig#options image style option}
14 * to a selected image.
15 *
16 * **Note**: Executing this command may change the image model element if the desired style requires an image of a different
17 * type. See {@link module:image/imagestyle/imagestylecommand~ImageStyleCommand#execute} to learn more.
18 *
19 * @extends module:core/command~Command
20 */
21export default class ImageStyleCommand extends Command {
22 /**
23 * Creates an instance of the image style command. When executed, the command applies one of
24 * {@link module:image/imagestyle~ImageStyleConfig#options style options} to the currently selected image.
25 *
26 * @param {module:core/editor/editor~Editor} editor The editor instance.
27 * @param {Array.<module:image/imagestyle~ImageStyleOptionDefinition>} styles
28 * The style options that this command supports.
29 */
30 constructor( editor, styles ) {
31 super( editor );
32
33 /**
34 * An object containing names of default style options for the inline and block images.
35 * If there is no default style option for the given image type in the configuration,
36 * the name will be `false`.
37 *
38 * @private
39 * @type {Object.<String,module:image/imagestyle~ImageStyleOptionDefinition#name>}
40 */
41 this._defaultStyles = {
42 imageBlock: false,
43 imageInline: false
44 };
45
46 /**
47 * The styles handled by this command.
48 *
49 * @private
50 * @type {module:image/imagestyle~ImageStyleConfig#options}
51 */
52 this._styles = new Map( styles.map( style => {
53 if ( style.isDefault ) {
54 for ( const modelElementName of style.modelElements ) {
55 this._defaultStyles[ modelElementName ] = style.name;
56 }
57 }
58
59 return [ style.name, style ];
60 } ) );
61 }
62
63 /**
64 * @inheritDoc
65 */
66 refresh() {
67 const editor = this.editor;
68 const imageUtils = editor.plugins.get( 'ImageUtils' );
69 const element = imageUtils.getClosestSelectedImageElement( this.editor.model.document.selection );
70
71 this.isEnabled = !!element;
72
73 if ( !this.isEnabled ) {
74 this.value = false;
75 } else if ( element.hasAttribute( 'imageStyle' ) ) {
76 this.value = element.getAttribute( 'imageStyle' );
77 } else {
78 this.value = this._defaultStyles[ element.name ];
79 }
80 }
81
82 /**
83 * Executes the command and applies the style to the currently selected image:
84 *
85 * editor.execute( 'imageStyle', { value: 'side' } );
86 *
87 * **Note**: Executing this command may change the image model element if the desired style requires an image
88 * of a different type. Learn more about {@link module:image/imagestyle~ImageStyleOptionDefinition#modelElements model element}
89 * configuration for the style option.
90 *
91 * @param {Object} options
92 * @param {module:image/imagestyle~ImageStyleOptionDefinition#name} options.value The name of the style (as configured in
93 * {@link module:image/imagestyle~ImageStyleConfig#options}).
94 * @fires execute
95 */
96 execute( options = {} ) {
97 const editor = this.editor;
98 const model = editor.model;
99 const imageUtils = editor.plugins.get( 'ImageUtils' );
100
101 model.change( writer => {
102 const requestedStyle = options.value;
103
104 let imageElement = imageUtils.getClosestSelectedImageElement( model.document.selection );
105
106 // Change the image type if a style requires it.
107 if ( requestedStyle && this.shouldConvertImageType( requestedStyle, imageElement ) ) {
108 this.editor.execute( imageUtils.isBlockImage( imageElement ) ? 'imageTypeInline' : 'imageTypeBlock' );
109
110 // Update the imageElement to the newly created image.
111 imageElement = imageUtils.getClosestSelectedImageElement( model.document.selection );
112 }
113
114 // Default style means that there is no `imageStyle` attribute in the model.
115 // https://github.com/ckeditor/ckeditor5-image/issues/147
116 if ( !requestedStyle || this._styles.get( requestedStyle ).isDefault ) {
117 writer.removeAttribute( 'imageStyle', imageElement );
118 } else {
119 writer.setAttribute( 'imageStyle', requestedStyle, imageElement );
120 }
121 } );
122 }
123
124 /**
125 * Returns `true` if requested style change would trigger the image type change.
126 *
127 * @param {module:image/imagestyle~ImageStyleOptionDefinition} requestedStyle The name of the style (as configured in
128 * {@link module:image/imagestyle~ImageStyleConfig#options}).
129 * @param {module:engine/model/element~Element} imageElement The image model element.
130 * @returns {Boolean}
131 */
132 shouldConvertImageType( requestedStyle, imageElement ) {
133 const supportedTypes = this._styles.get( requestedStyle ).modelElements;
134
135 return !supportedTypes.includes( imageElement.name );
136 }
137}