@ckeditor/ckeditor5-ckbox 40.1.0 → 41.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (137) hide show
  1. package/LICENSE.md +1 -1
  2. package/build/ckbox.js +3 -3
  3. package/build/translations/ar.js +1 -1
  4. package/build/translations/az.js +1 -1
  5. package/build/translations/bg.js +1 -1
  6. package/build/translations/bn.js +1 -1
  7. package/build/translations/ca.js +1 -1
  8. package/build/translations/cs.js +1 -1
  9. package/build/translations/da.js +1 -1
  10. package/build/translations/de.js +1 -1
  11. package/build/translations/el.js +1 -1
  12. package/build/translations/en-au.js +1 -1
  13. package/build/translations/es-co.js +1 -1
  14. package/build/translations/es.js +1 -1
  15. package/build/translations/et.js +1 -1
  16. package/build/translations/fa.js +1 -1
  17. package/build/translations/fi.js +1 -1
  18. package/build/translations/fr.js +1 -1
  19. package/build/translations/gl.js +1 -1
  20. package/build/translations/he.js +1 -1
  21. package/build/translations/hi.js +1 -1
  22. package/build/translations/hr.js +1 -1
  23. package/build/translations/hu.js +1 -1
  24. package/build/translations/id.js +1 -1
  25. package/build/translations/it.js +1 -1
  26. package/build/translations/ja.js +1 -1
  27. package/build/translations/ko.js +1 -1
  28. package/build/translations/lt.js +1 -1
  29. package/build/translations/lv.js +1 -1
  30. package/build/translations/ms.js +1 -1
  31. package/build/translations/nl.js +1 -1
  32. package/build/translations/no.js +1 -1
  33. package/build/translations/pl.js +1 -1
  34. package/build/translations/pt-br.js +1 -1
  35. package/build/translations/pt.js +1 -1
  36. package/build/translations/ro.js +1 -1
  37. package/build/translations/ru.js +1 -1
  38. package/build/translations/sk.js +1 -1
  39. package/build/translations/sq.js +1 -1
  40. package/build/translations/sr-latn.js +1 -1
  41. package/build/translations/sr.js +1 -1
  42. package/build/translations/sv.js +1 -1
  43. package/build/translations/th.js +1 -1
  44. package/build/translations/tr.js +1 -1
  45. package/build/translations/ug.js +1 -1
  46. package/build/translations/uk.js +1 -1
  47. package/build/translations/ur.js +1 -1
  48. package/build/translations/uz.js +1 -1
  49. package/build/translations/vi.js +1 -1
  50. package/build/translations/zh-cn.js +1 -1
  51. package/build/translations/zh.js +1 -1
  52. package/ckeditor5-metadata.json +18 -1
  53. package/lang/contexts.json +6 -2
  54. package/lang/translations/ar.po +19 -3
  55. package/lang/translations/az.po +19 -3
  56. package/lang/translations/bg.po +19 -3
  57. package/lang/translations/bn.po +19 -3
  58. package/lang/translations/ca.po +19 -3
  59. package/lang/translations/cs.po +19 -3
  60. package/lang/translations/da.po +19 -3
  61. package/lang/translations/de.po +19 -3
  62. package/lang/translations/el.po +19 -3
  63. package/lang/translations/en-au.po +19 -3
  64. package/lang/translations/en.po +19 -3
  65. package/lang/translations/es-co.po +19 -3
  66. package/lang/translations/es.po +19 -3
  67. package/lang/translations/et.po +19 -3
  68. package/lang/translations/fa.po +19 -3
  69. package/lang/translations/fi.po +19 -3
  70. package/lang/translations/fr.po +19 -3
  71. package/lang/translations/gl.po +19 -3
  72. package/lang/translations/he.po +19 -3
  73. package/lang/translations/hi.po +19 -3
  74. package/lang/translations/hr.po +19 -3
  75. package/lang/translations/hu.po +19 -3
  76. package/lang/translations/id.po +19 -3
  77. package/lang/translations/it.po +19 -3
  78. package/lang/translations/ja.po +19 -3
  79. package/lang/translations/ko.po +19 -3
  80. package/lang/translations/lt.po +19 -3
  81. package/lang/translations/lv.po +19 -3
  82. package/lang/translations/ms.po +19 -3
  83. package/lang/translations/nl.po +19 -3
  84. package/lang/translations/no.po +19 -3
  85. package/lang/translations/pl.po +19 -3
  86. package/lang/translations/pt-br.po +19 -3
  87. package/lang/translations/pt.po +19 -3
  88. package/lang/translations/ro.po +19 -3
  89. package/lang/translations/ru.po +19 -3
  90. package/lang/translations/sk.po +19 -3
  91. package/lang/translations/sq.po +19 -3
  92. package/lang/translations/sr-latn.po +19 -3
  93. package/lang/translations/sr.po +19 -3
  94. package/lang/translations/sv.po +19 -3
  95. package/lang/translations/th.po +19 -3
  96. package/lang/translations/tr.po +19 -3
  97. package/lang/translations/ug.po +19 -3
  98. package/lang/translations/uk.po +19 -3
  99. package/lang/translations/ur.po +19 -3
  100. package/lang/translations/uz.po +19 -3
  101. package/lang/translations/vi.po +19 -3
  102. package/lang/translations/zh-cn.po +19 -3
  103. package/lang/translations/zh.po +19 -3
  104. package/package.json +5 -3
  105. package/src/augmentation.d.ts +12 -2
  106. package/src/augmentation.js +1 -1
  107. package/src/ckbox.d.ts +4 -4
  108. package/src/ckbox.js +4 -4
  109. package/src/ckboxcommand.d.ts +10 -8
  110. package/src/ckboxcommand.js +9 -5
  111. package/src/ckboxconfig.d.ts +27 -1
  112. package/src/ckboxconfig.js +1 -1
  113. package/src/ckboxediting.d.ts +8 -15
  114. package/src/ckboxediting.js +12 -60
  115. package/src/ckboximageedit/ckboximageeditcommand.d.ts +97 -0
  116. package/src/ckboximageedit/ckboximageeditcommand.js +299 -0
  117. package/src/ckboximageedit/ckboximageeditediting.d.ts +28 -0
  118. package/src/ckboximageedit/ckboximageeditediting.js +36 -0
  119. package/src/ckboximageedit/ckboximageeditui.d.ts +24 -0
  120. package/src/ckboximageedit/ckboximageeditui.js +48 -0
  121. package/src/ckboximageedit/utils.d.ts +10 -0
  122. package/src/ckboximageedit/utils.js +48 -0
  123. package/src/ckboximageedit.d.ts +24 -0
  124. package/src/ckboximageedit.js +28 -0
  125. package/src/ckboxui.d.ts +2 -2
  126. package/src/ckboxui.js +31 -5
  127. package/src/ckboxuploadadapter.d.ts +4 -9
  128. package/src/ckboxuploadadapter.js +19 -164
  129. package/src/ckboxutils.d.ts +50 -0
  130. package/src/ckboxutils.js +183 -0
  131. package/src/index.d.ts +11 -7
  132. package/src/index.js +8 -5
  133. package/src/utils.d.ts +33 -2
  134. package/src/utils.js +94 -1
  135. package/theme/ckboximageedit.css +53 -0
  136. package/theme/icons/ckbox-image-edit.svg +1 -0
  137. package/theme/icons/browse-files.svg +0 -1
@@ -0,0 +1,299 @@
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
+ */
5
+ /* globals document, console, AbortController, URL, window */
6
+ /**
7
+ * @module ckbox/ckboximageedit/ckboximageeditcommand
8
+ */
9
+ import { Command, PendingActions } from 'ckeditor5/src/core.js';
10
+ import { CKEditorError, abortableDebounce, createElement, retry } from 'ckeditor5/src/utils.js';
11
+ import { Notification } from 'ckeditor5/src/ui.js';
12
+ import { isEqual } from 'lodash-es';
13
+ import { sendHttpRequest } from '../utils.js';
14
+ import { prepareImageAssetAttributes } from '../ckboxcommand.js';
15
+ import { createEditabilityChecker } from './utils.js';
16
+ import CKBoxUtils from '../ckboxutils.js';
17
+ /**
18
+ * The CKBox edit image command.
19
+ *
20
+ * Opens the CKBox dialog for editing the image.
21
+ */
22
+ export default class CKBoxImageEditCommand extends Command {
23
+ /**
24
+ * @inheritDoc
25
+ */
26
+ constructor(editor) {
27
+ super(editor);
28
+ /**
29
+ * The DOM element that acts as a mounting point for the CKBox Edit Image dialog.
30
+ */
31
+ this._wrapper = null;
32
+ /**
33
+ * The states of image processing in progress.
34
+ */
35
+ this._processInProgress = new Set();
36
+ this.value = false;
37
+ this._canEdit = createEditabilityChecker(editor.config.get('ckbox.allowExternalImagesEditing'));
38
+ this._prepareOptions = abortableDebounce((signal, state) => this._prepareOptionsAbortable(signal, state));
39
+ this._prepareListeners();
40
+ }
41
+ /**
42
+ * @inheritDoc
43
+ */
44
+ refresh() {
45
+ const editor = this.editor;
46
+ this.value = this._getValue();
47
+ const selectedElement = editor.model.document.selection.getSelectedElement();
48
+ this.isEnabled =
49
+ !!selectedElement &&
50
+ this._canEdit(selectedElement) &&
51
+ !this._checkIfElementIsBeingProcessed(selectedElement);
52
+ }
53
+ /**
54
+ * Opens the CKBox Image Editor dialog for editing the image.
55
+ */
56
+ execute() {
57
+ if (this._getValue()) {
58
+ return;
59
+ }
60
+ const wrapper = createElement(document, 'div', { class: 'ck ckbox-wrapper' });
61
+ this._wrapper = wrapper;
62
+ this.value = true;
63
+ document.body.appendChild(this._wrapper);
64
+ const imageElement = this.editor.model.document.selection.getSelectedElement();
65
+ const processingState = {
66
+ element: imageElement,
67
+ controller: new AbortController()
68
+ };
69
+ this._prepareOptions(processingState).then(options => window.CKBox.mountImageEditor(wrapper, options), error => {
70
+ const editor = this.editor;
71
+ const t = editor.t;
72
+ const notification = editor.plugins.get(Notification);
73
+ notification.showWarning(t('Failed to determine category of edited image.'), {
74
+ namespace: 'ckbox'
75
+ });
76
+ console.error(error);
77
+ this._handleImageEditorClose();
78
+ });
79
+ }
80
+ /**
81
+ * @inheritDoc
82
+ */
83
+ destroy() {
84
+ this._handleImageEditorClose();
85
+ this._prepareOptions.abort();
86
+ for (const state of this._processInProgress.values()) {
87
+ state.controller.abort();
88
+ }
89
+ super.destroy();
90
+ }
91
+ /**
92
+ * Indicates if the CKBox Image Editor dialog is already opened.
93
+ */
94
+ _getValue() {
95
+ return this._wrapper !== null;
96
+ }
97
+ /**
98
+ * Creates the options object for the CKBox Image Editor dialog.
99
+ */
100
+ async _prepareOptionsAbortable(signal, state) {
101
+ const editor = this.editor;
102
+ const ckboxConfig = editor.config.get('ckbox');
103
+ const ckboxUtils = editor.plugins.get(CKBoxUtils);
104
+ const { element } = state;
105
+ let imageMountOptions;
106
+ const ckboxImageId = element.getAttribute('ckboxImageId');
107
+ if (ckboxImageId) {
108
+ imageMountOptions = {
109
+ assetId: ckboxImageId
110
+ };
111
+ }
112
+ else {
113
+ const imageUrl = new URL(element.getAttribute('src'), document.baseURI).href;
114
+ const uploadCategoryId = await ckboxUtils.getCategoryIdForFile(imageUrl, { signal });
115
+ imageMountOptions = {
116
+ imageUrl,
117
+ uploadCategoryId
118
+ };
119
+ }
120
+ return {
121
+ ...imageMountOptions,
122
+ imageEditing: {
123
+ allowOverwrite: false
124
+ },
125
+ tokenUrl: ckboxConfig.tokenUrl,
126
+ ...(ckboxConfig.serviceOrigin && { serviceOrigin: ckboxConfig.serviceOrigin }),
127
+ onClose: () => this._handleImageEditorClose(),
128
+ onSave: (asset) => this._handleImageEditorSave(state, asset)
129
+ };
130
+ }
131
+ /**
132
+ * Initializes event lister for an event of removing an image.
133
+ */
134
+ _prepareListeners() {
135
+ // Abort editing processing when the image has been removed.
136
+ this.listenTo(this.editor.model.document, 'change:data', () => {
137
+ const processingStates = this._getProcessingStatesOfDeletedImages();
138
+ processingStates.forEach(processingState => {
139
+ processingState.controller.abort();
140
+ });
141
+ });
142
+ }
143
+ /**
144
+ * Gets processing states of images that have been deleted in the mean time.
145
+ */
146
+ _getProcessingStatesOfDeletedImages() {
147
+ const states = [];
148
+ for (const state of this._processInProgress.values()) {
149
+ if (state.element.root.rootName == '$graveyard') {
150
+ states.push(state);
151
+ }
152
+ }
153
+ return states;
154
+ }
155
+ _checkIfElementIsBeingProcessed(selectedElement) {
156
+ for (const { element } of this._processInProgress) {
157
+ if (isEqual(element, selectedElement)) {
158
+ return true;
159
+ }
160
+ }
161
+ return false;
162
+ }
163
+ /**
164
+ * Closes the CKBox Image Editor dialog.
165
+ */
166
+ _handleImageEditorClose() {
167
+ if (!this._wrapper) {
168
+ return;
169
+ }
170
+ this._wrapper.remove();
171
+ this._wrapper = null;
172
+ this.editor.editing.view.focus();
173
+ this.refresh();
174
+ }
175
+ /**
176
+ * Save edited image. In case server respond with "success" replace with edited image,
177
+ * otherwise show notification error.
178
+ */
179
+ _handleImageEditorSave(state, asset) {
180
+ const t = this.editor.locale.t;
181
+ const notification = this.editor.plugins.get(Notification);
182
+ const pendingActions = this.editor.plugins.get(PendingActions);
183
+ const action = pendingActions.add(t('Processing the edited image.'));
184
+ this._processInProgress.add(state);
185
+ this._showImageProcessingIndicator(state.element, asset);
186
+ this.refresh();
187
+ this._waitForAssetProcessed(asset.data.id, state.controller.signal)
188
+ .then(asset => {
189
+ this._replaceImage(state.element, asset);
190
+ }, error => {
191
+ // Remove processing indicator. It was added only to ViewElement.
192
+ this.editor.editing.reconvertItem(state.element);
193
+ if (state.controller.signal.aborted) {
194
+ return;
195
+ }
196
+ if (!error || error instanceof CKEditorError) {
197
+ notification.showWarning(t('Server failed to process the image.'), {
198
+ namespace: 'ckbox'
199
+ });
200
+ }
201
+ else {
202
+ console.error(error);
203
+ }
204
+ }).finally(() => {
205
+ this._processInProgress.delete(state);
206
+ pendingActions.remove(action);
207
+ this.refresh();
208
+ });
209
+ }
210
+ /**
211
+ * Get asset's status on server. If server responds with "success" status then
212
+ * image is already proceeded and ready for saving.
213
+ */
214
+ async _getAssetStatusFromServer(id, signal) {
215
+ const ckboxUtils = this.editor.plugins.get(CKBoxUtils);
216
+ const url = new URL('assets/' + id, this.editor.config.get('ckbox.serviceOrigin'));
217
+ const response = await sendHttpRequest({
218
+ url,
219
+ signal,
220
+ authorization: ckboxUtils.getToken().value
221
+ });
222
+ const status = response.metadata.metadataProcessingStatus;
223
+ if (!status || status == 'queued') {
224
+ /**
225
+ * Image has not been processed yet.
226
+ *
227
+ * @error ckbox-image-not-processed
228
+ */
229
+ throw new CKEditorError('ckbox-image-not-processed');
230
+ }
231
+ return { data: { ...response } };
232
+ }
233
+ /**
234
+ * Waits for an asset to be processed.
235
+ * It retries retrieving asset status from the server in case of failure.
236
+ */
237
+ async _waitForAssetProcessed(id, signal) {
238
+ const result = await retry(() => this._getAssetStatusFromServer(id, signal), {
239
+ signal,
240
+ maxAttempts: 5
241
+ });
242
+ if (result.data.metadata.metadataProcessingStatus != 'success') {
243
+ /**
244
+ * The image processing failed.
245
+ *
246
+ * @error ckbox-image-processing-failed
247
+ */
248
+ throw new CKEditorError('ckbox-image-processing-failed');
249
+ }
250
+ return result;
251
+ }
252
+ /**
253
+ * Shows processing indicator while image is processing.
254
+ *
255
+ * @param asset Data about certain asset.
256
+ */
257
+ _showImageProcessingIndicator(element, asset) {
258
+ const editor = this.editor;
259
+ editor.editing.view.change(writer => {
260
+ const imageElementView = editor.editing.mapper.toViewElement(element);
261
+ const imageUtils = this.editor.plugins.get('ImageUtils');
262
+ const img = imageUtils.findViewImgElement(imageElementView);
263
+ writer.removeStyle('aspect-ratio', img);
264
+ writer.setAttribute('width', asset.data.metadata.width, img);
265
+ writer.setAttribute('height', asset.data.metadata.height, img);
266
+ writer.setStyle('width', `${asset.data.metadata.width}px`, img);
267
+ writer.setStyle('height', `${asset.data.metadata.height}px`, img);
268
+ writer.addClass('image-processing', imageElementView);
269
+ });
270
+ }
271
+ /**
272
+ * Replace the edited image with the new one.
273
+ */
274
+ _replaceImage(element, asset) {
275
+ const editor = this.editor;
276
+ const { imageFallbackUrl, imageSources, imageWidth, imageHeight, imagePlaceholder } = prepareImageAssetAttributes(asset);
277
+ const previousSelectionRanges = Array.from(editor.model.document.selection.getRanges());
278
+ editor.model.change(writer => {
279
+ writer.setSelection(element, 'on');
280
+ editor.execute('insertImage', {
281
+ source: {
282
+ src: imageFallbackUrl,
283
+ sources: imageSources,
284
+ width: imageWidth,
285
+ height: imageHeight,
286
+ ...(imagePlaceholder ? { placeholder: imagePlaceholder } : null),
287
+ ...(element.hasAttribute('alt') ? { alt: element.getAttribute('alt') } : null)
288
+ }
289
+ });
290
+ const previousChildren = element.getChildren();
291
+ element = editor.model.document.selection.getSelectedElement();
292
+ for (const child of previousChildren) {
293
+ writer.append(writer.cloneElement(child), element);
294
+ }
295
+ writer.setAttribute('ckboxImageId', asset.data.id, element);
296
+ writer.setSelection(previousSelectionRanges);
297
+ });
298
+ }
299
+ }
@@ -0,0 +1,28 @@
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
+ */
5
+ /**
6
+ * @module ckbox/ckboximageedit/ckboximageeditediting
7
+ */
8
+ import { PendingActions, Plugin } from 'ckeditor5/src/core.js';
9
+ import { Notification } from 'ckeditor5/src/ui.js';
10
+ import CKBoxEditing from '../ckboxediting.js';
11
+ import CKBoxUtils from '../ckboxutils.js';
12
+ /**
13
+ * The CKBox image edit editing plugin.
14
+ */
15
+ export default class CKBoxImageEditEditing extends Plugin {
16
+ /**
17
+ * @inheritDoc
18
+ */
19
+ static get pluginName(): "CKBoxImageEditEditing";
20
+ /**
21
+ * @inheritDoc
22
+ */
23
+ static get requires(): readonly [typeof CKBoxEditing, typeof CKBoxUtils, typeof PendingActions, typeof Notification, "ImageUtils", "ImageEditing"];
24
+ /**
25
+ * @inheritDoc
26
+ */
27
+ init(): void;
28
+ }
@@ -0,0 +1,36 @@
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
+ */
5
+ /**
6
+ * @module ckbox/ckboximageedit/ckboximageeditediting
7
+ */
8
+ import { PendingActions, Plugin } from 'ckeditor5/src/core.js';
9
+ import { Notification } from 'ckeditor5/src/ui.js';
10
+ import CKBoxImageEditCommand from './ckboximageeditcommand.js';
11
+ import CKBoxEditing from '../ckboxediting.js';
12
+ import CKBoxUtils from '../ckboxutils.js';
13
+ /**
14
+ * The CKBox image edit editing plugin.
15
+ */
16
+ export default class CKBoxImageEditEditing extends Plugin {
17
+ /**
18
+ * @inheritDoc
19
+ */
20
+ static get pluginName() {
21
+ return 'CKBoxImageEditEditing';
22
+ }
23
+ /**
24
+ * @inheritDoc
25
+ */
26
+ static get requires() {
27
+ return [CKBoxEditing, CKBoxUtils, PendingActions, Notification, 'ImageUtils', 'ImageEditing'];
28
+ }
29
+ /**
30
+ * @inheritDoc
31
+ */
32
+ init() {
33
+ const { editor } = this;
34
+ editor.commands.add('ckboxImageEdit', new CKBoxImageEditCommand(editor));
35
+ }
36
+ }
@@ -0,0 +1,24 @@
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
+ */
5
+ /**
6
+ * @module ckbox/ckboximageedit/ckboximageeditui
7
+ */
8
+ import { Plugin } from 'ckeditor5/src/core.js';
9
+ /**
10
+ * The UI plugin of the CKBox image edit feature.
11
+ *
12
+ * It registers the `'ckboxImageEdit'` UI button in the editor's {@link module:ui/componentfactory~ComponentFactory component factory}
13
+ * that allows you to open the CKBox dialog and edit the image.
14
+ */
15
+ export default class CKBoxImageEditUI extends Plugin {
16
+ /**
17
+ * @inheritDoc
18
+ */
19
+ static get pluginName(): "CKBoxImageEditUI";
20
+ /**
21
+ * @inheritDoc
22
+ */
23
+ init(): void;
24
+ }
@@ -0,0 +1,48 @@
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
+ */
5
+ /**
6
+ * @module ckbox/ckboximageedit/ckboximageeditui
7
+ */
8
+ import { Plugin } from 'ckeditor5/src/core.js';
9
+ import { ButtonView } from 'ckeditor5/src/ui.js';
10
+ import ckboxImageEditIcon from '../../theme/icons/ckbox-image-edit.svg';
11
+ /**
12
+ * The UI plugin of the CKBox image edit feature.
13
+ *
14
+ * It registers the `'ckboxImageEdit'` UI button in the editor's {@link module:ui/componentfactory~ComponentFactory component factory}
15
+ * that allows you to open the CKBox dialog and edit the image.
16
+ */
17
+ export default class CKBoxImageEditUI extends Plugin {
18
+ /**
19
+ * @inheritDoc
20
+ */
21
+ static get pluginName() {
22
+ return 'CKBoxImageEditUI';
23
+ }
24
+ /**
25
+ * @inheritDoc
26
+ */
27
+ init() {
28
+ const editor = this.editor;
29
+ editor.ui.componentFactory.add('ckboxImageEdit', locale => {
30
+ const command = editor.commands.get('ckboxImageEdit');
31
+ const view = new ButtonView(locale);
32
+ const t = locale.t;
33
+ view.set({
34
+ label: t('Edit image'),
35
+ icon: ckboxImageEditIcon,
36
+ tooltip: true
37
+ });
38
+ view.bind('isOn').to(command, 'value', command, 'isEnabled', (value, isEnabled) => value && isEnabled);
39
+ view.bind('isEnabled').to(command);
40
+ // Execute the command.
41
+ this.listenTo(view, 'execute', () => {
42
+ editor.execute('ckboxImageEdit');
43
+ editor.editing.view.focus();
44
+ });
45
+ return view;
46
+ });
47
+ }
48
+ }
@@ -0,0 +1,10 @@
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
+ */
5
+ import type { Element } from 'ckeditor5/src/engine.js';
6
+ import type { CKBoxConfig } from '../ckboxconfig.js';
7
+ /**
8
+ * @internal
9
+ */
10
+ export declare function createEditabilityChecker(allowExternalImagesEditing: CKBoxConfig['allowExternalImagesEditing']): (element: Element) => boolean;
@@ -0,0 +1,48 @@
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
+ */
5
+ /**
6
+ * @module ckbox/ckboximageedit/utils
7
+ */
8
+ import { global } from 'ckeditor5/src/utils.js';
9
+ /**
10
+ * @internal
11
+ */
12
+ export function createEditabilityChecker(allowExternalImagesEditing) {
13
+ const checkUrl = createUrlChecker(allowExternalImagesEditing);
14
+ return element => {
15
+ const isImageElement = element.is('element', 'imageInline') ||
16
+ element.is('element', 'imageBlock');
17
+ if (!isImageElement) {
18
+ return false;
19
+ }
20
+ if (element.hasAttribute('ckboxImageId')) {
21
+ return true;
22
+ }
23
+ if (element.hasAttribute('src')) {
24
+ return checkUrl(element.getAttribute('src'));
25
+ }
26
+ return false;
27
+ };
28
+ }
29
+ function createUrlChecker(allowExternalImagesEditing) {
30
+ if (Array.isArray(allowExternalImagesEditing)) {
31
+ const urlMatchers = allowExternalImagesEditing.map(createUrlChecker);
32
+ return src => urlMatchers.some(matcher => matcher(src));
33
+ }
34
+ if (allowExternalImagesEditing == 'origin') {
35
+ const origin = global.window.location.origin;
36
+ return src => new URL(src, global.document.baseURI).origin == origin;
37
+ }
38
+ if (typeof allowExternalImagesEditing == 'function') {
39
+ return allowExternalImagesEditing;
40
+ }
41
+ if (allowExternalImagesEditing instanceof RegExp) {
42
+ return src => !!(src.match(allowExternalImagesEditing) ||
43
+ src.replace(/^https?:\/\//, '').match(allowExternalImagesEditing));
44
+ }
45
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
46
+ const shouldBeUndefned = allowExternalImagesEditing;
47
+ return () => false;
48
+ }
@@ -0,0 +1,24 @@
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
+ */
5
+ /**
6
+ * @module ckbox/ckboximageedit
7
+ */
8
+ import { Plugin } from 'ckeditor5/src/core.js';
9
+ import CKBoxImageEditEditing from './ckboximageedit/ckboximageeditediting.js';
10
+ import CKBoxImageEditUI from './ckboximageedit/ckboximageeditui.js';
11
+ import '../theme/ckboximageedit.css';
12
+ /**
13
+ * The CKBox image edit feature.
14
+ */
15
+ export default class CKBoxImageEdit extends Plugin {
16
+ /**
17
+ * @inheritDoc
18
+ */
19
+ static get pluginName(): "CKBoxImageEdit";
20
+ /**
21
+ * @inheritDoc
22
+ */
23
+ static get requires(): readonly [typeof CKBoxImageEditEditing, typeof CKBoxImageEditUI];
24
+ }
@@ -0,0 +1,28 @@
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
+ */
5
+ /**
6
+ * @module ckbox/ckboximageedit
7
+ */
8
+ import { Plugin } from 'ckeditor5/src/core.js';
9
+ import CKBoxImageEditEditing from './ckboximageedit/ckboximageeditediting.js';
10
+ import CKBoxImageEditUI from './ckboximageedit/ckboximageeditui.js';
11
+ import '../theme/ckboximageedit.css';
12
+ /**
13
+ * The CKBox image edit feature.
14
+ */
15
+ export default class CKBoxImageEdit extends Plugin {
16
+ /**
17
+ * @inheritDoc
18
+ */
19
+ static get pluginName() {
20
+ return 'CKBoxImageEdit';
21
+ }
22
+ /**
23
+ * @inheritDoc
24
+ */
25
+ static get requires() {
26
+ return [CKBoxImageEditEditing, CKBoxImageEditUI];
27
+ }
28
+ }
package/src/ckboxui.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
6
6
  * @module ckbox/ckboxui
7
7
  */
8
- import { Plugin } from 'ckeditor5/src/core';
8
+ import { Plugin } from 'ckeditor5/src/core.js';
9
9
  /**
10
10
  * The CKBoxUI plugin. It introduces the `'ckbox'` toolbar button.
11
11
  */
package/src/ckboxui.js CHANGED
@@ -1,13 +1,12 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
6
6
  * @module ckbox/ckboxui
7
7
  */
8
- import { Plugin } from 'ckeditor5/src/core';
9
- import { ButtonView } from 'ckeditor5/src/ui';
10
- import browseFilesIcon from '../theme/icons/browse-files.svg';
8
+ import { icons, Plugin } from 'ckeditor5/src/core.js';
9
+ import { ButtonView } from 'ckeditor5/src/ui.js';
11
10
  /**
12
11
  * The CKBoxUI plugin. It introduces the `'ckbox'` toolbar button.
13
12
  */
@@ -34,7 +33,7 @@ export default class CKBoxUI extends Plugin {
34
33
  const button = new ButtonView(locale);
35
34
  button.set({
36
35
  label: t('Open file manager'),
37
- icon: browseFilesIcon,
36
+ icon: icons.browseFiles,
38
37
  tooltip: true
39
38
  });
40
39
  button.bind('isOn', 'isEnabled').to(command, 'value', 'isEnabled');
@@ -43,5 +42,32 @@ export default class CKBoxUI extends Plugin {
43
42
  });
44
43
  return button;
45
44
  });
45
+ if (editor.plugins.has('ImageInsertUI')) {
46
+ const imageInsertUI = editor.plugins.get('ImageInsertUI');
47
+ imageInsertUI.registerIntegration({
48
+ name: 'assetManager',
49
+ observable: command,
50
+ buttonViewCreator: () => {
51
+ const button = this.editor.ui.componentFactory.create('ckbox');
52
+ button.icon = icons.imageAssetManager;
53
+ button.bind('label').to(imageInsertUI, 'isImageSelected', isImageSelected => isImageSelected ?
54
+ t('Replace image with file manager') :
55
+ t('Insert image with file manager'));
56
+ return button;
57
+ },
58
+ formViewCreator: () => {
59
+ const button = this.editor.ui.componentFactory.create('ckbox');
60
+ button.icon = icons.imageAssetManager;
61
+ button.withText = true;
62
+ button.bind('label').to(imageInsertUI, 'isImageSelected', isImageSelected => isImageSelected ?
63
+ t('Replace with file manager') :
64
+ t('Insert with file manager'));
65
+ button.on('execute', () => {
66
+ imageInsertUI.dropdownView.isOpen = false;
67
+ });
68
+ return button;
69
+ }
70
+ });
71
+ }
46
72
  }
47
73
  }
@@ -1,13 +1,13 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
6
6
  * @module ckbox/ckboxuploadadapter
7
7
  */
8
- import { Plugin } from 'ckeditor5/src/core';
9
- import { FileRepository } from 'ckeditor5/src/upload';
10
- import CKBoxEditing from './ckboxediting';
8
+ import { Plugin } from 'ckeditor5/src/core.js';
9
+ import { FileRepository } from 'ckeditor5/src/upload.js';
10
+ import CKBoxEditing from './ckboxediting.js';
11
11
  /**
12
12
  * A plugin that enables file uploads in CKEditor 5 using the CKBox server–side connector.
13
13
  * See the {@glink features/file-management/ckbox CKBox file manager integration} guide to learn how to configure
@@ -31,8 +31,3 @@ export default class CKBoxUploadAdapter extends Plugin {
31
31
  */
32
32
  afterInit(): Promise<void>;
33
33
  }
34
- export interface AvailableCategory {
35
- id: string;
36
- name: string;
37
- extensions: Array<string>;
38
- }