@ckeditor/ckeditor5-engine 46.0.3 → 46.1.0-alpha.1

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 (48) hide show
  1. package/dist/index.js +250 -11
  2. package/dist/index.js.map +1 -1
  3. package/package.json +2 -2
  4. package/src/index.d.ts +4 -2
  5. package/src/index.js +3 -1
  6. package/src/model/documentselection.d.ts +6 -0
  7. package/src/model/documentselection.js +20 -0
  8. package/src/model/markercollection.d.ts +6 -0
  9. package/src/model/markercollection.js +13 -0
  10. package/src/model/range.d.ts +1 -1
  11. package/src/model/range.js +1 -1
  12. package/src/model/selection.d.ts +6 -0
  13. package/src/model/selection.js +18 -0
  14. package/src/view/attributeelement.d.ts +6 -0
  15. package/src/view/attributeelement.js +10 -0
  16. package/src/view/containerelement.d.ts +6 -0
  17. package/src/view/containerelement.js +10 -0
  18. package/src/view/documentfragment.d.ts +7 -0
  19. package/src/view/documentfragment.js +13 -0
  20. package/src/view/documentselection.d.ts +6 -0
  21. package/src/view/documentselection.js +8 -0
  22. package/src/view/domconverter.js +4 -2
  23. package/src/view/editableelement.d.ts +6 -0
  24. package/src/view/editableelement.js +12 -0
  25. package/src/view/element.d.ts +6 -0
  26. package/src/view/element.js +20 -0
  27. package/src/view/emptyelement.d.ts +6 -0
  28. package/src/view/emptyelement.js +10 -0
  29. package/src/view/node.d.ts +2 -2
  30. package/src/view/node.js +9 -6
  31. package/src/view/observer/pointerobserver.d.ts +76 -0
  32. package/src/view/observer/pointerobserver.js +26 -0
  33. package/src/view/observer/selectionobserver.d.ts +4 -4
  34. package/src/view/observer/selectionobserver.js +22 -1
  35. package/src/view/position.d.ts +6 -0
  36. package/src/view/position.js +11 -0
  37. package/src/view/range.d.ts +6 -0
  38. package/src/view/range.js +11 -0
  39. package/src/view/rawelement.d.ts +6 -0
  40. package/src/view/rawelement.js +10 -0
  41. package/src/view/rooteditableelement.d.ts +6 -0
  42. package/src/view/rooteditableelement.js +8 -0
  43. package/src/view/selection.d.ts +6 -0
  44. package/src/view/selection.js +17 -0
  45. package/src/view/text.d.ts +6 -0
  46. package/src/view/text.js +11 -0
  47. package/src/view/uielement.d.ts +6 -0
  48. package/src/view/uielement.js +10 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ckeditor/ckeditor5-engine",
3
- "version": "46.0.3",
3
+ "version": "46.1.0-alpha.1",
4
4
  "description": "The editing engine of CKEditor 5 – the best browser-based rich text editor.",
5
5
  "keywords": [
6
6
  "wysiwyg",
@@ -24,7 +24,7 @@
24
24
  "type": "module",
25
25
  "main": "src/index.js",
26
26
  "dependencies": {
27
- "@ckeditor/ckeditor5-utils": "46.0.3",
27
+ "@ckeditor/ckeditor5-utils": "46.1.0-alpha.1",
28
28
  "es-toolkit": "1.39.5"
29
29
  },
30
30
  "author": "CKSource (http://cksource.com/)",
package/src/index.d.ts CHANGED
@@ -15,7 +15,7 @@ export type { UpcastDispatcher, UpcastConversionApi, UpcastConversionData, Upcas
15
15
  export { UpcastHelpers } from './conversion/upcasthelpers.js';
16
16
  export { DowncastHelpers, type DowncastStructureCreatorFunction, type DowncastAttributeElementCreatorFunction, type DowncastElementCreatorFunction, type DowncastHighlightDescriptor, type DowncastSlotFilter, type DowncastAttributeDescriptor, type DowncastMarkerElementCreatorFunction, type DowncastAddHighlightCallback, type DowncastHighlightDescriptorCreatorFunction, type DowncastRemoveHighlightCallback, type DowncastMarkerDataCreatorFunction, type DowncastAttributeCreatorFunction } from './conversion/downcasthelpers.js';
17
17
  export type { UpcastElementCreatorFunction, UpcastAttributeCreatorFunction, UpcastMarkerFromElementCreatorFunction, UpcastMarkerFromAttributeCreatorFunction } from './conversion/upcasthelpers.js';
18
- export type { Mapper, MapperModelToViewPositionEvent, MapperViewToModelPositionEvent, MapperModelToViewPositionEventData, MapperViewToModelPositionEventData } from './conversion/mapper.js';
18
+ export { Mapper, type MapperModelToViewPositionEvent, type MapperViewToModelPositionEvent, type MapperModelToViewPositionEventData, type MapperViewToModelPositionEventData } from './conversion/mapper.js';
19
19
  export type { ModelConsumable } from './conversion/modelconsumable.js';
20
20
  export type { Consumables, ViewConsumable } from './conversion/viewconsumable.js';
21
21
  export type { DataProcessor } from './dataprocessor/dataprocessor.js';
@@ -55,7 +55,7 @@ export type { ModelItem } from './model/item.js';
55
55
  export { ModelNode, type ModelNodeAttributes } from './model/node.js';
56
56
  export { ModelNodeList } from './model/nodelist.js';
57
57
  export { ModelRootElement } from './model/rootelement.js';
58
- export { ModelSchemaContext, type ModelSchema, type ModelSchemaCheckChildEvent, type ModelSchemaCheckAttributeEvent, type ModelSchemaAttributeCheckCallback, type ModelSchemaChildCheckCallback, type ModelAttributeProperties, type ModelSchemaItemDefinition, type ModelSchemaCompiledItemDefinition, type ModelSchemaContextDefinition, type ModelSchemaContextItem } from './model/schema.js';
58
+ export { ModelSchema, ModelSchemaContext, type ModelSchemaCheckChildEvent, type ModelSchemaCheckAttributeEvent, type ModelSchemaAttributeCheckCallback, type ModelSchemaChildCheckCallback, type ModelAttributeProperties, type ModelSchemaItemDefinition, type ModelSchemaCompiledItemDefinition, type ModelSchemaContextDefinition, type ModelSchemaContextItem } from './model/schema.js';
59
59
  export { ModelSelection, type ModelSelectionChangeEvent, type ModelSelectionChangeRangeEvent, type ModelSelectionChangeAttributeEvent, type ModelSelectable, type ModelPlaceOrOffset } from './model/selection.js';
60
60
  export { ModelTypeCheckable } from './model/typecheckable.js';
61
61
  export { ModelWriter } from './model/writer.js';
@@ -95,6 +95,7 @@ export { DomEventObserver } from './view/observer/domeventobserver.js';
95
95
  export { MouseObserver } from './view/observer/mouseobserver.js';
96
96
  export { TabObserver } from './view/observer/tabobserver.js';
97
97
  export { TouchObserver } from './view/observer/touchobserver.js';
98
+ export { PointerObserver } from './view/observer/pointerobserver.js';
98
99
  export { FakeSelectionObserver } from './view/observer/fakeselectionobserver.js';
99
100
  export { KeyObserver, type ViewDocumentKeyDownEvent, type ViewDocumentKeyUpEvent, type ViewDocumentKeyEventData } from './view/observer/keyobserver.js';
100
101
  export { MutationObserver, type ViewDocumentMutationEventData, type ObserverMutationData } from './view/observer/mutationobserver.js';
@@ -114,6 +115,7 @@ export type { ViewDocumentMutationsEvent } from './view/observer/mutationobserve
114
115
  export type { ViewDocumentLayoutChangedEvent } from './view/document.js';
115
116
  export type { ViewDocumentMouseDownEvent, ViewDocumentMouseUpEvent, ViewDocumentMouseOverEvent, ViewDocumentMouseOutEvent } from './view/observer/mouseobserver.js';
116
117
  export type { ViewDocumentTouchEndEvent, ViewDocumentTouchMoveEvent, ViewDocumentTouchStartEvent } from './view/observer/touchobserver.js';
118
+ export type { ViewDocumentPointerDownEvent, ViewDocumentPointerMoveEvent, ViewDocumentPointerUpEvent } from './view/observer/pointerobserver.js';
117
119
  export type { ViewDocumentTabEvent } from './view/observer/tabobserver.js';
118
120
  export type { ViewDocumentClickEvent } from './view/observer/clickobserver.js';
119
121
  export type { ViewDocumentObserverSelectionChangeEvent, ViewDocumentObserverSelectionChangeDoneEvent } from './view/observer/selectionobserver.js';
package/src/index.js CHANGED
@@ -14,6 +14,7 @@ export { Conversion } from './conversion/conversion.js';
14
14
  export { ConversionHelpers } from './conversion/conversionhelpers.js';
15
15
  export { UpcastHelpers } from './conversion/upcasthelpers.js';
16
16
  export { DowncastHelpers } from './conversion/downcasthelpers.js';
17
+ export { Mapper } from './conversion/mapper.js';
17
18
  export { HtmlDataProcessor } from './dataprocessor/htmldataprocessor.js';
18
19
  export { XmlDataProcessor } from './dataprocessor/xmldataprocessor.js';
19
20
  export { InsertOperation } from './model/operation/insertoperation.js';
@@ -48,7 +49,7 @@ export { Differ } from './model/differ.js';
48
49
  export { ModelNode } from './model/node.js';
49
50
  export { ModelNodeList } from './model/nodelist.js';
50
51
  export { ModelRootElement } from './model/rootelement.js';
51
- export { ModelSchemaContext } from './model/schema.js';
52
+ export { ModelSchema, ModelSchemaContext } from './model/schema.js';
52
53
  export { ModelSelection } from './model/selection.js';
53
54
  export { ModelTypeCheckable } from './model/typecheckable.js';
54
55
  export { ModelWriter } from './model/writer.js';
@@ -86,6 +87,7 @@ export { DomEventObserver } from './view/observer/domeventobserver.js';
86
87
  export { MouseObserver } from './view/observer/mouseobserver.js';
87
88
  export { TabObserver } from './view/observer/tabobserver.js';
88
89
  export { TouchObserver } from './view/observer/touchobserver.js';
90
+ export { PointerObserver } from './view/observer/pointerobserver.js';
89
91
  export { FakeSelectionObserver } from './view/observer/fakeselectionobserver.js';
90
92
  export { KeyObserver } from './view/observer/keyobserver.js';
91
93
  export { MutationObserver } from './view/observer/mutationobserver.js';
@@ -259,6 +259,12 @@ export declare class ModelDocumentSelection extends /* #__PURE__ */ ModelDocumen
259
259
  * @param prefixOrName The marker group prefix or marker name.
260
260
  */
261
261
  observeMarkers(prefixOrName: string): void;
262
+ /**
263
+ * Converts `DocumentSelection` to plain object and returns it.
264
+ *
265
+ * @returns `DocumentSelection` converted to plain object.
266
+ */
267
+ toJSON(): unknown;
262
268
  /**
263
269
  * Moves {@link module:engine/model/documentselection~ModelDocumentSelection#focus} to the specified location.
264
270
  * Should be used only within the {@link module:engine/model/writer~ModelWriter#setSelectionFocus} method.
@@ -311,6 +311,14 @@ export class ModelDocumentSelection extends /* #__PURE__ */ EmitterMixin(ModelTy
311
311
  observeMarkers(prefixOrName) {
312
312
  this._selection.observeMarkers(prefixOrName);
313
313
  }
314
+ /**
315
+ * Converts `DocumentSelection` to plain object and returns it.
316
+ *
317
+ * @returns `DocumentSelection` converted to plain object.
318
+ */
319
+ toJSON() {
320
+ return this._selection.toJSON();
321
+ }
314
322
  /**
315
323
  * Moves {@link module:engine/model/documentselection~ModelDocumentSelection#focus} to the specified location.
316
324
  * Should be used only within the {@link module:engine/model/writer~ModelWriter#setSelectionFocus} method.
@@ -642,6 +650,18 @@ class LiveSelection extends ModelSelection {
642
650
  this._ranges.push(liveRange);
643
651
  }
644
652
  }
653
+ /**
654
+ * Converts `LiveSelection` to plain object and returns it.
655
+ *
656
+ * @returns `LiveSelection` converted to plain object.
657
+ */
658
+ toJSON() {
659
+ const json = super.toJSON();
660
+ if (this.markers.length) {
661
+ json.markers = this.markers.map(marker => marker.toJSON());
662
+ }
663
+ return json;
664
+ }
645
665
  _validateSelectionRanges(ranges) {
646
666
  for (const range of ranges) {
647
667
  if (!this._document._validateSelectionRange(range)) {
@@ -270,6 +270,12 @@ declare class Marker extends /* #__PURE__ */ Marker_base {
270
270
  * that it's data is up-to-date.
271
271
  */
272
272
  getRange(): ModelRange;
273
+ /**
274
+ * Converts `Marker` to plain object and returns it.
275
+ *
276
+ * @returns `Marker` converted to plain object.
277
+ */
278
+ toJSON(): unknown;
273
279
  /**
274
280
  * Binds new live range to the marker and detach the old one if is attached.
275
281
  *
@@ -381,6 +381,19 @@ class Marker extends /* #__PURE__ */ EmitterMixin(ModelTypeCheckable) {
381
381
  }
382
382
  return this._liveRange.toRange();
383
383
  }
384
+ /**
385
+ * Converts `Marker` to plain object and returns it.
386
+ *
387
+ * @returns `Marker` converted to plain object.
388
+ */
389
+ toJSON() {
390
+ return {
391
+ name: this.name,
392
+ range: this._liveRange?.toJSON(),
393
+ usingOperations: this._managedUsingOperations,
394
+ affectsData: this._affectsData
395
+ };
396
+ }
384
397
  /**
385
398
  * Binds new live range to the marker and detach the old one if is attached.
386
399
  *
@@ -308,7 +308,7 @@ export declare class ModelRange extends ModelTypeCheckable implements Iterable<M
308
308
  /**
309
309
  * Converts `Range` to plain object and returns it.
310
310
  *
311
- * @returns `Node` converted to plain object.
311
+ * @returns `Range` converted to plain object.
312
312
  */
313
313
  toJSON(): unknown;
314
314
  /**
@@ -488,7 +488,7 @@ export class ModelRange extends ModelTypeCheckable {
488
488
  /**
489
489
  * Converts `Range` to plain object and returns it.
490
490
  *
491
- * @returns `Node` converted to plain object.
491
+ * @returns `Range` converted to plain object.
492
492
  */
493
493
  toJSON() {
494
494
  return {
@@ -391,6 +391,12 @@ export declare class ModelSelection extends /* #__PURE__ */ ModelSelection_base
391
391
  * Useful to check if e.g. the user has just pressed <kbd>Ctrl</kbd> + <kbd>A</kbd>.
392
392
  */
393
393
  containsEntireContent(element?: ModelElement): boolean;
394
+ /**
395
+ * Converts `Selection` to plain object and returns it.
396
+ *
397
+ * @returns `Selection` converted to plain object.
398
+ */
399
+ toJSON(): unknown;
394
400
  /**
395
401
  * Adds given range to internal {@link #_ranges ranges array}. Throws an error
396
402
  * if given range is intersecting with any range that is already stored in this selection.
@@ -617,6 +617,24 @@ export class ModelSelection extends /* #__PURE__ */ EmitterMixin(ModelTypeChecka
617
617
  return limitStartPosition.isTouching(this.getFirstPosition()) &&
618
618
  limitEndPosition.isTouching(this.getLastPosition());
619
619
  }
620
+ /**
621
+ * Converts `Selection` to plain object and returns it.
622
+ *
623
+ * @returns `Selection` converted to plain object.
624
+ */
625
+ toJSON() {
626
+ const json = {
627
+ ranges: Array.from(this.getRanges()).map(range => range.toJSON())
628
+ };
629
+ const attributes = Object.fromEntries(this.getAttributes());
630
+ if (Object.keys(attributes).length) {
631
+ json.attributes = attributes;
632
+ }
633
+ if (this.isBackward) {
634
+ json.isBackward = true;
635
+ }
636
+ return json;
637
+ }
620
638
  /**
621
639
  * Adds given range to internal {@link #_ranges ranges array}. Throws an error
622
640
  * if given range is intersecting with any range that is already stored in this selection.
@@ -96,6 +96,12 @@ export declare class ViewAttributeElement extends ViewElement {
96
96
  * * etc.
97
97
  */
98
98
  isSimilar(otherElement: ViewElement): boolean;
99
+ /**
100
+ * Converts `ViewAttributeElement` instance to plain object and returns it.
101
+ *
102
+ * @returns `ViewAttributeElement` instance converted to plain object.
103
+ */
104
+ toJSON(): unknown;
99
105
  /**
100
106
  * Clones provided element with priority.
101
107
  *
@@ -120,6 +120,16 @@ class ViewAttributeElement extends ViewElement {
120
120
  }
121
121
  return super.isSimilar(otherElement) && this.priority == otherElement.priority;
122
122
  }
123
+ /**
124
+ * Converts `ViewAttributeElement` instance to plain object and returns it.
125
+ *
126
+ * @returns `ViewAttributeElement` instance converted to plain object.
127
+ */
128
+ toJSON() {
129
+ const json = super.toJSON();
130
+ json.type = 'AttributeElement';
131
+ return json;
132
+ }
123
133
  /**
124
134
  * Clones provided element with priority.
125
135
  *
@@ -41,6 +41,12 @@ export declare class ViewContainerElement extends ViewElement {
41
41
  * @param children A list of nodes to be inserted into created element.
42
42
  */
43
43
  constructor(document: ViewDocument, name: string, attrs?: ViewElementAttributes, children?: ViewNode | Iterable<ViewNode>);
44
+ /**
45
+ * Converts `ViewContainerElement` instance to plain object and returns it.
46
+ *
47
+ * @returns `ViewContainerElement` instance converted to plain object.
48
+ */
49
+ toJSON(): unknown;
44
50
  }
45
51
  /**
46
52
  * Returns block {@link module:engine/view/filler filler} offset or `null` if block filler is not needed.
@@ -42,6 +42,16 @@ export class ViewContainerElement extends ViewElement {
42
42
  super(document, name, attrs, children);
43
43
  this.getFillerOffset = getViewFillerOffset;
44
44
  }
45
+ /**
46
+ * Converts `ViewContainerElement` instance to plain object and returns it.
47
+ *
48
+ * @returns `ViewContainerElement` instance converted to plain object.
49
+ */
50
+ toJSON() {
51
+ const json = super.toJSON();
52
+ json.type = 'ContainerElement';
53
+ return json;
54
+ }
45
55
  }
46
56
  // The magic of type inference using `is` method is centralized in `TypeCheckable` class.
47
57
  // Proper overload would interfere with that.
@@ -78,6 +78,13 @@ export declare class ViewDocumentFragment extends /* #__PURE__ */ ViewDocumentFr
78
78
  * Iterator provides `[ key, value ]` pairs for each stored property.
79
79
  */
80
80
  getCustomProperties(): Iterable<[string | symbol, unknown]>;
81
+ /**
82
+ * Converts `ViewDocumentFragment` instance to plain object and returns it.
83
+ * Takes care of converting all of this document fragment's children.
84
+ *
85
+ * @returns `ViewDocumentFragment` instance converted to plain object.
86
+ */
87
+ toJSON(): unknown;
81
88
  /**
82
89
  * {@link module:engine/view/documentfragment~ViewDocumentFragment#_insertChild Insert} a child node or a list of child nodes at the end
83
90
  * and sets the parent of these nodes to this fragment.
@@ -101,6 +101,19 @@ export class ViewDocumentFragment extends /* #__PURE__ */ EmitterMixin(ViewTypeC
101
101
  *getCustomProperties() {
102
102
  yield* this._customProperties.entries();
103
103
  }
104
+ /**
105
+ * Converts `ViewDocumentFragment` instance to plain object and returns it.
106
+ * Takes care of converting all of this document fragment's children.
107
+ *
108
+ * @returns `ViewDocumentFragment` instance converted to plain object.
109
+ */
110
+ toJSON() {
111
+ const json = [];
112
+ for (const node of this._children) {
113
+ json.push(node.toJSON());
114
+ }
115
+ return json;
116
+ }
104
117
  /**
105
118
  * {@link module:engine/view/documentfragment~ViewDocumentFragment#_insertChild Insert} a child node or a list of child nodes at the end
106
119
  * and sets the parent of these nodes to this fragment.
@@ -222,6 +222,12 @@ export declare class ViewDocumentSelection extends /* #__PURE__ */ ViewDocumentS
222
222
  * @returns `true` if selections are similar, `false` otherwise.
223
223
  */
224
224
  isSimilar(otherSelection: ViewSelection | ViewDocumentSelection): boolean;
225
+ /**
226
+ * Converts `ViewDocumentSelection` instance to plain object and returns it.
227
+ *
228
+ * @returns `ViewDocumentSelection` instance converted to plain object.
229
+ */
230
+ toJSON(): unknown;
225
231
  /**
226
232
  * Sets this selection's ranges and direction to the specified location based on the given
227
233
  * {@link module:engine/view/selection~ViewSelectable selectable}.
@@ -171,6 +171,14 @@ export class ViewDocumentSelection extends /* #__PURE__ */ EmitterMixin(ViewType
171
171
  isSimilar(otherSelection) {
172
172
  return this._selection.isSimilar(otherSelection);
173
173
  }
174
+ /**
175
+ * Converts `ViewDocumentSelection` instance to plain object and returns it.
176
+ *
177
+ * @returns `ViewDocumentSelection` instance converted to plain object.
178
+ */
179
+ toJSON() {
180
+ return this._selection.toJSON();
181
+ }
174
182
  /**
175
183
  * Sets this selection's ranges and direction to the specified location based on the given
176
184
  * {@link module:engine/view/selection~ViewSelectable selectable}.
@@ -872,7 +872,7 @@ export class ViewDomConverter {
872
872
  const { scrollLeft, scrollTop } = node;
873
873
  scrollPositions.push([scrollLeft, scrollTop]);
874
874
  });
875
- domEditable.focus();
875
+ domEditable.focus({ preventScroll: true });
876
876
  // Restore scrollLeft and scrollTop values starting from domEditable up to
877
877
  // document#documentElement.
878
878
  // https://github.com/ckeditor/ckeditor5-engine/issues/951
@@ -1412,7 +1412,9 @@ export class ViewDomConverter {
1412
1412
  }
1413
1413
  // ViewContainerElement is found on a way to next ViewText node, so given `node` was first/last
1414
1414
  // text node in its container element.
1415
- else if (item.is('containerElement')) {
1415
+ // The ol, ul, and li elements are rendered as an attribute element so we should check list of known block elements.
1416
+ // See: https://github.com/ckeditor/ckeditor5/issues/18960.
1417
+ else if (item.is('containerElement') || this._isBlockViewElement(item)) {
1416
1418
  return null;
1417
1419
  }
1418
1420
  }
@@ -58,5 +58,11 @@ export declare class ViewEditableElement extends /* #__PURE__ */ ViewEditableEle
58
58
  */
59
59
  constructor(document: ViewDocument, name: string, attributes?: ViewElementAttributes, children?: ViewNode | Iterable<ViewNode>);
60
60
  destroy(): void;
61
+ /**
62
+ * Converts `ViewEditableElement` instance to plain object and returns it.
63
+ *
64
+ * @returns `ViewEditableElement` instance converted to plain object.
65
+ */
66
+ toJSON(): unknown;
61
67
  }
62
68
  export {};
@@ -42,6 +42,18 @@ export class ViewEditableElement extends /* #__PURE__ */ ObservableMixin(ViewCon
42
42
  destroy() {
43
43
  this.stopListening();
44
44
  }
45
+ /**
46
+ * Converts `ViewEditableElement` instance to plain object and returns it.
47
+ *
48
+ * @returns `ViewEditableElement` instance converted to plain object.
49
+ */
50
+ toJSON() {
51
+ const json = super.toJSON();
52
+ json.type = 'EditableElement';
53
+ json.isReadOnly = this.isReadOnly;
54
+ json.isFocused = this.isFocused;
55
+ return json;
56
+ }
45
57
  }
46
58
  // The magic of type inference using `is` method is centralized in `TypeCheckable` class.
47
59
  // Proper overload would interfere with that.
@@ -299,6 +299,12 @@ export declare class ViewElement extends ViewNode {
299
299
  * @param attributeName The name of the attribute to be checked.
300
300
  */
301
301
  shouldRenderUnsafeAttribute(attributeName: string): boolean;
302
+ /**
303
+ * Converts `ViewElement` to plain object and returns it.
304
+ *
305
+ * @returns `ViewElement` converted to plain object.
306
+ */
307
+ toJSON(): unknown;
302
308
  /**
303
309
  * Clones provided element.
304
310
  *
@@ -442,6 +442,26 @@ export class ViewElement extends ViewNode {
442
442
  shouldRenderUnsafeAttribute(attributeName) {
443
443
  return this._unsafeAttributesToRender.includes(attributeName);
444
444
  }
445
+ /**
446
+ * Converts `ViewElement` to plain object and returns it.
447
+ *
448
+ * @returns `ViewElement` converted to plain object.
449
+ */
450
+ toJSON() {
451
+ const json = super.toJSON();
452
+ json.name = this.name;
453
+ json.type = 'Element';
454
+ if (this._attrs.size) {
455
+ json.attributes = Object.fromEntries(this.getAttributes());
456
+ }
457
+ if (this._children.length > 0) {
458
+ json.children = [];
459
+ for (const node of this._children) {
460
+ json.children.push(node.toJSON());
461
+ }
462
+ }
463
+ return json;
464
+ }
445
465
  /**
446
466
  * Clones provided element.
447
467
  *
@@ -30,6 +30,12 @@ export declare class ViewEmptyElement extends ViewElement {
30
30
  * @param children A list of nodes to be inserted into created element.
31
31
  */
32
32
  constructor(document: ViewDocument, name: string, attributes?: ViewElementAttributes, children?: ViewNode | Iterable<ViewNode>);
33
+ /**
34
+ * Converts `ViewEmptyElement` instance to plain object and returns it.
35
+ *
36
+ * @returns `ViewEmptyElement` instance converted to plain object.
37
+ */
38
+ toJSON(): unknown;
33
39
  /**
34
40
  * Overrides {@link module:engine/view/element~ViewElement#_insertChild} method.
35
41
  * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `view-emptyelement-cannot-add` to prevent
@@ -32,6 +32,16 @@ export class ViewEmptyElement extends ViewElement {
32
32
  super(document, name, attributes, children);
33
33
  this.getFillerOffset = getFillerOffset;
34
34
  }
35
+ /**
36
+ * Converts `ViewEmptyElement` instance to plain object and returns it.
37
+ *
38
+ * @returns `ViewEmptyElement` instance converted to plain object.
39
+ */
40
+ toJSON() {
41
+ const json = super.toJSON();
42
+ json.type = 'EmptyElement';
43
+ return json;
44
+ }
35
45
  /**
36
46
  * Overrides {@link module:engine/view/element~ViewElement#_insertChild} method.
37
47
  * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `view-emptyelement-cannot-add` to prevent
@@ -129,9 +129,9 @@ export declare abstract class ViewNode extends /* #__PURE__ */ ViewNode_base {
129
129
  index: number;
130
130
  }): void;
131
131
  /**
132
- * Custom toJSON method to solve child-parent circular dependencies.
132
+ * Converts `ViewNode` to plain object and returns it.
133
133
  *
134
- * @returns Clone of this object with the parent property removed.
134
+ * @returns `ViewNode` converted to plain object.
135
135
  */
136
136
  toJSON(): unknown;
137
137
  /**
package/src/view/node.js CHANGED
@@ -7,7 +7,6 @@
7
7
  */
8
8
  import { ViewTypeCheckable } from './typecheckable.js';
9
9
  import { CKEditorError, EmitterMixin, compareArrays } from '@ckeditor/ckeditor5-utils';
10
- import { clone } from 'es-toolkit/compat';
11
10
  /**
12
11
  * Abstract view node class.
13
12
  *
@@ -217,14 +216,18 @@ export class ViewNode extends /* #__PURE__ */ EmitterMixin(ViewTypeCheckable) {
217
216
  }
218
217
  }
219
218
  /**
220
- * Custom toJSON method to solve child-parent circular dependencies.
219
+ * Converts `ViewNode` to plain object and returns it.
221
220
  *
222
- * @returns Clone of this object with the parent property removed.
221
+ * @returns `ViewNode` converted to plain object.
223
222
  */
224
223
  toJSON() {
225
- const json = clone(this);
226
- // Due to circular references we need to remove parent reference.
227
- delete json.parent;
224
+ const json = {
225
+ path: this.getPath(),
226
+ type: 'Node'
227
+ };
228
+ if (this !== this.root && this.root.is('rootElement')) {
229
+ json.root = this.root.toJSON();
230
+ }
228
231
  return json;
229
232
  }
230
233
  }
@@ -0,0 +1,76 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
4
+ */
5
+ /**
6
+ * @module engine/view/observer/pointerobserver
7
+ */
8
+ import { DomEventObserver } from './domeventobserver.js';
9
+ import { type ViewDocumentDomEventData } from './domeventdata.js';
10
+ /**
11
+ * Pointer events observer.
12
+ *
13
+ * Note that this observer is not available by default. To make it available it needs to be added to
14
+ * {@link module:engine/view/view~EditingView} by {@link module:engine/view/view~EditingView#addObserver} method.
15
+ */
16
+ export declare class PointerObserver extends DomEventObserver<'pointerdown' | 'pointerup' | 'pointermove'> {
17
+ /**
18
+ * @inheritDoc
19
+ */
20
+ readonly domEventType: readonly ["pointerdown", "pointerup", "pointermove"];
21
+ /**
22
+ * @inheritDoc
23
+ */
24
+ onDomEvent(domEvent: PointerEvent): void;
25
+ }
26
+ /**
27
+ * Fired when a pointer is down on one of the editing roots of the editor.
28
+ *
29
+ * Introduced by {@link module:engine/view/observer/pointerobserver~PointerObserver}.
30
+ *
31
+ * Note that this event is not available by default. To make it available,
32
+ * {@link module:engine/view/observer/pointerobserver~PointerObserver} needs to be added to {@link module:engine/view/view~EditingView}
33
+ * by the {@link module:engine/view/view~EditingView#addObserver} method.
34
+ *
35
+ * @see module:engine/view/observer/pointerobserver~PointerObserver
36
+ * @eventName module:engine/view/document~ViewDocument#pointerdown
37
+ * @param data The event data.
38
+ */
39
+ export type ViewDocumentPointerDownEvent = {
40
+ name: 'pointerdown';
41
+ args: [data: ViewDocumentDomEventData<PointerEvent>];
42
+ };
43
+ /**
44
+ * Fired when a pointer is up on one of the editing roots of the editor.
45
+ *
46
+ * Introduced by {@link module:engine/view/observer/pointerobserver~PointerObserver}.
47
+ *
48
+ * Note that this event is not available by default. To make it available,
49
+ * {@link module:engine/view/observer/pointerobserver~PointerObserver} needs to be added to {@link module:engine/view/view~EditingView}
50
+ * by the {@link module:engine/view/view~EditingView#addObserver} method.
51
+ *
52
+ * @see module:engine/view/observer/pointerobserver~PointerObserver
53
+ * @eventName module:engine/view/document~ViewDocument#pointerup
54
+ * @param data The event data.
55
+ */
56
+ export type ViewDocumentPointerUpEvent = {
57
+ name: 'pointerup';
58
+ args: [data: ViewDocumentDomEventData<PointerEvent>];
59
+ };
60
+ /**
61
+ * Fired when a pointer is moved on one of the editing roots of the editor.
62
+ *
63
+ * Introduced by {@link module:engine/view/observer/pointerobserver~PointerObserver}.
64
+ *
65
+ * Note that this event is not available by default. To make it available,
66
+ * {@link module:engine/view/observer/pointerobserver~PointerObserver} needs to be added to {@link module:engine/view/view~EditingView}
67
+ * by the {@link module:engine/view/view~EditingView#addObserver} method.
68
+ *
69
+ * @see module:engine/view/observer/pointerobserver~PointerObserver
70
+ * @eventName module:engine/view/document~ViewDocument#pointermove
71
+ * @param data The event data.
72
+ */
73
+ export type ViewDocumentPointerMoveEvent = {
74
+ name: 'pointermove';
75
+ args: [data: ViewDocumentDomEventData<PointerEvent>];
76
+ };
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
4
+ */
5
+ /**
6
+ * @module engine/view/observer/pointerobserver
7
+ */
8
+ import { DomEventObserver } from './domeventobserver.js';
9
+ /**
10
+ * Pointer events observer.
11
+ *
12
+ * Note that this observer is not available by default. To make it available it needs to be added to
13
+ * {@link module:engine/view/view~EditingView} by {@link module:engine/view/view~EditingView#addObserver} method.
14
+ */
15
+ export class PointerObserver extends DomEventObserver {
16
+ /**
17
+ * @inheritDoc
18
+ */
19
+ domEventType = ['pointerdown', 'pointerup', 'pointermove'];
20
+ /**
21
+ * @inheritDoc
22
+ */
23
+ onDomEvent(domEvent) {
24
+ this.fire(domEvent.type, domEvent);
25
+ }
26
+ }
@@ -8,10 +8,10 @@
8
8
  import { Observer } from './observer.js';
9
9
  import { MutationObserver } from './mutationobserver.js';
10
10
  import { FocusObserver } from './focusobserver.js';
11
- import { type EditingView } from '../view.js';
12
- import { type ViewDocumentSelection } from '../documentselection.js';
13
- import { type ViewDomConverter } from '../domconverter.js';
14
- import { type ViewSelection } from '../selection.js';
11
+ import type { EditingView } from '../view.js';
12
+ import type { ViewDocumentSelection } from '../documentselection.js';
13
+ import type { ViewDomConverter } from '../domconverter.js';
14
+ import type { ViewSelection } from '../selection.js';
15
15
  type DomSelection = globalThis.Selection;
16
16
  /**
17
17
  * Selection observer class observes selection changes in the document. If a selection changes on the document this