@ckeditor/ckeditor5-engine 42.0.2-alpha.2 → 43.0.0-alpha.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 (38) hide show
  1. package/CHANGELOG.md +1 -820
  2. package/dist/dev-utils/model.d.ts +2 -0
  3. package/dist/dev-utils/view.d.ts +1 -0
  4. package/dist/index.d.ts +3 -1
  5. package/dist/index.js +466 -271
  6. package/dist/index.js.map +1 -1
  7. package/dist/model/schema.d.ts +149 -51
  8. package/dist/view/observer/focusobserver.d.ts +12 -0
  9. package/dist/view/observer/mutationobserver.d.ts +34 -5
  10. package/dist/view/observer/selectionobserver.d.ts +1 -2
  11. package/dist/view/renderer.d.ts +12 -0
  12. package/dist/view/view.d.ts +1 -4
  13. package/package.json +2 -2
  14. package/src/conversion/upcasthelpers.js +0 -7
  15. package/src/dev-utils/model.d.ts +2 -0
  16. package/src/dev-utils/model.js +4 -2
  17. package/src/dev-utils/utils.js +7 -0
  18. package/src/dev-utils/view.d.ts +1 -0
  19. package/src/dev-utils/view.js +3 -0
  20. package/src/index.d.ts +3 -1
  21. package/src/index.js +2 -0
  22. package/src/model/model.js +1 -5
  23. package/src/model/schema.d.ts +149 -51
  24. package/src/model/schema.js +200 -70
  25. package/src/model/utils/insertcontent.js +21 -65
  26. package/src/view/domconverter.js +13 -9
  27. package/src/view/observer/compositionobserver.js +2 -0
  28. package/src/view/observer/focusobserver.d.ts +12 -0
  29. package/src/view/observer/focusobserver.js +55 -25
  30. package/src/view/observer/inputobserver.js +7 -5
  31. package/src/view/observer/mutationobserver.d.ts +34 -5
  32. package/src/view/observer/mutationobserver.js +8 -11
  33. package/src/view/observer/selectionobserver.d.ts +1 -2
  34. package/src/view/observer/selectionobserver.js +27 -9
  35. package/src/view/renderer.d.ts +12 -0
  36. package/src/view/renderer.js +111 -63
  37. package/src/view/view.d.ts +1 -4
  38. package/src/view/view.js +9 -0
@@ -21,6 +21,10 @@ export default class FocusObserver extends DomEventObserver {
21
21
  */
22
22
  constructor(view) {
23
23
  super(view);
24
+ /**
25
+ * Identifier of the timeout currently used by focus listener to delay rendering execution.
26
+ */
27
+ this._renderTimeoutId = null;
24
28
  /**
25
29
  * Set to `true` if the document is in the process of setting the focus.
26
30
  *
@@ -33,31 +37,17 @@ export default class FocusObserver extends DomEventObserver {
33
37
  this.domEventType = ['focus', 'blur'];
34
38
  this.useCapture = true;
35
39
  const document = this.document;
36
- document.on('focus', () => {
37
- this._isFocusChanging = true;
38
- // Unfortunately native `selectionchange` event is fired asynchronously.
39
- // We need to wait until `SelectionObserver` handle the event and then render. Otherwise rendering will
40
- // overwrite new DOM selection with selection from the view.
41
- // See https://github.com/ckeditor/ckeditor5-engine/issues/795 for more details.
42
- // Long timeout is needed to solve #676 and https://github.com/ckeditor/ckeditor5-engine/issues/1157 issues.
43
- //
44
- // Using `view.change()` instead of `view.forceRender()` to prevent double rendering
45
- // in a situation where `selectionchange` already caused selection change.
46
- this._renderTimeoutId = setTimeout(() => {
47
- this.flush();
48
- view.change(() => { });
49
- }, 50);
50
- });
51
- document.on('blur', (evt, data) => {
52
- const selectedEditable = document.selection.editableElement;
53
- if (selectedEditable === null || selectedEditable === data.target) {
54
- document.isFocused = false;
55
- this._isFocusChanging = false;
56
- // Re-render the document to update view elements
57
- // (changing document.isFocused already marked view as changed since last rendering).
58
- view.change(() => { });
40
+ document.on('focus', () => this._handleFocus());
41
+ document.on('blur', (evt, data) => this._handleBlur(data));
42
+ // Focus the editor in cases where browser dispatches `beforeinput` event to a not-focused editable element.
43
+ // This is flushed by the beforeinput listener in the `InsertTextObserver`.
44
+ // Note that focus is set only if the document is not focused yet.
45
+ // See https://github.com/ckeditor/ckeditor5/issues/14702.
46
+ document.on('beforeinput', () => {
47
+ if (!document.isFocused) {
48
+ this._handleFocus();
59
49
  }
60
- });
50
+ }, { priority: 'highest' });
61
51
  }
62
52
  /**
63
53
  * Finishes setting the document focus state.
@@ -78,9 +68,49 @@ export default class FocusObserver extends DomEventObserver {
78
68
  * @inheritDoc
79
69
  */
80
70
  destroy() {
71
+ this._clearTimeout();
72
+ super.destroy();
73
+ }
74
+ /**
75
+ * The `focus` event handler.
76
+ */
77
+ _handleFocus() {
78
+ this._clearTimeout();
79
+ this._isFocusChanging = true;
80
+ // Unfortunately native `selectionchange` event is fired asynchronously.
81
+ // We need to wait until `SelectionObserver` handle the event and then render. Otherwise rendering will
82
+ // overwrite new DOM selection with selection from the view.
83
+ // See https://github.com/ckeditor/ckeditor5-engine/issues/795 for more details.
84
+ // Long timeout is needed to solve #676 and https://github.com/ckeditor/ckeditor5-engine/issues/1157 issues.
85
+ //
86
+ // Using `view.change()` instead of `view.forceRender()` to prevent double rendering
87
+ // in a situation where `selectionchange` already caused selection change.
88
+ this._renderTimeoutId = setTimeout(() => {
89
+ this._renderTimeoutId = null;
90
+ this.flush();
91
+ this.view.change(() => { });
92
+ }, 50);
93
+ }
94
+ /**
95
+ * The `blur` event handler.
96
+ */
97
+ _handleBlur(data) {
98
+ const selectedEditable = this.document.selection.editableElement;
99
+ if (selectedEditable === null || selectedEditable === data.target) {
100
+ this.document.isFocused = false;
101
+ this._isFocusChanging = false;
102
+ // Re-render the document to update view elements
103
+ // (changing document.isFocused already marked view as changed since last rendering).
104
+ this.view.change(() => { });
105
+ }
106
+ }
107
+ /**
108
+ * Clears timeout.
109
+ */
110
+ _clearTimeout() {
81
111
  if (this._renderTimeoutId) {
82
112
  clearTimeout(this._renderTimeoutId);
113
+ this._renderTimeoutId = null;
83
114
  }
84
- super.destroy();
85
115
  }
86
116
  }
@@ -8,6 +8,7 @@
8
8
  import DomEventObserver from './domeventobserver.js';
9
9
  import DataTransfer from '../datatransfer.js';
10
10
  import { env } from '@ckeditor/ckeditor5-utils';
11
+ // @if CK_DEBUG_TYPING // const { _debouncedLine } = require( '../../dev-utils/utils.js' );
11
12
  /**
12
13
  * Observer for events connected with data input.
13
14
  *
@@ -27,6 +28,7 @@ export default class InputObserver extends DomEventObserver {
27
28
  */
28
29
  onDomEvent(domEvent) {
29
30
  // @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
31
+ // @if CK_DEBUG_TYPING // _debouncedLine();
30
32
  // @if CK_DEBUG_TYPING // console.group( `%c[InputObserver]%c ${ domEvent.type }: ${ domEvent.inputType }`,
31
33
  // @if CK_DEBUG_TYPING // 'color: green', 'color: default'
32
34
  // @if CK_DEBUG_TYPING // );
@@ -44,7 +46,7 @@ export default class InputObserver extends DomEventObserver {
44
46
  data = domEvent.data;
45
47
  // @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
46
48
  // @if CK_DEBUG_TYPING // console.info( `%c[InputObserver]%c event data: %c${ JSON.stringify( data ) }`,
47
- // @if CK_DEBUG_TYPING // 'color: green;font-weight: bold', 'font-weight:bold', 'color: blue;'
49
+ // @if CK_DEBUG_TYPING // 'color: green; font-weight: bold', 'font-weight: bold', 'color: blue;'
48
50
  // @if CK_DEBUG_TYPING // );
49
51
  // @if CK_DEBUG_TYPING // }
50
52
  }
@@ -52,7 +54,7 @@ export default class InputObserver extends DomEventObserver {
52
54
  data = dataTransfer.getData('text/plain');
53
55
  // @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
54
56
  // @if CK_DEBUG_TYPING // console.info( `%c[InputObserver]%c event data transfer: %c${ JSON.stringify( data ) }`,
55
- // @if CK_DEBUG_TYPING // 'color: green;font-weight: bold', 'font-weight:bold', 'color: blue;'
57
+ // @if CK_DEBUG_TYPING // 'color: green; font-weight: bold', 'font-weight: bold', 'color: blue;'
56
58
  // @if CK_DEBUG_TYPING // );
57
59
  // @if CK_DEBUG_TYPING // }
58
60
  }
@@ -63,7 +65,7 @@ export default class InputObserver extends DomEventObserver {
63
65
  targetRanges = Array.from(viewDocument.selection.getRanges());
64
66
  // @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
65
67
  // @if CK_DEBUG_TYPING // console.info( '%c[InputObserver]%c using fake selection:',
66
- // @if CK_DEBUG_TYPING // 'color: green;font-weight: bold', 'font-weight:bold', targetRanges,
68
+ // @if CK_DEBUG_TYPING // 'color: green; font-weight: bold', 'font-weight: bold', targetRanges,
67
69
  // @if CK_DEBUG_TYPING // viewDocument.selection.isFake ? 'fake view selection' : 'fake DOM parent'
68
70
  // @if CK_DEBUG_TYPING // );
69
71
  // @if CK_DEBUG_TYPING // }
@@ -85,7 +87,7 @@ export default class InputObserver extends DomEventObserver {
85
87
  }).filter((range) => !!range);
86
88
  // @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
87
89
  // @if CK_DEBUG_TYPING // console.info( '%c[InputObserver]%c using target ranges:',
88
- // @if CK_DEBUG_TYPING // 'color: green;font-weight: bold', 'font-weight:bold', targetRanges
90
+ // @if CK_DEBUG_TYPING // 'color: green; font-weight: bold', 'font-weight: bold', targetRanges
89
91
  // @if CK_DEBUG_TYPING // );
90
92
  // @if CK_DEBUG_TYPING // }
91
93
  }
@@ -96,7 +98,7 @@ export default class InputObserver extends DomEventObserver {
96
98
  targetRanges = Array.from(view.domConverter.domSelectionToView(domSelection).getRanges());
97
99
  // @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
98
100
  // @if CK_DEBUG_TYPING // console.info( '%c[InputObserver]%c using selection ranges:',
99
- // @if CK_DEBUG_TYPING // 'color: green;font-weight: bold', 'font-weight:bold', targetRanges
101
+ // @if CK_DEBUG_TYPING // 'color: green; font-weight: bold', 'font-weight: bold', targetRanges
100
102
  // @if CK_DEBUG_TYPING // );
101
103
  // @if CK_DEBUG_TYPING // }
102
104
  }
@@ -7,8 +7,9 @@
7
7
  */
8
8
  import Observer from './observer.js';
9
9
  import type DomConverter from '../domconverter.js';
10
- import type Renderer from '../renderer.js';
11
10
  import type View from '../view.js';
11
+ import type ViewNode from '../node.js';
12
+ import type { ChangeType } from '../document.js';
12
13
  /**
13
14
  * Mutation observer's role is to watch for any DOM changes inside the editor that weren't
14
15
  * done by the editor's {@link module:engine/view/renderer~Renderer} itself and reverting these changes.
@@ -25,10 +26,6 @@ export default class MutationObserver extends Observer {
25
26
  * Reference to the {@link module:engine/view/view~View#domConverter}.
26
27
  */
27
28
  readonly domConverter: DomConverter;
28
- /**
29
- * Reference to the {@link module:engine/view/view~View#_renderer}.
30
- */
31
- readonly renderer: Renderer;
32
29
  /**
33
30
  * Native mutation observer config.
34
31
  */
@@ -84,3 +81,35 @@ export default class MutationObserver extends Observer {
84
81
  */
85
82
  private _isBogusBrMutation;
86
83
  }
84
+ /**
85
+ * Event fired on DOM mutations detected.
86
+ *
87
+ * This event is introduced by {@link module:engine/view/observer/mutationobserver~MutationObserver} and available
88
+ * by default in all editor instances (attached by {@link module:engine/view/view~View}).
89
+ *
90
+ * @eventName module:engine/view/document~Document#mutations
91
+ * @param data Event data containing detailed information about the event.
92
+ */
93
+ export type ViewDocumentMutationsEvent = {
94
+ name: 'mutations';
95
+ args: [data: MutationsEventData];
96
+ };
97
+ /**
98
+ * The value of {@link ~ViewDocumentMutationsEvent}.
99
+ */
100
+ export type MutationsEventData = {
101
+ mutations: Array<MutationData>;
102
+ };
103
+ /**
104
+ * A single entry in {@link ~MutationsEventData} mutations array.
105
+ */
106
+ export type MutationData = {
107
+ /**
108
+ * Type of mutation detected.
109
+ */
110
+ type: ChangeType;
111
+ /**
112
+ * The view node related to the detected mutation.
113
+ */
114
+ node: ViewNode;
115
+ };
@@ -9,6 +9,7 @@
9
9
  import Observer from './observer.js';
10
10
  import { startsWithFiller } from '../filler.js';
11
11
  import { isEqualWith } from 'lodash-es';
12
+ // @if CK_DEBUG_TYPING // const { _debouncedLine } = require( '../../dev-utils/utils.js' );
12
13
  /**
13
14
  * Mutation observer's role is to watch for any DOM changes inside the editor that weren't
14
15
  * done by the editor's {@link module:engine/view/renderer~Renderer} itself and reverting these changes.
@@ -32,7 +33,6 @@ export default class MutationObserver extends Observer {
32
33
  subtree: true
33
34
  };
34
35
  this.domConverter = view.domConverter;
35
- this.renderer = view._renderer;
36
36
  this._domElements = new Set();
37
37
  this._mutationObserver = new window.MutationObserver(this._onMutations.bind(this));
38
38
  }
@@ -139,10 +139,9 @@ export default class MutationObserver extends Observer {
139
139
  }
140
140
  // Now we build the list of mutations to mark elements. We did not do it earlier to avoid marking the
141
141
  // same node multiple times in case of duplication.
142
- let hasMutations = false;
142
+ const mutations = [];
143
143
  for (const textNode of mutatedTextNodes) {
144
- hasMutations = true;
145
- this.renderer.markToSync('text', textNode);
144
+ mutations.push({ type: 'text', node: textNode });
146
145
  }
147
146
  for (const viewElement of elementsWithMutatedChildren) {
148
147
  const domElement = domConverter.mapViewToDom(viewElement);
@@ -151,20 +150,18 @@ export default class MutationObserver extends Observer {
151
150
  // It may happen that as a result of many changes (sth was inserted and then removed),
152
151
  // both elements haven't really changed. #1031
153
152
  if (!isEqualWith(viewChildren, newViewChildren, sameNodes)) {
154
- hasMutations = true;
155
- this.renderer.markToSync('children', viewElement);
153
+ mutations.push({ type: 'children', node: viewElement });
156
154
  }
157
155
  }
158
156
  // In case only non-relevant mutations were recorded it skips the event and force render (#5600).
159
- if (hasMutations) {
157
+ if (mutations.length) {
160
158
  // @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
159
+ // @if CK_DEBUG_TYPING // _debouncedLine();
161
160
  // @if CK_DEBUG_TYPING // console.group( '%c[MutationObserver]%c Mutations detected',
162
- // @if CK_DEBUG_TYPING // 'font-weight:bold;color:green', ''
161
+ // @if CK_DEBUG_TYPING // 'font-weight: bold; color: green', 'font-weight: bold'
163
162
  // @if CK_DEBUG_TYPING // );
164
163
  // @if CK_DEBUG_TYPING // }
165
- // At this point we have "dirty DOM" (changed) and de-synched view (which has not been changed).
166
- // In order to "reset DOM" we render the view again.
167
- this.view.forceRender();
164
+ this.document.fire('mutations', { mutations });
168
165
  // @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
169
166
  // @if CK_DEBUG_TYPING // console.groupEnd();
170
167
  // @if CK_DEBUG_TYPING // }
@@ -7,11 +7,11 @@
7
7
  */
8
8
  import Observer from './observer.js';
9
9
  import MutationObserver from './mutationobserver.js';
10
+ import FocusObserver from './focusobserver.js';
10
11
  import type View from '../view.js';
11
12
  import type DocumentSelection from '../documentselection.js';
12
13
  import type DomConverter from '../domconverter.js';
13
14
  import type Selection from '../selection.js';
14
- import FocusObserver from './focusobserver.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
@@ -88,7 +88,6 @@ export default class SelectionObserver extends Observer {
88
88
  * a selection changes and fires {@link module:engine/view/document~Document#event:selectionChange} event on every change
89
89
  * and {@link module:engine/view/document~Document#event:selectionChangeDone} when a selection stop changing.
90
90
  *
91
- * @param domEvent DOM event.
92
91
  * @param domDocument DOM document.
93
92
  */
94
93
  private _handleSelectionChange;
@@ -8,9 +8,9 @@
8
8
  /* global setInterval, clearInterval */
9
9
  import Observer from './observer.js';
10
10
  import MutationObserver from './mutationobserver.js';
11
+ import FocusObserver from './focusobserver.js';
11
12
  import { env } from '@ckeditor/ckeditor5-utils';
12
13
  import { debounce } from 'lodash-es';
13
- import FocusObserver from './focusobserver.js';
14
14
  /**
15
15
  * Selection observer class observes selection changes in the document. If a selection changes on the document this
16
16
  * observer checks if the DOM selection is different from the {@link module:engine/view/document~Document#selection view selection}.
@@ -52,7 +52,7 @@ export default class SelectionObserver extends Observer {
52
52
  }
53
53
  // Make sure that model selection is up-to-date at the end of selecting process.
54
54
  // Sometimes `selectionchange` events could arrive after the `mouseup` event and that selection could be already outdated.
55
- this._handleSelectionChange(null, domDocument);
55
+ this._handleSelectionChange(domDocument);
56
56
  this.document.isSelecting = false;
57
57
  // The safety timeout can be canceled when the document leaves the "is selecting" state.
58
58
  this._documentIsSelectingInactivityTimeoutDebounced.cancel();
@@ -72,10 +72,11 @@ export default class SelectionObserver extends Observer {
72
72
  this.listenTo(domDocument, 'mouseup', endDocumentIsSelecting, { priority: 'highest', useCapture: true });
73
73
  this.listenTo(domDocument, 'selectionchange', (evt, domEvent) => {
74
74
  // @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
75
+ // @if CK_DEBUG_TYPING // _debouncedLine();
75
76
  // @if CK_DEBUG_TYPING // const domSelection = domDocument.defaultView!.getSelection();
76
- // @if CK_DEBUG_TYPING // console.group( '%c[SelectionObserver]%c selectionchange', 'color:green', ''
77
+ // @if CK_DEBUG_TYPING // console.group( '%c[SelectionObserver]%c selectionchange', 'color: green', ''
77
78
  // @if CK_DEBUG_TYPING // );
78
- // @if CK_DEBUG_TYPING // console.info( '%c[SelectionObserver]%c DOM Selection:', 'font-weight:bold;color:green', '',
79
+ // @if CK_DEBUG_TYPING // console.info( '%c[SelectionObserver]%c DOM Selection:', 'font-weight: bold; color: green', '',
79
80
  // @if CK_DEBUG_TYPING // { node: domSelection!.anchorNode, offset: domSelection!.anchorOffset },
80
81
  // @if CK_DEBUG_TYPING // { node: domSelection!.focusNode, offset: domSelection!.focusOffset }
81
82
  // @if CK_DEBUG_TYPING // );
@@ -85,13 +86,13 @@ export default class SelectionObserver extends Observer {
85
86
  if (this.document.isComposing && !env.isAndroid) {
86
87
  // @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
87
88
  // @if CK_DEBUG_TYPING // console.info( '%c[SelectionObserver]%c Selection change ignored (isComposing)',
88
- // @if CK_DEBUG_TYPING // 'font-weight:bold;color:green', ''
89
+ // @if CK_DEBUG_TYPING // 'font-weight: bold; color: green', ''
89
90
  // @if CK_DEBUG_TYPING // );
90
91
  // @if CK_DEBUG_TYPING // console.groupEnd();
91
92
  // @if CK_DEBUG_TYPING // }
92
93
  return;
93
94
  }
94
- this._handleSelectionChange(domEvent, domDocument);
95
+ this._handleSelectionChange(domDocument);
95
96
  // @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
96
97
  // @if CK_DEBUG_TYPING // console.groupEnd();
97
98
  // @if CK_DEBUG_TYPING // }
@@ -99,6 +100,24 @@ export default class SelectionObserver extends Observer {
99
100
  // using their mouse).
100
101
  this._documentIsSelectingInactivityTimeoutDebounced();
101
102
  });
103
+ // Update the model DocumentSelection just after the Renderer and the SelectionObserver are locked.
104
+ // We do this synchronously (without waiting for the `selectionchange` DOM event) as browser updates
105
+ // the DOM selection (but not visually) to span the text that is under composition and could be replaced.
106
+ this.listenTo(this.view.document, 'compositionstart', () => {
107
+ // @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
108
+ // @if CK_DEBUG_TYPING // const domSelection = domDocument.defaultView!.getSelection();
109
+ // @if CK_DEBUG_TYPING // console.group( '%c[SelectionObserver]%c update selection on compositionstart', 'color: green', ''
110
+ // @if CK_DEBUG_TYPING // );
111
+ // @if CK_DEBUG_TYPING // console.info( '%c[SelectionObserver]%c DOM Selection:', 'font-weight: bold; color: green', '',
112
+ // @if CK_DEBUG_TYPING // { node: domSelection!.anchorNode, offset: domSelection!.anchorOffset },
113
+ // @if CK_DEBUG_TYPING // { node: domSelection!.focusNode, offset: domSelection!.focusOffset }
114
+ // @if CK_DEBUG_TYPING // );
115
+ // @if CK_DEBUG_TYPING // }
116
+ this._handleSelectionChange(domDocument);
117
+ // @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
118
+ // @if CK_DEBUG_TYPING // console.groupEnd();
119
+ // @if CK_DEBUG_TYPING // }
120
+ }, { priority: 'lowest' });
102
121
  this._documents.add(domDocument);
103
122
  }
104
123
  /**
@@ -128,10 +147,9 @@ export default class SelectionObserver extends Observer {
128
147
  * a selection changes and fires {@link module:engine/view/document~Document#event:selectionChange} event on every change
129
148
  * and {@link module:engine/view/document~Document#event:selectionChangeDone} when a selection stop changing.
130
149
  *
131
- * @param domEvent DOM event.
132
150
  * @param domDocument DOM document.
133
151
  */
134
- _handleSelectionChange(domEvent, domDocument) {
152
+ _handleSelectionChange(domDocument) {
135
153
  if (!this.isEnabled) {
136
154
  return;
137
155
  }
@@ -180,7 +198,7 @@ export default class SelectionObserver extends Observer {
180
198
  };
181
199
  // @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
182
200
  // @if CK_DEBUG_TYPING // console.info( '%c[SelectionObserver]%c Fire selection change:',
183
- // @if CK_DEBUG_TYPING // 'font-weight:bold;color:green', '',
201
+ // @if CK_DEBUG_TYPING // 'font-weight: bold; color: green', '',
184
202
  // @if CK_DEBUG_TYPING // newViewSelection.getFirstRange()
185
203
  // @if CK_DEBUG_TYPING // );
186
204
  // @if CK_DEBUG_TYPING // }
@@ -213,6 +213,18 @@ export default class Renderer extends /* #__PURE__ */ Renderer_base {
213
213
  * @returns Actions array modified with the `update` actions.
214
214
  */
215
215
  private _findUpdateActions;
216
+ /**
217
+ * Checks if text needs to be updated and possibly updates it by removing and inserting only parts
218
+ * of the data from the existing text node to reduce impact on the IME composition.
219
+ *
220
+ * @param domText DOM text node to update.
221
+ * @param expectedText The expected data of a text node.
222
+ */
223
+ private _updateTextNode;
224
+ /**
225
+ * Part of the `_updateTextNode` method extracted for easier testing.
226
+ */
227
+ private _updateTextNodeInternal;
216
228
  /**
217
229
  * Marks text nodes to be synchronized.
218
230
  *