@ckeditor/ckeditor5-core 30.0.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/LICENSE.md +17 -0
- package/README.md +18 -0
- package/lang/contexts.json +8 -0
- package/lang/translations/af.po +41 -0
- package/lang/translations/ar.po +41 -0
- package/lang/translations/ast.po +41 -0
- package/lang/translations/az.po +41 -0
- package/lang/translations/bg.po +41 -0
- package/lang/translations/ca.po +41 -0
- package/lang/translations/cs.po +41 -0
- package/lang/translations/da.po +41 -0
- package/lang/translations/de-ch.po +41 -0
- package/lang/translations/de.po +41 -0
- package/lang/translations/el.po +41 -0
- package/lang/translations/en-au.po +41 -0
- package/lang/translations/en-gb.po +41 -0
- package/lang/translations/en.po +41 -0
- package/lang/translations/eo.po +41 -0
- package/lang/translations/es.po +41 -0
- package/lang/translations/et.po +41 -0
- package/lang/translations/eu.po +41 -0
- package/lang/translations/fa.po +41 -0
- package/lang/translations/fi.po +41 -0
- package/lang/translations/fr.po +41 -0
- package/lang/translations/gl.po +41 -0
- package/lang/translations/he.po +41 -0
- package/lang/translations/hi.po +41 -0
- package/lang/translations/hr.po +41 -0
- package/lang/translations/hu.po +41 -0
- package/lang/translations/id.po +41 -0
- package/lang/translations/it.po +41 -0
- package/lang/translations/ja.po +41 -0
- package/lang/translations/km.po +41 -0
- package/lang/translations/kn.po +41 -0
- package/lang/translations/ko.po +41 -0
- package/lang/translations/ku.po +41 -0
- package/lang/translations/lt.po +41 -0
- package/lang/translations/lv.po +41 -0
- package/lang/translations/nb.po +41 -0
- package/lang/translations/ne.po +41 -0
- package/lang/translations/nl.po +41 -0
- package/lang/translations/no.po +41 -0
- package/lang/translations/oc.po +41 -0
- package/lang/translations/pl.po +41 -0
- package/lang/translations/pt-br.po +41 -0
- package/lang/translations/pt.po +41 -0
- package/lang/translations/ro.po +41 -0
- package/lang/translations/ru.po +41 -0
- package/lang/translations/sk.po +41 -0
- package/lang/translations/sl.po +41 -0
- package/lang/translations/sq.po +41 -0
- package/lang/translations/sr-latn.po +41 -0
- package/lang/translations/sr.po +41 -0
- package/lang/translations/sv.po +41 -0
- package/lang/translations/th.po +41 -0
- package/lang/translations/tk.po +41 -0
- package/lang/translations/tr.po +41 -0
- package/lang/translations/tt.po +41 -0
- package/lang/translations/ug.po +41 -0
- package/lang/translations/uk.po +41 -0
- package/lang/translations/vi.po +41 -0
- package/lang/translations/zh-cn.po +41 -0
- package/lang/translations/zh.po +41 -0
- package/package.json +65 -0
- package/src/command.js +244 -0
- package/src/commandcollection.js +109 -0
- package/src/context.js +355 -0
- package/src/contextplugin.js +61 -0
- package/src/editingkeystrokehandler.js +72 -0
- package/src/editor/editor.js +448 -0
- package/src/editor/editorconfig.jsdoc +325 -0
- package/src/editor/editorui.js +275 -0
- package/src/editor/editorwithui.jsdoc +29 -0
- package/src/editor/utils/attachtoform.js +67 -0
- package/src/editor/utils/dataapimixin.js +81 -0
- package/src/editor/utils/elementapimixin.js +65 -0
- package/src/editor/utils/securesourceelement.js +49 -0
- package/src/index.js +95 -0
- package/src/multicommand.js +101 -0
- package/src/pendingactions.js +155 -0
- package/src/plugin.js +292 -0
- package/src/plugincollection.js +597 -0
- package/theme/icons/align-bottom.svg +1 -0
- package/theme/icons/align-center.svg +1 -0
- package/theme/icons/align-justify.svg +1 -0
- package/theme/icons/align-left.svg +1 -0
- package/theme/icons/align-middle.svg +1 -0
- package/theme/icons/align-right.svg +1 -0
- package/theme/icons/align-top.svg +1 -0
- package/theme/icons/cancel.svg +1 -0
- package/theme/icons/caption.svg +1 -0
- package/theme/icons/check.svg +1 -0
- package/theme/icons/cog.svg +1 -0
- package/theme/icons/eraser.svg +1 -0
- package/theme/icons/image.svg +1 -0
- package/theme/icons/low-vision.svg +1 -0
- package/theme/icons/object-center.svg +1 -0
- package/theme/icons/object-full-width.svg +1 -0
- package/theme/icons/object-inline-left.svg +1 -0
- package/theme/icons/object-inline-right.svg +1 -0
- package/theme/icons/object-inline.svg +1 -0
- package/theme/icons/object-left.svg +1 -0
- package/theme/icons/object-right.svg +1 -0
- package/theme/icons/object-size-full.svg +1 -0
- package/theme/icons/object-size-large.svg +1 -0
- package/theme/icons/object-size-medium.svg +1 -0
- package/theme/icons/object-size-small.svg +1 -0
- package/theme/icons/pencil.svg +1 -0
- package/theme/icons/pilcrow.svg +1 -0
- package/theme/icons/quote.svg +1 -0
- package/theme/icons/three-vertical-dots.svg +1 -0
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
|
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @module core/editor/editorconfig
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* CKEditor configuration options.
|
|
12
|
+
*
|
|
13
|
+
* An object defining the editor configuration can be passed when initializing the editor:
|
|
14
|
+
*
|
|
15
|
+
* EditorClass
|
|
16
|
+
* .create( {
|
|
17
|
+
* toolbar: [ 'bold', 'italic' ],
|
|
18
|
+
* image: {
|
|
19
|
+
* styles: [
|
|
20
|
+
* ...
|
|
21
|
+
* ]
|
|
22
|
+
* }
|
|
23
|
+
* } )
|
|
24
|
+
* .then( ... )
|
|
25
|
+
* .catch( ... );
|
|
26
|
+
*
|
|
27
|
+
* Check the {@glink builds/guides/integration/configuration Configuration guide} for more information
|
|
28
|
+
* about setting configuration options.
|
|
29
|
+
*
|
|
30
|
+
* @interface EditorConfig
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The initial editor data to be used instead of the provided element's HTML content.
|
|
35
|
+
*
|
|
36
|
+
* ClassicEditor
|
|
37
|
+
* .create( document.querySelector( '#editor' ), {
|
|
38
|
+
* initialData: '<h2>Initial data</h2><p>Foo bar.</p>'
|
|
39
|
+
* } )
|
|
40
|
+
* .then( ... )
|
|
41
|
+
* .catch( ... );
|
|
42
|
+
*
|
|
43
|
+
* By default, the editor is initialized with the content of the element on which this editor is initialized.
|
|
44
|
+
* See {@link module:core/editor/editor~Editor.create Editor.create()}.
|
|
45
|
+
*
|
|
46
|
+
* This configuration option lets you override initial data if an element is passed to `Editor.create()`.
|
|
47
|
+
* It is especially useful if it is difficult for your integration to put the data inside the HTML element.
|
|
48
|
+
*
|
|
49
|
+
* **Note:** If initial data is passed to `Editor.create()` as a parameter and, at the same time, via this configuration option,
|
|
50
|
+
* an error will be thrown as those two options exclude themselves.
|
|
51
|
+
*
|
|
52
|
+
* @member {String} module:core/editor/editorconfig~EditorConfig#initialData
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The `config.initialData` option cannot be used together with initial data passed as the first parameter of
|
|
57
|
+
* {@link module:core/editor/editor~Editor.create `Editor.create()`}.
|
|
58
|
+
*
|
|
59
|
+
* @error editor-create-initial-data
|
|
60
|
+
*/
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* The list of plugins to load.
|
|
64
|
+
*
|
|
65
|
+
* If you use an {@glink builds/guides/overview editor build} you can define the list of plugins to load
|
|
66
|
+
* using the names of plugins that are available:
|
|
67
|
+
*
|
|
68
|
+
* const config = {
|
|
69
|
+
* plugins: [ 'Bold', 'Italic', 'Typing', 'Enter', ... ]
|
|
70
|
+
* };
|
|
71
|
+
*
|
|
72
|
+
* You can check the list of plugins available in a build using this snippet:
|
|
73
|
+
*
|
|
74
|
+
* ClassicEditor.builtinPlugins.map( plugin => plugin.pluginName );
|
|
75
|
+
*
|
|
76
|
+
* If you use an editor creator directly (imported from a package like `@ckeditor/ckeditor5-editor-classic`) or you
|
|
77
|
+
* want to load additional plugins which were not included in a build you use, then you need to specify
|
|
78
|
+
* the plugins using their constructors:
|
|
79
|
+
*
|
|
80
|
+
* // A preset of plugins is a plugin as well.
|
|
81
|
+
* import Essentials from '@ckeditor/ckeditor5-essentials/src/essentials';
|
|
82
|
+
* // The bold plugin.
|
|
83
|
+
* import Bold from '@ckeditor/ckeditor5-editor-basic-styles/src/bold';
|
|
84
|
+
*
|
|
85
|
+
* const config = {
|
|
86
|
+
* plugins: [ Essentials, Bold ]
|
|
87
|
+
* };
|
|
88
|
+
*
|
|
89
|
+
* **Note:** To load additional plugins, you should use the {@link #extraPlugins `extraPlugins`} configuration.
|
|
90
|
+
* To narrow the list of loaded plugins, use the {@link #removePlugins `removePlugins`} configuration.
|
|
91
|
+
*
|
|
92
|
+
* @member {Array.<String|Function>} module:core/editor/editorconfig~EditorConfig#plugins
|
|
93
|
+
*/
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* The list of additional plugins to load along those already available in the
|
|
97
|
+
* {@glink builds/guides/overview editor build}. It extends the {@link #plugins `plugins`} configuration.
|
|
98
|
+
*
|
|
99
|
+
* function MyPlugin( editor ) {
|
|
100
|
+
* // ...
|
|
101
|
+
* }
|
|
102
|
+
*
|
|
103
|
+
* const config = {
|
|
104
|
+
* extraPlugins: [ MyPlugin ]
|
|
105
|
+
* };
|
|
106
|
+
*
|
|
107
|
+
* **Note:** This configuration works only for simple plugins which utilize the
|
|
108
|
+
* {@link module:core/plugin~PluginInterface plugin interface} and have no dependencies. To extend a
|
|
109
|
+
* build with complex features, create a {@glink builds/guides/development/custom-builds custom build}.
|
|
110
|
+
*
|
|
111
|
+
* **Note:** Make sure you include the new features in you toolbar configuration. Learn more
|
|
112
|
+
* about the {@glink features/toolbar/toolbar toolbar setup}.
|
|
113
|
+
*
|
|
114
|
+
* @member {Array.<Function>} module:core/editor/editorconfig~EditorConfig#extraPlugins
|
|
115
|
+
*/
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* The list of plugins which should not be loaded despite being available in an {@glink builds/guides/overview editor build}.
|
|
119
|
+
*
|
|
120
|
+
* const config = {
|
|
121
|
+
* removePlugins: [ 'Bold', 'Italic' ]
|
|
122
|
+
* };
|
|
123
|
+
*
|
|
124
|
+
* **Note:** Be careful when removing plugins using `config.removePlugins` from CKEditor builds.
|
|
125
|
+
* If removed plugins were providing toolbar buttons, the default toolbar configuration included in a build
|
|
126
|
+
* will become invalid. In such case you need to provide the updated
|
|
127
|
+
* {@link module:core/editor/editorconfig~EditorConfig#toolbar toolbar configuration}.
|
|
128
|
+
*
|
|
129
|
+
* @member {Array.<String|Function>} module:core/editor/editorconfig~EditorConfig#removePlugins
|
|
130
|
+
*/
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* The editor toolbar configuration.
|
|
134
|
+
*
|
|
135
|
+
* Simple format (specifies only toolbar items):
|
|
136
|
+
*
|
|
137
|
+
* const config = {
|
|
138
|
+
* toolbar: [ 'bold', 'italic', '|', 'undo', 'redo' ]
|
|
139
|
+
* };
|
|
140
|
+
*
|
|
141
|
+
* Extended format:
|
|
142
|
+
*
|
|
143
|
+
* const config = {
|
|
144
|
+
* toolbar: {
|
|
145
|
+
* items: [ 'bold', 'italic', '|', 'undo', 'redo', '-', 'numberedList', 'bulletedList' ],
|
|
146
|
+
*
|
|
147
|
+
* shouldNotGroupWhenFull: true
|
|
148
|
+
* }
|
|
149
|
+
* };
|
|
150
|
+
*
|
|
151
|
+
* Options which can be set using the extended format:
|
|
152
|
+
*
|
|
153
|
+
* * **`toolbar.items`** – An array of toolbar item names. The components (buttons, dropdowns, etc.) which can be used
|
|
154
|
+
* as toolbar items are defined in `editor.ui.componentFactory` and can be listed using the following snippet:
|
|
155
|
+
*
|
|
156
|
+
* Array.from( editor.ui.componentFactory.names() );
|
|
157
|
+
*
|
|
158
|
+
* You can also use `'|'` to create a separator between groups of items:
|
|
159
|
+
*
|
|
160
|
+
* toolbar: [ 'bold', 'italic', '|', 'undo', 'redo' ]
|
|
161
|
+
*
|
|
162
|
+
* or `'-'` to make a line break and render items in multiple lines:
|
|
163
|
+
*
|
|
164
|
+
* toolbar: [ 'bold', 'italic', '-', 'undo', 'redo' ]
|
|
165
|
+
*
|
|
166
|
+
* Line break will work only in the extended format when `shouldNotGroupWhenFull` option is set to `true`.
|
|
167
|
+
*
|
|
168
|
+
* * **`toolbar.viewportTopOffset` (deprecated)** – The offset (in pixels) from the top of the viewport used when positioning a sticky toolbar.
|
|
169
|
+
* Useful when a page with which the editor is being integrated has some other sticky or fixed elements
|
|
170
|
+
* (e.g. the top menu). Thanks to setting the toolbar offset the toolbar will not be positioned underneath or above the page's UI.
|
|
171
|
+
*
|
|
172
|
+
* **This property has been deprecated and will be removed in the future versions of CKEditor. Please use `{@link module:core/editor/editorconfig~EditorConfig#ui EditorConfig#ui.viewportOffset}` instead.**
|
|
173
|
+
*
|
|
174
|
+
* * **`toolbar.shouldNotGroupWhenFull`** – When set to `true`, the toolbar will stop grouping items
|
|
175
|
+
* and let them wrap to the next line if there is not enough space to display them in a single row.
|
|
176
|
+
*
|
|
177
|
+
* @member {Array.<String>|Object} module:core/editor/editorconfig~EditorConfig#toolbar
|
|
178
|
+
*/
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* The configuration of the editor language.
|
|
182
|
+
*
|
|
183
|
+
* ClassicEditor
|
|
184
|
+
* .create( document.querySelector( '#editor' ), {
|
|
185
|
+
* language: ... // Editor language configuration.
|
|
186
|
+
* } )
|
|
187
|
+
* .then( editor => {
|
|
188
|
+
* console.log( editor );
|
|
189
|
+
* } )
|
|
190
|
+
* .catch( error => {
|
|
191
|
+
* console.error( error );
|
|
192
|
+
* } );
|
|
193
|
+
*
|
|
194
|
+
* See {@link module:core/editor/editorconfig~EditorConfig all editor options}.
|
|
195
|
+
*
|
|
196
|
+
* @interface LanguageConfig
|
|
197
|
+
*/
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* The language of the editor UI and its content.
|
|
201
|
+
*
|
|
202
|
+
* Note: You do not have to specify this option if your build is optimized for one UI language or if it is
|
|
203
|
+
* the default language (English is the default language for CDN builds), unless you want to change
|
|
204
|
+
* the language of your content.
|
|
205
|
+
*
|
|
206
|
+
* Simple usage (change the language of the UI and the content):
|
|
207
|
+
*
|
|
208
|
+
* ClassicEditor
|
|
209
|
+
* .create( document.querySelector( '#editor' ), {
|
|
210
|
+
* // The UI of the editor as well as its content will be in German.
|
|
211
|
+
* language: 'de'
|
|
212
|
+
* } )
|
|
213
|
+
* .then( editor => {
|
|
214
|
+
* console.log( editor );
|
|
215
|
+
* } )
|
|
216
|
+
* .catch( error => {
|
|
217
|
+
* console.error( error );
|
|
218
|
+
* } );
|
|
219
|
+
*
|
|
220
|
+
* Use different languages for the UI and the content using the {@link module:core/editor/editorconfig~LanguageConfig configuration} syntax:
|
|
221
|
+
*
|
|
222
|
+
* ClassicEditor
|
|
223
|
+
* .create( document.querySelector( '#editor' ), {
|
|
224
|
+
* language: {
|
|
225
|
+
* // The UI will be in English.
|
|
226
|
+
* ui: 'en',
|
|
227
|
+
*
|
|
228
|
+
* // But the content will be edited in Arabic.
|
|
229
|
+
* content: 'ar'
|
|
230
|
+
* }
|
|
231
|
+
* } )
|
|
232
|
+
* .then( editor => {
|
|
233
|
+
* console.log( editor );
|
|
234
|
+
* } )
|
|
235
|
+
* .catch( error => {
|
|
236
|
+
* console.error( error );
|
|
237
|
+
* } );
|
|
238
|
+
*
|
|
239
|
+
* The language of the content has an impact on the editing experience, for instance it affects screen readers
|
|
240
|
+
* and spell checkers. It is also particularly useful for typing in certain languages (e.g. right–to–left ones)
|
|
241
|
+
* because it changes the default alignment of the text.
|
|
242
|
+
*
|
|
243
|
+
* The language codes are defined in the [ISO 639-1](https://en.wikipedia.org/wiki/ISO_639-1) standard.
|
|
244
|
+
*
|
|
245
|
+
* You need to add the corresponding translation file for the new UI language to work.
|
|
246
|
+
* Translation files are available on CDN for predefined builds:
|
|
247
|
+
*
|
|
248
|
+
* `<script src="https://cdn.ckeditor.com/ckeditor5/[version.number]/[distribution]/lang/[lang].js"></script>`
|
|
249
|
+
*
|
|
250
|
+
* But you can add them manually by coping from the `node_modules/@ckeditor/ckeditor5-build-[name]/build/lang/[lang].js'`.
|
|
251
|
+
*
|
|
252
|
+
* Check the {@glink features/ui-language UI language guide} for more information about the localization options and translation process.
|
|
253
|
+
*
|
|
254
|
+
* @member {String|module:core/editor/editorconfig~LanguageConfig} module:core/editor/editorconfig~EditorConfig#language
|
|
255
|
+
*/
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Allows to use different language for the editor UI.
|
|
259
|
+
*
|
|
260
|
+
* The language codes are defined in the [ISO 639-1](https://en.wikipedia.org/wiki/ISO_639-1) standard.
|
|
261
|
+
*
|
|
262
|
+
* @member {String} module:core/editor/editorconfig~LanguageConfig#ui
|
|
263
|
+
*/
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Allows to use different language of the editor content.
|
|
267
|
+
*
|
|
268
|
+
* The language codes are defined in the [ISO 639-1](https://en.wikipedia.org/wiki/ISO_639-1) standard.
|
|
269
|
+
*
|
|
270
|
+
* @member {String} module:core/editor/editorconfig~LanguageConfig#content
|
|
271
|
+
*/
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Specifies the text displayed in the editor when there is no content (editor is empty). It is intended to
|
|
275
|
+
* help users locate the editor in the application (form) and prompt them to input the content. Work similarly
|
|
276
|
+
* as to the native DOM
|
|
277
|
+
* [`placeholder` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#The_placeholder_attribute)
|
|
278
|
+
* used by inputs.
|
|
279
|
+
*
|
|
280
|
+
* const config = {
|
|
281
|
+
* placeholder: 'Type some text...'
|
|
282
|
+
* };
|
|
283
|
+
*
|
|
284
|
+
* The placeholder text is displayed as a pseudo–element of an empty paragraph in the editor content.
|
|
285
|
+
* The paragraph has the `.ck-placeholder` CSS class and the `data-placeholder` attribute.
|
|
286
|
+
*
|
|
287
|
+
* <p data-placeholder="Type some text..." class="ck-placeholder">
|
|
288
|
+
* ::before
|
|
289
|
+
* </p>
|
|
290
|
+
*
|
|
291
|
+
* **Note**: Placeholder text can also be set using the `placeholder` attribute if a `<textarea>` is passed to
|
|
292
|
+
* the `create()` method, e.g. {@link module:editor-classic/classiceditor~ClassicEditor.create `ClassicEditor.create()`}.
|
|
293
|
+
*
|
|
294
|
+
* **Note**: This configuration has precedence over the value of the `placeholder` attribute of a `<textarea>`
|
|
295
|
+
* element passed to the `create()` method.
|
|
296
|
+
*
|
|
297
|
+
* See the {@glink features/editor-placeholder "Editor placeholder" guide} for more information and live examples.
|
|
298
|
+
*
|
|
299
|
+
* @member {String} module:core/editor/editorconfig~EditorConfig#placeholder
|
|
300
|
+
*/
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* The editor UI configuration.
|
|
304
|
+
*
|
|
305
|
+
* ClassicEditor
|
|
306
|
+
* .create( document.querySelector( '#editor' ), {
|
|
307
|
+
* ui: { ... }
|
|
308
|
+
* } )
|
|
309
|
+
* .then( ... )
|
|
310
|
+
* .catch( ... );
|
|
311
|
+
*
|
|
312
|
+
* Options which can be set using the UI config:
|
|
313
|
+
*
|
|
314
|
+
* * **`ui.viewportOffset`** – The offset (in pixels) of the viewport from every direction used when positioning a sticky toolbar or other absolutely positioned UI elements.
|
|
315
|
+
* Useful when a page with which the editor is being integrated has some other sticky or fixed elements
|
|
316
|
+
* (e.g. the top menu). Thanks to setting the UI viewport offset the toolbar and other contextual balloons will not be positioned underneath or above the page's UI.
|
|
317
|
+
*
|
|
318
|
+
* ui: {
|
|
319
|
+
* viewportOffset: { top: 10, right: 10, bottom: 10, left: 10 }
|
|
320
|
+
* }
|
|
321
|
+
*
|
|
322
|
+
* **Note:** If you want to modify the viewport offset in runtime (after editor was created), you can do that by overriding {@link module:core/editor/editorui~EditorUI#viewportOffset `editor.ui.viewportOffset`}.
|
|
323
|
+
*
|
|
324
|
+
* @member {Object} module:core/editor/editorconfig~EditorConfig#ui
|
|
325
|
+
*/
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
|
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @module core/editor/editorui
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/* globals console */
|
|
11
|
+
|
|
12
|
+
import ComponentFactory from '@ckeditor/ckeditor5-ui/src/componentfactory';
|
|
13
|
+
import FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';
|
|
14
|
+
|
|
15
|
+
import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';
|
|
16
|
+
import mix from '@ckeditor/ckeditor5-utils/src/mix';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* A class providing the minimal interface that is required to successfully bootstrap any editor UI.
|
|
20
|
+
*
|
|
21
|
+
* @mixes module:utils/emittermixin~EmitterMixin
|
|
22
|
+
*/
|
|
23
|
+
export default class EditorUI {
|
|
24
|
+
/**
|
|
25
|
+
* Creates an instance of the editor UI class.
|
|
26
|
+
*
|
|
27
|
+
* @param {module:core/editor/editor~Editor} editor The editor instance.
|
|
28
|
+
*/
|
|
29
|
+
constructor( editor ) {
|
|
30
|
+
/**
|
|
31
|
+
* The editor that the UI belongs to.
|
|
32
|
+
*
|
|
33
|
+
* @readonly
|
|
34
|
+
* @member {module:core/editor/editor~Editor} #editor
|
|
35
|
+
*/
|
|
36
|
+
this.editor = editor;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* An instance of the {@link module:ui/componentfactory~ComponentFactory}, a registry used by plugins
|
|
40
|
+
* to register factories of specific UI components.
|
|
41
|
+
*
|
|
42
|
+
* @readonly
|
|
43
|
+
* @member {module:ui/componentfactory~ComponentFactory} #componentFactory
|
|
44
|
+
*/
|
|
45
|
+
this.componentFactory = new ComponentFactory( editor );
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Stores the information about the editor UI focus and propagates it so various plugins and components
|
|
49
|
+
* are unified as a focus group.
|
|
50
|
+
*
|
|
51
|
+
* @readonly
|
|
52
|
+
* @member {module:utils/focustracker~FocusTracker} #focusTracker
|
|
53
|
+
*/
|
|
54
|
+
this.focusTracker = new FocusTracker();
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Stores viewport offsets from every direction.
|
|
58
|
+
*
|
|
59
|
+
* Viewport offset can be used to constrain balloons or other UI elements into an element smaller than the viewport.
|
|
60
|
+
* This can be useful if there are any other absolutely positioned elements that may interfere with editor UI.
|
|
61
|
+
*
|
|
62
|
+
* Example `editor.ui.viewportOffset` returns:
|
|
63
|
+
*
|
|
64
|
+
* ```js
|
|
65
|
+
* {
|
|
66
|
+
* top: 50,
|
|
67
|
+
* right: 50,
|
|
68
|
+
* bottom: 50,
|
|
69
|
+
* left: 50
|
|
70
|
+
* }
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
* This property can be overriden after editor already being initialized:
|
|
74
|
+
*
|
|
75
|
+
* ```js
|
|
76
|
+
* editor.ui.viewportOffset = {
|
|
77
|
+
* top: 100,
|
|
78
|
+
* right: 0,
|
|
79
|
+
* bottom: 0,
|
|
80
|
+
* left: 0
|
|
81
|
+
* };
|
|
82
|
+
* ```
|
|
83
|
+
*
|
|
84
|
+
* @observable
|
|
85
|
+
* @member {Object} #viewportOffset
|
|
86
|
+
*/
|
|
87
|
+
this.set( 'viewportOffset', this._readViewportOffsetFromConfig() );
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Stores all editable elements used by the editor instance.
|
|
91
|
+
*
|
|
92
|
+
* @private
|
|
93
|
+
* @member {Map.<String,HTMLElement>}
|
|
94
|
+
*/
|
|
95
|
+
this._editableElementsMap = new Map();
|
|
96
|
+
|
|
97
|
+
// Informs UI components that should be refreshed after layout change.
|
|
98
|
+
this.listenTo( editor.editing.view.document, 'layoutChanged', () => this.update() );
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* The main (outermost) DOM element of the editor UI.
|
|
103
|
+
*
|
|
104
|
+
* For example, in {@link module:editor-classic/classiceditor~ClassicEditor} it is a `<div>` which
|
|
105
|
+
* wraps the editable element and the toolbar. In {@link module:editor-inline/inlineeditor~InlineEditor}
|
|
106
|
+
* it is the editable element itself (as there is no other wrapper). However, in
|
|
107
|
+
* {@link module:editor-decoupled/decouplededitor~DecoupledEditor} it is set to `null` because this editor does not
|
|
108
|
+
* come with a single "main" HTML element (its editable element and toolbar are separate).
|
|
109
|
+
*
|
|
110
|
+
* This property can be understood as a shorthand for retrieving the element that a specific editor integration
|
|
111
|
+
* considers to be its main DOM element.
|
|
112
|
+
*
|
|
113
|
+
* @readonly
|
|
114
|
+
* @member {HTMLElement|null} #element
|
|
115
|
+
*/
|
|
116
|
+
get element() {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Fires the {@link module:core/editor/editorui~EditorUI#event:update `update`} event.
|
|
122
|
+
*
|
|
123
|
+
* This method should be called when the editor UI (e.g. positions of its balloons) needs to be updated due to
|
|
124
|
+
* some environmental change which CKEditor 5 is not aware of (e.g. resize of a container in which it is used).
|
|
125
|
+
*/
|
|
126
|
+
update() {
|
|
127
|
+
this.fire( 'update' );
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Destroys the UI.
|
|
132
|
+
*/
|
|
133
|
+
destroy() {
|
|
134
|
+
this.stopListening();
|
|
135
|
+
|
|
136
|
+
this.focusTracker.destroy();
|
|
137
|
+
|
|
138
|
+
// Clean–up the references to the CKEditor instance stored in the native editable DOM elements.
|
|
139
|
+
for ( const domElement of this._editableElementsMap.values() ) {
|
|
140
|
+
domElement.ckeditorInstance = null;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
this._editableElementsMap = new Map();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Store the native DOM editable element used by the editor under
|
|
148
|
+
* a unique name.
|
|
149
|
+
*
|
|
150
|
+
* @param {String} rootName The unique name of the editable element.
|
|
151
|
+
* @param {HTMLElement} domElement The native DOM editable element.
|
|
152
|
+
*/
|
|
153
|
+
setEditableElement( rootName, domElement ) {
|
|
154
|
+
this._editableElementsMap.set( rootName, domElement );
|
|
155
|
+
|
|
156
|
+
// Put a reference to the CKEditor instance in the editable native DOM element.
|
|
157
|
+
// It helps 3rd–party software (browser extensions, other libraries) access and recognize
|
|
158
|
+
// CKEditor 5 instances (editing roots) and use their API (there is no global editor
|
|
159
|
+
// instance registry).
|
|
160
|
+
if ( !domElement.ckeditorInstance ) {
|
|
161
|
+
domElement.ckeditorInstance = this.editor;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Returns the editable editor element with the given name or null if editable does not exist.
|
|
167
|
+
*
|
|
168
|
+
* @param {String} [rootName=main] The editable name.
|
|
169
|
+
* @returns {HTMLElement|undefined}
|
|
170
|
+
*/
|
|
171
|
+
getEditableElement( rootName = 'main' ) {
|
|
172
|
+
return this._editableElementsMap.get( rootName );
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Returns array of names of all editor editable elements.
|
|
177
|
+
*
|
|
178
|
+
* @returns {Iterable.<String>}
|
|
179
|
+
*/
|
|
180
|
+
getEditableElementsNames() {
|
|
181
|
+
return this._editableElementsMap.keys();
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Stores all editable elements used by the editor instance.
|
|
186
|
+
*
|
|
187
|
+
* @protected
|
|
188
|
+
* @deprecated
|
|
189
|
+
* @member {Map.<String,HTMLElement>}
|
|
190
|
+
*/
|
|
191
|
+
get _editableElements() {
|
|
192
|
+
/**
|
|
193
|
+
* The {@link module:core/editor/editorui~EditorUI#_editableElements `EditorUI#_editableElements`} property has been
|
|
194
|
+
* deprecated and will be removed in the near future. Please use {@link #setEditableElement `setEditableElement()`} and
|
|
195
|
+
* {@link #getEditableElement `getEditableElement()`} methods instead.
|
|
196
|
+
*
|
|
197
|
+
* @error editor-ui-deprecated-editable-elements
|
|
198
|
+
* @param {module:core/editor/editorui~EditorUI} editorUI Editor UI instance the deprecated property belongs to.
|
|
199
|
+
*/
|
|
200
|
+
console.warn(
|
|
201
|
+
'editor-ui-deprecated-editable-elements: ' +
|
|
202
|
+
'The EditorUI#_editableElements property has been deprecated and will be removed in the near future.',
|
|
203
|
+
{ editorUI: this } );
|
|
204
|
+
|
|
205
|
+
return this._editableElementsMap;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Returns viewport offsets object:
|
|
210
|
+
*
|
|
211
|
+
* ```js
|
|
212
|
+
* {
|
|
213
|
+
* top: Number,
|
|
214
|
+
* right: Number,
|
|
215
|
+
* bottom: Number,
|
|
216
|
+
* left: Number
|
|
217
|
+
* }
|
|
218
|
+
* ```
|
|
219
|
+
*
|
|
220
|
+
* Only top property is currently supported.
|
|
221
|
+
*
|
|
222
|
+
* @private
|
|
223
|
+
* @return {Object}
|
|
224
|
+
*/
|
|
225
|
+
_readViewportOffsetFromConfig() {
|
|
226
|
+
const editor = this.editor;
|
|
227
|
+
const viewportOffsetConfig = editor.config.get( 'ui.viewportOffset' );
|
|
228
|
+
|
|
229
|
+
if ( viewportOffsetConfig ) {
|
|
230
|
+
return viewportOffsetConfig;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const legacyOffsetConfig = editor.config.get( 'toolbar.viewportTopOffset' );
|
|
234
|
+
|
|
235
|
+
// Fall back to deprecated toolbar config.
|
|
236
|
+
if ( legacyOffsetConfig ) {
|
|
237
|
+
/**
|
|
238
|
+
* The {@link module:core/editor/editorconfig~EditorConfig#toolbar `EditorConfig#toolbar.viewportTopOffset`}
|
|
239
|
+
* property has been deprecated and will be removed in the near future. Please use
|
|
240
|
+
* {@link module:core/editor/editorconfig~EditorConfig#ui `EditorConfig#ui.viewportOffset`} instead.
|
|
241
|
+
*
|
|
242
|
+
* @error editor-ui-deprecated-viewport-offset-config
|
|
243
|
+
*/
|
|
244
|
+
console.warn(
|
|
245
|
+
'editor-ui-deprecated-viewport-offset-config: ' +
|
|
246
|
+
'The `toolbar.vieportTopOffset` configuration option is deprecated. ' +
|
|
247
|
+
'It will be removed from future CKEditor versions. Use `ui.viewportOffset.top` instead.'
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
return { top: legacyOffsetConfig };
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// More keys to come in the future.
|
|
254
|
+
return { top: 0 };
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Fired when the editor UI is ready.
|
|
259
|
+
*
|
|
260
|
+
* Fired before {@link module:engine/controller/datacontroller~DataController#event:ready}.
|
|
261
|
+
*
|
|
262
|
+
* @event ready
|
|
263
|
+
*/
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Fired whenever the UI (all related components) should be refreshed.
|
|
267
|
+
*
|
|
268
|
+
* **Note:**: The event is fired after each {@link module:engine/view/document~Document#event:layoutChanged}.
|
|
269
|
+
* It can also be fired manually via the {@link module:core/editor/editorui~EditorUI#update} method.
|
|
270
|
+
*
|
|
271
|
+
* @event update
|
|
272
|
+
*/
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
mix( EditorUI, ObservableMixin );
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
|
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @module core/editor/editorwithui
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Interface defining a type of {@link module:core/editor/editor~Editor editor} which has a UI.
|
|
12
|
+
*
|
|
13
|
+
* Most editors (like {@link module:editor-classic/classiceditor~ClassicEditor} or
|
|
14
|
+
* {@link module:editor-inline/inlineeditor~InlineEditor}) implement this interface, however, it is not required to do so.
|
|
15
|
+
*
|
|
16
|
+
* Editors with an external UI (i.e. Bootstrap-based) or a headless editor may not implement this interface.
|
|
17
|
+
* When developing editor features you can consider this by splitting them into two parts: the "editing" part,
|
|
18
|
+
* which bases on {@link module:core/editor/editor~Editor} itself, and the UI part which bases on this interface.
|
|
19
|
+
* This will make your features compatible with more types of editors.
|
|
20
|
+
*
|
|
21
|
+
* @interface EditorWithUI
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The editor UI instance.
|
|
26
|
+
*
|
|
27
|
+
* @readonly
|
|
28
|
+
* @member {module:core/editor/editorui~EditorUI} #ui
|
|
29
|
+
*/
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
|
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { isFunction } from 'lodash-es';
|
|
7
|
+
import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @module core/editor/utils/attachtoform
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Checks if the editor is initialized on a `<textarea>` element that belongs to a form. If yes, it updates the editor's element
|
|
15
|
+
* content before submitting the form.
|
|
16
|
+
*
|
|
17
|
+
* This helper requires the {@link module:core/editor/utils/elementapimixin~ElementApi ElementApi interface}.
|
|
18
|
+
*
|
|
19
|
+
* @param {module:core/editor/editor~Editor} editor Editor instance.
|
|
20
|
+
*/
|
|
21
|
+
export default function attachToForm( editor ) {
|
|
22
|
+
if ( !isFunction( editor.updateSourceElement ) ) {
|
|
23
|
+
/**
|
|
24
|
+
* The editor passed to `attachToForm()` must implement the
|
|
25
|
+
* {@link module:core/editor/utils/elementapimixin~ElementApi} interface.
|
|
26
|
+
*
|
|
27
|
+
* @error attachtoform-missing-elementapi-interface
|
|
28
|
+
*/
|
|
29
|
+
throw new CKEditorError(
|
|
30
|
+
'attachtoform-missing-elementapi-interface',
|
|
31
|
+
editor
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const sourceElement = editor.sourceElement;
|
|
36
|
+
|
|
37
|
+
// Only when replacing a textarea which is inside of a form element.
|
|
38
|
+
if ( sourceElement && sourceElement.tagName.toLowerCase() === 'textarea' && sourceElement.form ) {
|
|
39
|
+
let originalSubmit;
|
|
40
|
+
const form = sourceElement.form;
|
|
41
|
+
const onSubmit = () => editor.updateSourceElement();
|
|
42
|
+
|
|
43
|
+
// Replace the original form#submit() to call a custom submit function first.
|
|
44
|
+
// Check if #submit is a function because the form might have an input named "submit".
|
|
45
|
+
if ( isFunction( form.submit ) ) {
|
|
46
|
+
originalSubmit = form.submit;
|
|
47
|
+
|
|
48
|
+
form.submit = () => {
|
|
49
|
+
onSubmit();
|
|
50
|
+
originalSubmit.apply( form );
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Update the replaced textarea with data before each form#submit event.
|
|
55
|
+
form.addEventListener( 'submit', onSubmit );
|
|
56
|
+
|
|
57
|
+
// Remove the submit listener and revert the original submit method on
|
|
58
|
+
// editor#destroy.
|
|
59
|
+
editor.on( 'destroy', () => {
|
|
60
|
+
form.removeEventListener( 'submit', onSubmit );
|
|
61
|
+
|
|
62
|
+
if ( originalSubmit ) {
|
|
63
|
+
form.submit = originalSubmit;
|
|
64
|
+
}
|
|
65
|
+
} );
|
|
66
|
+
}
|
|
67
|
+
}
|