1 | /**
|
2 | * @license Copyright (c) 2003-2023, 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 | import { Command } from 'ckeditor5/src/core';
|
6 | /**
|
7 | * The image style command. It is used to apply {@link module:image/imageconfig~ImageStyleConfig#options image style option}
|
8 | * to a selected image.
|
9 | *
|
10 | * **Note**: Executing this command may change the image model element if the desired style requires an image of a different
|
11 | * type. See {@link module:image/imagestyle/imagestylecommand~ImageStyleCommand#execute} to learn more.
|
12 | */
|
13 | export default class ImageStyleCommand extends Command {
|
14 | /**
|
15 | * Creates an instance of the image style command. When executed, the command applies one of
|
16 | * {@link module:image/imageconfig~ImageStyleConfig#options style options} to the currently selected image.
|
17 | *
|
18 | * @param editor The editor instance.
|
19 | * @param styles The style options that this command supports.
|
20 | */
|
21 | constructor(editor, styles) {
|
22 | super(editor);
|
23 | this._defaultStyles = {
|
24 | imageBlock: false,
|
25 | imageInline: false
|
26 | };
|
27 | this._styles = new Map(styles.map(style => {
|
28 | if (style.isDefault) {
|
29 | for (const modelElementName of style.modelElements) {
|
30 | this._defaultStyles[modelElementName] = style.name;
|
31 | }
|
32 | }
|
33 | return [style.name, style];
|
34 | }));
|
35 | }
|
36 | /**
|
37 | * @inheritDoc
|
38 | */
|
39 | refresh() {
|
40 | const editor = this.editor;
|
41 | const imageUtils = editor.plugins.get('ImageUtils');
|
42 | const element = imageUtils.getClosestSelectedImageElement(this.editor.model.document.selection);
|
43 | this.isEnabled = !!element;
|
44 | if (!this.isEnabled) {
|
45 | this.value = false;
|
46 | }
|
47 | else if (element.hasAttribute('imageStyle')) {
|
48 | this.value = element.getAttribute('imageStyle');
|
49 | }
|
50 | else {
|
51 | this.value = this._defaultStyles[element.name];
|
52 | }
|
53 | }
|
54 | /**
|
55 | * Executes the command and applies the style to the currently selected image:
|
56 | *
|
57 | * ```ts
|
58 | * editor.execute( 'imageStyle', { value: 'side' } );
|
59 | * ```
|
60 | *
|
61 | * **Note**: Executing this command may change the image model element if the desired style requires an image
|
62 | * of a different type. Learn more about {@link module:image/imageconfig~ImageStyleOptionDefinition#modelElements model element}
|
63 | * configuration for the style option.
|
64 | *
|
65 | * @param options.value The name of the style (as configured in {@link module:image/imageconfig~ImageStyleConfig#options}).
|
66 | * @param options.setImageSizes Specifies whether the image `width` and `height` attributes should be set automatically.
|
67 | * The default is `true`.
|
68 | * @fires execute
|
69 | */
|
70 | execute(options = {}) {
|
71 | const editor = this.editor;
|
72 | const model = editor.model;
|
73 | const imageUtils = editor.plugins.get('ImageUtils');
|
74 | model.change(writer => {
|
75 | const requestedStyle = options.value;
|
76 | const { setImageSizes = true } = options;
|
77 | let imageElement = imageUtils.getClosestSelectedImageElement(model.document.selection);
|
78 | // Change the image type if a style requires it.
|
79 | if (requestedStyle && this.shouldConvertImageType(requestedStyle, imageElement)) {
|
80 | this.editor.execute(imageUtils.isBlockImage(imageElement) ? 'imageTypeInline' : 'imageTypeBlock', { setImageSizes });
|
81 | // Update the imageElement to the newly created image.
|
82 | imageElement = imageUtils.getClosestSelectedImageElement(model.document.selection);
|
83 | }
|
84 | // Default style means that there is no `imageStyle` attribute in the model.
|
85 | // https://github.com/ckeditor/ckeditor5-image/issues/147
|
86 | if (!requestedStyle || this._styles.get(requestedStyle).isDefault) {
|
87 | writer.removeAttribute('imageStyle', imageElement);
|
88 | }
|
89 | else {
|
90 | writer.setAttribute('imageStyle', requestedStyle, imageElement);
|
91 | }
|
92 | if (setImageSizes) {
|
93 | imageUtils.setImageNaturalSizeAttributes(imageElement);
|
94 | }
|
95 | });
|
96 | }
|
97 | /**
|
98 | * Returns `true` if requested style change would trigger the image type change.
|
99 | *
|
100 | * @param requestedStyle The name of the style (as configured in {@link module:image/imageconfig~ImageStyleConfig#options}).
|
101 | * @param imageElement The image model element.
|
102 | */
|
103 | shouldConvertImageType(requestedStyle, imageElement) {
|
104 | const supportedTypes = this._styles.get(requestedStyle).modelElements;
|
105 | return !supportedTypes.includes(imageElement.name);
|
106 | }
|
107 | }
|