@ckeditor/ckeditor5-engine 35.3.2 → 36.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 (123) hide show
  1. package/LICENSE.md +1 -1
  2. package/package.json +22 -22
  3. package/src/controller/datacontroller.js +10 -8
  4. package/src/controller/editingcontroller.js +3 -4
  5. package/src/conversion/conversion.js +2 -3
  6. package/src/conversion/conversionhelpers.js +1 -1
  7. package/src/conversion/downcastdispatcher.js +3 -3
  8. package/src/conversion/downcasthelpers.js +2 -3
  9. package/src/conversion/mapper.js +3 -4
  10. package/src/conversion/modelconsumable.js +2 -2
  11. package/src/conversion/upcastdispatcher.js +3 -4
  12. package/src/conversion/upcasthelpers.js +10 -3
  13. package/src/conversion/viewconsumable.js +2 -2
  14. package/src/dataprocessor/basichtmlwriter.js +1 -1
  15. package/src/dataprocessor/dataprocessor.js +1 -1
  16. package/src/dataprocessor/htmldataprocessor.js +3 -3
  17. package/src/dataprocessor/htmlwriter.js +1 -1
  18. package/src/dataprocessor/xmldataprocessor.js +6 -2
  19. package/src/dev-utils/model.js +3 -3
  20. package/src/dev-utils/operationreplayer.js +1 -1
  21. package/src/dev-utils/utils.js +1 -1
  22. package/src/dev-utils/view.js +1 -1
  23. package/src/index.js +13 -3
  24. package/src/model/batch.js +10 -47
  25. package/src/model/differ.js +81 -174
  26. package/src/model/document.js +38 -97
  27. package/src/model/documentfragment.js +44 -97
  28. package/src/model/documentselection.js +152 -251
  29. package/src/model/element.js +48 -101
  30. package/src/model/history.js +15 -46
  31. package/src/model/item.js +1 -1
  32. package/src/model/liveposition.js +11 -39
  33. package/src/model/liverange.js +14 -38
  34. package/src/model/markercollection.js +42 -115
  35. package/src/model/model.js +214 -292
  36. package/src/model/node.js +36 -128
  37. package/src/model/nodelist.js +12 -41
  38. package/src/model/operation/attributeoperation.js +14 -45
  39. package/src/model/operation/detachoperation.js +4 -17
  40. package/src/model/operation/insertoperation.js +7 -35
  41. package/src/model/operation/markeroperation.js +9 -48
  42. package/src/model/operation/mergeoperation.js +9 -42
  43. package/src/model/operation/moveoperation.js +15 -39
  44. package/src/model/operation/nooperation.js +1 -7
  45. package/src/model/operation/operation.js +5 -63
  46. package/src/model/operation/operationfactory.js +3 -6
  47. package/src/model/operation/renameoperation.js +9 -29
  48. package/src/model/operation/rootattributeoperation.js +19 -48
  49. package/src/model/operation/splitoperation.js +10 -48
  50. package/src/model/operation/transform.js +110 -151
  51. package/src/model/operation/utils.js +37 -52
  52. package/src/model/position.js +118 -230
  53. package/src/model/range.js +146 -202
  54. package/src/model/rootelement.js +8 -47
  55. package/src/model/schema.js +245 -282
  56. package/src/model/selection.js +135 -196
  57. package/src/model/text.js +10 -37
  58. package/src/model/textproxy.js +16 -70
  59. package/src/model/treewalker.js +11 -102
  60. package/src/model/typecheckable.js +1 -1
  61. package/src/model/utils/autoparagraphing.js +11 -12
  62. package/src/model/utils/deletecontent.js +93 -62
  63. package/src/model/utils/findoptimalinsertionrange.js +25 -25
  64. package/src/model/utils/getselectedcontent.js +3 -6
  65. package/src/model/utils/insertcontent.js +37 -130
  66. package/src/model/utils/insertobject.js +40 -40
  67. package/src/model/utils/modifyselection.js +24 -34
  68. package/src/model/utils/selection-post-fixer.js +53 -59
  69. package/src/model/writer.js +209 -316
  70. package/src/view/attributeelement.js +2 -2
  71. package/src/view/containerelement.js +1 -1
  72. package/src/view/datatransfer.js +1 -1
  73. package/src/view/document.js +3 -5
  74. package/src/view/documentfragment.js +50 -4
  75. package/src/view/documentselection.js +2 -3
  76. package/src/view/domconverter.js +4 -8
  77. package/src/view/downcastwriter.js +2 -3
  78. package/src/view/editableelement.js +2 -3
  79. package/src/view/element.js +6 -8
  80. package/src/view/elementdefinition.js +1 -1
  81. package/src/view/emptyelement.js +2 -2
  82. package/src/view/filler.js +2 -3
  83. package/src/view/item.js +1 -1
  84. package/src/view/matcher.js +2 -2
  85. package/src/view/node.js +2 -5
  86. package/src/view/observer/arrowkeysobserver.js +1 -1
  87. package/src/view/observer/bubblingemittermixin.js +3 -6
  88. package/src/view/observer/bubblingeventinfo.js +2 -2
  89. package/src/view/observer/clickobserver.js +1 -1
  90. package/src/view/observer/compositionobserver.js +1 -1
  91. package/src/view/observer/domeventdata.js +1 -1
  92. package/src/view/observer/domeventobserver.js +1 -1
  93. package/src/view/observer/fakeselectionobserver.js +2 -2
  94. package/src/view/observer/focusobserver.js +25 -3
  95. package/src/view/observer/inputobserver.js +2 -2
  96. package/src/view/observer/keyobserver.js +2 -2
  97. package/src/view/observer/mouseobserver.js +1 -1
  98. package/src/view/observer/mutationobserver.js +1 -1
  99. package/src/view/observer/observer.js +3 -3
  100. package/src/view/observer/selectionobserver.js +21 -3
  101. package/src/view/observer/tabobserver.js +2 -2
  102. package/src/view/placeholder.js +1 -1
  103. package/src/view/position.js +2 -3
  104. package/src/view/range.js +1 -1
  105. package/src/view/rawelement.js +2 -2
  106. package/src/view/renderer.js +3 -12
  107. package/src/view/rooteditableelement.js +1 -1
  108. package/src/view/selection.js +2 -6
  109. package/src/view/styles/background.js +1 -1
  110. package/src/view/styles/border.js +1 -1
  111. package/src/view/styles/margin.js +1 -1
  112. package/src/view/styles/padding.js +1 -1
  113. package/src/view/styles/utils.js +1 -1
  114. package/src/view/stylesmap.js +1 -1
  115. package/src/view/text.js +1 -1
  116. package/src/view/textproxy.js +2 -2
  117. package/src/view/treewalker.js +2 -2
  118. package/src/view/typecheckable.js +1 -1
  119. package/src/view/uielement.js +2 -3
  120. package/src/view/upcastwriter.js +1 -1
  121. package/src/view/view.js +7 -7
  122. package/theme/placeholder.css +1 -1
  123. package/theme/renderer.css +1 -1
@@ -1,12 +1,12 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
6
6
  * @module engine/view/attributeelement
7
7
  */
8
8
  import Element from './element';
9
- import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
9
+ import { CKEditorError } from '@ckeditor/ckeditor5-utils';
10
10
  // Default attribute priority.
11
11
  const DEFAULT_PRIORITY = 10;
12
12
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -1,15 +1,13 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
- /* eslint-disable new-cap */
6
5
  /**
7
6
  * @module engine/view/document
8
7
  */
9
8
  import DocumentSelection from './documentselection';
10
- import Collection from '@ckeditor/ckeditor5-utils/src/collection';
11
9
  import BubblingEmitterMixin from './observer/bubblingemittermixin';
12
- import { Observable } from '@ckeditor/ckeditor5-utils/src/observablemixin';
10
+ import { Collection, ObservableMixin } from '@ckeditor/ckeditor5-utils';
13
11
  // @if CK_DEBUG_ENGINE // const { logDocument } = require( '../dev-utils/utils' );
14
12
  /**
15
13
  * Document class creates an abstract layer over the content editable area, contains a tree of view elements and
@@ -18,7 +16,7 @@ import { Observable } from '@ckeditor/ckeditor5-utils/src/observablemixin';
18
16
  * @mixes module:engine/view/observer/bubblingemittermixin~BubblingEmitterMixin
19
17
  * @mixes module:utils/observablemixin~ObservableMixin
20
18
  */
21
- export default class Document extends BubblingEmitterMixin(Observable) {
19
+ export default class Document extends BubblingEmitterMixin(ObservableMixin()) {
22
20
  /**
23
21
  * Creates a Document instance.
24
22
  *
@@ -1,16 +1,14 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
- /* eslint-disable new-cap */
6
5
  /**
7
6
  * @module engine/view/documentfragment
8
7
  */
9
8
  import TypeCheckable from './typecheckable';
10
9
  import Text from './text';
11
10
  import TextProxy from './textproxy';
12
- import isIterable from '@ckeditor/ckeditor5-utils/src/isiterable';
13
- import EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';
11
+ import { EmitterMixin, isIterable } from '@ckeditor/ckeditor5-utils';
14
12
  /**
15
13
  * Document fragment.
16
14
  *
@@ -46,6 +44,14 @@ export default class DocumentFragment extends EmitterMixin(TypeCheckable) {
46
44
  if (children) {
47
45
  this._insertChild(0, children);
48
46
  }
47
+ /**
48
+ * Map of custom properties.
49
+ * Custom properties can be added to document fragment instance.
50
+ *
51
+ * @protected
52
+ * @member {Map}
53
+ */
54
+ this._customProperties = new Map();
49
55
  }
50
56
  /**
51
57
  * Iterable interface.
@@ -93,6 +99,24 @@ export default class DocumentFragment extends EmitterMixin(TypeCheckable) {
93
99
  get parent() {
94
100
  return null;
95
101
  }
102
+ /**
103
+ * Returns the custom property value for the given key.
104
+ *
105
+ * @param {String|Symbol} key
106
+ * @returns {*}
107
+ */
108
+ getCustomProperty(key) {
109
+ return this._customProperties.get(key);
110
+ }
111
+ /**
112
+ * Returns an iterator which iterates over this document fragment's custom properties.
113
+ * Iterator provides `[ key, value ]` pairs for each stored property.
114
+ *
115
+ * @returns {Iterable.<*>}
116
+ */
117
+ *getCustomProperties() {
118
+ yield* this._customProperties.entries();
119
+ }
96
120
  /**
97
121
  * {@link module:engine/view/documentfragment~DocumentFragment#_insertChild Insert} a child node or a list of child nodes at the end
98
122
  * and sets the parent of these nodes to this fragment.
@@ -179,6 +203,28 @@ export default class DocumentFragment extends EmitterMixin(TypeCheckable) {
179
203
  _fireChange(type, node) {
180
204
  this.fire('change:' + type, node);
181
205
  }
206
+ /**
207
+ * Sets a custom property. They can be used to add special data to elements.
208
+ *
209
+ * @see module:engine/view/downcastwriter~DowncastWriter#setCustomProperty
210
+ * @protected
211
+ * @param {String|Symbol} key
212
+ * @param {*} value
213
+ */
214
+ _setCustomProperty(key, value) {
215
+ this._customProperties.set(key, value);
216
+ }
217
+ /**
218
+ * Removes the custom property stored under the given key.
219
+ *
220
+ * @see module:engine/view/downcastwriter~DowncastWriter#removeCustomProperty
221
+ * @protected
222
+ * @param {String|Symbol} key
223
+ * @returns {Boolean} Returns true if property was removed.
224
+ */
225
+ _removeCustomProperty(key) {
226
+ return this._customProperties.delete(key);
227
+ }
182
228
  }
183
229
  /**
184
230
  * Checks whether this object is of the given type.
@@ -1,14 +1,13 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
- /* eslint-disable new-cap */
6
5
  /**
7
6
  * @module engine/view/documentselection
8
7
  */
9
8
  import TypeCheckable from './typecheckable';
10
9
  import Selection from './selection';
11
- import EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';
10
+ import { EmitterMixin } from '@ckeditor/ckeditor5-utils';
12
11
  /**
13
12
  * Class representing the document selection in the view.
14
13
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -16,12 +16,7 @@ import ViewDocumentFragment from './documentfragment';
16
16
  import ViewTreeWalker from './treewalker';
17
17
  import { default as Matcher } from './matcher';
18
18
  import { BR_FILLER, INLINE_FILLER_LENGTH, NBSP_FILLER, MARKED_NBSP_FILLER, getDataWithoutFiller, isInlineFiller, startsWithFiller } from './filler';
19
- import global from '@ckeditor/ckeditor5-utils/src/dom/global';
20
- import { logWarning } from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
21
- import indexOf from '@ckeditor/ckeditor5-utils/src/dom/indexof';
22
- import getAncestors from '@ckeditor/ckeditor5-utils/src/dom/getancestors';
23
- import isText from '@ckeditor/ckeditor5-utils/src/dom/istext';
24
- import isComment from '@ckeditor/ckeditor5-utils/src/dom/iscomment';
19
+ import { global, logWarning, indexOf, getAncestors, isText, isComment, first } from '@ckeditor/ckeditor5-utils';
25
20
  const BR_FILLER_REF = BR_FILLER(global.document); // eslint-disable-line new-cap
26
21
  const NBSP_FILLER_REF = NBSP_FILLER(global.document); // eslint-disable-line new-cap
27
22
  const MARKED_NBSP_FILLER_REF = MARKED_NBSP_FILLER(global.document); // eslint-disable-line new-cap
@@ -438,7 +433,8 @@ export default class DomConverter {
438
433
  yield this._getBlockFiller();
439
434
  }
440
435
  const transparentRendering = childView.is('element') &&
441
- childView.getCustomProperty('dataPipeline:transparentRendering');
436
+ !!childView.getCustomProperty('dataPipeline:transparentRendering') &&
437
+ !first(childView.getAttributes());
442
438
  if (transparentRendering && this.renderingMode == 'data') {
443
439
  yield* this.viewChildrenToDom(childView, options);
444
440
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -13,9 +13,8 @@ import AttributeElement from './attributeelement';
13
13
  import EmptyElement from './emptyelement';
14
14
  import UIElement from './uielement';
15
15
  import RawElement from './rawelement';
16
- import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
16
+ import { CKEditorError, isIterable } from '@ckeditor/ckeditor5-utils';
17
17
  import DocumentFragment from './documentfragment';
18
- import isIterable from '@ckeditor/ckeditor5-utils/src/isiterable';
19
18
  import Text from './text';
20
19
  import EditableElement from './editableelement';
21
20
  import { isPlainObject } from 'lodash-es';
@@ -1,13 +1,12 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
- /* eslint-disable new-cap */
6
5
  /**
7
6
  * @module engine/view/editableelement
8
7
  */
9
8
  import ContainerElement from './containerelement';
10
- import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';
9
+ import { ObservableMixin } from '@ckeditor/ckeditor5-utils';
11
10
  /**
12
11
  * Editable element which can be a {@link module:engine/view/rooteditableelement~RootEditableElement root}
13
12
  * or nested editable area in the editor.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -8,9 +8,7 @@
8
8
  import Node from './node';
9
9
  import Text from './text';
10
10
  import TextProxy from './textproxy';
11
- import toMap from '@ckeditor/ckeditor5-utils/src/tomap';
12
- import toArray from '@ckeditor/ckeditor5-utils/src/toarray';
13
- import isIterable from '@ckeditor/ckeditor5-utils/src/isiterable';
11
+ import { isIterable, toArray, toMap } from '@ckeditor/ckeditor5-utils';
14
12
  import { default as Matcher } from './matcher';
15
13
  import { default as StylesMap } from './stylesmap';
16
14
  import { isPlainObject } from 'lodash-es';
@@ -581,16 +579,16 @@ export default class Element extends Node {
581
579
  * @fires module:engine/view/node~Node#change
582
580
  */
583
581
  _setAttribute(key, value) {
584
- value = String(value);
582
+ const stringValue = String(value);
585
583
  this._fireChange('attributes', this);
586
584
  if (key == 'class') {
587
- parseClasses(this._classes, value);
585
+ parseClasses(this._classes, stringValue);
588
586
  }
589
587
  else if (key == 'style') {
590
- this._styles.setTo(value);
588
+ this._styles.setTo(stringValue);
591
589
  }
592
590
  else {
593
- this._attrs.set(key, value);
591
+ this._attrs.set(key, stringValue);
594
592
  }
595
593
  }
596
594
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  export {};
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import Element from './element';
9
9
  import Node from './node';
10
- import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
10
+ import { CKEditorError } from '@ckeditor/ckeditor5-utils';
11
11
  /**
12
12
  * Empty element class. It is used to represent elements that cannot contain any child nodes (for example `<img>` elements).
13
13
  *
@@ -1,9 +1,8 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
- import { keyCodes } from '@ckeditor/ckeditor5-utils/src/keyboard';
6
- import isText from '@ckeditor/ckeditor5-utils/src/dom/istext';
5
+ import { keyCodes, isText } from '@ckeditor/ckeditor5-utils';
7
6
  /**
8
7
  * Set of utilities related to handling block and inline fillers.
9
8
  *
package/src/view/item.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  export {};
@@ -1,9 +1,9 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  import { isPlainObject } from 'lodash-es';
6
- import { logWarning } from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
6
+ import { logWarning } from '@ckeditor/ckeditor5-utils';
7
7
  /**
8
8
  * View matcher class.
9
9
  * Instance of this class can be used to find {@link module:engine/view/element~Element elements} that match given pattern.
package/src/view/node.js CHANGED
@@ -1,15 +1,12 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
- /* eslint-disable new-cap */
6
5
  /**
7
6
  * @module engine/view/node
8
7
  */
9
8
  import TypeCheckable from './typecheckable';
10
- import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
11
- import EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';
12
- import compareArrays from '@ckeditor/ckeditor5-utils/src/comparearrays';
9
+ import { CKEditorError, EmitterMixin, compareArrays } from '@ckeditor/ckeditor5-utils';
13
10
  import { clone } from 'lodash-es';
14
11
  // To check if component is loaded more than once.
15
12
  import '@ckeditor/ckeditor5-utils/src/version';
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -1,14 +1,11 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
6
6
  * @module engine/view/observer/bubblingemittermixin
7
7
  */
8
- import EventInfo from '@ckeditor/ckeditor5-utils/src/eventinfo';
9
- import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
10
- import { Emitter } from '@ckeditor/ckeditor5-utils/src/emittermixin';
11
- import toArray from '@ckeditor/ckeditor5-utils/src/toarray';
8
+ import { CKEditorError, EmitterMixin, EventInfo, toArray } from '@ckeditor/ckeditor5-utils';
12
9
  import BubblingEventInfo from './bubblingeventinfo';
13
10
  const contextsSymbol = Symbol('bubbling contexts');
14
11
  /**
@@ -81,7 +78,7 @@ export default function BubblingEmitterMixin(base) {
81
78
  for (const context of contexts) {
82
79
  let emitter = eventContexts.get(context);
83
80
  if (!emitter) {
84
- emitter = new Emitter();
81
+ emitter = new (EmitterMixin())();
85
82
  eventContexts.set(context, emitter);
86
83
  }
87
84
  this.listenTo(emitter, event, callback, options);
@@ -1,11 +1,11 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
6
6
  * @module engine/view/observer/bubblingeventinfo
7
7
  */
8
- import EventInfo from '@ckeditor/ckeditor5-utils/src/eventinfo';
8
+ import { EventInfo } from '@ckeditor/ckeditor5-utils';
9
9
  /**
10
10
  * The event object passed to bubbling event callbacks. It is used to provide information about the event as well as a tool to
11
11
  * manipulate it.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import Observer from './observer';
9
9
  import ViewSelection from '../selection';
10
- import { keyCodes } from '@ckeditor/ckeditor5-utils/src/keyboard';
10
+ import { keyCodes } from '@ckeditor/ckeditor5-utils';
11
11
  import { debounce } from 'lodash-es';
12
12
  /**
13
13
  * Fake selection observer class. If view selection is fake it is placed in dummy DOM container. This observer listens
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -20,11 +20,20 @@ import DomEventObserver from './domeventobserver';
20
20
  export default class FocusObserver extends DomEventObserver {
21
21
  constructor(view) {
22
22
  super(view);
23
+ this._isFocusChanging = false;
23
24
  this.domEventType = ['focus', 'blur'];
24
25
  this.useCapture = true;
25
26
  const document = this.document;
26
27
  document.on('focus', () => {
27
- document.isFocused = true;
28
+ /**
29
+ * Set to `true` if the document is in the process of setting the focus.
30
+ *
31
+ * The flag is used to indicate that setting the focus is in progress.
32
+ *
33
+ * @internal
34
+ * @type {Boolean} module:engine/view/observer/focusobserver#_isFocusChanging
35
+ */
36
+ this._isFocusChanging = true;
28
37
  // Unfortunately native `selectionchange` event is fired asynchronously.
29
38
  // We need to wait until `SelectionObserver` handle the event and then render. Otherwise rendering will
30
39
  // overwrite new DOM selection with selection from the view.
@@ -33,12 +42,16 @@ export default class FocusObserver extends DomEventObserver {
33
42
  //
34
43
  // Using `view.change()` instead of `view.forceRender()` to prevent double rendering
35
44
  // in a situation where `selectionchange` already caused selection change.
36
- this._renderTimeoutId = setTimeout(() => view.change(() => { }), 50);
45
+ this._renderTimeoutId = setTimeout(() => {
46
+ this.flush();
47
+ view.change(() => { });
48
+ }, 50);
37
49
  });
38
50
  document.on('blur', (evt, data) => {
39
51
  const selectedEditable = document.selection.editableElement;
40
52
  if (selectedEditable === null || selectedEditable === data.target) {
41
53
  document.isFocused = false;
54
+ this._isFocusChanging = false;
42
55
  // Re-render the document to update view elements
43
56
  // (changing document.isFocused already marked view as changed since last rendering).
44
57
  view.change(() => { });
@@ -51,6 +64,15 @@ export default class FocusObserver extends DomEventObserver {
51
64
  * @member {Number} #_renderTimeoutId
52
65
  */
53
66
  }
67
+ /**
68
+ * Finishes setting the document focus state.
69
+ */
70
+ flush() {
71
+ if (this._isFocusChanging) {
72
+ this._isFocusChanging = false;
73
+ this.document.isFocused = true;
74
+ }
75
+ }
54
76
  onDomEvent(domEvent) {
55
77
  this.fire(domEvent.type, domEvent);
56
78
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import DomEventObserver from './domeventobserver';
9
9
  import DataTransfer from '../datatransfer';
10
- import env from '@ckeditor/ckeditor5-utils/src/env';
10
+ import { env } from '@ckeditor/ckeditor5-utils';
11
11
  /**
12
12
  * Observer for events connected with data input.
13
13
  *
@@ -1,12 +1,12 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
6
6
  * @module engine/view/observer/keyobserver
7
7
  */
8
8
  import DomEventObserver from './domeventobserver';
9
- import { getCode } from '@ckeditor/ckeditor5-utils/src/keyboard';
9
+ import { getCode } from '@ckeditor/ckeditor5-utils';
10
10
  /**
11
11
  * Observer for events connected with pressing keyboard keys.
12
12
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -1,11 +1,11 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
6
6
  * @module engine/view/observer/observer
7
7
  */
8
- import { Emitter as DomEmitter } from '@ckeditor/ckeditor5-utils/src/dom/emittermixin';
8
+ import { DomEmitterMixin } from '@ckeditor/ckeditor5-utils';
9
9
  /**
10
10
  * Abstract base observer class. Observers are classes which listen to DOM events, do the preliminary
11
11
  * processing and fire events on the {@link module:engine/view/document~Document} objects.
@@ -14,7 +14,7 @@ import { Emitter as DomEmitter } from '@ckeditor/ckeditor5-utils/src/dom/emitter
14
14
  *
15
15
  * @abstract
16
16
  */
17
- export default class Observer extends DomEmitter {
17
+ export default class Observer extends DomEmitterMixin() {
18
18
  /**
19
19
  * Creates an instance of the observer.
20
20
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -8,8 +8,9 @@
8
8
  /* global setInterval, clearInterval */
9
9
  import Observer from './observer';
10
10
  import MutationObserver from './mutationobserver';
11
- import env from '@ckeditor/ckeditor5-utils/src/env';
11
+ import { env } from '@ckeditor/ckeditor5-utils';
12
12
  import { debounce } from 'lodash-es';
13
+ import FocusObserver from './focusobserver';
13
14
  /**
14
15
  * Selection observer class observes selection changes in the document. If a selection changes on the document this
15
16
  * observer checks if the DOM selection is different from the {@link module:engine/view/document~Document#selection view selection}.
@@ -35,6 +36,15 @@ export default class SelectionObserver extends Observer {
35
36
  * module:engine/view/observer/selectionobserver~SelectionObserver#mutationObserver
36
37
  */
37
38
  this.mutationObserver = view.getObserver(MutationObserver);
39
+ /**
40
+ * Instance of the focus observer. Selection observer calls
41
+ * {@link module:engine/view/observer/focusobserver~FocusObserver#flush} to mark the latest focus change as complete.
42
+ *
43
+ * @readonly
44
+ * @member {module:engine/view/observer/focusobserver~FocusObserver}
45
+ * module:engine/view/observer/focusobserver~FocusObserver#focusObserver
46
+ */
47
+ this.focusObserver = view.getObserver(FocusObserver);
38
48
  /**
39
49
  * Reference to the view {@link module:engine/view/documentselection~DocumentSelection} object used to compare
40
50
  * new selection with it.
@@ -171,6 +181,12 @@ export default class SelectionObserver extends Observer {
171
181
  this._fireSelectionChangeDoneDebounced.cancel();
172
182
  this._documentIsSelectingInactivityTimeoutDebounced.cancel();
173
183
  }
184
+ // @if CK_DEBUG // _reportInfiniteLoop() {
185
+ // @if CK_DEBUG // throw new Error(
186
+ // @if CK_DEBUG // 'Selection change observer detected an infinite rendering loop.\n\n' +
187
+ // @if CK_DEBUG // '⚠️⚠️ Report this error on https://github.com/ckeditor/ckeditor5/issues/11658.'
188
+ // @if CK_DEBUG // );
189
+ // @if CK_DEBUG // }
174
190
  /**
175
191
  * Selection change listener. {@link module:engine/view/observer/mutationobserver~MutationObserver#flush Flush} mutations, check if
176
192
  * a selection changes and fires {@link module:engine/view/document~Document#event:selectionChange} event on every change
@@ -212,9 +228,11 @@ export default class SelectionObserver extends Observer {
212
228
  // by the browser and browser fixes it automatically what causes `selectionchange` event on
213
229
  // which a loopback through a model tries to re-render the wrong selection and again.
214
230
  //
215
- // @if CK_DEBUG // console.warn( 'Selection change observer detected an infinite rendering loop.' );
231
+ // @if CK_DEBUG // this._reportInfiniteLoop();
216
232
  return;
217
233
  }
234
+ // Mark the latest focus change as complete (we got new selection after the focus so the selection is in the focused element).
235
+ this.focusObserver.flush();
218
236
  if (this.selection.isSimilar(newViewSelection)) {
219
237
  // If selection was equal and we are at this point of algorithm, it means that it was incorrect.
220
238
  // Just re-render it, no need to fire any events, etc.