@ckeditor/ckeditor5-image 40.1.0 → 40.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -25
- package/build/image.js +2 -2
- package/build/translations/ar.js +1 -1
- package/build/translations/ast.js +1 -1
- package/build/translations/az.js +1 -1
- package/build/translations/bg.js +1 -1
- package/build/translations/bn.js +1 -1
- package/build/translations/bs.js +1 -1
- package/build/translations/ca.js +1 -1
- package/build/translations/cs.js +1 -1
- package/build/translations/da.js +1 -1
- package/build/translations/de-ch.js +1 -1
- package/build/translations/de.js +1 -1
- package/build/translations/el.js +1 -1
- package/build/translations/en-au.js +1 -1
- package/build/translations/en-gb.js +1 -1
- package/build/translations/eo.js +1 -1
- package/build/translations/es.js +1 -1
- package/build/translations/et.js +1 -1
- package/build/translations/eu.js +1 -1
- package/build/translations/fa.js +1 -1
- package/build/translations/fi.js +1 -1
- package/build/translations/fr.js +1 -1
- package/build/translations/gl.js +1 -1
- package/build/translations/he.js +1 -1
- package/build/translations/hi.js +1 -1
- package/build/translations/hr.js +1 -1
- package/build/translations/hu.js +1 -1
- package/build/translations/id.js +1 -1
- package/build/translations/it.js +1 -1
- package/build/translations/ja.js +1 -1
- package/build/translations/jv.js +1 -1
- package/build/translations/km.js +1 -1
- package/build/translations/kn.js +1 -1
- package/build/translations/ko.js +1 -1
- package/build/translations/ku.js +1 -1
- package/build/translations/lt.js +1 -1
- package/build/translations/lv.js +1 -1
- package/build/translations/ms.js +1 -1
- package/build/translations/nb.js +1 -1
- package/build/translations/ne.js +1 -1
- package/build/translations/nl.js +1 -1
- package/build/translations/no.js +1 -1
- package/build/translations/pl.js +1 -1
- package/build/translations/pt-br.js +1 -1
- package/build/translations/pt.js +1 -1
- package/build/translations/ro.js +1 -1
- package/build/translations/ru.js +1 -1
- package/build/translations/si.js +1 -1
- package/build/translations/sk.js +1 -1
- package/build/translations/sq.js +1 -1
- package/build/translations/sr-latn.js +1 -1
- package/build/translations/sr.js +1 -1
- package/build/translations/sv.js +1 -1
- package/build/translations/th.js +1 -1
- package/build/translations/tk.js +1 -1
- package/build/translations/tr.js +1 -1
- package/build/translations/tt.js +1 -1
- package/build/translations/ug.js +1 -1
- package/build/translations/uk.js +1 -1
- package/build/translations/ur.js +1 -1
- package/build/translations/uz.js +1 -1
- package/build/translations/vi.js +1 -1
- package/build/translations/zh-cn.js +1 -1
- package/build/translations/zh.js +1 -1
- package/ckeditor5-metadata.json +3 -3
- package/lang/contexts.json +5 -0
- package/lang/translations/ar.po +20 -0
- package/lang/translations/ast.po +20 -0
- package/lang/translations/az.po +20 -0
- package/lang/translations/bg.po +20 -0
- package/lang/translations/bn.po +20 -0
- package/lang/translations/bs.po +20 -0
- package/lang/translations/ca.po +20 -0
- package/lang/translations/cs.po +20 -0
- package/lang/translations/da.po +20 -0
- package/lang/translations/de-ch.po +20 -0
- package/lang/translations/de.po +20 -0
- package/lang/translations/el.po +20 -0
- package/lang/translations/en-au.po +20 -0
- package/lang/translations/en-gb.po +20 -0
- package/lang/translations/en.po +20 -0
- package/lang/translations/eo.po +20 -0
- package/lang/translations/es.po +20 -0
- package/lang/translations/et.po +20 -0
- package/lang/translations/eu.po +20 -0
- package/lang/translations/fa.po +20 -0
- package/lang/translations/fi.po +20 -0
- package/lang/translations/fr.po +20 -0
- package/lang/translations/gl.po +20 -0
- package/lang/translations/he.po +20 -0
- package/lang/translations/hi.po +20 -0
- package/lang/translations/hr.po +20 -0
- package/lang/translations/hu.po +20 -0
- package/lang/translations/id.po +20 -0
- package/lang/translations/it.po +20 -0
- package/lang/translations/ja.po +20 -0
- package/lang/translations/jv.po +20 -0
- package/lang/translations/km.po +20 -0
- package/lang/translations/kn.po +20 -0
- package/lang/translations/ko.po +20 -0
- package/lang/translations/ku.po +20 -0
- package/lang/translations/lt.po +20 -0
- package/lang/translations/lv.po +20 -0
- package/lang/translations/ms.po +20 -0
- package/lang/translations/nb.po +20 -0
- package/lang/translations/ne.po +20 -0
- package/lang/translations/nl.po +20 -0
- package/lang/translations/no.po +20 -0
- package/lang/translations/pl.po +20 -0
- package/lang/translations/pt-br.po +20 -0
- package/lang/translations/pt.po +20 -0
- package/lang/translations/ro.po +20 -0
- package/lang/translations/ru.po +20 -0
- package/lang/translations/si.po +20 -0
- package/lang/translations/sk.po +20 -0
- package/lang/translations/sq.po +20 -0
- package/lang/translations/sr-latn.po +20 -0
- package/lang/translations/sr.po +20 -0
- package/lang/translations/sv.po +20 -0
- package/lang/translations/th.po +20 -0
- package/lang/translations/tk.po +20 -0
- package/lang/translations/tr.po +20 -0
- package/lang/translations/tt.po +20 -0
- package/lang/translations/ug.po +21 -1
- package/lang/translations/uk.po +20 -0
- package/lang/translations/ur.po +20 -0
- package/lang/translations/uz.po +20 -0
- package/lang/translations/vi.po +20 -0
- package/lang/translations/zh-cn.po +20 -0
- package/lang/translations/zh.po +20 -0
- package/package.json +3 -3
- package/src/imageblock.d.ts +2 -1
- package/src/imageblock.js +2 -1
- package/src/imageconfig.d.ts +9 -13
- package/src/imageinline.d.ts +2 -1
- package/src/imageinline.js +2 -1
- package/src/imageinsert/imageinsertui.d.ts +38 -10
- package/src/imageinsert/imageinsertui.js +126 -93
- package/src/imageinsert/imageinsertviaurlui.d.ts +44 -0
- package/src/imageinsert/imageinsertviaurlui.js +122 -0
- package/src/imageinsert/ui/imageinsertformview.d.ts +56 -0
- package/src/imageinsert/ui/imageinsertformview.js +112 -0
- package/src/imageinsert/ui/imageinserturlview.d.ts +107 -0
- package/src/imageinsert/ui/imageinserturlview.js +156 -0
- package/src/imageinsertviaurl.d.ts +2 -1
- package/src/imageinsertviaurl.js +2 -1
- package/src/imagetextalternative/ui/textalternativeformview.d.ts +18 -0
- package/src/imageupload/imageuploadui.js +30 -6
- package/theme/imageinsert.css +5 -17
- package/src/imageinsert/ui/imageinsertformrowview.d.ts +0 -61
- package/src/imageinsert/ui/imageinsertformrowview.js +0 -54
- package/src/imageinsert/ui/imageinsertpanelview.d.ts +0 -106
- package/src/imageinsert/ui/imageinsertpanelview.js +0 -161
- package/src/imageinsert/utils.d.ts +0 -25
- package/src/imageinsert/utils.js +0 -58
- package/theme/imageinsertformrowview.css +0 -36
package/src/imageconfig.d.ts
CHANGED
|
@@ -448,30 +448,26 @@ export interface ImageInsertConfig {
|
|
|
448
448
|
* The image insert panel view configuration contains a list of {@link module:image/imageinsert~ImageInsert} integrations.
|
|
449
449
|
*
|
|
450
450
|
* The option accepts string tokens.
|
|
451
|
-
* * for predefined integrations, we have
|
|
452
|
-
*
|
|
453
|
-
*
|
|
454
|
-
* {@link module:ui/componentfactory~ComponentFactory component factory}.
|
|
455
|
-
* If you have a plugin `PluginX` that registers `pluginXButton` component, then the integration token
|
|
456
|
-
* in that case should be `pluginXButton`.
|
|
451
|
+
* * for predefined integrations, we have 3 special strings: `upload`, `url`, and `assetManager`.
|
|
452
|
+
* * for custom integrations, each string should be a name of the integration registered by the
|
|
453
|
+
* {@link module:image/imageinsert/imageinsertui~ImageInsertUI#registerIntegration `ImageInsertUI#registerIntegration()`}.
|
|
457
454
|
*
|
|
458
455
|
* ```ts
|
|
459
|
-
* // Add `
|
|
456
|
+
* // Add `upload`, `assetManager` and `url` integrations.
|
|
460
457
|
* const imageInsertConfig = {
|
|
461
458
|
* insert: {
|
|
462
459
|
* integrations: [
|
|
463
|
-
* '
|
|
464
|
-
* '
|
|
465
|
-
* '
|
|
460
|
+
* 'upload',
|
|
461
|
+
* 'assetManager',
|
|
462
|
+
* 'url'
|
|
466
463
|
* ]
|
|
467
464
|
* }
|
|
468
465
|
* };
|
|
469
466
|
* ```
|
|
470
467
|
*
|
|
471
|
-
* @
|
|
472
|
-
* @default [ 'insertImageViaUrl' ]
|
|
468
|
+
* @default [ 'upload', 'assetManager', 'url' ]
|
|
473
469
|
*/
|
|
474
|
-
integrations
|
|
470
|
+
integrations?: Array<string>;
|
|
475
471
|
/**
|
|
476
472
|
* This option allows to override the image type used by the {@link module:image/image/insertimagecommand~InsertImageCommand}
|
|
477
473
|
* when the user inserts new images into the editor content. By default, all images inserted into the editor will be block
|
package/src/imageinline.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { Plugin } from 'ckeditor5/src/core';
|
|
|
9
9
|
import { Widget } from 'ckeditor5/src/widget';
|
|
10
10
|
import ImageTextAlternative from './imagetextalternative';
|
|
11
11
|
import ImageInlineEditing from './image/imageinlineediting';
|
|
12
|
+
import ImageInsertUI from './imageinsert/imageinsertui';
|
|
12
13
|
import '../theme/image.css';
|
|
13
14
|
/**
|
|
14
15
|
* The image inline plugin.
|
|
@@ -25,7 +26,7 @@ export default class ImageInline extends Plugin {
|
|
|
25
26
|
/**
|
|
26
27
|
* @inheritDoc
|
|
27
28
|
*/
|
|
28
|
-
static get requires(): readonly [typeof ImageInlineEditing, typeof Widget, typeof ImageTextAlternative];
|
|
29
|
+
static get requires(): readonly [typeof ImageInlineEditing, typeof Widget, typeof ImageTextAlternative, typeof ImageInsertUI];
|
|
29
30
|
/**
|
|
30
31
|
* @inheritDoc
|
|
31
32
|
*/
|
package/src/imageinline.js
CHANGED
|
@@ -9,6 +9,7 @@ import { Plugin } from 'ckeditor5/src/core';
|
|
|
9
9
|
import { Widget } from 'ckeditor5/src/widget';
|
|
10
10
|
import ImageTextAlternative from './imagetextalternative';
|
|
11
11
|
import ImageInlineEditing from './image/imageinlineediting';
|
|
12
|
+
import ImageInsertUI from './imageinsert/imageinsertui';
|
|
12
13
|
import '../theme/image.css';
|
|
13
14
|
/**
|
|
14
15
|
* The image inline plugin.
|
|
@@ -26,7 +27,7 @@ export default class ImageInline extends Plugin {
|
|
|
26
27
|
* @inheritDoc
|
|
27
28
|
*/
|
|
28
29
|
static get requires() {
|
|
29
|
-
return [ImageInlineEditing, Widget, ImageTextAlternative];
|
|
30
|
+
return [ImageInlineEditing, Widget, ImageTextAlternative, ImageInsertUI];
|
|
30
31
|
}
|
|
31
32
|
/**
|
|
32
33
|
* @inheritDoc
|
|
@@ -5,8 +5,10 @@
|
|
|
5
5
|
/**
|
|
6
6
|
* @module image/imageinsert/imageinsertui
|
|
7
7
|
*/
|
|
8
|
-
import { Plugin } from 'ckeditor5/src/core';
|
|
9
|
-
import { type
|
|
8
|
+
import { Plugin, type Editor } from 'ckeditor5/src/core';
|
|
9
|
+
import { type Observable } from 'ckeditor5/src/utils';
|
|
10
|
+
import { type ButtonView, type DropdownView, type FocusableView } from 'ckeditor5/src/ui';
|
|
11
|
+
import ImageUtils from '../imageutils';
|
|
10
12
|
/**
|
|
11
13
|
* The image insert dropdown plugin.
|
|
12
14
|
*
|
|
@@ -21,24 +23,50 @@ export default class ImageInsertUI extends Plugin {
|
|
|
21
23
|
* @inheritDoc
|
|
22
24
|
*/
|
|
23
25
|
static get pluginName(): "ImageInsertUI";
|
|
26
|
+
/**
|
|
27
|
+
* @inheritDoc
|
|
28
|
+
*/
|
|
29
|
+
static get requires(): readonly [typeof ImageUtils];
|
|
24
30
|
/**
|
|
25
31
|
* The dropdown view responsible for displaying the image insert UI.
|
|
26
32
|
*/
|
|
27
33
|
dropdownView?: DropdownView;
|
|
34
|
+
/**
|
|
35
|
+
* Observable property used to alter labels while some image is selected and when it is not.
|
|
36
|
+
*
|
|
37
|
+
* @observable
|
|
38
|
+
*/
|
|
39
|
+
isImageSelected: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Registered integrations map.
|
|
42
|
+
*/
|
|
43
|
+
private _integrations;
|
|
44
|
+
/**
|
|
45
|
+
* @inheritDoc
|
|
46
|
+
*/
|
|
47
|
+
constructor(editor: Editor);
|
|
28
48
|
/**
|
|
29
49
|
* @inheritDoc
|
|
30
50
|
*/
|
|
31
51
|
init(): void;
|
|
32
52
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* @param locale The localization services instance.
|
|
53
|
+
* Registers the insert image dropdown integration.
|
|
36
54
|
*/
|
|
37
|
-
|
|
55
|
+
registerIntegration({ name, observable, buttonViewCreator, formViewCreator, requiresForm }: {
|
|
56
|
+
name: string;
|
|
57
|
+
observable: Observable & {
|
|
58
|
+
isEnabled: boolean;
|
|
59
|
+
};
|
|
60
|
+
buttonViewCreator: (isOnlyOne: boolean) => ButtonView;
|
|
61
|
+
formViewCreator: (isOnlyOne: boolean) => FocusableView;
|
|
62
|
+
requiresForm?: boolean;
|
|
63
|
+
}): void;
|
|
38
64
|
/**
|
|
39
|
-
*
|
|
40
|
-
|
|
41
|
-
|
|
65
|
+
* Creates the toolbar component.
|
|
66
|
+
*/
|
|
67
|
+
private _createToolbarComponent;
|
|
68
|
+
/**
|
|
69
|
+
* Validates the integrations list.
|
|
42
70
|
*/
|
|
43
|
-
private
|
|
71
|
+
private _prepareIntegrations;
|
|
44
72
|
}
|
|
@@ -5,10 +5,11 @@
|
|
|
5
5
|
/**
|
|
6
6
|
* @module image/imageinsert/imageinsertui
|
|
7
7
|
*/
|
|
8
|
-
import { Plugin
|
|
9
|
-
import {
|
|
10
|
-
import
|
|
11
|
-
import
|
|
8
|
+
import { Plugin } from 'ckeditor5/src/core';
|
|
9
|
+
import { logWarning } from 'ckeditor5/src/utils';
|
|
10
|
+
import { createDropdown, SplitButtonView } from 'ckeditor5/src/ui';
|
|
11
|
+
import ImageInsertFormView from './ui/imageinsertformview';
|
|
12
|
+
import ImageUtils from '../imageutils';
|
|
12
13
|
/**
|
|
13
14
|
* The image insert dropdown plugin.
|
|
14
15
|
*
|
|
@@ -25,117 +26,149 @@ export default class ImageInsertUI extends Plugin {
|
|
|
25
26
|
static get pluginName() {
|
|
26
27
|
return 'ImageInsertUI';
|
|
27
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* @inheritDoc
|
|
31
|
+
*/
|
|
32
|
+
static get requires() {
|
|
33
|
+
return [ImageUtils];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* @inheritDoc
|
|
37
|
+
*/
|
|
38
|
+
constructor(editor) {
|
|
39
|
+
super(editor);
|
|
40
|
+
/**
|
|
41
|
+
* Registered integrations map.
|
|
42
|
+
*/
|
|
43
|
+
this._integrations = new Map();
|
|
44
|
+
editor.config.define('image.insert.integrations', [
|
|
45
|
+
'upload',
|
|
46
|
+
'assetManager',
|
|
47
|
+
'url'
|
|
48
|
+
]);
|
|
49
|
+
}
|
|
28
50
|
/**
|
|
29
51
|
* @inheritDoc
|
|
30
52
|
*/
|
|
31
53
|
init() {
|
|
32
54
|
const editor = this.editor;
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
55
|
+
const selection = editor.model.document.selection;
|
|
56
|
+
const imageUtils = editor.plugins.get('ImageUtils');
|
|
57
|
+
this.set('isImageSelected', false);
|
|
58
|
+
this.listenTo(editor.model.document, 'change', () => {
|
|
59
|
+
this.isImageSelected = imageUtils.isImage(selection.getSelectedElement());
|
|
60
|
+
});
|
|
61
|
+
const componentCreator = (locale) => this._createToolbarComponent(locale);
|
|
36
62
|
// Register `insertImage` dropdown and add `imageInsert` dropdown as an alias for backward compatibility.
|
|
37
63
|
editor.ui.componentFactory.add('insertImage', componentCreator);
|
|
38
64
|
editor.ui.componentFactory.add('imageInsert', componentCreator);
|
|
39
65
|
}
|
|
40
66
|
/**
|
|
41
|
-
*
|
|
42
|
-
|
|
43
|
-
|
|
67
|
+
* Registers the insert image dropdown integration.
|
|
68
|
+
*/
|
|
69
|
+
registerIntegration({ name, observable, buttonViewCreator, formViewCreator, requiresForm }) {
|
|
70
|
+
if (this._integrations.has(name)) {
|
|
71
|
+
/**
|
|
72
|
+
* There are two insert-image integrations registered with the same name.
|
|
73
|
+
*
|
|
74
|
+
* Make sure that you do not load multiple asset manager plugins.
|
|
75
|
+
*
|
|
76
|
+
* @error image-insert-integration-exists
|
|
77
|
+
*/
|
|
78
|
+
logWarning('image-insert-integration-exists', { name });
|
|
79
|
+
}
|
|
80
|
+
this._integrations.set(name, {
|
|
81
|
+
observable,
|
|
82
|
+
buttonViewCreator,
|
|
83
|
+
formViewCreator,
|
|
84
|
+
requiresForm: !!requiresForm
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Creates the toolbar component.
|
|
44
89
|
*/
|
|
45
|
-
|
|
90
|
+
_createToolbarComponent(locale) {
|
|
46
91
|
const editor = this.editor;
|
|
47
92
|
const t = locale.t;
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
panelView.extendTemplate({
|
|
59
|
-
attributes: {
|
|
60
|
-
class: 'ck-image-insert__panel'
|
|
93
|
+
const integrations = this._prepareIntegrations();
|
|
94
|
+
if (!integrations.length) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
let dropdownButton;
|
|
98
|
+
const firstIntegration = integrations[0];
|
|
99
|
+
if (integrations.length == 1) {
|
|
100
|
+
// Do not use dropdown for a single integration button (integration that does not require form view).
|
|
101
|
+
if (!firstIntegration.requiresForm) {
|
|
102
|
+
return firstIntegration.buttonViewCreator(true);
|
|
61
103
|
}
|
|
62
|
-
|
|
63
|
-
if (uploadImageCommand) {
|
|
64
|
-
const splitButtonView = this.dropdownView.buttonView;
|
|
65
|
-
// We are injecting custom button replacement to readonly field.
|
|
66
|
-
splitButtonView.actionView = editor.ui.componentFactory.create('uploadImage');
|
|
67
|
-
// After we replaced action button with `uploadImage` component,
|
|
68
|
-
// we have lost a proper styling and some minor visual quirks have appeared.
|
|
69
|
-
// Brining back original split button classes helps fix the button styling
|
|
70
|
-
// See https://github.com/ckeditor/ckeditor5/issues/7986.
|
|
71
|
-
splitButtonView.actionView.extendTemplate({
|
|
72
|
-
attributes: {
|
|
73
|
-
class: 'ck ck-button ck-splitbutton__action'
|
|
74
|
-
}
|
|
75
|
-
});
|
|
104
|
+
dropdownButton = firstIntegration.buttonViewCreator(true);
|
|
76
105
|
}
|
|
77
|
-
|
|
106
|
+
else {
|
|
107
|
+
const actionButton = firstIntegration.buttonViewCreator(false);
|
|
108
|
+
dropdownButton = new SplitButtonView(locale, actionButton);
|
|
109
|
+
dropdownButton.tooltip = true;
|
|
110
|
+
dropdownButton.bind('label').to(this, 'isImageSelected', isImageSelected => isImageSelected ?
|
|
111
|
+
t('Replace image') :
|
|
112
|
+
t('Insert image'));
|
|
113
|
+
}
|
|
114
|
+
const dropdownView = this.dropdownView = createDropdown(locale, dropdownButton);
|
|
115
|
+
const observables = integrations.map(({ observable }) => observable);
|
|
116
|
+
dropdownView.bind('isEnabled').toMany(observables, 'isEnabled', (...isEnabled) => (isEnabled.some(isEnabled => isEnabled)));
|
|
117
|
+
dropdownView.once('change:isOpen', () => {
|
|
118
|
+
const integrationViews = integrations.map(({ formViewCreator }) => formViewCreator(integrations.length == 1));
|
|
119
|
+
const imageInsertFormView = new ImageInsertFormView(editor.locale, integrationViews);
|
|
120
|
+
dropdownView.panelView.children.add(imageInsertFormView);
|
|
121
|
+
});
|
|
122
|
+
return dropdownView;
|
|
78
123
|
}
|
|
79
124
|
/**
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
* @param command An uploadImage or insertImage command.
|
|
125
|
+
* Validates the integrations list.
|
|
83
126
|
*/
|
|
84
|
-
|
|
127
|
+
_prepareIntegrations() {
|
|
85
128
|
const editor = this.editor;
|
|
86
|
-
const
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
if (
|
|
103
|
-
if (
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
insertButtonView.label = t('Insert');
|
|
111
|
-
insertImageViaUrlForm.label = t('Insert image via URL');
|
|
129
|
+
const items = editor.config.get('image.insert.integrations');
|
|
130
|
+
const result = [];
|
|
131
|
+
if (!items.length) {
|
|
132
|
+
/**
|
|
133
|
+
* The insert image feature requires a list of integrations to be provided in the editor configuration.
|
|
134
|
+
*
|
|
135
|
+
* The default list of integrations is `upload`, `assetManager`, `url`. Those integrations are included
|
|
136
|
+
* in the insert image dropdown if the given feature plugin is loaded. You should omit the `integrations`
|
|
137
|
+
* configuration key to use the default set or provide a selected list of integrations that should be used.
|
|
138
|
+
*
|
|
139
|
+
* @error image-insert-integrations-not-specified
|
|
140
|
+
*/
|
|
141
|
+
logWarning('image-insert-integrations-not-specified');
|
|
142
|
+
return result;
|
|
143
|
+
}
|
|
144
|
+
for (const item of items) {
|
|
145
|
+
if (!this._integrations.has(item)) {
|
|
146
|
+
if (!['upload', 'assetManager', 'url'].includes(item)) {
|
|
147
|
+
/**
|
|
148
|
+
* The specified insert image integration name is unknown or the providing plugin is not loaded in the editor.
|
|
149
|
+
*
|
|
150
|
+
* @error image-insert-unknown-integration
|
|
151
|
+
*/
|
|
152
|
+
logWarning('image-insert-unknown-integration', { item });
|
|
112
153
|
}
|
|
154
|
+
continue;
|
|
113
155
|
}
|
|
114
|
-
|
|
115
|
-
// default action of the drop-down is executed (i.e. the panel showed up). Otherwise, the
|
|
116
|
-
// invisible form/input cannot be focused/selected.
|
|
117
|
-
}, { priority: 'low' });
|
|
118
|
-
this.delegate('cancel').to(dropdownView);
|
|
119
|
-
dropdownView.on('submit', () => {
|
|
120
|
-
closePanel();
|
|
121
|
-
onSubmit();
|
|
122
|
-
});
|
|
123
|
-
dropdownView.on('cancel', () => {
|
|
124
|
-
closePanel();
|
|
125
|
-
});
|
|
126
|
-
function onSubmit() {
|
|
127
|
-
const selectedElement = editor.model.document.selection.getSelectedElement();
|
|
128
|
-
if (imageUtils.isImage(selectedElement)) {
|
|
129
|
-
editor.execute('replaceImageSource', { source: imageInsertView.imageURLInputValue });
|
|
130
|
-
}
|
|
131
|
-
else {
|
|
132
|
-
editor.execute('insertImage', { source: imageInsertView.imageURLInputValue });
|
|
133
|
-
}
|
|
156
|
+
result.push(this._integrations.get(item));
|
|
134
157
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
158
|
+
if (!result.length) {
|
|
159
|
+
/**
|
|
160
|
+
* The image insert feature requires integrations to be registered by separate features.
|
|
161
|
+
*
|
|
162
|
+
* The `insertImage` toolbar button requires integrations to be registered by other features.
|
|
163
|
+
* For example {@link module:image/imageupload~ImageUpload ImageUpload},
|
|
164
|
+
* {@link module:image/imageinsert~ImageInsert ImageInsert},
|
|
165
|
+
* {@link module:image/imageinsertviaurl~ImageInsertViaUrl ImageInsertViaUrl},
|
|
166
|
+
* {@link module:ckbox/ckbox~CKBox CKBox}
|
|
167
|
+
*
|
|
168
|
+
* @error image-insert-integrations-not-registered
|
|
169
|
+
*/
|
|
170
|
+
logWarning('image-insert-integrations-not-registered');
|
|
138
171
|
}
|
|
139
|
-
return
|
|
172
|
+
return result;
|
|
140
173
|
}
|
|
141
174
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
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
|
+
/**
|
|
6
|
+
* @module image/imageinsert/imageinsertviaurlui
|
|
7
|
+
*/
|
|
8
|
+
import { Plugin } from 'ckeditor5/src/core';
|
|
9
|
+
import ImageInsertUI from './imageinsertui';
|
|
10
|
+
/**
|
|
11
|
+
* The image insert via URL plugin (UI part).
|
|
12
|
+
*
|
|
13
|
+
* For a detailed overview, check the {@glink features/images/images-inserting
|
|
14
|
+
* Insert images via source URL} documentation.
|
|
15
|
+
*
|
|
16
|
+
* This plugin registers the {@link module:image/imageinsert/imageinsertui~ImageInsertUI} integration for `url`.
|
|
17
|
+
*/
|
|
18
|
+
export default class ImageInsertViaUrlUI extends Plugin {
|
|
19
|
+
private _imageInsertUI;
|
|
20
|
+
/**
|
|
21
|
+
* @inheritDoc
|
|
22
|
+
*/
|
|
23
|
+
static get pluginName(): "ImageInsertViaUrlUI";
|
|
24
|
+
/**
|
|
25
|
+
* @inheritDoc
|
|
26
|
+
*/
|
|
27
|
+
static get requires(): readonly [typeof ImageInsertUI];
|
|
28
|
+
/**
|
|
29
|
+
* @inheritDoc
|
|
30
|
+
*/
|
|
31
|
+
init(): void;
|
|
32
|
+
/**
|
|
33
|
+
* Creates the view displayed in the dropdown.
|
|
34
|
+
*/
|
|
35
|
+
private _createInsertUrlView;
|
|
36
|
+
/**
|
|
37
|
+
* Creates the toolbar button.
|
|
38
|
+
*/
|
|
39
|
+
private _createInsertUrlButton;
|
|
40
|
+
/**
|
|
41
|
+
* Closes the dropdown.
|
|
42
|
+
*/
|
|
43
|
+
private _closePanel;
|
|
44
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
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
|
+
/**
|
|
6
|
+
* @module image/imageinsert/imageinsertviaurlui
|
|
7
|
+
*/
|
|
8
|
+
import { icons, Plugin } from 'ckeditor5/src/core';
|
|
9
|
+
import { ButtonView, CollapsibleView, DropdownButtonView } from 'ckeditor5/src/ui';
|
|
10
|
+
import ImageInsertUI from './imageinsertui';
|
|
11
|
+
import ImageInsertUrlView from './ui/imageinserturlview';
|
|
12
|
+
/**
|
|
13
|
+
* The image insert via URL plugin (UI part).
|
|
14
|
+
*
|
|
15
|
+
* For a detailed overview, check the {@glink features/images/images-inserting
|
|
16
|
+
* Insert images via source URL} documentation.
|
|
17
|
+
*
|
|
18
|
+
* This plugin registers the {@link module:image/imageinsert/imageinsertui~ImageInsertUI} integration for `url`.
|
|
19
|
+
*/
|
|
20
|
+
export default class ImageInsertViaUrlUI extends Plugin {
|
|
21
|
+
/**
|
|
22
|
+
* @inheritDoc
|
|
23
|
+
*/
|
|
24
|
+
static get pluginName() {
|
|
25
|
+
return 'ImageInsertViaUrlUI';
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* @inheritDoc
|
|
29
|
+
*/
|
|
30
|
+
static get requires() {
|
|
31
|
+
return [ImageInsertUI];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* @inheritDoc
|
|
35
|
+
*/
|
|
36
|
+
init() {
|
|
37
|
+
this._imageInsertUI = this.editor.plugins.get('ImageInsertUI');
|
|
38
|
+
const insertImageCommand = this.editor.commands.get('insertImage');
|
|
39
|
+
this._imageInsertUI.registerIntegration({
|
|
40
|
+
name: 'url',
|
|
41
|
+
observable: insertImageCommand,
|
|
42
|
+
requiresForm: true,
|
|
43
|
+
buttonViewCreator: isOnlyOne => this._createInsertUrlButton(isOnlyOne),
|
|
44
|
+
formViewCreator: isOnlyOne => this._createInsertUrlView(isOnlyOne)
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Creates the view displayed in the dropdown.
|
|
49
|
+
*/
|
|
50
|
+
_createInsertUrlView(isOnlyOne) {
|
|
51
|
+
const editor = this.editor;
|
|
52
|
+
const locale = editor.locale;
|
|
53
|
+
const t = locale.t;
|
|
54
|
+
const replaceImageSourceCommand = editor.commands.get('replaceImageSource');
|
|
55
|
+
const insertImageCommand = editor.commands.get('insertImage');
|
|
56
|
+
const imageInsertUrlView = new ImageInsertUrlView(locale);
|
|
57
|
+
const collapsibleView = isOnlyOne ? null : new CollapsibleView(locale, [imageInsertUrlView]);
|
|
58
|
+
imageInsertUrlView.bind('isImageSelected').to(this._imageInsertUI);
|
|
59
|
+
imageInsertUrlView.bind('isEnabled').toMany([insertImageCommand, replaceImageSourceCommand], 'isEnabled', (...isEnabled) => (isEnabled.some(isCommandEnabled => isCommandEnabled)));
|
|
60
|
+
// Set initial value because integrations are created on first dropdown open.
|
|
61
|
+
imageInsertUrlView.imageURLInputValue = replaceImageSourceCommand.value || '';
|
|
62
|
+
this._imageInsertUI.dropdownView.on('change:isOpen', () => {
|
|
63
|
+
if (this._imageInsertUI.dropdownView.isOpen) {
|
|
64
|
+
// Make sure that each time the panel shows up, the URL field remains in sync with the value of
|
|
65
|
+
// the command. If the user typed in the input, then canceled and re-opened it without changing
|
|
66
|
+
// the value of the media command (e.g. because they didn't change the selection), they would see
|
|
67
|
+
// the old value instead of the actual value of the command.
|
|
68
|
+
imageInsertUrlView.imageURLInputValue = replaceImageSourceCommand.value || '';
|
|
69
|
+
if (collapsibleView) {
|
|
70
|
+
collapsibleView.isCollapsed = true;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// Note: Use the low priority to make sure the following listener starts working after the
|
|
74
|
+
// default action of the drop-down is executed (i.e. the panel showed up). Otherwise, the
|
|
75
|
+
// invisible form/input cannot be focused/selected.
|
|
76
|
+
}, { priority: 'low' });
|
|
77
|
+
imageInsertUrlView.on('submit', () => {
|
|
78
|
+
if (replaceImageSourceCommand.isEnabled) {
|
|
79
|
+
editor.execute('replaceImageSource', { source: imageInsertUrlView.imageURLInputValue });
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
editor.execute('insertImage', { source: imageInsertUrlView.imageURLInputValue });
|
|
83
|
+
}
|
|
84
|
+
this._closePanel();
|
|
85
|
+
});
|
|
86
|
+
imageInsertUrlView.on('cancel', () => this._closePanel());
|
|
87
|
+
if (collapsibleView) {
|
|
88
|
+
collapsibleView.set({
|
|
89
|
+
isCollapsed: true
|
|
90
|
+
});
|
|
91
|
+
collapsibleView.bind('label').to(this._imageInsertUI, 'isImageSelected', isImageSelected => isImageSelected ?
|
|
92
|
+
t('Update image URL') :
|
|
93
|
+
t('Insert image via URL'));
|
|
94
|
+
return collapsibleView;
|
|
95
|
+
}
|
|
96
|
+
return imageInsertUrlView;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Creates the toolbar button.
|
|
100
|
+
*/
|
|
101
|
+
_createInsertUrlButton(isOnlyOne) {
|
|
102
|
+
const ButtonClass = isOnlyOne ? DropdownButtonView : ButtonView;
|
|
103
|
+
const editor = this.editor;
|
|
104
|
+
const button = new ButtonClass(editor.locale);
|
|
105
|
+
const t = editor.locale.t;
|
|
106
|
+
button.set({
|
|
107
|
+
icon: icons.imageUrl,
|
|
108
|
+
tooltip: true
|
|
109
|
+
});
|
|
110
|
+
button.bind('label').to(this._imageInsertUI, 'isImageSelected', isImageSelected => isImageSelected ?
|
|
111
|
+
t('Update image URL') :
|
|
112
|
+
t('Insert image via URL'));
|
|
113
|
+
return button;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Closes the dropdown.
|
|
117
|
+
*/
|
|
118
|
+
_closePanel() {
|
|
119
|
+
this.editor.editing.view.focus();
|
|
120
|
+
this._imageInsertUI.dropdownView.isOpen = false;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
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
|
+
/**
|
|
6
|
+
* @module image/imageinsert/ui/imageinsertformview
|
|
7
|
+
*/
|
|
8
|
+
import { View, ViewCollection, FocusCycler } from 'ckeditor5/src/ui';
|
|
9
|
+
import { FocusTracker, KeystrokeHandler, type Locale } from 'ckeditor5/src/utils';
|
|
10
|
+
import '../../../theme/imageinsert.css';
|
|
11
|
+
/**
|
|
12
|
+
* The view displayed in the insert image dropdown.
|
|
13
|
+
*
|
|
14
|
+
* See {@link module:image/imageinsert/imageinsertui~ImageInsertUI}.
|
|
15
|
+
*/
|
|
16
|
+
export default class ImageInsertFormView extends View {
|
|
17
|
+
/**
|
|
18
|
+
* Tracks information about DOM focus in the form.
|
|
19
|
+
*/
|
|
20
|
+
readonly focusTracker: FocusTracker;
|
|
21
|
+
/**
|
|
22
|
+
* An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.
|
|
23
|
+
*/
|
|
24
|
+
readonly keystrokes: KeystrokeHandler;
|
|
25
|
+
/**
|
|
26
|
+
* A collection of views that can be focused in the form.
|
|
27
|
+
*/
|
|
28
|
+
protected readonly _focusables: ViewCollection;
|
|
29
|
+
/**
|
|
30
|
+
* Helps cycling over {@link #_focusables} in the form.
|
|
31
|
+
*/
|
|
32
|
+
protected readonly _focusCycler: FocusCycler;
|
|
33
|
+
/**
|
|
34
|
+
* A collection of the defined integrations for inserting the images.
|
|
35
|
+
*/
|
|
36
|
+
private readonly children;
|
|
37
|
+
/**
|
|
38
|
+
* Creates a view for the dropdown panel of {@link module:image/imageinsert/imageinsertui~ImageInsertUI}.
|
|
39
|
+
*
|
|
40
|
+
* @param locale The localization services instance.
|
|
41
|
+
* @param integrations An integrations object that contains components (or tokens for components) to be shown in the panel view.
|
|
42
|
+
*/
|
|
43
|
+
constructor(locale: Locale, integrations?: Array<View>);
|
|
44
|
+
/**
|
|
45
|
+
* @inheritDoc
|
|
46
|
+
*/
|
|
47
|
+
render(): void;
|
|
48
|
+
/**
|
|
49
|
+
* @inheritDoc
|
|
50
|
+
*/
|
|
51
|
+
destroy(): void;
|
|
52
|
+
/**
|
|
53
|
+
* Focuses the first {@link #_focusables focusable} in the form.
|
|
54
|
+
*/
|
|
55
|
+
focus(): void;
|
|
56
|
+
}
|