@ckeditor/ckeditor5-engine 34.2.0 → 35.1.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 (125) hide show
  1. package/CHANGELOG.md +823 -0
  2. package/LICENSE.md +4 -0
  3. package/package.json +32 -25
  4. package/src/controller/datacontroller.js +467 -561
  5. package/src/controller/editingcontroller.js +168 -204
  6. package/src/conversion/conversion.js +541 -565
  7. package/src/conversion/conversionhelpers.js +24 -28
  8. package/src/conversion/downcastdispatcher.js +457 -686
  9. package/src/conversion/downcasthelpers.js +1583 -1965
  10. package/src/conversion/mapper.js +518 -707
  11. package/src/conversion/modelconsumable.js +240 -283
  12. package/src/conversion/upcastdispatcher.js +372 -718
  13. package/src/conversion/upcasthelpers.js +707 -818
  14. package/src/conversion/viewconsumable.js +524 -581
  15. package/src/dataprocessor/basichtmlwriter.js +12 -16
  16. package/src/dataprocessor/dataprocessor.js +5 -0
  17. package/src/dataprocessor/htmldataprocessor.js +101 -117
  18. package/src/dataprocessor/htmlwriter.js +1 -18
  19. package/src/dataprocessor/xmldataprocessor.js +117 -138
  20. package/src/dev-utils/model.js +260 -352
  21. package/src/dev-utils/operationreplayer.js +106 -126
  22. package/src/dev-utils/utils.js +34 -51
  23. package/src/dev-utils/view.js +632 -753
  24. package/src/index.js +0 -11
  25. package/src/model/batch.js +111 -127
  26. package/src/model/differ.js +988 -1233
  27. package/src/model/document.js +340 -449
  28. package/src/model/documentfragment.js +327 -364
  29. package/src/model/documentselection.js +996 -1189
  30. package/src/model/element.js +306 -410
  31. package/src/model/history.js +224 -262
  32. package/src/model/item.js +5 -0
  33. package/src/model/liveposition.js +84 -145
  34. package/src/model/liverange.js +108 -185
  35. package/src/model/markercollection.js +379 -480
  36. package/src/model/model.js +883 -1034
  37. package/src/model/node.js +419 -463
  38. package/src/model/nodelist.js +175 -201
  39. package/src/model/operation/attributeoperation.js +153 -182
  40. package/src/model/operation/detachoperation.js +64 -83
  41. package/src/model/operation/insertoperation.js +135 -166
  42. package/src/model/operation/markeroperation.js +114 -140
  43. package/src/model/operation/mergeoperation.js +163 -191
  44. package/src/model/operation/moveoperation.js +157 -187
  45. package/src/model/operation/nooperation.js +28 -38
  46. package/src/model/operation/operation.js +106 -125
  47. package/src/model/operation/operationfactory.js +30 -34
  48. package/src/model/operation/renameoperation.js +109 -135
  49. package/src/model/operation/rootattributeoperation.js +155 -188
  50. package/src/model/operation/splitoperation.js +196 -232
  51. package/src/model/operation/transform.js +1833 -2204
  52. package/src/model/operation/utils.js +140 -204
  53. package/src/model/position.js +899 -1053
  54. package/src/model/range.js +910 -1028
  55. package/src/model/rootelement.js +77 -97
  56. package/src/model/schema.js +1189 -1835
  57. package/src/model/selection.js +745 -862
  58. package/src/model/text.js +90 -114
  59. package/src/model/textproxy.js +204 -240
  60. package/src/model/treewalker.js +316 -397
  61. package/src/model/typecheckable.js +16 -0
  62. package/src/model/utils/autoparagraphing.js +32 -44
  63. package/src/model/utils/deletecontent.js +334 -418
  64. package/src/model/utils/findoptimalinsertionrange.js +25 -36
  65. package/src/model/utils/getselectedcontent.js +96 -118
  66. package/src/model/utils/insertcontent.js +654 -773
  67. package/src/model/utils/insertobject.js +96 -119
  68. package/src/model/utils/modifyselection.js +120 -158
  69. package/src/model/utils/selection-post-fixer.js +153 -201
  70. package/src/model/writer.js +1305 -1474
  71. package/src/view/attributeelement.js +189 -225
  72. package/src/view/containerelement.js +75 -85
  73. package/src/view/document.js +172 -215
  74. package/src/view/documentfragment.js +200 -249
  75. package/src/view/documentselection.js +338 -367
  76. package/src/view/domconverter.js +1371 -1613
  77. package/src/view/downcastwriter.js +1747 -2076
  78. package/src/view/editableelement.js +81 -97
  79. package/src/view/element.js +739 -890
  80. package/src/view/elementdefinition.js +5 -0
  81. package/src/view/emptyelement.js +82 -92
  82. package/src/view/filler.js +35 -50
  83. package/src/view/item.js +5 -0
  84. package/src/view/matcher.js +260 -559
  85. package/src/view/node.js +274 -360
  86. package/src/view/observer/arrowkeysobserver.js +19 -28
  87. package/src/view/observer/bubblingemittermixin.js +120 -263
  88. package/src/view/observer/bubblingeventinfo.js +47 -55
  89. package/src/view/observer/clickobserver.js +7 -13
  90. package/src/view/observer/compositionobserver.js +14 -24
  91. package/src/view/observer/domeventdata.js +57 -67
  92. package/src/view/observer/domeventobserver.js +40 -64
  93. package/src/view/observer/fakeselectionobserver.js +81 -96
  94. package/src/view/observer/focusobserver.js +45 -61
  95. package/src/view/observer/inputobserver.js +7 -13
  96. package/src/view/observer/keyobserver.js +17 -27
  97. package/src/view/observer/mouseobserver.js +7 -14
  98. package/src/view/observer/mutationobserver.js +220 -315
  99. package/src/view/observer/observer.js +81 -102
  100. package/src/view/observer/selectionobserver.js +191 -246
  101. package/src/view/observer/tabobserver.js +23 -36
  102. package/src/view/placeholder.js +128 -173
  103. package/src/view/position.js +350 -401
  104. package/src/view/range.js +453 -513
  105. package/src/view/rawelement.js +85 -112
  106. package/src/view/renderer.js +874 -1014
  107. package/src/view/rooteditableelement.js +80 -90
  108. package/src/view/selection.js +608 -689
  109. package/src/view/styles/background.js +43 -44
  110. package/src/view/styles/border.js +220 -276
  111. package/src/view/styles/margin.js +8 -17
  112. package/src/view/styles/padding.js +8 -16
  113. package/src/view/styles/utils.js +127 -160
  114. package/src/view/stylesmap.js +728 -905
  115. package/src/view/text.js +102 -126
  116. package/src/view/textproxy.js +144 -170
  117. package/src/view/treewalker.js +383 -479
  118. package/src/view/typecheckable.js +19 -0
  119. package/src/view/uielement.js +166 -187
  120. package/src/view/upcastwriter.js +395 -449
  121. package/src/view/view.js +569 -664
  122. package/src/dataprocessor/dataprocessor.jsdoc +0 -64
  123. package/src/model/item.jsdoc +0 -14
  124. package/src/view/elementdefinition.jsdoc +0 -59
  125. 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
  }