@ckeditor/ckeditor5-engine 38.2.0-alpha.0 → 39.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +0 -1
  2. package/package.json +3 -4
  3. package/src/controller/editingcontroller.js +2 -2
  4. package/src/conversion/downcastdispatcher.d.ts +15 -0
  5. package/src/conversion/downcastdispatcher.js +28 -19
  6. package/src/conversion/downcasthelpers.d.ts +6 -6
  7. package/src/conversion/downcasthelpers.js +6 -6
  8. package/src/dev-utils/view.js +1 -1
  9. package/src/index.d.ts +1 -0
  10. package/src/index.js +1 -0
  11. package/src/model/differ.d.ts +14 -0
  12. package/src/model/differ.js +70 -11
  13. package/src/model/document.d.ts +9 -1
  14. package/src/model/document.js +14 -9
  15. package/src/model/documentselection.js +8 -2
  16. package/src/model/model.d.ts +0 -1
  17. package/src/model/model.js +0 -1
  18. package/src/model/operation/rootoperation.d.ts +0 -4
  19. package/src/model/operation/rootoperation.js +0 -24
  20. package/src/model/operation/transform.js +2 -2
  21. package/src/model/rootelement.d.ts +6 -0
  22. package/src/model/rootelement.js +6 -0
  23. package/src/model/schema.d.ts +10 -0
  24. package/src/model/schema.js +5 -0
  25. package/src/model/utils/autoparagraphing.js +1 -2
  26. package/src/view/domconverter.d.ts +43 -53
  27. package/src/view/domconverter.js +266 -214
  28. package/src/view/editableelement.d.ts +10 -0
  29. package/src/view/editableelement.js +1 -0
  30. package/src/view/filler.d.ts +2 -2
  31. package/src/view/filler.js +6 -4
  32. package/src/view/observer/selectionobserver.js +2 -2
  33. package/src/view/placeholder.d.ts +13 -5
  34. package/src/view/placeholder.js +21 -12
  35. package/src/view/renderer.js +1 -2
  36. package/src/view/view.d.ts +14 -7
  37. package/src/view/view.js +13 -1
@@ -151,6 +151,8 @@ export default class SelectionObserver extends Observer {
151
151
  return;
152
152
  }
153
153
  this.view.hasDomSelection = true;
154
+ // Mark the latest focus change as complete (we got new selection after the focus so the selection is in the focused element).
155
+ this.focusObserver.flush();
154
156
  if (this.selection.isEqual(newViewSelection) && this.domConverter.isDomSelectionCorrect(domSelection)) {
155
157
  return;
156
158
  }
@@ -165,8 +167,6 @@ export default class SelectionObserver extends Observer {
165
167
  this._reportInfiniteLoop();
166
168
  return;
167
169
  }
168
- // Mark the latest focus change as complete (we got new selection after the focus so the selection is in the focused element).
169
- this.focusObserver.flush();
170
170
  if (this.selection.isSimilar(newViewSelection)) {
171
171
  // If selection was equal and we are at this point of algorithm, it means that it was incorrect.
172
172
  // Just re-render it, no need to fire any events, etc.
@@ -7,30 +7,29 @@
7
7
  */
8
8
  import '../../theme/placeholder.css';
9
9
  import type DowncastWriter from './downcastwriter';
10
+ import type EditableElement from './editableelement';
10
11
  import type Element from './element';
11
12
  import type View from './view';
12
13
  /**
13
14
  * A helper that enables a placeholder on the provided view element (also updates its visibility).
14
15
  * The placeholder is a CSS pseudo–element (with a text content) attached to the element.
15
16
  *
16
- * To change the placeholder text, simply call this method again with new options.
17
+ * To change the placeholder text, change value of the `placeholder` property in the provided `element`.
17
18
  *
18
19
  * To disable the placeholder, use {@link module:engine/view/placeholder~disablePlaceholder `disablePlaceholder()`} helper.
19
20
  *
20
21
  * @param options Configuration options of the placeholder.
21
22
  * @param options.view Editing view instance.
22
23
  * @param options.element Element that will gain a placeholder. See `options.isDirectHost` to learn more.
23
- * @param options.text Placeholder text.
24
24
  * @param options.isDirectHost If set `false`, the placeholder will not be enabled directly
25
25
  * in the passed `element` but in one of its children (selected automatically, i.e. a first empty child element).
26
26
  * Useful when attaching placeholders to elements that can host other elements (not just text), for instance,
27
27
  * editable root elements.
28
28
  * @param options.keepOnFocus If set `true`, the placeholder stay visible when the host element is focused.
29
29
  */
30
- export declare function enablePlaceholder({ view, element, text, isDirectHost, keepOnFocus }: {
30
+ export declare function enablePlaceholder({ view, element, isDirectHost, keepOnFocus }: {
31
31
  view: View;
32
- element: Element;
33
- text: string;
32
+ element: PlaceholderableElement | EditableElement;
34
33
  isDirectHost?: boolean;
35
34
  keepOnFocus?: boolean;
36
35
  }): void;
@@ -83,3 +82,12 @@ export declare function hidePlaceholder(writer: DowncastWriter, element: Element
83
82
  * @param keepOnFocus Focusing the element will keep the placeholder visible.
84
83
  */
85
84
  export declare function needsPlaceholder(element: Element, keepOnFocus: boolean): boolean;
85
+ /**
86
+ * Element that could have a placeholder.
87
+ */
88
+ export interface PlaceholderableElement extends Element {
89
+ /**
90
+ * The text of element's placeholder.
91
+ */
92
+ placeholder?: string;
93
+ }
@@ -12,21 +12,20 @@ const documentPlaceholders = new WeakMap();
12
12
  * A helper that enables a placeholder on the provided view element (also updates its visibility).
13
13
  * The placeholder is a CSS pseudo–element (with a text content) attached to the element.
14
14
  *
15
- * To change the placeholder text, simply call this method again with new options.
15
+ * To change the placeholder text, change value of the `placeholder` property in the provided `element`.
16
16
  *
17
17
  * To disable the placeholder, use {@link module:engine/view/placeholder~disablePlaceholder `disablePlaceholder()`} helper.
18
18
  *
19
19
  * @param options Configuration options of the placeholder.
20
20
  * @param options.view Editing view instance.
21
21
  * @param options.element Element that will gain a placeholder. See `options.isDirectHost` to learn more.
22
- * @param options.text Placeholder text.
23
22
  * @param options.isDirectHost If set `false`, the placeholder will not be enabled directly
24
23
  * in the passed `element` but in one of its children (selected automatically, i.e. a first empty child element).
25
24
  * Useful when attaching placeholders to elements that can host other elements (not just text), for instance,
26
25
  * editable root elements.
27
26
  * @param options.keepOnFocus If set `true`, the placeholder stay visible when the host element is focused.
28
27
  */
29
- export function enablePlaceholder({ view, element, text, isDirectHost = true, keepOnFocus = false }) {
28
+ export function enablePlaceholder({ view, element, isDirectHost = true, keepOnFocus = false }) {
30
29
  const doc = view.document;
31
30
  // Use a single a single post fixer per—document to update all placeholders.
32
31
  if (!documentPlaceholders.has(doc)) {
@@ -39,15 +38,25 @@ export function enablePlaceholder({ view, element, text, isDirectHost = true, ke
39
38
  view.change(writer => updateDocumentPlaceholders(doc, writer));
40
39
  }, { priority: 'high' });
41
40
  }
42
- // Store information about the element placeholder under its document.
43
- documentPlaceholders.get(doc).set(element, {
44
- text,
45
- isDirectHost,
46
- keepOnFocus,
47
- hostElement: isDirectHost ? element : null
48
- });
49
- // Update the placeholders right away.
50
- view.change(writer => updateDocumentPlaceholders(doc, writer));
41
+ if (element.is('editableElement')) {
42
+ element.on('change:placeholder', (evtInfo, evt, text) => {
43
+ setPlaceholder(text);
44
+ });
45
+ }
46
+ if (element.placeholder) {
47
+ setPlaceholder(element.placeholder);
48
+ }
49
+ function setPlaceholder(text) {
50
+ // Store information about the element placeholder under its document.
51
+ documentPlaceholders.get(doc).set(element, {
52
+ text,
53
+ isDirectHost,
54
+ keepOnFocus,
55
+ hostElement: isDirectHost ? element : null
56
+ });
57
+ // Update the placeholders right away.
58
+ view.change(writer => updateDocumentPlaceholders(doc, writer));
59
+ }
51
60
  }
52
61
  /**
53
62
  * Disables the placeholder functionality from a given element.
@@ -747,8 +747,7 @@ export default class Renderer extends ObservableMixin() {
747
747
  // @if CK_DEBUG_TYPING // 'color: green;font-weight: bold', '', anchor, focus
748
748
  // @if CK_DEBUG_TYPING // );
749
749
  // @if CK_DEBUG_TYPING // }
750
- domSelection.collapse(anchor.parent, anchor.offset);
751
- domSelection.extend(focus.parent, focus.offset);
750
+ domSelection.setBaseAndExtent(anchor.parent, anchor.offset, focus.parent, focus.offset);
752
751
  // Firefox–specific hack (https://github.com/ckeditor/ckeditor5-engine/issues/1439).
753
752
  if (env.isGecko) {
754
753
  fixGeckoSelectionAfterBr(focus, domSelection);
@@ -17,6 +17,15 @@ import type { StylesProcessor } from './stylesmap';
17
17
  import type Element from './element';
18
18
  import type Node from './node';
19
19
  import type Item from './item';
20
+ import KeyObserver from './observer/keyobserver';
21
+ import FakeSelectionObserver from './observer/fakeselectionobserver';
22
+ import MutationObserver from './observer/mutationobserver';
23
+ import SelectionObserver from './observer/selectionobserver';
24
+ import FocusObserver from './observer/focusobserver';
25
+ import CompositionObserver from './observer/compositionobserver';
26
+ import InputObserver from './observer/inputobserver';
27
+ import ArrowKeysObserver from './observer/arrowkeysobserver';
28
+ import TabObserver from './observer/tabobserver';
20
29
  type IfTrue<T> = T extends true ? true : never;
21
30
  type DomRange = globalThis.Range;
22
31
  declare const View_base: {
@@ -168,13 +177,7 @@ export default class View extends View_base {
168
177
  * @returns Added observer instance.
169
178
  */
170
179
  addObserver(ObserverConstructor: ObserverConstructor): Observer;
171
- /**
172
- * Returns observer of the given type or `undefined` if such observer has not been added yet.
173
- *
174
- * @param ObserverConstructor The constructor of an observer to get.
175
- * @returns Observer instance or undefined.
176
- */
177
- getObserver<T extends ObserverConstructor>(ObserverConstructor: T): InstanceType<T> | undefined;
180
+ getObserver<T extends ObserverConstructor>(ObserverConstructor: T): T extends AlwaysRegisteredObservers ? InstanceType<T> : InstanceType<T> | undefined;
178
181
  /**
179
182
  * Disables all added observers.
180
183
  */
@@ -477,4 +480,8 @@ export type ViewScrollToTheSelectionEventData = {
477
480
  alignToTop?: boolean;
478
481
  forceScroll?: boolean;
479
482
  };
483
+ /**
484
+ * Observers that are always registered.
485
+ */
486
+ export type AlwaysRegisteredObservers = typeof MutationObserver | typeof FocusObserver | typeof SelectionObserver | typeof KeyObserver | typeof FakeSelectionObserver | typeof CompositionObserver | typeof ArrowKeysObserver | typeof InputObserver | typeof TabObserver;
480
487
  export {};
package/src/view/view.js CHANGED
@@ -21,7 +21,7 @@ import CompositionObserver from './observer/compositionobserver';
21
21
  import InputObserver from './observer/inputobserver';
22
22
  import ArrowKeysObserver from './observer/arrowkeysobserver';
23
23
  import TabObserver from './observer/tabobserver';
24
- import { CKEditorError, ObservableMixin, scrollViewportToShowTarget } from '@ckeditor/ckeditor5-utils';
24
+ import { CKEditorError, env, ObservableMixin, scrollViewportToShowTarget } from '@ckeditor/ckeditor5-utils';
25
25
  import { injectUiElementHandling } from './uielement';
26
26
  import { injectQuirksHandling } from './filler';
27
27
  import { cloneDeep } from 'lodash-es';
@@ -104,6 +104,7 @@ export default class View extends ObservableMixin() {
104
104
  .to(this.document, 'isFocused', 'isSelecting', 'isComposing');
105
105
  this._writer = new DowncastWriter(this.document);
106
106
  // Add default observers.
107
+ // Make sure that this list matches AlwaysRegisteredObservers type.
107
108
  this.addObserver(MutationObserver);
108
109
  this.addObserver(FocusObserver);
109
110
  this.addObserver(SelectionObserver);
@@ -132,6 +133,17 @@ export default class View extends ObservableMixin() {
132
133
  this.listenTo(this.document, 'change:isFocused', () => {
133
134
  this._hasChangedSinceTheLastRendering = true;
134
135
  });
136
+ // Remove ranges from DOM selection if editor is blurred.
137
+ // See https://github.com/ckeditor/ckeditor5/issues/5753.
138
+ if (env.isiOS) {
139
+ this.listenTo(this.document, 'blur', (evt, data) => {
140
+ const relatedViewElement = this.domConverter.mapDomToView(data.domEvent.relatedTarget);
141
+ // Do not modify DOM selection if focus is moved to other editable of the same editor.
142
+ if (!relatedViewElement) {
143
+ this.domConverter._clearDomSelection();
144
+ }
145
+ });
146
+ }
135
147
  }
136
148
  /**
137
149
  * Attaches a DOM root element to the view element and enable all observers on that element.