@ckeditor/ckeditor5-engine 44.3.0 → 45.0.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.
- package/LICENSE.md +1 -1
- package/dist/index.js +305 -129
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/controller/datacontroller.js +40 -0
- package/src/controller/editingcontroller.js +16 -0
- package/src/conversion/conversion.js +6 -4
- package/src/conversion/conversionhelpers.js +1 -0
- package/src/conversion/downcastdispatcher.js +10 -0
- package/src/conversion/downcasthelpers.js +1 -1
- package/src/conversion/mapper.js +92 -95
- package/src/conversion/modelconsumable.js +13 -15
- package/src/conversion/upcastdispatcher.js +28 -24
- package/src/conversion/upcasthelpers.d.ts +1 -1
- package/src/conversion/upcasthelpers.js +2 -2
- package/src/conversion/viewconsumable.js +19 -20
- package/src/dataprocessor/htmldataprocessor.js +13 -1
- package/src/dataprocessor/xmldataprocessor.js +21 -1
- package/src/dev-utils/model.js +1 -1
- package/src/dev-utils/operationreplayer.js +3 -0
- package/src/dev-utils/utils.js +35 -1
- package/src/dev-utils/view.js +13 -0
- package/src/model/batch.js +20 -0
- package/src/model/differ.js +92 -88
- package/src/model/document.d.ts +1 -3
- package/src/model/document.js +38 -1
- package/src/model/documentfragment.js +10 -10
- package/src/model/documentselection.js +44 -32
- package/src/model/element.js +8 -4
- package/src/model/history.js +31 -33
- package/src/model/markercollection.js +25 -7
- package/src/model/model.js +21 -0
- package/src/model/node.js +22 -18
- package/src/model/nodelist.js +12 -12
- package/src/model/operation/attributeoperation.js +25 -1
- package/src/model/operation/detachoperation.js +8 -0
- package/src/model/operation/insertoperation.js +18 -0
- package/src/model/operation/markeroperation.js +29 -0
- package/src/model/operation/mergeoperation.js +16 -0
- package/src/model/operation/moveoperation.js +12 -0
- package/src/model/operation/operation.js +19 -0
- package/src/model/operation/renameoperation.js +12 -0
- package/src/model/operation/rootattributeoperation.js +20 -0
- package/src/model/operation/rootoperation.js +16 -0
- package/src/model/operation/splitoperation.js +19 -0
- package/src/model/operation/transform.js +5 -0
- package/src/model/position.js +40 -0
- package/src/model/range.js +8 -0
- package/src/model/rootelement.js +18 -10
- package/src/model/schema.js +25 -23
- package/src/model/selection.js +10 -10
- package/src/model/text.js +6 -0
- package/src/model/textproxy.js +12 -0
- package/src/model/treewalker.js +49 -0
- package/src/model/utils/insertcontent.js +60 -25
- package/src/model/writer.js +8 -0
- package/src/view/attributeelement.js +23 -23
- package/src/view/datatransfer.js +8 -0
- package/src/view/document.js +21 -4
- package/src/view/documentfragment.js +13 -9
- package/src/view/documentselection.js +4 -0
- package/src/view/domconverter.d.ts +6 -1
- package/src/view/domconverter.js +109 -48
- package/src/view/downcastwriter.js +14 -10
- package/src/view/element.js +29 -17
- package/src/view/matcher.js +1 -1
- package/src/view/node.js +9 -1
- package/src/view/observer/bubblingeventinfo.js +12 -0
- package/src/view/observer/clickobserver.js +4 -7
- package/src/view/observer/compositionobserver.js +14 -12
- package/src/view/observer/domeventdata.js +17 -1
- package/src/view/observer/domeventobserver.js +10 -13
- package/src/view/observer/fakeselectionobserver.d.ts +1 -1
- package/src/view/observer/fakeselectionobserver.js +5 -1
- package/src/view/observer/focusobserver.js +65 -14
- package/src/view/observer/inputobserver.js +33 -26
- package/src/view/observer/keyobserver.js +4 -7
- package/src/view/observer/mouseobserver.js +4 -7
- package/src/view/observer/mutationobserver.js +23 -6
- package/src/view/observer/observer.js +12 -4
- package/src/view/observer/selectionobserver.d.ts +6 -1
- package/src/view/observer/selectionobserver.js +94 -17
- package/src/view/observer/touchobserver.js +4 -7
- package/src/view/position.js +8 -0
- package/src/view/range.js +8 -0
- package/src/view/renderer.js +142 -70
- package/src/view/selection.js +16 -0
- package/src/view/stylesmap.js +26 -11
- package/src/view/text.js +6 -0
- package/src/view/textproxy.js +12 -0
- package/src/view/tokenlist.js +4 -6
- package/src/view/treewalker.js +42 -0
- package/src/view/upcastwriter.js +5 -1
- package/src/view/view.js +51 -33
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
|
4
4
|
*/
|
|
5
5
|
import { logWarning, EmitterMixin, CKEditorError, compareArrays, toArray, toMap, isIterable, ObservableMixin, count, EventInfo, Collection, keyCodes, isText, env, remove as remove$1, insertAt, diff, fastDiff, isNode, isComment, indexOf, global, isValidAttributeName, first, getAncestors, DomEmitterMixin, getCode, isArrowKeyCode, scrollViewportToShowTarget, uid, spliceArray, priorities, isInsideSurrogatePair, isInsideCombinedSymbol, isInsideEmojiSequence } from '@ckeditor/ckeditor5-utils/dist/index.js';
|
|
6
|
-
import { clone, isObject, unset, get, merge, set, isPlainObject, extend, debounce, isEqualWith, cloneDeep, isEqual } from '
|
|
6
|
+
import { clone, isObject, unset, get, merge, set, isPlainObject, extend, debounce, isEqualWith, cloneDeep, isEqual } from 'es-toolkit/compat';
|
|
7
7
|
|
|
8
8
|
// Each document stores information about its placeholder elements and check functions.
|
|
9
9
|
const documentPlaceholders = new WeakMap();
|
|
@@ -1923,10 +1923,10 @@ TextProxy$1.prototype.is = function(type) {
|
|
|
1923
1923
|
return [];
|
|
1924
1924
|
}
|
|
1925
1925
|
if (expand) {
|
|
1926
|
-
this._cachedExpandedStyleNames
|
|
1926
|
+
this._cachedExpandedStyleNames ||= this._styleProcessor.getStyleNames(this._styles);
|
|
1927
1927
|
return this._cachedExpandedStyleNames;
|
|
1928
1928
|
}
|
|
1929
|
-
this._cachedStyleNames
|
|
1929
|
+
this._cachedStyleNames ||= this.getStylesEntries().map(([key])=>key);
|
|
1930
1930
|
return this._cachedStyleNames;
|
|
1931
1931
|
}
|
|
1932
1932
|
/**
|
|
@@ -8376,16 +8376,18 @@ const validNodesToInsert = [
|
|
|
8376
8376
|
// and we should not do it because the difference between view and DOM could lead to position mapping problems.
|
|
8377
8377
|
if (this.isComposing && !env.isAndroid) {
|
|
8378
8378
|
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
8379
|
-
// @if CK_DEBUG_TYPING // console.info(
|
|
8380
|
-
// @if CK_DEBUG_TYPING // '
|
|
8381
|
-
// @if CK_DEBUG_TYPING //
|
|
8379
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'Renderer',
|
|
8380
|
+
// @if CK_DEBUG_TYPING // '%cRendering aborted while isComposing.',
|
|
8381
|
+
// @if CK_DEBUG_TYPING // 'font-style: italic'
|
|
8382
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
8382
8383
|
// @if CK_DEBUG_TYPING // }
|
|
8383
8384
|
return;
|
|
8384
8385
|
}
|
|
8385
8386
|
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
8386
|
-
// @if CK_DEBUG_TYPING // console.group( '
|
|
8387
|
-
// @if CK_DEBUG_TYPING // '
|
|
8388
|
-
// @if CK_DEBUG_TYPING //
|
|
8387
|
+
// @if CK_DEBUG_TYPING // console.group( ..._buildLogMessage( this, 'Renderer',
|
|
8388
|
+
// @if CK_DEBUG_TYPING // '%cRendering',
|
|
8389
|
+
// @if CK_DEBUG_TYPING // 'font-weight: bold'
|
|
8390
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
8389
8391
|
// @if CK_DEBUG_TYPING // }
|
|
8390
8392
|
let inlineFillerPosition = null;
|
|
8391
8393
|
const isInlineFillerRenderingPossible = env.isBlink && !env.isAndroid ? !this.isSelecting : true;
|
|
@@ -8662,9 +8664,10 @@ const validNodesToInsert = [
|
|
|
8662
8664
|
expectedText = INLINE_FILLER + expectedText;
|
|
8663
8665
|
}
|
|
8664
8666
|
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
8665
|
-
// @if CK_DEBUG_TYPING // console.group(
|
|
8666
|
-
// @if CK_DEBUG_TYPING // '
|
|
8667
|
-
// @if CK_DEBUG_TYPING //
|
|
8667
|
+
// @if CK_DEBUG_TYPING // console.group( ..._buildLogMessage( this, 'Renderer',
|
|
8668
|
+
// @if CK_DEBUG_TYPING // '%cUpdate text',
|
|
8669
|
+
// @if CK_DEBUG_TYPING // 'font-weight: normal'
|
|
8670
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
8668
8671
|
// @if CK_DEBUG_TYPING // }
|
|
8669
8672
|
this._updateTextNode(domText, expectedText);
|
|
8670
8673
|
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
@@ -8719,9 +8722,10 @@ const validNodesToInsert = [
|
|
|
8719
8722
|
return;
|
|
8720
8723
|
}
|
|
8721
8724
|
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
8722
|
-
// @if CK_DEBUG_TYPING // console.group(
|
|
8723
|
-
// @if CK_DEBUG_TYPING // '
|
|
8724
|
-
// @if CK_DEBUG_TYPING //
|
|
8725
|
+
// @if CK_DEBUG_TYPING // console.group( ..._buildLogMessage( this, 'Renderer',
|
|
8726
|
+
// @if CK_DEBUG_TYPING // '%cUpdate children',
|
|
8727
|
+
// @if CK_DEBUG_TYPING // 'font-weight: normal'
|
|
8728
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
8725
8729
|
// @if CK_DEBUG_TYPING // }
|
|
8726
8730
|
// IME on Android inserts a new text node while typing after a link
|
|
8727
8731
|
// instead of updating an existing text node that follows the link.
|
|
@@ -8753,9 +8757,10 @@ const validNodesToInsert = [
|
|
|
8753
8757
|
// The composition and different "language" browser extensions are fragile to text node being completely replaced.
|
|
8754
8758
|
const actions = this._findUpdateActions(diff, actualDomChildren, expectedDomChildren, areTextNodes);
|
|
8755
8759
|
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping && actions.every( a => a == 'equal' ) ) {
|
|
8756
|
-
// @if CK_DEBUG_TYPING // console.info(
|
|
8757
|
-
// @if CK_DEBUG_TYPING // '
|
|
8758
|
-
// @if CK_DEBUG_TYPING //
|
|
8760
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'Renderer',
|
|
8761
|
+
// @if CK_DEBUG_TYPING // '%cNothing to update.',
|
|
8762
|
+
// @if CK_DEBUG_TYPING // 'font-style: italic'
|
|
8763
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
8759
8764
|
// @if CK_DEBUG_TYPING // }
|
|
8760
8765
|
let i = 0;
|
|
8761
8766
|
const nodesToUnbind = new Set();
|
|
@@ -8770,19 +8775,20 @@ const validNodesToInsert = [
|
|
|
8770
8775
|
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
8771
8776
|
// @if CK_DEBUG_TYPING // const node = actualDomChildren[ i ];
|
|
8772
8777
|
// @if CK_DEBUG_TYPING // if ( isText( node ) ) {
|
|
8773
|
-
// @if CK_DEBUG_TYPING // console.info(
|
|
8778
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'Renderer',
|
|
8779
|
+
// @if CK_DEBUG_TYPING // '%cRemove text node' +
|
|
8774
8780
|
// @if CK_DEBUG_TYPING // `${ this.isComposing ? ' while composing (may break composition)' : '' }: ` +
|
|
8775
8781
|
// @if CK_DEBUG_TYPING // `%c${ _escapeTextNodeData( node.data ) }%c (${ node.data.length })`,
|
|
8776
|
-
// @if CK_DEBUG_TYPING // 'color:
|
|
8777
|
-
// @if CK_DEBUG_TYPING //
|
|
8778
|
-
// @if CK_DEBUG_TYPING // );
|
|
8782
|
+
// @if CK_DEBUG_TYPING // this.isComposing ? 'color: red; font-weight: bold' : '',
|
|
8783
|
+
// @if CK_DEBUG_TYPING // 'color: blue', ''
|
|
8784
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
8779
8785
|
// @if CK_DEBUG_TYPING // } else {
|
|
8780
|
-
// @if CK_DEBUG_TYPING // console.info(
|
|
8786
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'Renderer',
|
|
8787
|
+
// @if CK_DEBUG_TYPING // '%cRemove element' +
|
|
8781
8788
|
// @if CK_DEBUG_TYPING // `${ this.isComposing ? ' while composing (may break composition)' : '' }: `,
|
|
8782
|
-
// @if CK_DEBUG_TYPING // 'color: green; font-weight: bold',
|
|
8783
8789
|
// @if CK_DEBUG_TYPING // this.isComposing ? 'color: red; font-weight: bold' : '',
|
|
8784
8790
|
// @if CK_DEBUG_TYPING // node
|
|
8785
|
-
// @if CK_DEBUG_TYPING // );
|
|
8791
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
8786
8792
|
// @if CK_DEBUG_TYPING // }
|
|
8787
8793
|
// @if CK_DEBUG_TYPING // }
|
|
8788
8794
|
nodesToUnbind.add(actualDomChildren[i]);
|
|
@@ -8797,18 +8803,20 @@ const validNodesToInsert = [
|
|
|
8797
8803
|
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
8798
8804
|
// @if CK_DEBUG_TYPING // const node = expectedDomChildren[ i ];
|
|
8799
8805
|
// @if CK_DEBUG_TYPING // if ( isText( node ) ) {
|
|
8800
|
-
// @if CK_DEBUG_TYPING // console.info(
|
|
8806
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'Renderer',
|
|
8807
|
+
// @if CK_DEBUG_TYPING // '%cInsert text node' +
|
|
8801
8808
|
// @if CK_DEBUG_TYPING // `${ this.isComposing ? ' while composing (may break composition)' : '' }: ` +
|
|
8802
8809
|
// @if CK_DEBUG_TYPING // `%c${ _escapeTextNodeData( node.data ) }%c (${ node.data.length })`,
|
|
8803
|
-
// @if CK_DEBUG_TYPING // 'color: green; font-weight: bold',
|
|
8804
8810
|
// @if CK_DEBUG_TYPING // this.isComposing ? 'color: red; font-weight: bold' : '',
|
|
8805
|
-
// @if CK_DEBUG_TYPING // 'color: blue',
|
|
8806
|
-
// @if CK_DEBUG_TYPING //
|
|
8811
|
+
// @if CK_DEBUG_TYPING // 'color: blue',
|
|
8812
|
+
// @if CK_DEBUG_TYPING // ''
|
|
8813
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
8807
8814
|
// @if CK_DEBUG_TYPING // } else {
|
|
8808
|
-
// @if CK_DEBUG_TYPING // console.info(
|
|
8809
|
-
// @if CK_DEBUG_TYPING // '
|
|
8815
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'Renderer',
|
|
8816
|
+
// @if CK_DEBUG_TYPING // '%cInsert element:',
|
|
8817
|
+
// @if CK_DEBUG_TYPING // 'font-weight: normal',
|
|
8810
8818
|
// @if CK_DEBUG_TYPING // node
|
|
8811
|
-
// @if CK_DEBUG_TYPING // );
|
|
8819
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
8812
8820
|
// @if CK_DEBUG_TYPING // }
|
|
8813
8821
|
// @if CK_DEBUG_TYPING // }
|
|
8814
8822
|
insertAt(domElement, i, expectedDomChildren[i]);
|
|
@@ -8901,10 +8909,13 @@ const validNodesToInsert = [
|
|
|
8901
8909
|
const actualText = domText.data;
|
|
8902
8910
|
if (actualText == expectedText) {
|
|
8903
8911
|
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
8904
|
-
// @if CK_DEBUG_TYPING // console.info(
|
|
8912
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'Renderer',
|
|
8913
|
+
// @if CK_DEBUG_TYPING // '%cText node does not need update:%c ' +
|
|
8905
8914
|
// @if CK_DEBUG_TYPING // `${ _escapeTextNodeData( actualText ) }%c (${ actualText.length })`,
|
|
8906
|
-
// @if CK_DEBUG_TYPING // '
|
|
8907
|
-
// @if CK_DEBUG_TYPING //
|
|
8915
|
+
// @if CK_DEBUG_TYPING // 'font-style: italic',
|
|
8916
|
+
// @if CK_DEBUG_TYPING // 'color: blue',
|
|
8917
|
+
// @if CK_DEBUG_TYPING // ''
|
|
8918
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
8908
8919
|
// @if CK_DEBUG_TYPING // }
|
|
8909
8920
|
return;
|
|
8910
8921
|
}
|
|
@@ -8914,22 +8925,31 @@ const validNodesToInsert = [
|
|
|
8914
8925
|
// See: https://github.com/ckeditor/ckeditor5/issues/13994.
|
|
8915
8926
|
if (env.isAndroid && this.isComposing && actualText.replace(/\u00A0/g, ' ') == expectedText.replace(/\u00A0/g, ' ')) {
|
|
8916
8927
|
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
8917
|
-
// @if CK_DEBUG_TYPING // console.info(
|
|
8918
|
-
// @if CK_DEBUG_TYPING //
|
|
8919
|
-
// @if CK_DEBUG_TYPING //
|
|
8920
|
-
// @if CK_DEBUG_TYPING //
|
|
8921
|
-
// @if CK_DEBUG_TYPING //
|
|
8928
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'Renderer',
|
|
8929
|
+
// @if CK_DEBUG_TYPING // '%cText node ignore NBSP changes while composing: ' +
|
|
8930
|
+
// @if CK_DEBUG_TYPING // `%c${ _escapeTextNodeData( actualText ) }%c (${ actualText.length }) -> ` +
|
|
8931
|
+
// @if CK_DEBUG_TYPING // `%c${ _escapeTextNodeData( expectedText ) }%c (${ expectedText.length })`,
|
|
8932
|
+
// @if CK_DEBUG_TYPING // 'font-style: italic',
|
|
8933
|
+
// @if CK_DEBUG_TYPING // 'color: blue',
|
|
8934
|
+
// @if CK_DEBUG_TYPING // '',
|
|
8935
|
+
// @if CK_DEBUG_TYPING // 'color: blue',
|
|
8936
|
+
// @if CK_DEBUG_TYPING // ''
|
|
8937
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
8922
8938
|
// @if CK_DEBUG_TYPING // }
|
|
8923
8939
|
return;
|
|
8924
8940
|
}
|
|
8925
8941
|
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
8926
|
-
// @if CK_DEBUG_TYPING // console.info(
|
|
8942
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'Renderer',
|
|
8943
|
+
// @if CK_DEBUG_TYPING // '%cUpdate text node' +
|
|
8927
8944
|
// @if CK_DEBUG_TYPING // `${ this.isComposing ? ' while composing (may break composition)' : '' }: ` +
|
|
8928
|
-
// @if CK_DEBUG_TYPING // `%c${ _escapeTextNodeData( actualText ) }%c (${ actualText.length })
|
|
8929
|
-
// @if CK_DEBUG_TYPING //
|
|
8930
|
-
// @if CK_DEBUG_TYPING //
|
|
8931
|
-
// @if CK_DEBUG_TYPING // 'color: blue',
|
|
8932
|
-
// @if CK_DEBUG_TYPING //
|
|
8945
|
+
// @if CK_DEBUG_TYPING // `%c${ _escapeTextNodeData( actualText ) }%c (${ actualText.length }) -> ` +
|
|
8946
|
+
// @if CK_DEBUG_TYPING // `%c${ _escapeTextNodeData( expectedText ) }%c (${ expectedText.length })`,
|
|
8947
|
+
// @if CK_DEBUG_TYPING // this.isComposing ? 'color: red; font-weight: bold' : '',
|
|
8948
|
+
// @if CK_DEBUG_TYPING // 'color: blue',
|
|
8949
|
+
// @if CK_DEBUG_TYPING // '',
|
|
8950
|
+
// @if CK_DEBUG_TYPING // 'color: blue',
|
|
8951
|
+
// @if CK_DEBUG_TYPING // ''
|
|
8952
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
8933
8953
|
// @if CK_DEBUG_TYPING // }
|
|
8934
8954
|
this._updateTextNodeInternal(domText, expectedText);
|
|
8935
8955
|
}
|
|
@@ -8975,6 +8995,11 @@ const validNodesToInsert = [
|
|
|
8975
8995
|
}
|
|
8976
8996
|
// If there is no selection - remove DOM and fake selections.
|
|
8977
8997
|
if (this.selection.rangeCount === 0) {
|
|
8998
|
+
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
8999
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'Renderer',
|
|
9000
|
+
// @if CK_DEBUG_TYPING // 'Update DOM selection: remove all ranges'
|
|
9001
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
9002
|
+
// @if CK_DEBUG_TYPING // }
|
|
8978
9003
|
this._removeDomSelection();
|
|
8979
9004
|
this._removeFakeSelection();
|
|
8980
9005
|
return;
|
|
@@ -8982,8 +9007,19 @@ const validNodesToInsert = [
|
|
|
8982
9007
|
const domRoot = this.domConverter.mapViewToDom(this.selection.editableElement);
|
|
8983
9008
|
// Do nothing if there is no focus, or there is no DOM element corresponding to selection's editable element.
|
|
8984
9009
|
if (!this.isFocused || !domRoot) {
|
|
9010
|
+
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
9011
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'Renderer',
|
|
9012
|
+
// @if CK_DEBUG_TYPING // 'Skip updating DOM selection:',
|
|
9013
|
+
// @if CK_DEBUG_TYPING // `isFocused: ${ this.isFocused }, hasDomRoot: ${ !!domRoot }`
|
|
9014
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
9015
|
+
// @if CK_DEBUG_TYPING // }
|
|
8985
9016
|
return;
|
|
8986
9017
|
}
|
|
9018
|
+
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
9019
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'Renderer',
|
|
9020
|
+
// @if CK_DEBUG_TYPING // 'Update DOM selection'
|
|
9021
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
9022
|
+
// @if CK_DEBUG_TYPING // }
|
|
8987
9023
|
// Render fake selection - create the fake selection container (if needed) and move DOM selection to it.
|
|
8988
9024
|
if (this.selection.isFake) {
|
|
8989
9025
|
this._updateFakeSelection(domRoot);
|
|
@@ -9013,6 +9049,11 @@ const validNodesToInsert = [
|
|
|
9013
9049
|
domRoot.appendChild(container);
|
|
9014
9050
|
}
|
|
9015
9051
|
container.textContent = this.selection.fakeSelectionLabel || '\u00A0';
|
|
9052
|
+
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
9053
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'Renderer',
|
|
9054
|
+
// @if CK_DEBUG_TYPING // 'Set DOM fake selection'
|
|
9055
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
9056
|
+
// @if CK_DEBUG_TYPING // }
|
|
9016
9057
|
const domSelection = domDocument.getSelection();
|
|
9017
9058
|
const domRange = domDocument.createRange();
|
|
9018
9059
|
domSelection.removeAllRanges();
|
|
@@ -9027,6 +9068,12 @@ const validNodesToInsert = [
|
|
|
9027
9068
|
const domSelection = domRoot.ownerDocument.defaultView.getSelection();
|
|
9028
9069
|
// Let's check whether DOM selection needs updating at all.
|
|
9029
9070
|
if (!this._domSelectionNeedsUpdate(domSelection)) {
|
|
9071
|
+
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
9072
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'Renderer',
|
|
9073
|
+
// @if CK_DEBUG_TYPING // '%cDOM selection is already correct',
|
|
9074
|
+
// @if CK_DEBUG_TYPING // 'font-style: italic;'
|
|
9075
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
9076
|
+
// @if CK_DEBUG_TYPING // }
|
|
9030
9077
|
return;
|
|
9031
9078
|
}
|
|
9032
9079
|
// Multi-range selection is not available in most browsers, and, at least in Chrome, trying to
|
|
@@ -9037,9 +9084,11 @@ const validNodesToInsert = [
|
|
|
9037
9084
|
const anchor = this.domConverter.viewPositionToDom(this.selection.anchor);
|
|
9038
9085
|
const focus = this.domConverter.viewPositionToDom(this.selection.focus);
|
|
9039
9086
|
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
9040
|
-
// @if CK_DEBUG_TYPING // console.info(
|
|
9041
|
-
// @if CK_DEBUG_TYPING // '
|
|
9042
|
-
// @if CK_DEBUG_TYPING //
|
|
9087
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'Renderer',
|
|
9088
|
+
// @if CK_DEBUG_TYPING // 'Update DOM selection:',
|
|
9089
|
+
// @if CK_DEBUG_TYPING // anchor,
|
|
9090
|
+
// @if CK_DEBUG_TYPING // focus
|
|
9091
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
9043
9092
|
// @if CK_DEBUG_TYPING // }
|
|
9044
9093
|
domSelection.setBaseAndExtent(anchor.parent, anchor.offset, focus.parent, focus.offset);
|
|
9045
9094
|
// Firefox–specific hack (https://github.com/ckeditor/ckeditor5-engine/issues/1439).
|
|
@@ -9111,12 +9160,26 @@ const validNodesToInsert = [
|
|
|
9111
9160
|
/**
|
|
9112
9161
|
* Checks if focus needs to be updated and possibly updates it.
|
|
9113
9162
|
*/ _updateFocus() {
|
|
9163
|
+
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
9164
|
+
// @if CK_DEBUG_TYPING // console.group( ..._buildLogMessage( this, 'Renderer',
|
|
9165
|
+
// @if CK_DEBUG_TYPING // `update focus: ${ this.isFocused ? 'focused' : 'not focused' }`
|
|
9166
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
9167
|
+
// @if CK_DEBUG_TYPING // }
|
|
9114
9168
|
if (this.isFocused) {
|
|
9115
9169
|
const editable = this.selection.editableElement;
|
|
9170
|
+
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
9171
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'Renderer',
|
|
9172
|
+
// @if CK_DEBUG_TYPING // 'focus editable:',
|
|
9173
|
+
// @if CK_DEBUG_TYPING // { editable }
|
|
9174
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
9175
|
+
// @if CK_DEBUG_TYPING // }
|
|
9116
9176
|
if (editable) {
|
|
9117
9177
|
this.domConverter.focus(editable);
|
|
9118
9178
|
}
|
|
9119
9179
|
}
|
|
9180
|
+
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
9181
|
+
// @if CK_DEBUG_TYPING // console.groupEnd();
|
|
9182
|
+
// @if CK_DEBUG_TYPING // }
|
|
9120
9183
|
}
|
|
9121
9184
|
}
|
|
9122
9185
|
/**
|
|
@@ -9298,7 +9361,7 @@ const UNSAFE_ELEMENT_REPLACEMENT_ATTRIBUTE = 'data-ck-unsafe-element';
|
|
|
9298
9361
|
* `<span data-ck-unsafe-element="[element name]"></span>` while rendering in the editing mode.
|
|
9299
9362
|
*/ unsafeElements;
|
|
9300
9363
|
/**
|
|
9301
|
-
* The DOM Document used to create DOM nodes.
|
|
9364
|
+
* The DOM Document used by `DomConverter` to create DOM nodes.
|
|
9302
9365
|
*/ _domDocument;
|
|
9303
9366
|
/**
|
|
9304
9367
|
* The DOM-to-view mapping.
|
|
@@ -9403,6 +9466,11 @@ const UNSAFE_ELEMENT_REPLACEMENT_ATTRIBUTE = 'data-ck-unsafe-element';
|
|
|
9403
9466
|
];
|
|
9404
9467
|
this._domDocument = this.renderingMode === 'editing' ? global.document : global.document.implementation.createHTMLDocument('');
|
|
9405
9468
|
}
|
|
9469
|
+
/**
|
|
9470
|
+
* The DOM Document used by `DomConverter` to create DOM nodes.
|
|
9471
|
+
*/ get domDocument() {
|
|
9472
|
+
return this._domDocument;
|
|
9473
|
+
}
|
|
9406
9474
|
/**
|
|
9407
9475
|
* Binds a given DOM element that represents fake selection to a **position** of a
|
|
9408
9476
|
* {@link module:engine/view/documentselection~DocumentSelection document selection}.
|
|
@@ -10075,33 +10143,46 @@ const UNSAFE_ELEMENT_REPLACEMENT_ATTRIBUTE = 'data-ck-unsafe-element';
|
|
|
10075
10143
|
* Focuses DOM editable that is corresponding to provided {@link module:engine/view/editableelement~EditableElement}.
|
|
10076
10144
|
*/ focus(viewEditable) {
|
|
10077
10145
|
const domEditable = this.mapViewToDom(viewEditable);
|
|
10078
|
-
if (domEditable
|
|
10079
|
-
//
|
|
10080
|
-
|
|
10081
|
-
|
|
10082
|
-
//
|
|
10083
|
-
//
|
|
10084
|
-
|
|
10085
|
-
|
|
10086
|
-
scrollPositions.push([
|
|
10087
|
-
scrollLeft,
|
|
10088
|
-
scrollTop
|
|
10089
|
-
]);
|
|
10090
|
-
});
|
|
10091
|
-
domEditable.focus();
|
|
10092
|
-
// Restore scrollLeft and scrollTop values starting from domEditable up to
|
|
10093
|
-
// document#documentElement.
|
|
10094
|
-
// https://github.com/ckeditor/ckeditor5-engine/issues/951
|
|
10095
|
-
// https://github.com/ckeditor/ckeditor5-engine/issues/957
|
|
10096
|
-
forEachDomElementAncestor(domEditable, (node)=>{
|
|
10097
|
-
const [scrollLeft, scrollTop] = scrollPositions.shift();
|
|
10098
|
-
node.scrollLeft = scrollLeft;
|
|
10099
|
-
node.scrollTop = scrollTop;
|
|
10100
|
-
});
|
|
10101
|
-
// Restore the scrollX and scrollY positions after the focus.
|
|
10102
|
-
// https://github.com/ckeditor/ckeditor5-engine/issues/951
|
|
10103
|
-
global.window.scrollTo(scrollX, scrollY);
|
|
10146
|
+
if (!domEditable || domEditable.ownerDocument.activeElement === domEditable) {
|
|
10147
|
+
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
10148
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'DomConverter',
|
|
10149
|
+
// @if CK_DEBUG_TYPING // '%cDOM editable is already active or does not exist',
|
|
10150
|
+
// @if CK_DEBUG_TYPING // 'font-style: italic'
|
|
10151
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
10152
|
+
// @if CK_DEBUG_TYPING // }
|
|
10153
|
+
return;
|
|
10104
10154
|
}
|
|
10155
|
+
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
10156
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'DomConverter',
|
|
10157
|
+
// @if CK_DEBUG_TYPING // 'Focus DOM editable:',
|
|
10158
|
+
// @if CK_DEBUG_TYPING // { domEditable }
|
|
10159
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
10160
|
+
// @if CK_DEBUG_TYPING // }
|
|
10161
|
+
// Save the scrollX and scrollY positions before the focus.
|
|
10162
|
+
const { scrollX, scrollY } = global.window;
|
|
10163
|
+
const scrollPositions = [];
|
|
10164
|
+
// Save all scrollLeft and scrollTop values starting from domEditable up to
|
|
10165
|
+
// document#documentElement.
|
|
10166
|
+
forEachDomElementAncestor(domEditable, (node)=>{
|
|
10167
|
+
const { scrollLeft, scrollTop } = node;
|
|
10168
|
+
scrollPositions.push([
|
|
10169
|
+
scrollLeft,
|
|
10170
|
+
scrollTop
|
|
10171
|
+
]);
|
|
10172
|
+
});
|
|
10173
|
+
domEditable.focus();
|
|
10174
|
+
// Restore scrollLeft and scrollTop values starting from domEditable up to
|
|
10175
|
+
// document#documentElement.
|
|
10176
|
+
// https://github.com/ckeditor/ckeditor5-engine/issues/951
|
|
10177
|
+
// https://github.com/ckeditor/ckeditor5-engine/issues/957
|
|
10178
|
+
forEachDomElementAncestor(domEditable, (node)=>{
|
|
10179
|
+
const [scrollLeft, scrollTop] = scrollPositions.shift();
|
|
10180
|
+
node.scrollLeft = scrollLeft;
|
|
10181
|
+
node.scrollTop = scrollTop;
|
|
10182
|
+
});
|
|
10183
|
+
// Restore the scrollX and scrollY positions after the focus.
|
|
10184
|
+
// https://github.com/ckeditor/ckeditor5-engine/issues/951
|
|
10185
|
+
global.window.scrollTo(scrollX, scrollY);
|
|
10105
10186
|
}
|
|
10106
10187
|
/**
|
|
10107
10188
|
* Remove DOM selection from blurred editable, so it won't interfere with clicking on dropdowns (especially on iOS).
|
|
@@ -11042,7 +11123,7 @@ const UNSAFE_ELEMENT_REPLACEMENT_ATTRIBUTE = 'data-ck-unsafe-element';
|
|
|
11042
11123
|
* {@link module:engine/view/observer/selectionobserver~SelectionObserver SelectionObserver}.
|
|
11043
11124
|
*/ class FakeSelectionObserver extends Observer {
|
|
11044
11125
|
/**
|
|
11045
|
-
* Fires debounced event `selectionChangeDone`. It uses `
|
|
11126
|
+
* Fires debounced event `selectionChangeDone`. It uses `es-toolkit#debounce` method to delay function call.
|
|
11046
11127
|
*/ _fireSelectionChangeDoneDebounced;
|
|
11047
11128
|
/**
|
|
11048
11129
|
* Creates new FakeSelectionObserver instance.
|
|
@@ -11119,7 +11200,7 @@ const UNSAFE_ELEMENT_REPLACEMENT_ATTRIBUTE = 'data-ck-unsafe-element';
|
|
|
11119
11200
|
}
|
|
11120
11201
|
}
|
|
11121
11202
|
|
|
11122
|
-
// @if CK_DEBUG_TYPING // const { _debouncedLine } = require( '../../dev-utils/utils.js' );
|
|
11203
|
+
// @if CK_DEBUG_TYPING // const { _debouncedLine, _buildLogMessage } = require( '../../dev-utils/utils.js' );
|
|
11123
11204
|
/**
|
|
11124
11205
|
* Mutation observer's role is to watch for any DOM changes inside the editor that weren't
|
|
11125
11206
|
* done by the editor's {@link module:engine/view/renderer~Renderer} itself and reverting these changes.
|
|
@@ -11274,9 +11355,10 @@ const UNSAFE_ELEMENT_REPLACEMENT_ATTRIBUTE = 'data-ck-unsafe-element';
|
|
|
11274
11355
|
if (mutations.length) {
|
|
11275
11356
|
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
11276
11357
|
// @if CK_DEBUG_TYPING // _debouncedLine();
|
|
11277
|
-
// @if CK_DEBUG_TYPING // console.group(
|
|
11278
|
-
// @if CK_DEBUG_TYPING // '
|
|
11279
|
-
// @if CK_DEBUG_TYPING //
|
|
11358
|
+
// @if CK_DEBUG_TYPING // console.group( ..._buildLogMessage( this, 'MutationObserver',
|
|
11359
|
+
// @if CK_DEBUG_TYPING // '%cMutations detected',
|
|
11360
|
+
// @if CK_DEBUG_TYPING // 'font-weight: bold'
|
|
11361
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
11280
11362
|
// @if CK_DEBUG_TYPING // }
|
|
11281
11363
|
this.document.fire('mutations', {
|
|
11282
11364
|
mutations
|
|
@@ -11304,7 +11386,7 @@ const UNSAFE_ELEMENT_REPLACEMENT_ATTRIBUTE = 'data-ck-unsafe-element';
|
|
|
11304
11386
|
}
|
|
11305
11387
|
}
|
|
11306
11388
|
function sameNodes(child1, child2) {
|
|
11307
|
-
// First level of comparison (array of children vs array of children) – use the
|
|
11389
|
+
// First level of comparison (array of children vs array of children) – use the es-toolkit's default behavior.
|
|
11308
11390
|
if (Array.isArray(child1)) {
|
|
11309
11391
|
return;
|
|
11310
11392
|
}
|
|
@@ -11318,6 +11400,7 @@ function sameNodes(child1, child2) {
|
|
|
11318
11400
|
return false;
|
|
11319
11401
|
}
|
|
11320
11402
|
|
|
11403
|
+
// @if CK_DEBUG_TYPING // const { _debouncedLine, _buildLogMessage } = require( '../../dev-utils/utils.js' );
|
|
11321
11404
|
/**
|
|
11322
11405
|
* {@link module:engine/view/document~Document#event:focus Focus}
|
|
11323
11406
|
* and {@link module:engine/view/document~Document#event:blur blur} events observer.
|
|
@@ -11364,14 +11447,42 @@ function sameNodes(child1, child2) {
|
|
|
11364
11447
|
* Finishes setting the document focus state.
|
|
11365
11448
|
*/ flush() {
|
|
11366
11449
|
if (this._isFocusChanging) {
|
|
11450
|
+
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
11451
|
+
// @if CK_DEBUG_TYPING // _debouncedLine();
|
|
11452
|
+
// @if CK_DEBUG_TYPING // console.group( ..._buildLogMessage( this, 'FocusObserver',
|
|
11453
|
+
// @if CK_DEBUG_TYPING // 'flush focus'
|
|
11454
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
11455
|
+
// @if CK_DEBUG_TYPING // }
|
|
11367
11456
|
this._isFocusChanging = false;
|
|
11368
11457
|
this.document.isFocused = true;
|
|
11458
|
+
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
11459
|
+
// @if CK_DEBUG_TYPING // console.groupEnd();
|
|
11460
|
+
// @if CK_DEBUG_TYPING // }
|
|
11369
11461
|
}
|
|
11370
11462
|
}
|
|
11371
11463
|
/**
|
|
11372
11464
|
* @inheritDoc
|
|
11373
11465
|
*/ onDomEvent(domEvent) {
|
|
11466
|
+
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
11467
|
+
// @if CK_DEBUG_TYPING // _debouncedLine();
|
|
11468
|
+
// @if CK_DEBUG_TYPING // console.group( ..._buildLogMessage( this, 'FocusObserver',
|
|
11469
|
+
// @if CK_DEBUG_TYPING // `${ domEvent.type } event`
|
|
11470
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
11471
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'FocusObserver',
|
|
11472
|
+
// @if CK_DEBUG_TYPING // 'DOM target:',
|
|
11473
|
+
// @if CK_DEBUG_TYPING // { target: domEvent.target, relatedTarget: domEvent.relatedTarget }
|
|
11474
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
11475
|
+
// @if CK_DEBUG_TYPING // const domSelection = window.getSelection();
|
|
11476
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'FocusObserver',
|
|
11477
|
+
// @if CK_DEBUG_TYPING // 'DOM Selection:',
|
|
11478
|
+
// @if CK_DEBUG_TYPING // { node: domSelection!.anchorNode, offset: domSelection!.anchorOffset },
|
|
11479
|
+
// @if CK_DEBUG_TYPING // { node: domSelection!.focusNode, offset: domSelection!.focusOffset }
|
|
11480
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
11481
|
+
// @if CK_DEBUG_TYPING // }
|
|
11374
11482
|
this.fire(domEvent.type, domEvent);
|
|
11483
|
+
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
11484
|
+
// @if CK_DEBUG_TYPING // console.groupEnd();
|
|
11485
|
+
// @if CK_DEBUG_TYPING // }
|
|
11375
11486
|
}
|
|
11376
11487
|
/**
|
|
11377
11488
|
* @inheritDoc
|
|
@@ -11394,20 +11505,42 @@ function sameNodes(child1, child2) {
|
|
|
11394
11505
|
// in a situation where `selectionchange` already caused selection change.
|
|
11395
11506
|
this._renderTimeoutId = setTimeout(()=>{
|
|
11396
11507
|
this._renderTimeoutId = null;
|
|
11508
|
+
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
11509
|
+
// @if CK_DEBUG_TYPING // console.group( ..._buildLogMessage( this, 'FocusObserver',
|
|
11510
|
+
// @if CK_DEBUG_TYPING // 'flush on timeout'
|
|
11511
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
11512
|
+
// @if CK_DEBUG_TYPING // }
|
|
11397
11513
|
this.flush();
|
|
11398
11514
|
this.view.change(()=>{});
|
|
11515
|
+
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
11516
|
+
// @if CK_DEBUG_TYPING // console.groupEnd();
|
|
11517
|
+
// @if CK_DEBUG_TYPING // }
|
|
11399
11518
|
}, 50);
|
|
11400
11519
|
}
|
|
11401
11520
|
/**
|
|
11402
11521
|
* The `blur` event handler.
|
|
11403
11522
|
*/ _handleBlur(data) {
|
|
11404
11523
|
const selectedEditable = this.document.selection.editableElement;
|
|
11524
|
+
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
11525
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'FocusObserver',
|
|
11526
|
+
// @if CK_DEBUG_TYPING // 'selectedEditable:',
|
|
11527
|
+
// @if CK_DEBUG_TYPING // { selectedEditable }
|
|
11528
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
11529
|
+
// @if CK_DEBUG_TYPING // }
|
|
11405
11530
|
if (selectedEditable === null || selectedEditable === data.target) {
|
|
11531
|
+
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
11532
|
+
// @if CK_DEBUG_TYPING // console.group( ..._buildLogMessage( this, 'FocusObserver',
|
|
11533
|
+
// @if CK_DEBUG_TYPING // 'document no longer focused'
|
|
11534
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
11535
|
+
// @if CK_DEBUG_TYPING // }
|
|
11406
11536
|
this.document.isFocused = false;
|
|
11407
11537
|
this._isFocusChanging = false;
|
|
11408
11538
|
// Re-render the document to update view elements
|
|
11409
11539
|
// (changing document.isFocused already marked view as changed since last rendering).
|
|
11410
11540
|
this.view.change(()=>{});
|
|
11541
|
+
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
11542
|
+
// @if CK_DEBUG_TYPING // console.groupEnd();
|
|
11543
|
+
// @if CK_DEBUG_TYPING // }
|
|
11411
11544
|
}
|
|
11412
11545
|
}
|
|
11413
11546
|
/**
|
|
@@ -11449,9 +11582,9 @@ function sameNodes(child1, child2) {
|
|
|
11449
11582
|
/**
|
|
11450
11583
|
* A set of documents which have added `selectionchange` listener to avoid adding a listener twice to the same
|
|
11451
11584
|
* document.
|
|
11452
|
-
*/ _documents;
|
|
11585
|
+
*/ _documents = new WeakSet();
|
|
11453
11586
|
/**
|
|
11454
|
-
* Fires debounced event `selectionChangeDone`. It uses `
|
|
11587
|
+
* Fires debounced event `selectionChangeDone`. It uses `es-toolkit#debounce` method to delay function call.
|
|
11455
11588
|
*/ _fireSelectionChangeDoneDebounced;
|
|
11456
11589
|
/**
|
|
11457
11590
|
* When called, starts clearing the {@link #_loopbackCounter} counter in time intervals. When the number of selection
|
|
@@ -11465,20 +11598,36 @@ function sameNodes(child1, child2) {
|
|
|
11465
11598
|
*/ _documentIsSelectingInactivityTimeoutDebounced;
|
|
11466
11599
|
/**
|
|
11467
11600
|
* Private property to check if the code does not enter infinite loop.
|
|
11468
|
-
*/ _loopbackCounter;
|
|
11601
|
+
*/ _loopbackCounter = 0;
|
|
11602
|
+
/**
|
|
11603
|
+
* A set of DOM documents that have a pending selection change.
|
|
11604
|
+
* Pending selection change is recorded while selection change event is detected on non focused editable.
|
|
11605
|
+
*/ _pendingSelectionChange = new Set();
|
|
11469
11606
|
constructor(view){
|
|
11470
11607
|
super(view);
|
|
11471
11608
|
this.mutationObserver = view.getObserver(MutationObserver);
|
|
11472
11609
|
this.focusObserver = view.getObserver(FocusObserver);
|
|
11473
11610
|
this.selection = this.document.selection;
|
|
11474
11611
|
this.domConverter = view.domConverter;
|
|
11475
|
-
this._documents = new WeakSet();
|
|
11476
11612
|
this._fireSelectionChangeDoneDebounced = debounce((data)=>{
|
|
11477
11613
|
this.document.fire('selectionChangeDone', data);
|
|
11478
11614
|
}, 200);
|
|
11479
11615
|
this._clearInfiniteLoopInterval = setInterval(()=>this._clearInfiniteLoop(), 1000);
|
|
11480
11616
|
this._documentIsSelectingInactivityTimeoutDebounced = debounce(()=>this.document.isSelecting = false, 5000);
|
|
11481
|
-
this.
|
|
11617
|
+
this.view.document.on('change:isFocused', (evt, name, isFocused)=>{
|
|
11618
|
+
if (isFocused && this._pendingSelectionChange.size) {
|
|
11619
|
+
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
11620
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'SelectionObserver',
|
|
11621
|
+
// @if CK_DEBUG_TYPING // 'Flush pending selection change'
|
|
11622
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
11623
|
+
// @if CK_DEBUG_TYPING // }
|
|
11624
|
+
// Iterate over a copy of set because it is modified in selection change handler.
|
|
11625
|
+
for (const domDocument of Array.from(this._pendingSelectionChange)){
|
|
11626
|
+
this._handleSelectionChange(domDocument);
|
|
11627
|
+
}
|
|
11628
|
+
this._pendingSelectionChange.clear();
|
|
11629
|
+
}
|
|
11630
|
+
});
|
|
11482
11631
|
}
|
|
11483
11632
|
/**
|
|
11484
11633
|
* @inheritDoc
|
|
@@ -11528,20 +11677,22 @@ function sameNodes(child1, child2) {
|
|
|
11528
11677
|
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
11529
11678
|
// @if CK_DEBUG_TYPING // _debouncedLine();
|
|
11530
11679
|
// @if CK_DEBUG_TYPING // const domSelection = domDocument.defaultView!.getSelection();
|
|
11531
|
-
// @if CK_DEBUG_TYPING // console.group(
|
|
11532
|
-
// @if CK_DEBUG_TYPING //
|
|
11533
|
-
// @if CK_DEBUG_TYPING //
|
|
11680
|
+
// @if CK_DEBUG_TYPING // console.group( ..._buildLogMessage( this, 'SelectionObserver',
|
|
11681
|
+
// @if CK_DEBUG_TYPING // 'selectionchange'
|
|
11682
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
11683
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'SelectionObserver',
|
|
11684
|
+
// @if CK_DEBUG_TYPING // 'DOM Selection:',
|
|
11534
11685
|
// @if CK_DEBUG_TYPING // { node: domSelection!.anchorNode, offset: domSelection!.anchorOffset },
|
|
11535
11686
|
// @if CK_DEBUG_TYPING // { node: domSelection!.focusNode, offset: domSelection!.focusOffset }
|
|
11536
|
-
// @if CK_DEBUG_TYPING // );
|
|
11687
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
11537
11688
|
// @if CK_DEBUG_TYPING // }
|
|
11538
11689
|
// The Renderer is disabled while composing on non-android browsers, so we can't update the view selection
|
|
11539
11690
|
// because the DOM and view tree drifted apart. Position mapping could fail because of it.
|
|
11540
11691
|
if (this.document.isComposing && !env.isAndroid) {
|
|
11541
11692
|
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
11542
|
-
// @if CK_DEBUG_TYPING // console.info(
|
|
11543
|
-
// @if CK_DEBUG_TYPING //
|
|
11544
|
-
// @if CK_DEBUG_TYPING //
|
|
11693
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'SelectionObserver',
|
|
11694
|
+
// @if CK_DEBUG_TYPING // 'Selection change ignored (isComposing)'
|
|
11695
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
11545
11696
|
// @if CK_DEBUG_TYPING // console.groupEnd();
|
|
11546
11697
|
// @if CK_DEBUG_TYPING // }
|
|
11547
11698
|
return;
|
|
@@ -11560,12 +11711,14 @@ function sameNodes(child1, child2) {
|
|
|
11560
11711
|
this.listenTo(this.view.document, 'compositionstart', ()=>{
|
|
11561
11712
|
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
11562
11713
|
// @if CK_DEBUG_TYPING // const domSelection = domDocument.defaultView!.getSelection();
|
|
11563
|
-
// @if CK_DEBUG_TYPING // console.group(
|
|
11564
|
-
// @if CK_DEBUG_TYPING //
|
|
11565
|
-
// @if CK_DEBUG_TYPING //
|
|
11714
|
+
// @if CK_DEBUG_TYPING // console.group( ..._buildLogMessage( this, 'SelectionObserver',
|
|
11715
|
+
// @if CK_DEBUG_TYPING // 'update selection on compositionstart'
|
|
11716
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
11717
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'SelectionObserver',
|
|
11718
|
+
// @if CK_DEBUG_TYPING // 'DOM Selection:',
|
|
11566
11719
|
// @if CK_DEBUG_TYPING // { node: domSelection!.anchorNode, offset: domSelection!.anchorOffset },
|
|
11567
11720
|
// @if CK_DEBUG_TYPING // { node: domSelection!.focusNode, offset: domSelection!.focusOffset }
|
|
11568
|
-
// @if CK_DEBUG_TYPING // );
|
|
11721
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
11569
11722
|
// @if CK_DEBUG_TYPING // }
|
|
11570
11723
|
this._handleSelectionChange(domDocument);
|
|
11571
11724
|
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
@@ -11623,6 +11776,17 @@ function sameNodes(child1, child2) {
|
|
|
11623
11776
|
this.view.hasDomSelection = true;
|
|
11624
11777
|
// Mark the latest focus change as complete (we got new selection after the focus so the selection is in the focused element).
|
|
11625
11778
|
this.focusObserver.flush();
|
|
11779
|
+
// Ignore selection change as the editable is not focused.
|
|
11780
|
+
if (!this.view.document.isFocused) {
|
|
11781
|
+
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
11782
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'SelectionObserver',
|
|
11783
|
+
// @if CK_DEBUG_TYPING // 'Ignore selection change while editable is not focused'
|
|
11784
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
11785
|
+
// @if CK_DEBUG_TYPING // }
|
|
11786
|
+
this._pendingSelectionChange.add(domDocument);
|
|
11787
|
+
return;
|
|
11788
|
+
}
|
|
11789
|
+
this._pendingSelectionChange.delete(domDocument);
|
|
11626
11790
|
if (this.selection.isEqual(newViewSelection) && this.domConverter.isDomSelectionCorrect(domSelection)) {
|
|
11627
11791
|
return;
|
|
11628
11792
|
}
|
|
@@ -11648,10 +11812,10 @@ function sameNodes(child1, child2) {
|
|
|
11648
11812
|
domSelection
|
|
11649
11813
|
};
|
|
11650
11814
|
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
11651
|
-
// @if CK_DEBUG_TYPING // console.info(
|
|
11652
|
-
// @if CK_DEBUG_TYPING // '
|
|
11815
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'SelectionObserver',
|
|
11816
|
+
// @if CK_DEBUG_TYPING // 'Fire selection change:',
|
|
11653
11817
|
// @if CK_DEBUG_TYPING // newViewSelection.getFirstRange()
|
|
11654
|
-
// @if CK_DEBUG_TYPING // );
|
|
11818
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
11655
11819
|
// @if CK_DEBUG_TYPING // }
|
|
11656
11820
|
// Prepare data for new selection and fire appropriate events.
|
|
11657
11821
|
this.document.fire('selectionChange', data);
|
|
@@ -11669,7 +11833,7 @@ function sameNodes(child1, child2) {
|
|
|
11669
11833
|
}
|
|
11670
11834
|
}
|
|
11671
11835
|
|
|
11672
|
-
// @if CK_DEBUG_TYPING // const { _debouncedLine } = require( '../../dev-utils/utils.js' );
|
|
11836
|
+
// @if CK_DEBUG_TYPING // const { _debouncedLine, _buildLogMessage } = require( '../../dev-utils/utils.js' );
|
|
11673
11837
|
/**
|
|
11674
11838
|
* {@link module:engine/view/document~Document#event:compositionstart Compositionstart},
|
|
11675
11839
|
* {@link module:engine/view/document~Document#event:compositionupdate compositionupdate} and
|
|
@@ -11691,10 +11855,10 @@ function sameNodes(child1, child2) {
|
|
|
11691
11855
|
const document = this.document;
|
|
11692
11856
|
document.on('compositionstart', ()=>{
|
|
11693
11857
|
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
11694
|
-
// @if CK_DEBUG_TYPING // console.log( '
|
|
11695
|
-
// @if CK_DEBUG_TYPING // '┌───────────────────────────── isComposing = true ─────────────────────────────┐',
|
|
11858
|
+
// @if CK_DEBUG_TYPING // console.log( ..._buildLogMessage( this, 'CompositionObserver',
|
|
11859
|
+
// @if CK_DEBUG_TYPING // '%c┌───────────────────────────── isComposing = true ─────────────────────────────┐',
|
|
11696
11860
|
// @if CK_DEBUG_TYPING // 'font-weight: bold; color: green'
|
|
11697
|
-
// @if CK_DEBUG_TYPING // );
|
|
11861
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
11698
11862
|
// @if CK_DEBUG_TYPING // }
|
|
11699
11863
|
document.isComposing = true;
|
|
11700
11864
|
}, {
|
|
@@ -11702,10 +11866,10 @@ function sameNodes(child1, child2) {
|
|
|
11702
11866
|
});
|
|
11703
11867
|
document.on('compositionend', ()=>{
|
|
11704
11868
|
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
11705
|
-
// @if CK_DEBUG_TYPING // console.log( '
|
|
11706
|
-
// @if CK_DEBUG_TYPING // '└───────────────────────────── isComposing = false ─────────────────────────────┘',
|
|
11869
|
+
// @if CK_DEBUG_TYPING // console.log( ..._buildLogMessage( this, 'CompositionObserver',
|
|
11870
|
+
// @if CK_DEBUG_TYPING // '%c└───────────────────────────── isComposing = false ─────────────────────────────┘',
|
|
11707
11871
|
// @if CK_DEBUG_TYPING // 'font-weight: bold; color: green'
|
|
11708
|
-
// @if CK_DEBUG_TYPING // );
|
|
11872
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
11709
11873
|
// @if CK_DEBUG_TYPING // }
|
|
11710
11874
|
document.isComposing = false;
|
|
11711
11875
|
}, {
|
|
@@ -11717,7 +11881,9 @@ function sameNodes(child1, child2) {
|
|
|
11717
11881
|
*/ onDomEvent(domEvent) {
|
|
11718
11882
|
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
11719
11883
|
// @if CK_DEBUG_TYPING // _debouncedLine();
|
|
11720
|
-
// @if CK_DEBUG_TYPING // console.group(
|
|
11884
|
+
// @if CK_DEBUG_TYPING // console.group( ..._buildLogMessage( this, 'CompositionObserver',
|
|
11885
|
+
// @if CK_DEBUG_TYPING // `${ domEvent.type }`
|
|
11886
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
11721
11887
|
// @if CK_DEBUG_TYPING // }
|
|
11722
11888
|
this.fire(domEvent.type, domEvent, {
|
|
11723
11889
|
data: domEvent.data
|
|
@@ -11822,7 +11988,7 @@ function getFiles(nativeDataTransfer) {
|
|
|
11822
11988
|
return items.filter((item)=>item.kind === 'file').map((item)=>item.getAsFile());
|
|
11823
11989
|
}
|
|
11824
11990
|
|
|
11825
|
-
// @if CK_DEBUG_TYPING // const { _debouncedLine } = require( '../../dev-utils/utils.js' );
|
|
11991
|
+
// @if CK_DEBUG_TYPING // const { _debouncedLine, _buildLogMessage } = require( '../../dev-utils/utils.js' );
|
|
11826
11992
|
/**
|
|
11827
11993
|
* Observer for events connected with data input.
|
|
11828
11994
|
*
|
|
@@ -11837,9 +12003,9 @@ function getFiles(nativeDataTransfer) {
|
|
|
11837
12003
|
*/ onDomEvent(domEvent) {
|
|
11838
12004
|
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
11839
12005
|
// @if CK_DEBUG_TYPING // _debouncedLine();
|
|
11840
|
-
// @if CK_DEBUG_TYPING // console.group(
|
|
11841
|
-
// @if CK_DEBUG_TYPING //
|
|
11842
|
-
// @if CK_DEBUG_TYPING // );
|
|
12006
|
+
// @if CK_DEBUG_TYPING // console.group( ..._buildLogMessage( this, 'InputObserver',
|
|
12007
|
+
// @if CK_DEBUG_TYPING // `${ domEvent.type }: ${ domEvent.inputType }`
|
|
12008
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
11843
12009
|
// @if CK_DEBUG_TYPING // }
|
|
11844
12010
|
const domTargetRanges = domEvent.getTargetRanges();
|
|
11845
12011
|
const view = this.view;
|
|
@@ -11853,16 +12019,20 @@ function getFiles(nativeDataTransfer) {
|
|
|
11853
12019
|
if (domEvent.data !== null) {
|
|
11854
12020
|
data = domEvent.data;
|
|
11855
12021
|
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
11856
|
-
// @if CK_DEBUG_TYPING // console.info(
|
|
11857
|
-
// @if CK_DEBUG_TYPING //
|
|
11858
|
-
// @if CK_DEBUG_TYPING //
|
|
12022
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'InputObserver',
|
|
12023
|
+
// @if CK_DEBUG_TYPING // `%cevent data: %c${ JSON.stringify( data ) }`,
|
|
12024
|
+
// @if CK_DEBUG_TYPING // 'font-weight: bold',
|
|
12025
|
+
// @if CK_DEBUG_TYPING // 'color: blue;'
|
|
12026
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
11859
12027
|
// @if CK_DEBUG_TYPING // }
|
|
11860
12028
|
} else if (dataTransfer) {
|
|
11861
12029
|
data = dataTransfer.getData('text/plain');
|
|
11862
12030
|
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
11863
|
-
// @if CK_DEBUG_TYPING // console.info(
|
|
11864
|
-
// @if CK_DEBUG_TYPING //
|
|
11865
|
-
// @if CK_DEBUG_TYPING //
|
|
12031
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'InputObserver',
|
|
12032
|
+
// @if CK_DEBUG_TYPING // `%cevent data transfer: %c${ JSON.stringify( data ) }`,
|
|
12033
|
+
// @if CK_DEBUG_TYPING // 'font-weight: bold',
|
|
12034
|
+
// @if CK_DEBUG_TYPING // 'color: blue;'
|
|
12035
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
11866
12036
|
// @if CK_DEBUG_TYPING // }
|
|
11867
12037
|
}
|
|
11868
12038
|
// If the editor selection is fake (an object is selected), the DOM range does not make sense because it is anchored
|
|
@@ -11871,10 +12041,12 @@ function getFiles(nativeDataTransfer) {
|
|
|
11871
12041
|
// Future-proof: in case of multi-range fake selections being possible.
|
|
11872
12042
|
targetRanges = Array.from(viewDocument.selection.getRanges());
|
|
11873
12043
|
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
11874
|
-
// @if CK_DEBUG_TYPING // console.info(
|
|
11875
|
-
// @if CK_DEBUG_TYPING // '
|
|
12044
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'InputObserver',
|
|
12045
|
+
// @if CK_DEBUG_TYPING // '%cusing fake selection:',
|
|
12046
|
+
// @if CK_DEBUG_TYPING // 'font-weight: bold',
|
|
12047
|
+
// @if CK_DEBUG_TYPING // targetRanges,
|
|
11876
12048
|
// @if CK_DEBUG_TYPING // viewDocument.selection.isFake ? 'fake view selection' : 'fake DOM parent'
|
|
11877
|
-
// @if CK_DEBUG_TYPING // );
|
|
12049
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
11878
12050
|
// @if CK_DEBUG_TYPING // }
|
|
11879
12051
|
} else if (domTargetRanges.length) {
|
|
11880
12052
|
targetRanges = domTargetRanges.map((domRange)=>{
|
|
@@ -11891,17 +12063,21 @@ function getFiles(nativeDataTransfer) {
|
|
|
11891
12063
|
}
|
|
11892
12064
|
}).filter((range)=>!!range);
|
|
11893
12065
|
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
11894
|
-
// @if CK_DEBUG_TYPING // console.info(
|
|
11895
|
-
// @if CK_DEBUG_TYPING // '
|
|
11896
|
-
// @if CK_DEBUG_TYPING //
|
|
12066
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'InputObserver',
|
|
12067
|
+
// @if CK_DEBUG_TYPING // '%cusing target ranges:',
|
|
12068
|
+
// @if CK_DEBUG_TYPING // 'font-weight: bold',
|
|
12069
|
+
// @if CK_DEBUG_TYPING // targetRanges
|
|
12070
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
11897
12071
|
// @if CK_DEBUG_TYPING // }
|
|
11898
12072
|
} else if (env.isAndroid) {
|
|
11899
12073
|
const domSelection = domEvent.target.ownerDocument.defaultView.getSelection();
|
|
11900
12074
|
targetRanges = Array.from(view.domConverter.domSelectionToView(domSelection).getRanges());
|
|
11901
12075
|
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
11902
|
-
// @if CK_DEBUG_TYPING // console.info(
|
|
11903
|
-
// @if CK_DEBUG_TYPING // '
|
|
11904
|
-
// @if CK_DEBUG_TYPING //
|
|
12076
|
+
// @if CK_DEBUG_TYPING // console.info( ..._buildLogMessage( this, 'InputObserver',
|
|
12077
|
+
// @if CK_DEBUG_TYPING // '%cusing selection ranges:',
|
|
12078
|
+
// @if CK_DEBUG_TYPING // 'font-weight: bold',
|
|
12079
|
+
// @if CK_DEBUG_TYPING // targetRanges
|
|
12080
|
+
// @if CK_DEBUG_TYPING // ) );
|
|
11905
12081
|
// @if CK_DEBUG_TYPING // }
|
|
11906
12082
|
}
|
|
11907
12083
|
// Android sometimes fires insertCompositionText with a new-line character at the end of the data
|
|
@@ -22448,7 +22624,7 @@ function getFromAttributeCreator(config) {
|
|
|
22448
22624
|
return;
|
|
22449
22625
|
}
|
|
22450
22626
|
const modelKey = config.model.key;
|
|
22451
|
-
const modelValue = typeof config.model.value == 'function' ? config.model.value(data.viewItem, conversionApi) : config.model.value;
|
|
22627
|
+
const modelValue = typeof config.model.value == 'function' ? config.model.value(data.viewItem, conversionApi, data) : config.model.value;
|
|
22452
22628
|
// Do not convert if attribute building function returned falsy value.
|
|
22453
22629
|
if (modelValue === null) {
|
|
22454
22630
|
return;
|