@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.
Files changed (111) hide show
  1. package/LICENSE.md +17 -0
  2. package/README.md +18 -0
  3. package/lang/contexts.json +8 -0
  4. package/lang/translations/af.po +41 -0
  5. package/lang/translations/ar.po +41 -0
  6. package/lang/translations/ast.po +41 -0
  7. package/lang/translations/az.po +41 -0
  8. package/lang/translations/bg.po +41 -0
  9. package/lang/translations/ca.po +41 -0
  10. package/lang/translations/cs.po +41 -0
  11. package/lang/translations/da.po +41 -0
  12. package/lang/translations/de-ch.po +41 -0
  13. package/lang/translations/de.po +41 -0
  14. package/lang/translations/el.po +41 -0
  15. package/lang/translations/en-au.po +41 -0
  16. package/lang/translations/en-gb.po +41 -0
  17. package/lang/translations/en.po +41 -0
  18. package/lang/translations/eo.po +41 -0
  19. package/lang/translations/es.po +41 -0
  20. package/lang/translations/et.po +41 -0
  21. package/lang/translations/eu.po +41 -0
  22. package/lang/translations/fa.po +41 -0
  23. package/lang/translations/fi.po +41 -0
  24. package/lang/translations/fr.po +41 -0
  25. package/lang/translations/gl.po +41 -0
  26. package/lang/translations/he.po +41 -0
  27. package/lang/translations/hi.po +41 -0
  28. package/lang/translations/hr.po +41 -0
  29. package/lang/translations/hu.po +41 -0
  30. package/lang/translations/id.po +41 -0
  31. package/lang/translations/it.po +41 -0
  32. package/lang/translations/ja.po +41 -0
  33. package/lang/translations/km.po +41 -0
  34. package/lang/translations/kn.po +41 -0
  35. package/lang/translations/ko.po +41 -0
  36. package/lang/translations/ku.po +41 -0
  37. package/lang/translations/lt.po +41 -0
  38. package/lang/translations/lv.po +41 -0
  39. package/lang/translations/nb.po +41 -0
  40. package/lang/translations/ne.po +41 -0
  41. package/lang/translations/nl.po +41 -0
  42. package/lang/translations/no.po +41 -0
  43. package/lang/translations/oc.po +41 -0
  44. package/lang/translations/pl.po +41 -0
  45. package/lang/translations/pt-br.po +41 -0
  46. package/lang/translations/pt.po +41 -0
  47. package/lang/translations/ro.po +41 -0
  48. package/lang/translations/ru.po +41 -0
  49. package/lang/translations/sk.po +41 -0
  50. package/lang/translations/sl.po +41 -0
  51. package/lang/translations/sq.po +41 -0
  52. package/lang/translations/sr-latn.po +41 -0
  53. package/lang/translations/sr.po +41 -0
  54. package/lang/translations/sv.po +41 -0
  55. package/lang/translations/th.po +41 -0
  56. package/lang/translations/tk.po +41 -0
  57. package/lang/translations/tr.po +41 -0
  58. package/lang/translations/tt.po +41 -0
  59. package/lang/translations/ug.po +41 -0
  60. package/lang/translations/uk.po +41 -0
  61. package/lang/translations/vi.po +41 -0
  62. package/lang/translations/zh-cn.po +41 -0
  63. package/lang/translations/zh.po +41 -0
  64. package/package.json +65 -0
  65. package/src/command.js +244 -0
  66. package/src/commandcollection.js +109 -0
  67. package/src/context.js +355 -0
  68. package/src/contextplugin.js +61 -0
  69. package/src/editingkeystrokehandler.js +72 -0
  70. package/src/editor/editor.js +448 -0
  71. package/src/editor/editorconfig.jsdoc +325 -0
  72. package/src/editor/editorui.js +275 -0
  73. package/src/editor/editorwithui.jsdoc +29 -0
  74. package/src/editor/utils/attachtoform.js +67 -0
  75. package/src/editor/utils/dataapimixin.js +81 -0
  76. package/src/editor/utils/elementapimixin.js +65 -0
  77. package/src/editor/utils/securesourceelement.js +49 -0
  78. package/src/index.js +95 -0
  79. package/src/multicommand.js +101 -0
  80. package/src/pendingactions.js +155 -0
  81. package/src/plugin.js +292 -0
  82. package/src/plugincollection.js +597 -0
  83. package/theme/icons/align-bottom.svg +1 -0
  84. package/theme/icons/align-center.svg +1 -0
  85. package/theme/icons/align-justify.svg +1 -0
  86. package/theme/icons/align-left.svg +1 -0
  87. package/theme/icons/align-middle.svg +1 -0
  88. package/theme/icons/align-right.svg +1 -0
  89. package/theme/icons/align-top.svg +1 -0
  90. package/theme/icons/cancel.svg +1 -0
  91. package/theme/icons/caption.svg +1 -0
  92. package/theme/icons/check.svg +1 -0
  93. package/theme/icons/cog.svg +1 -0
  94. package/theme/icons/eraser.svg +1 -0
  95. package/theme/icons/image.svg +1 -0
  96. package/theme/icons/low-vision.svg +1 -0
  97. package/theme/icons/object-center.svg +1 -0
  98. package/theme/icons/object-full-width.svg +1 -0
  99. package/theme/icons/object-inline-left.svg +1 -0
  100. package/theme/icons/object-inline-right.svg +1 -0
  101. package/theme/icons/object-inline.svg +1 -0
  102. package/theme/icons/object-left.svg +1 -0
  103. package/theme/icons/object-right.svg +1 -0
  104. package/theme/icons/object-size-full.svg +1 -0
  105. package/theme/icons/object-size-large.svg +1 -0
  106. package/theme/icons/object-size-medium.svg +1 -0
  107. package/theme/icons/object-size-small.svg +1 -0
  108. package/theme/icons/pencil.svg +1 -0
  109. package/theme/icons/pilcrow.svg +1 -0
  110. package/theme/icons/quote.svg +1 -0
  111. 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`** &ndash; 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)** &ndash; 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`** &ndash; 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`** &ndash; 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
+ }