UNPKG

5.9 kBJavaScriptView Raw
1/**
2 * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3 * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4 */
5import { Command } from 'ckeditor5/src/core.js';
6import ImageBlockEditing from '../image/imageblockediting.js';
7/**
8 * The toggle image caption command.
9 *
10 * This command is registered by {@link module:image/imagecaption/imagecaptionediting~ImageCaptionEditing} as the
11 * `'toggleImageCaption'` editor command.
12 *
13 * Executing this command:
14 *
15 * * either adds or removes the image caption of a selected image (depending on whether the caption is present or not),
16 * * removes the image caption if the selection is anchored in one.
17 *
18 * ```ts
19 * // Toggle the presence of the caption.
20 * editor.execute( 'toggleImageCaption' );
21 * ```
22 *
23 * **Note**: Upon executing this command, the selection will be set on the image if previously anchored in the caption element.
24 *
25 * **Note**: You can move the selection to the caption right away as it shows up upon executing this command by using
26 * the `focusCaptionOnShow` option:
27 *
28 * ```ts
29 * editor.execute( 'toggleImageCaption', { focusCaptionOnShow: true } );
30 * ```
31 */
32export default class ToggleImageCaptionCommand extends Command {
33 /**
34 * @inheritDoc
35 */
36 refresh() {
37 const editor = this.editor;
38 const imageCaptionUtils = editor.plugins.get('ImageCaptionUtils');
39 const imageUtils = editor.plugins.get('ImageUtils');
40 // Only block images can get captions.
41 if (!editor.plugins.has(ImageBlockEditing)) {
42 this.isEnabled = false;
43 this.value = false;
44 return;
45 }
46 const selection = editor.model.document.selection;
47 const selectedElement = selection.getSelectedElement();
48 if (!selectedElement) {
49 const ancestorCaptionElement = imageCaptionUtils.getCaptionFromModelSelection(selection);
50 this.isEnabled = !!ancestorCaptionElement;
51 this.value = !!ancestorCaptionElement;
52 return;
53 }
54 // Block images support captions by default but the command should also be enabled for inline
55 // images because toggling the caption when one is selected should convert it into a block image.
56 this.isEnabled = imageUtils.isImage(selectedElement);
57 if (!this.isEnabled) {
58 this.value = false;
59 }
60 else {
61 this.value = !!imageCaptionUtils.getCaptionFromImageModelElement(selectedElement);
62 }
63 }
64 /**
65 * Executes the command.
66 *
67 * ```ts
68 * editor.execute( 'toggleImageCaption' );
69 * ```
70 *
71 * @param options Options for the executed command.
72 * @param options.focusCaptionOnShow When true and the caption shows up, the selection will be moved into it straight away.
73 * @fires execute
74 */
75 execute(options = {}) {
76 const { focusCaptionOnShow } = options;
77 this.editor.model.change(writer => {
78 if (this.value) {
79 this._hideImageCaption(writer);
80 }
81 else {
82 this._showImageCaption(writer, focusCaptionOnShow);
83 }
84 });
85 }
86 /**
87 * Shows the caption of the `<imageBlock>` or `<imageInline>`. Also:
88 *
89 * * it converts `<imageInline>` to `<imageBlock>` to show the caption,
90 * * it attempts to restore the caption content from the `ImageCaptionEditing` caption registry,
91 * * it moves the selection to the caption right away, it the `focusCaptionOnShow` option was set.
92 */
93 _showImageCaption(writer, focusCaptionOnShow) {
94 const model = this.editor.model;
95 const selection = model.document.selection;
96 const imageCaptionEditing = this.editor.plugins.get('ImageCaptionEditing');
97 const imageUtils = this.editor.plugins.get('ImageUtils');
98 let selectedImage = selection.getSelectedElement();
99 const savedCaption = imageCaptionEditing._getSavedCaption(selectedImage);
100 // Convert imageInline -> image first.
101 if (imageUtils.isInlineImage(selectedImage)) {
102 this.editor.execute('imageTypeBlock');
103 // Executing the command created a new model element. Let's pick it again.
104 selectedImage = selection.getSelectedElement();
105 }
106 // Try restoring the caption from the ImageCaptionEditing plugin storage.
107 const newCaptionElement = savedCaption || writer.createElement('caption');
108 writer.append(newCaptionElement, selectedImage);
109 if (focusCaptionOnShow) {
110 writer.setSelection(newCaptionElement, 'in');
111 }
112 }
113 /**
114 * Hides the caption of a selected image (or an image caption the selection is anchored to).
115 *
116 * The content of the caption is stored in the `ImageCaptionEditing` caption registry to make this
117 * a reversible action.
118 */
119 _hideImageCaption(writer) {
120 const editor = this.editor;
121 const selection = editor.model.document.selection;
122 const imageCaptionEditing = editor.plugins.get('ImageCaptionEditing');
123 const imageCaptionUtils = editor.plugins.get('ImageCaptionUtils');
124 let selectedImage = selection.getSelectedElement();
125 let captionElement;
126 if (selectedImage) {
127 captionElement = imageCaptionUtils.getCaptionFromImageModelElement(selectedImage);
128 }
129 else {
130 captionElement = imageCaptionUtils.getCaptionFromModelSelection(selection);
131 selectedImage = captionElement.parent;
132 }
133 // Store the caption content so it can be restored quickly if the user changes their mind even if they toggle image<->imageInline.
134 imageCaptionEditing._saveCaption(selectedImage, captionElement);
135 writer.setSelection(selectedImage, 'on');
136 writer.remove(captionElement);
137 }
138}