@ckeditor/ckeditor5-engine 35.0.1 → 35.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/CHANGELOG.md +4 -4
  2. package/package.json +30 -24
  3. package/src/controller/datacontroller.js +467 -561
  4. package/src/controller/editingcontroller.js +168 -204
  5. package/src/conversion/conversion.js +541 -565
  6. package/src/conversion/conversionhelpers.js +24 -28
  7. package/src/conversion/downcastdispatcher.js +457 -686
  8. package/src/conversion/downcasthelpers.js +1583 -1965
  9. package/src/conversion/mapper.js +518 -707
  10. package/src/conversion/modelconsumable.js +240 -283
  11. package/src/conversion/upcastdispatcher.js +372 -718
  12. package/src/conversion/upcasthelpers.js +707 -818
  13. package/src/conversion/viewconsumable.js +524 -581
  14. package/src/dataprocessor/basichtmlwriter.js +12 -16
  15. package/src/dataprocessor/dataprocessor.js +5 -0
  16. package/src/dataprocessor/htmldataprocessor.js +100 -116
  17. package/src/dataprocessor/htmlwriter.js +1 -18
  18. package/src/dataprocessor/xmldataprocessor.js +116 -137
  19. package/src/dev-utils/model.js +260 -352
  20. package/src/dev-utils/operationreplayer.js +106 -126
  21. package/src/dev-utils/utils.js +34 -51
  22. package/src/dev-utils/view.js +632 -753
  23. package/src/index.js +0 -11
  24. package/src/model/batch.js +111 -127
  25. package/src/model/differ.js +988 -1233
  26. package/src/model/document.js +340 -449
  27. package/src/model/documentfragment.js +327 -364
  28. package/src/model/documentselection.js +996 -1189
  29. package/src/model/element.js +306 -410
  30. package/src/model/history.js +224 -262
  31. package/src/model/item.js +5 -0
  32. package/src/model/liveposition.js +84 -145
  33. package/src/model/liverange.js +108 -185
  34. package/src/model/markercollection.js +379 -480
  35. package/src/model/model.js +883 -1034
  36. package/src/model/node.js +419 -463
  37. package/src/model/nodelist.js +176 -201
  38. package/src/model/operation/attributeoperation.js +153 -182
  39. package/src/model/operation/detachoperation.js +64 -83
  40. package/src/model/operation/insertoperation.js +135 -166
  41. package/src/model/operation/markeroperation.js +114 -140
  42. package/src/model/operation/mergeoperation.js +163 -191
  43. package/src/model/operation/moveoperation.js +157 -187
  44. package/src/model/operation/nooperation.js +28 -38
  45. package/src/model/operation/operation.js +106 -125
  46. package/src/model/operation/operationfactory.js +30 -34
  47. package/src/model/operation/renameoperation.js +109 -135
  48. package/src/model/operation/rootattributeoperation.js +155 -188
  49. package/src/model/operation/splitoperation.js +196 -232
  50. package/src/model/operation/transform.js +1833 -2204
  51. package/src/model/operation/utils.js +140 -204
  52. package/src/model/position.js +980 -1053
  53. package/src/model/range.js +910 -1028
  54. package/src/model/rootelement.js +77 -97
  55. package/src/model/schema.js +1189 -1835
  56. package/src/model/selection.js +745 -862
  57. package/src/model/text.js +90 -114
  58. package/src/model/textproxy.js +204 -240
  59. package/src/model/treewalker.js +316 -397
  60. package/src/model/typecheckable.js +16 -0
  61. package/src/model/utils/autoparagraphing.js +32 -44
  62. package/src/model/utils/deletecontent.js +334 -418
  63. package/src/model/utils/findoptimalinsertionrange.js +25 -36
  64. package/src/model/utils/getselectedcontent.js +96 -118
  65. package/src/model/utils/insertcontent.js +757 -773
  66. package/src/model/utils/insertobject.js +96 -119
  67. package/src/model/utils/modifyselection.js +120 -158
  68. package/src/model/utils/selection-post-fixer.js +153 -201
  69. package/src/model/writer.js +1305 -1474
  70. package/src/view/attributeelement.js +189 -225
  71. package/src/view/containerelement.js +75 -85
  72. package/src/view/document.js +172 -215
  73. package/src/view/documentfragment.js +200 -249
  74. package/src/view/documentselection.js +338 -367
  75. package/src/view/domconverter.js +1370 -1617
  76. package/src/view/downcastwriter.js +1747 -2076
  77. package/src/view/editableelement.js +81 -97
  78. package/src/view/element.js +739 -890
  79. package/src/view/elementdefinition.js +5 -0
  80. package/src/view/emptyelement.js +82 -92
  81. package/src/view/filler.js +35 -50
  82. package/src/view/item.js +5 -0
  83. package/src/view/matcher.js +260 -559
  84. package/src/view/node.js +274 -360
  85. package/src/view/observer/arrowkeysobserver.js +19 -28
  86. package/src/view/observer/bubblingemittermixin.js +120 -263
  87. package/src/view/observer/bubblingeventinfo.js +47 -55
  88. package/src/view/observer/clickobserver.js +7 -13
  89. package/src/view/observer/compositionobserver.js +14 -24
  90. package/src/view/observer/domeventdata.js +57 -67
  91. package/src/view/observer/domeventobserver.js +40 -64
  92. package/src/view/observer/fakeselectionobserver.js +81 -96
  93. package/src/view/observer/focusobserver.js +45 -61
  94. package/src/view/observer/inputobserver.js +7 -13
  95. package/src/view/observer/keyobserver.js +17 -27
  96. package/src/view/observer/mouseobserver.js +7 -14
  97. package/src/view/observer/mutationobserver.js +220 -315
  98. package/src/view/observer/observer.js +81 -102
  99. package/src/view/observer/selectionobserver.js +199 -246
  100. package/src/view/observer/tabobserver.js +23 -36
  101. package/src/view/placeholder.js +128 -173
  102. package/src/view/position.js +350 -401
  103. package/src/view/range.js +453 -513
  104. package/src/view/rawelement.js +85 -112
  105. package/src/view/renderer.js +874 -1018
  106. package/src/view/rooteditableelement.js +80 -90
  107. package/src/view/selection.js +608 -689
  108. package/src/view/styles/background.js +43 -44
  109. package/src/view/styles/border.js +220 -276
  110. package/src/view/styles/margin.js +8 -17
  111. package/src/view/styles/padding.js +8 -16
  112. package/src/view/styles/utils.js +127 -160
  113. package/src/view/stylesmap.js +728 -905
  114. package/src/view/text.js +102 -126
  115. package/src/view/textproxy.js +144 -170
  116. package/src/view/treewalker.js +383 -479
  117. package/src/view/typecheckable.js +19 -0
  118. package/src/view/uielement.js +166 -187
  119. package/src/view/upcastwriter.js +395 -449
  120. package/src/view/view.js +569 -664
  121. package/src/dataprocessor/dataprocessor.jsdoc +0 -64
  122. package/src/model/item.jsdoc +0 -14
  123. package/src/view/elementdefinition.jsdoc +0 -59
  124. package/src/view/item.jsdoc +0 -14
@@ -2,17 +2,15 @@
2
2
  * @license Copyright (c) 2003-2022, 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
+ /* eslint-disable new-cap */
6
6
  /**
7
7
  * @module engine/view/documentfragment
8
8
  */
9
-
9
+ import TypeCheckable from './typecheckable';
10
10
  import Text from './text';
11
11
  import TextProxy from './textproxy';
12
- import mix from '@ckeditor/ckeditor5-utils/src/mix';
13
12
  import isIterable from '@ckeditor/ckeditor5-utils/src/isiterable';
14
13
  import EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';
15
-
16
14
  /**
17
15
  * Document fragment.
18
16
  *
@@ -20,254 +18,207 @@ import EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';
20
18
  * {@link module:engine/view/upcastwriter~UpcastWriter#createDocumentFragment `UpcastWriter#createDocumentFragment()`}
21
19
  * method.
22
20
  */
23
- export default class DocumentFragment {
24
- /**
25
- * Creates new DocumentFragment instance.
26
- *
27
- * @protected
28
- * @param {module:engine/view/document~Document} document The document to which this document fragment belongs.
29
- * @param {module:engine/view/node~Node|Iterable.<module:engine/view/node~Node>} [children]
30
- * A list of nodes to be inserted into the created document fragment.
31
- */
32
- constructor( document, children ) {
33
- /**
34
- * The document to which this document fragment belongs.
35
- *
36
- * @readonly
37
- * @member {module:engine/view/document~Document}
38
- */
39
- this.document = document;
40
-
41
- /**
42
- * Array of child nodes.
43
- *
44
- * @protected
45
- * @member {Array.<module:engine/view/element~Element>} module:engine/view/documentfragment~DocumentFragment#_children
46
- */
47
- this._children = [];
48
-
49
- if ( children ) {
50
- this._insertChild( 0, children );
51
- }
52
- }
53
-
54
- /**
55
- * Iterable interface.
56
- *
57
- * Iterates over nodes added to this document fragment.
58
- *
59
- * @returns {Iterable.<module:engine/view/node~Node>}
60
- */
61
- [ Symbol.iterator ]() {
62
- return this._children[ Symbol.iterator ]();
63
- }
64
-
65
- /**
66
- * Number of child nodes in this document fragment.
67
- *
68
- * @readonly
69
- * @type {Number}
70
- */
71
- get childCount() {
72
- return this._children.length;
73
- }
74
-
75
- /**
76
- * Is `true` if there are no nodes inside this document fragment, `false` otherwise.
77
- *
78
- * @readonly
79
- * @type {Boolean}
80
- */
81
- get isEmpty() {
82
- return this.childCount === 0;
83
- }
84
-
85
- /**
86
- * Artificial root of `DocumentFragment`. Returns itself. Added for compatibility reasons.
87
- *
88
- * @readonly
89
- * @type {module:engine/model/documentfragment~DocumentFragment}
90
- */
91
- get root() {
92
- return this;
93
- }
94
-
95
- /**
96
- * Artificial parent of `DocumentFragment`. Returns `null`. Added for compatibility reasons.
97
- *
98
- * @readonly
99
- * @type {null}
100
- */
101
- get parent() {
102
- return null;
103
- }
104
-
105
- /**
106
- * Checks whether this object is of the given type.
107
- *
108
- * docFrag.is( 'documentFragment' ); // -> true
109
- * docFrag.is( 'view:documentFragment' ); // -> true
110
- *
111
- * docFrag.is( 'model:documentFragment' ); // -> false
112
- * docFrag.is( 'element' ); // -> false
113
- * docFrag.is( 'node' ); // -> false
114
- *
115
- * {@link module:engine/view/node~Node#is Check the entire list of view objects} which implement the `is()` method.
116
- *
117
- * @param {String} type
118
- * @returns {Boolean}
119
- */
120
- is( type ) {
121
- return type === 'documentFragment' || type === 'view:documentFragment';
122
- }
123
-
124
- /**
125
- * {@link module:engine/view/documentfragment~DocumentFragment#_insertChild Insert} a child node or a list of child nodes at the end
126
- * and sets the parent of these nodes to this fragment.
127
- *
128
- * @param {module:engine/view/item~Item|Iterable.<module:engine/view/item~Item>} items Items to be inserted.
129
- * @returns {Number} Number of appended nodes.
130
- */
131
- _appendChild( items ) {
132
- return this._insertChild( this.childCount, items );
133
- }
134
-
135
- /**
136
- * Gets child at the given index.
137
- *
138
- * @param {Number} index Index of child.
139
- * @returns {module:engine/view/node~Node} Child node.
140
- */
141
- getChild( index ) {
142
- return this._children[ index ];
143
- }
144
-
145
- /**
146
- * Gets index of the given child node. Returns `-1` if child node is not found.
147
- *
148
- * @param {module:engine/view/node~Node} node Child node.
149
- * @returns {Number} Index of the child node.
150
- */
151
- getChildIndex( node ) {
152
- return this._children.indexOf( node );
153
- }
154
-
155
- /**
156
- * Gets child nodes iterator.
157
- *
158
- * @returns {Iterable.<module:engine/view/node~Node>} Child nodes iterator.
159
- */
160
- getChildren() {
161
- return this._children[ Symbol.iterator ]();
162
- }
163
-
164
- /**
165
- * Inserts a child node or a list of child nodes on the given index and sets the parent of these nodes to
166
- * this fragment.
167
- *
168
- * @param {Number} index Position where nodes should be inserted.
169
- * @param {module:engine/view/item~Item|Iterable.<module:engine/view/item~Item>} items Items to be inserted.
170
- * @returns {Number} Number of inserted nodes.
171
- */
172
- _insertChild( index, items ) {
173
- this._fireChange( 'children', this );
174
- let count = 0;
175
-
176
- const nodes = normalize( this.document, items );
177
-
178
- for ( const node of nodes ) {
179
- // If node that is being added to this element is already inside another element, first remove it from the old parent.
180
- if ( node.parent !== null ) {
181
- node._remove();
182
- }
183
-
184
- node.parent = this;
185
-
186
- this._children.splice( index, 0, node );
187
- index++;
188
- count++;
189
- }
190
-
191
- return count;
192
- }
193
-
194
- /**
195
- * Removes number of child nodes starting at the given index and set the parent of these nodes to `null`.
196
- *
197
- * @param {Number} index Number of the first node to remove.
198
- * @param {Number} [howMany=1] Number of nodes to remove.
199
- * @returns {Array.<module:engine/view/node~Node>} The array of removed nodes.
200
- */
201
- _removeChildren( index, howMany = 1 ) {
202
- this._fireChange( 'children', this );
203
-
204
- for ( let i = index; i < index + howMany; i++ ) {
205
- this._children[ i ].parent = null;
206
- }
207
-
208
- return this._children.splice( index, howMany );
209
- }
210
-
211
- /**
212
- * Fires `change` event with given type of the change.
213
- *
214
- * @private
215
- * @param {module:engine/view/document~ChangeType} type Type of the change.
216
- * @param {module:engine/view/node~Node} node Changed node.
217
- * @fires module:engine/view/node~Node#change
218
- */
219
- _fireChange( type, node ) {
220
- this.fire( 'change:' + type, node );
221
- }
222
-
223
- // @if CK_DEBUG_ENGINE // printTree() {
224
- // @if CK_DEBUG_ENGINE // let string = 'ViewDocumentFragment: [';
225
-
226
- // @if CK_DEBUG_ENGINE // for ( const child of this.getChildren() ) {
227
- // @if CK_DEBUG_ENGINE // if ( child.is( '$text' ) ) {
228
- // @if CK_DEBUG_ENGINE // string += '\n' + '\t'.repeat( 1 ) + child.data;
229
- // @if CK_DEBUG_ENGINE // } else {
230
- // @if CK_DEBUG_ENGINE // string += '\n' + child.printTree( 1 );
231
- // @if CK_DEBUG_ENGINE // }
232
- // @if CK_DEBUG_ENGINE // }
233
-
234
- // @if CK_DEBUG_ENGINE // string += '\n]';
235
-
236
- // @if CK_DEBUG_ENGINE // return string;
237
- // @if CK_DEBUG_ENGINE // }
238
-
239
- // @if CK_DEBUG_ENGINE // logTree() {
240
- // @if CK_DEBUG_ENGINE // console.log( this.printTree() );
241
- // @if CK_DEBUG_ENGINE // }
21
+ export default class DocumentFragment extends EmitterMixin(TypeCheckable) {
22
+ /**
23
+ * Creates new DocumentFragment instance.
24
+ *
25
+ * @protected
26
+ * @param {module:engine/view/document~Document} document The document to which this document fragment belongs.
27
+ * @param {module:engine/view/node~Node|Iterable.<module:engine/view/node~Node>} [children]
28
+ * A list of nodes to be inserted into the created document fragment.
29
+ */
30
+ constructor(document, children) {
31
+ super();
32
+ /**
33
+ * The document to which this document fragment belongs.
34
+ *
35
+ * @readonly
36
+ * @member {module:engine/view/document~Document}
37
+ */
38
+ this.document = document;
39
+ /**
40
+ * Array of child nodes.
41
+ *
42
+ * @protected
43
+ * @member {Array.<module:engine/view/node~Node>} module:engine/view/documentfragment~DocumentFragment#_children
44
+ */
45
+ this._children = [];
46
+ if (children) {
47
+ this._insertChild(0, children);
48
+ }
49
+ }
50
+ /**
51
+ * Iterable interface.
52
+ *
53
+ * Iterates over nodes added to this document fragment.
54
+ *
55
+ * @returns {Iterable.<module:engine/view/node~Node>}
56
+ */
57
+ [Symbol.iterator]() {
58
+ return this._children[Symbol.iterator]();
59
+ }
60
+ /**
61
+ * Number of child nodes in this document fragment.
62
+ *
63
+ * @readonly
64
+ * @type {Number}
65
+ */
66
+ get childCount() {
67
+ return this._children.length;
68
+ }
69
+ /**
70
+ * Is `true` if there are no nodes inside this document fragment, `false` otherwise.
71
+ *
72
+ * @readonly
73
+ * @type {Boolean}
74
+ */
75
+ get isEmpty() {
76
+ return this.childCount === 0;
77
+ }
78
+ /**
79
+ * Artificial root of `DocumentFragment`. Returns itself. Added for compatibility reasons.
80
+ *
81
+ * @readonly
82
+ * @type {module:engine/model/documentfragment~DocumentFragment}
83
+ */
84
+ get root() {
85
+ return this;
86
+ }
87
+ /**
88
+ * Artificial parent of `DocumentFragment`. Returns `null`. Added for compatibility reasons.
89
+ *
90
+ * @readonly
91
+ * @type {null}
92
+ */
93
+ get parent() {
94
+ return null;
95
+ }
96
+ /**
97
+ * {@link module:engine/view/documentfragment~DocumentFragment#_insertChild Insert} a child node or a list of child nodes at the end
98
+ * and sets the parent of these nodes to this fragment.
99
+ *
100
+ * @param {module:engine/view/item~Item|Iterable.<module:engine/view/item~Item>} items Items to be inserted.
101
+ * @returns {Number} Number of appended nodes.
102
+ */
103
+ _appendChild(items) {
104
+ return this._insertChild(this.childCount, items);
105
+ }
106
+ /**
107
+ * Gets child at the given index.
108
+ *
109
+ * @param {Number} index Index of child.
110
+ * @returns {module:engine/view/node~Node} Child node.
111
+ */
112
+ getChild(index) {
113
+ return this._children[index];
114
+ }
115
+ /**
116
+ * Gets index of the given child node. Returns `-1` if child node is not found.
117
+ *
118
+ * @param {module:engine/view/node~Node} node Child node.
119
+ * @returns {Number} Index of the child node.
120
+ */
121
+ getChildIndex(node) {
122
+ return this._children.indexOf(node);
123
+ }
124
+ /**
125
+ * Gets child nodes iterator.
126
+ *
127
+ * @returns {Iterable.<module:engine/view/node~Node>} Child nodes iterator.
128
+ */
129
+ getChildren() {
130
+ return this._children[Symbol.iterator]();
131
+ }
132
+ /**
133
+ * Inserts a child node or a list of child nodes on the given index and sets the parent of these nodes to
134
+ * this fragment.
135
+ *
136
+ * @param {Number} index Position where nodes should be inserted.
137
+ * @param {module:engine/view/item~Item|Iterable.<module:engine/view/item~Item>} items Items to be inserted.
138
+ * @returns {Number} Number of inserted nodes.
139
+ */
140
+ _insertChild(index, items) {
141
+ this._fireChange('children', this);
142
+ let count = 0;
143
+ const nodes = normalize(this.document, items);
144
+ for (const node of nodes) {
145
+ // If node that is being added to this element is already inside another element, first remove it from the old parent.
146
+ if (node.parent !== null) {
147
+ node._remove();
148
+ }
149
+ node.parent = this;
150
+ this._children.splice(index, 0, node);
151
+ index++;
152
+ count++;
153
+ }
154
+ return count;
155
+ }
156
+ /**
157
+ * Removes number of child nodes starting at the given index and set the parent of these nodes to `null`.
158
+ *
159
+ * @internal
160
+ * @param {Number} index Number of the first node to remove.
161
+ * @param {Number} [howMany=1] Number of nodes to remove.
162
+ * @returns {Array.<module:engine/view/node~Node>} The array of removed nodes.
163
+ */
164
+ _removeChildren(index, howMany = 1) {
165
+ this._fireChange('children', this);
166
+ for (let i = index; i < index + howMany; i++) {
167
+ this._children[i].parent = null;
168
+ }
169
+ return this._children.splice(index, howMany);
170
+ }
171
+ /**
172
+ * Fires `change` event with given type of the change.
173
+ *
174
+ * @private
175
+ * @param {module:engine/view/document~ChangeType} type Type of the change.
176
+ * @param {module:engine/view/node~Node} node Changed node.
177
+ * @fires module:engine/view/node~Node#change
178
+ */
179
+ _fireChange(type, node) {
180
+ this.fire('change:' + type, node);
181
+ }
242
182
  }
243
-
244
- mix( DocumentFragment, EmitterMixin );
245
-
183
+ /**
184
+ * Checks whether this object is of the given type.
185
+ *
186
+ * docFrag.is( 'documentFragment' ); // -> true
187
+ * docFrag.is( 'view:documentFragment' ); // -> true
188
+ *
189
+ * docFrag.is( 'model:documentFragment' ); // -> false
190
+ * docFrag.is( 'element' ); // -> false
191
+ * docFrag.is( 'node' ); // -> false
192
+ *
193
+ * {@link module:engine/view/node~Node#is Check the entire list of view objects} which implement the `is()` method.
194
+ *
195
+ * @param {String} type
196
+ * @returns {Boolean}
197
+ */
198
+ DocumentFragment.prototype.is = function (type) {
199
+ return type === 'documentFragment' || type === 'view:documentFragment';
200
+ };
246
201
  // Converts strings to Text and non-iterables to arrays.
247
202
  //
248
203
  // @param {String|module:engine/view/item~Item|Iterable.<String|module:engine/view/item~Item>}
249
204
  // @returns {Iterable.<module:engine/view/node~Node>}
250
- function normalize( document, nodes ) {
251
- // Separate condition because string is iterable.
252
- if ( typeof nodes == 'string' ) {
253
- return [ new Text( document, nodes ) ];
254
- }
255
-
256
- if ( !isIterable( nodes ) ) {
257
- nodes = [ nodes ];
258
- }
259
-
260
- // Array.from to enable .map() on non-arrays.
261
- return Array.from( nodes )
262
- .map( node => {
263
- if ( typeof node == 'string' ) {
264
- return new Text( document, node );
265
- }
266
-
267
- if ( node instanceof TextProxy ) {
268
- return new Text( document, node.data );
269
- }
270
-
271
- return node;
272
- } );
205
+ function normalize(document, nodes) {
206
+ // Separate condition because string is iterable.
207
+ if (typeof nodes == 'string') {
208
+ return [new Text(document, nodes)];
209
+ }
210
+ if (!isIterable(nodes)) {
211
+ nodes = [nodes];
212
+ }
213
+ // Array.from to enable .map() on non-arrays.
214
+ return Array.from(nodes)
215
+ .map(node => {
216
+ if (typeof node == 'string') {
217
+ return new Text(document, node);
218
+ }
219
+ if (node instanceof TextProxy) {
220
+ return new Text(document, node.data);
221
+ }
222
+ return node;
223
+ });
273
224
  }