@ckeditor/ckeditor5-engine 37.0.0 → 37.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +22 -22
- package/src/controller/editingcontroller.js +27 -1
- package/src/conversion/downcasthelpers.js +1 -1
- package/src/model/markercollection.d.ts +1 -1
- package/src/model/markercollection.js +1 -1
- package/src/model/model.js +2 -2
- package/src/model/selection.d.ts +13 -3
- package/src/model/selection.js +71 -6
- package/src/model/typecheckable.js +1 -1
- package/src/model/utils/insertcontent.js +4 -4
- package/src/model/utils/selection-post-fixer.d.ts +9 -0
- package/src/model/utils/selection-post-fixer.js +3 -1
- package/src/view/domconverter.js +2 -1
- package/src/view/matcher.js +1 -1
- package/src/view/observer/bubblingemittermixin.js +1 -1
- package/src/view/observer/selectionobserver.js +1 -1
- package/src/view/position.js +1 -4
- package/src/view/typecheckable.js +1 -1
- package/src/view/view.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ckeditor/ckeditor5-engine",
|
|
3
|
-
"version": "37.
|
|
3
|
+
"version": "37.1.0",
|
|
4
4
|
"description": "The editing engine of CKEditor 5 – the best browser-based rich text editor.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"wysiwyg",
|
|
@@ -23,30 +23,30 @@
|
|
|
23
23
|
],
|
|
24
24
|
"main": "src/index.js",
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@ckeditor/ckeditor5-utils": "^37.
|
|
26
|
+
"@ckeditor/ckeditor5-utils": "^37.1.0",
|
|
27
27
|
"lodash-es": "^4.17.15"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@ckeditor/ckeditor5-basic-styles": "^37.
|
|
31
|
-
"@ckeditor/ckeditor5-block-quote": "^37.
|
|
32
|
-
"@ckeditor/ckeditor5-clipboard": "^37.
|
|
33
|
-
"@ckeditor/ckeditor5-cloud-services": "^37.
|
|
34
|
-
"@ckeditor/ckeditor5-core": "^37.
|
|
35
|
-
"@ckeditor/ckeditor5-editor-classic": "^37.
|
|
36
|
-
"@ckeditor/ckeditor5-enter": "^37.
|
|
37
|
-
"@ckeditor/ckeditor5-essentials": "^37.
|
|
38
|
-
"@ckeditor/ckeditor5-heading": "^37.
|
|
39
|
-
"@ckeditor/ckeditor5-image": "^37.
|
|
40
|
-
"@ckeditor/ckeditor5-link": "^37.
|
|
41
|
-
"@ckeditor/ckeditor5-list": "^37.
|
|
42
|
-
"@ckeditor/ckeditor5-mention": "^37.
|
|
43
|
-
"@ckeditor/ckeditor5-paragraph": "^37.
|
|
44
|
-
"@ckeditor/ckeditor5-table": "^37.
|
|
45
|
-
"@ckeditor/ckeditor5-theme-lark": "^37.
|
|
46
|
-
"@ckeditor/ckeditor5-typing": "^37.
|
|
47
|
-
"@ckeditor/ckeditor5-ui": "^37.
|
|
48
|
-
"@ckeditor/ckeditor5-undo": "^37.
|
|
49
|
-
"@ckeditor/ckeditor5-widget": "^37.
|
|
30
|
+
"@ckeditor/ckeditor5-basic-styles": "^37.1.0",
|
|
31
|
+
"@ckeditor/ckeditor5-block-quote": "^37.1.0",
|
|
32
|
+
"@ckeditor/ckeditor5-clipboard": "^37.1.0",
|
|
33
|
+
"@ckeditor/ckeditor5-cloud-services": "^37.1.0",
|
|
34
|
+
"@ckeditor/ckeditor5-core": "^37.1.0",
|
|
35
|
+
"@ckeditor/ckeditor5-editor-classic": "^37.1.0",
|
|
36
|
+
"@ckeditor/ckeditor5-enter": "^37.1.0",
|
|
37
|
+
"@ckeditor/ckeditor5-essentials": "^37.1.0",
|
|
38
|
+
"@ckeditor/ckeditor5-heading": "^37.1.0",
|
|
39
|
+
"@ckeditor/ckeditor5-image": "^37.1.0",
|
|
40
|
+
"@ckeditor/ckeditor5-link": "^37.1.0",
|
|
41
|
+
"@ckeditor/ckeditor5-list": "^37.1.0",
|
|
42
|
+
"@ckeditor/ckeditor5-mention": "^37.1.0",
|
|
43
|
+
"@ckeditor/ckeditor5-paragraph": "^37.1.0",
|
|
44
|
+
"@ckeditor/ckeditor5-table": "^37.1.0",
|
|
45
|
+
"@ckeditor/ckeditor5-theme-lark": "^37.1.0",
|
|
46
|
+
"@ckeditor/ckeditor5-typing": "^37.1.0",
|
|
47
|
+
"@ckeditor/ckeditor5-ui": "^37.1.0",
|
|
48
|
+
"@ckeditor/ckeditor5-undo": "^37.1.0",
|
|
49
|
+
"@ckeditor/ckeditor5-widget": "^37.1.0",
|
|
50
50
|
"typescript": "^4.8.4",
|
|
51
51
|
"webpack": "^5.58.1",
|
|
52
52
|
"webpack-cli": "^4.9.0"
|
|
@@ -5,13 +5,14 @@
|
|
|
5
5
|
/**
|
|
6
6
|
* @module engine/controller/editingcontroller
|
|
7
7
|
*/
|
|
8
|
-
import { CKEditorError, ObservableMixin } from '@ckeditor/ckeditor5-utils';
|
|
8
|
+
import { CKEditorError, ObservableMixin, env } from '@ckeditor/ckeditor5-utils';
|
|
9
9
|
import RootEditableElement from '../view/rooteditableelement';
|
|
10
10
|
import View from '../view/view';
|
|
11
11
|
import Mapper from '../conversion/mapper';
|
|
12
12
|
import DowncastDispatcher from '../conversion/downcastdispatcher';
|
|
13
13
|
import { clearAttributes, convertCollapsedSelection, convertRangeSelection, insertAttributesAndChildren, insertText, remove } from '../conversion/downcasthelpers';
|
|
14
14
|
import { convertSelectionChange } from '../conversion/upcasthelpers';
|
|
15
|
+
import { tryFixingRange } from '../model/utils/selection-post-fixer';
|
|
15
16
|
// @if CK_DEBUG_ENGINE // const { dumpTrees, initDocumentDumping } = require( '../dev-utils/utils' );
|
|
16
17
|
/**
|
|
17
18
|
* A controller for the editing pipeline. The editing pipeline controls the {@link ~EditingController#model model} rendering,
|
|
@@ -59,6 +60,8 @@ export default class EditingController extends ObservableMixin() {
|
|
|
59
60
|
}, { priority: 'low' });
|
|
60
61
|
// Convert selection from the view to the model when it changes in the view.
|
|
61
62
|
this.listenTo(this.view.document, 'selectionChange', convertSelectionChange(this.model, this.mapper));
|
|
63
|
+
// Fix `beforeinput` target ranges so that they map to the valid model ranges.
|
|
64
|
+
this.listenTo(this.view.document, 'beforeinput', fixTargetRanges(this.mapper, this.model.schema, this.view), { priority: 'high' });
|
|
62
65
|
// Attach default model converters.
|
|
63
66
|
this.downcastDispatcher.on('insert:$text', insertText(), { priority: 'lowest' });
|
|
64
67
|
this.downcastDispatcher.on('insert', insertAttributesAndChildren(), { priority: 'lowest' });
|
|
@@ -163,3 +166,26 @@ export default class EditingController extends ObservableMixin() {
|
|
|
163
166
|
});
|
|
164
167
|
}
|
|
165
168
|
}
|
|
169
|
+
/**
|
|
170
|
+
* Checks whether the target ranges provided by the `beforeInput` event can be properly mapped to model ranges and fixes them if needed.
|
|
171
|
+
*
|
|
172
|
+
* This is using the same logic as the selection post-fixer.
|
|
173
|
+
*/
|
|
174
|
+
function fixTargetRanges(mapper, schema, view) {
|
|
175
|
+
return (evt, data) => {
|
|
176
|
+
// The Renderer is disabled while composing on non-android browsers, so we can't be sure that target ranges
|
|
177
|
+
// could be properly mapped to view and model because the DOM and view tree drifted apart.
|
|
178
|
+
if (view.document.isComposing && !env.isAndroid) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
for (let i = 0; i < data.targetRanges.length; i++) {
|
|
182
|
+
const viewRange = data.targetRanges[i];
|
|
183
|
+
const modelRange = mapper.toModelRange(viewRange);
|
|
184
|
+
const correctedRange = tryFixingRange(modelRange, schema);
|
|
185
|
+
if (!correctedRange || correctedRange.isEqual(modelRange)) {
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
data.targetRanges[i] = mapper.toViewRange(correctedRange);
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
}
|
|
@@ -1958,7 +1958,7 @@ function createChangeReducerCallback(model) {
|
|
|
1958
1958
|
}
|
|
1959
1959
|
}
|
|
1960
1960
|
else {
|
|
1961
|
-
/* istanbul ignore else: This is always true because otherwise it would not register a reducer callback. */
|
|
1961
|
+
/* istanbul ignore else: This is always true because otherwise it would not register a reducer callback. -- @preserve */
|
|
1962
1962
|
if (model.children) {
|
|
1963
1963
|
return true;
|
|
1964
1964
|
}
|
|
@@ -137,7 +137,7 @@ export interface MarkerData {
|
|
|
137
137
|
}
|
|
138
138
|
declare const Marker_base: import("@ckeditor/ckeditor5-utils").Mixed<typeof TypeCheckable, import("@ckeditor/ckeditor5-utils").Emitter>;
|
|
139
139
|
/**
|
|
140
|
-
* `Marker` is a continuous
|
|
140
|
+
* `Marker` is a continuous part of model (like a range), is named and represent some kind of information about marked
|
|
141
141
|
* part of model document. In contrary to {@link module:engine/model/node~Node nodes}, which are building blocks of
|
|
142
142
|
* model document tree, markers are not stored directly in document tree but in
|
|
143
143
|
* {@link module:engine/model/model~Model#markers model markers' collection}. Still, they are document data, by giving
|
|
@@ -214,7 +214,7 @@ export default class MarkerCollection extends EmitterMixin() {
|
|
|
214
214
|
}
|
|
215
215
|
}
|
|
216
216
|
/**
|
|
217
|
-
* `Marker` is a continuous
|
|
217
|
+
* `Marker` is a continuous part of model (like a range), is named and represent some kind of information about marked
|
|
218
218
|
* part of model document. In contrary to {@link module:engine/model/node~Node nodes}, which are building blocks of
|
|
219
219
|
* model document tree, markers are not stored directly in document tree but in
|
|
220
220
|
* {@link module:engine/model/model~Model#markers model markers' collection}. Still, they are document data, by giving
|
package/src/model/model.js
CHANGED
|
@@ -168,7 +168,7 @@ export default class Model extends ObservableMixin() {
|
|
|
168
168
|
}
|
|
169
169
|
catch (err) {
|
|
170
170
|
// @if CK_DEBUG // throw err;
|
|
171
|
-
/* istanbul ignore next */
|
|
171
|
+
/* istanbul ignore next -- @preserve */
|
|
172
172
|
CKEditorError.rethrowUnexpectedError(err, this);
|
|
173
173
|
}
|
|
174
174
|
}
|
|
@@ -191,7 +191,7 @@ export default class Model extends ObservableMixin() {
|
|
|
191
191
|
}
|
|
192
192
|
catch (err) {
|
|
193
193
|
// @if CK_DEBUG // throw err;
|
|
194
|
-
/* istanbul ignore next */
|
|
194
|
+
/* istanbul ignore next -- @preserve */
|
|
195
195
|
CKEditorError.rethrowUnexpectedError(err, this);
|
|
196
196
|
}
|
|
197
197
|
}
|
package/src/model/selection.d.ts
CHANGED
|
@@ -362,13 +362,23 @@ export default class Selection extends Selection_base {
|
|
|
362
362
|
* </block>
|
|
363
363
|
* ```
|
|
364
364
|
*
|
|
365
|
-
* **Special case**:
|
|
366
|
-
* this block wasn't selected. See [#984](https://github.com/ckeditor/ckeditor5-engine/issues/984) for more details.
|
|
365
|
+
* **Special case**: Selection ignores first and/or last blocks if nothing (from user perspective) is selected in them.
|
|
367
366
|
*
|
|
368
367
|
* ```xml
|
|
368
|
+
* // Selection ends and the beginning of the last block.
|
|
369
369
|
* <paragraph>[a</paragraph>
|
|
370
370
|
* <paragraph>b</paragraph>
|
|
371
|
-
* <paragraph>]c</paragraph> //
|
|
371
|
+
* <paragraph>]c</paragraph> // This block will not be returned
|
|
372
|
+
*
|
|
373
|
+
* // Selection begins at the end of the first block.
|
|
374
|
+
* <paragraph>a[</paragraph> // This block will not be returned
|
|
375
|
+
* <paragraph>b</paragraph>
|
|
376
|
+
* <paragraph>c]</paragraph>
|
|
377
|
+
*
|
|
378
|
+
* // Selection begings at the end of the first block and ends at the beginning of the last block.
|
|
379
|
+
* <paragraph>a[</paragraph> // This block will not be returned
|
|
380
|
+
* <paragraph>b</paragraph>
|
|
381
|
+
* <paragraph>]c</paragraph> // This block will not be returned
|
|
372
382
|
* ```
|
|
373
383
|
*/
|
|
374
384
|
getSelectedBlocks(): IterableIterator<Element>;
|
package/src/model/selection.js
CHANGED
|
@@ -557,13 +557,23 @@ export default class Selection extends EmitterMixin(TypeCheckable) {
|
|
|
557
557
|
* </block>
|
|
558
558
|
* ```
|
|
559
559
|
*
|
|
560
|
-
* **Special case**:
|
|
561
|
-
* this block wasn't selected. See [#984](https://github.com/ckeditor/ckeditor5-engine/issues/984) for more details.
|
|
560
|
+
* **Special case**: Selection ignores first and/or last blocks if nothing (from user perspective) is selected in them.
|
|
562
561
|
*
|
|
563
562
|
* ```xml
|
|
563
|
+
* // Selection ends and the beginning of the last block.
|
|
564
564
|
* <paragraph>[a</paragraph>
|
|
565
565
|
* <paragraph>b</paragraph>
|
|
566
|
-
* <paragraph>]c</paragraph> //
|
|
566
|
+
* <paragraph>]c</paragraph> // This block will not be returned
|
|
567
|
+
*
|
|
568
|
+
* // Selection begins at the end of the first block.
|
|
569
|
+
* <paragraph>a[</paragraph> // This block will not be returned
|
|
570
|
+
* <paragraph>b</paragraph>
|
|
571
|
+
* <paragraph>c]</paragraph>
|
|
572
|
+
*
|
|
573
|
+
* // Selection begings at the end of the first block and ends at the beginning of the last block.
|
|
574
|
+
* <paragraph>a[</paragraph> // This block will not be returned
|
|
575
|
+
* <paragraph>b</paragraph>
|
|
576
|
+
* <paragraph>]c</paragraph> // This block will not be returned
|
|
567
577
|
* ```
|
|
568
578
|
*/
|
|
569
579
|
*getSelectedBlocks() {
|
|
@@ -571,7 +581,7 @@ export default class Selection extends EmitterMixin(TypeCheckable) {
|
|
|
571
581
|
for (const range of this.getRanges()) {
|
|
572
582
|
// Get start block of range in case of a collapsed range.
|
|
573
583
|
const startBlock = getParentBlock(range.start, visited);
|
|
574
|
-
if (
|
|
584
|
+
if (isStartBlockSelected(startBlock, range)) {
|
|
575
585
|
yield startBlock;
|
|
576
586
|
}
|
|
577
587
|
for (const value of range.getWalker()) {
|
|
@@ -581,8 +591,7 @@ export default class Selection extends EmitterMixin(TypeCheckable) {
|
|
|
581
591
|
}
|
|
582
592
|
}
|
|
583
593
|
const endBlock = getParentBlock(range.end, visited);
|
|
584
|
-
|
|
585
|
-
if (endBlock && !range.end.isTouching(Position._createAt(endBlock, 0)) && isTopBlockInRange(endBlock, range)) {
|
|
594
|
+
if (isEndBlockSelected(endBlock, range)) {
|
|
586
595
|
yield endBlock;
|
|
587
596
|
}
|
|
588
597
|
}
|
|
@@ -709,6 +718,62 @@ function isTopBlockInRange(block, range) {
|
|
|
709
718
|
const isParentInRange = range.containsRange(Range._createOn(parentBlock), true);
|
|
710
719
|
return !isParentInRange;
|
|
711
720
|
}
|
|
721
|
+
/**
|
|
722
|
+
* If a selection starts at the end of a block, that block is not returned as from user perspective this block wasn't selected.
|
|
723
|
+
* See [#11585](https://github.com/ckeditor/ckeditor5/issues/11585) for more details.
|
|
724
|
+
*
|
|
725
|
+
* ```xml
|
|
726
|
+
* <paragraph>a[</paragraph> // This block will not be returned
|
|
727
|
+
* <paragraph>b</paragraph>
|
|
728
|
+
* <paragraph>c]</paragraph>
|
|
729
|
+
* ```
|
|
730
|
+
*
|
|
731
|
+
* Collapsed selection is not affected by it:
|
|
732
|
+
*
|
|
733
|
+
* ```xml
|
|
734
|
+
* <paragraph>a[]</paragraph> // This block will be returned
|
|
735
|
+
* ```
|
|
736
|
+
*/
|
|
737
|
+
function isStartBlockSelected(startBlock, range) {
|
|
738
|
+
if (!startBlock) {
|
|
739
|
+
return false;
|
|
740
|
+
}
|
|
741
|
+
if (range.isCollapsed || startBlock.isEmpty) {
|
|
742
|
+
return true;
|
|
743
|
+
}
|
|
744
|
+
if (range.start.isTouching(Position._createAt(startBlock, startBlock.maxOffset))) {
|
|
745
|
+
return false;
|
|
746
|
+
}
|
|
747
|
+
return isTopBlockInRange(startBlock, range);
|
|
748
|
+
}
|
|
749
|
+
/**
|
|
750
|
+
* If a selection ends at the beginning of a block, that block is not returned as from user perspective this block wasn't selected.
|
|
751
|
+
* See [#984](https://github.com/ckeditor/ckeditor5-engine/issues/984) for more details.
|
|
752
|
+
*
|
|
753
|
+
* ```xml
|
|
754
|
+
* <paragraph>[a</paragraph>
|
|
755
|
+
* <paragraph>b</paragraph>
|
|
756
|
+
* <paragraph>]c</paragraph> // this block will not be returned
|
|
757
|
+
* ```
|
|
758
|
+
*
|
|
759
|
+
* Collapsed selection is not affected by it:
|
|
760
|
+
*
|
|
761
|
+
* ```xml
|
|
762
|
+
* <paragraph>[]a</paragraph> // this block will be returned
|
|
763
|
+
* ```
|
|
764
|
+
*/
|
|
765
|
+
function isEndBlockSelected(endBlock, range) {
|
|
766
|
+
if (!endBlock) {
|
|
767
|
+
return false;
|
|
768
|
+
}
|
|
769
|
+
if (range.isCollapsed || endBlock.isEmpty) {
|
|
770
|
+
return true;
|
|
771
|
+
}
|
|
772
|
+
if (range.end.isTouching(Position._createAt(endBlock, 0))) {
|
|
773
|
+
return false;
|
|
774
|
+
}
|
|
775
|
+
return isTopBlockInRange(endBlock, range);
|
|
776
|
+
}
|
|
712
777
|
/**
|
|
713
778
|
* Returns first ancestor block of a node.
|
|
714
779
|
*/
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
4
|
*/
|
|
5
5
|
export default class TypeCheckable {
|
|
6
|
-
/* istanbul ignore next */
|
|
6
|
+
/* istanbul ignore next -- @preserve */
|
|
7
7
|
is() {
|
|
8
8
|
// There are a lot of overloads above.
|
|
9
9
|
// Overriding method in derived classes remove them and only `is( type: string ): boolean` is visible which we don't want.
|
|
@@ -162,7 +162,7 @@ export default function insertContent(model, content, selectable) {
|
|
|
162
162
|
selectionLiveRange.detach();
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
|
-
/* istanbul ignore else */
|
|
165
|
+
/* istanbul ignore else -- @preserve */
|
|
166
166
|
if (newRange) {
|
|
167
167
|
if (selection instanceof DocumentSelection) {
|
|
168
168
|
writer.setSelection(newRange);
|
|
@@ -253,7 +253,7 @@ class Insertion {
|
|
|
253
253
|
// If the real end was after the last auto paragraph then update relevant properties.
|
|
254
254
|
if (positionAfterNode.isAfter(positionAfterLastNode)) {
|
|
255
255
|
this._lastNode = node;
|
|
256
|
-
/* istanbul ignore if */
|
|
256
|
+
/* istanbul ignore if -- @preserve */
|
|
257
257
|
if (this.position.parent != node || !this.position.isAtEnd) {
|
|
258
258
|
// Algorithm's correctness check. We should never end up here but it's good to know that we did.
|
|
259
259
|
// At this point the insertion position should be at the end of the last auto paragraph.
|
|
@@ -386,7 +386,7 @@ class Insertion {
|
|
|
386
386
|
* @param node The node to insert.
|
|
387
387
|
*/
|
|
388
388
|
_appendToFragment(node) {
|
|
389
|
-
/* istanbul ignore if */
|
|
389
|
+
/* istanbul ignore if -- @preserve */
|
|
390
390
|
if (!this.schema.checkChild(this.position, node)) {
|
|
391
391
|
// Algorithm's correctness check. We should never end up here but it's good to know that we did.
|
|
392
392
|
// Note that it would often be a silent issue if we insert node in a place where it's not allowed.
|
|
@@ -517,7 +517,7 @@ class Insertion {
|
|
|
517
517
|
}
|
|
518
518
|
const mergePosRight = LivePosition._createAfter(node);
|
|
519
519
|
mergePosRight.stickiness = 'toNext';
|
|
520
|
-
/* istanbul ignore if */
|
|
520
|
+
/* istanbul ignore if -- @preserve */
|
|
521
521
|
if (!this.position.isEqual(mergePosRight)) {
|
|
522
522
|
// Algorithm's correctness check. We should never end up here but it's good to know that we did.
|
|
523
523
|
// At this point the insertion position should be after the node we'll merge. If it isn't,
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import Range from '../range';
|
|
6
6
|
import type Model from '../model';
|
|
7
|
+
import type Schema from '../schema';
|
|
7
8
|
/**
|
|
8
9
|
* Injects selection post-fixer to the model.
|
|
9
10
|
*
|
|
@@ -56,6 +57,14 @@ import type Model from '../model';
|
|
|
56
57
|
* them to select `isLimit=true` elements.
|
|
57
58
|
*/
|
|
58
59
|
export declare function injectSelectionPostFixer(model: Model): void;
|
|
60
|
+
/**
|
|
61
|
+
* Tries fixing a range if it's incorrect.
|
|
62
|
+
*
|
|
63
|
+
* **Note:** This helper is used by the selection post-fixer and to fix the `beforeinput` target ranges.
|
|
64
|
+
*
|
|
65
|
+
* @returns Returns fixed range or null if range is valid.
|
|
66
|
+
*/
|
|
67
|
+
export declare function tryFixingRange(range: Range, schema: Schema): Range | null;
|
|
59
68
|
/**
|
|
60
69
|
* Returns a minimal non-intersecting array of ranges without duplicates.
|
|
61
70
|
*
|
|
@@ -97,9 +97,11 @@ function selectionPostFixer(writer, model) {
|
|
|
97
97
|
/**
|
|
98
98
|
* Tries fixing a range if it's incorrect.
|
|
99
99
|
*
|
|
100
|
+
* **Note:** This helper is used by the selection post-fixer and to fix the `beforeinput` target ranges.
|
|
101
|
+
*
|
|
100
102
|
* @returns Returns fixed range or null if range is valid.
|
|
101
103
|
*/
|
|
102
|
-
function tryFixingRange(range, schema) {
|
|
104
|
+
export function tryFixingRange(range, schema) {
|
|
103
105
|
if (range.isCollapsed) {
|
|
104
106
|
return tryFixingCollapsedRange(range, schema);
|
|
105
107
|
}
|
package/src/view/domconverter.js
CHANGED
|
@@ -641,7 +641,8 @@ export default class DomConverter {
|
|
|
641
641
|
}
|
|
642
642
|
else {
|
|
643
643
|
const domBefore = domParent.childNodes[domOffset - 1];
|
|
644
|
-
|
|
644
|
+
// Jump over an inline filler (and also on Firefox jump over a block filler while pressing backspace in an empty paragraph).
|
|
645
|
+
if (isText(domBefore) && isInlineFiller(domBefore) || domBefore && this.isBlockFiller(domBefore)) {
|
|
645
646
|
return this.domPositionToView(domBefore.parentNode, indexOf(domBefore));
|
|
646
647
|
}
|
|
647
648
|
const viewBefore = isText(domBefore) ?
|
package/src/view/matcher.js
CHANGED
|
@@ -423,7 +423,7 @@ function matchAttributes(patterns, element) {
|
|
|
423
423
|
*/
|
|
424
424
|
function matchClasses(patterns, element) {
|
|
425
425
|
// We don't need `getter` here because patterns for classes are always normalized to `[ className, true ]`.
|
|
426
|
-
return matchPatterns(patterns, element.getClassNames(), /* istanbul ignore next */ () => { });
|
|
426
|
+
return matchPatterns(patterns, element.getClassNames(), /* istanbul ignore next -- @preserve */ () => { });
|
|
427
427
|
}
|
|
428
428
|
/**
|
|
429
429
|
* Checks if styles of provided element can be matched against provided patterns.
|
|
@@ -116,7 +116,7 @@ export default class SelectionObserver extends Observer {
|
|
|
116
116
|
this._fireSelectionChangeDoneDebounced.cancel();
|
|
117
117
|
this._documentIsSelectingInactivityTimeoutDebounced.cancel();
|
|
118
118
|
}
|
|
119
|
-
/* istanbul ignore next */
|
|
119
|
+
/* istanbul ignore next -- @preserve */
|
|
120
120
|
_reportInfiniteLoop() {
|
|
121
121
|
// @if CK_DEBUG // throw new Error(
|
|
122
122
|
// @if CK_DEBUG // 'Selection change observer detected an infinite rendering loop.\n\n' +
|
package/src/view/position.js
CHANGED
|
@@ -209,11 +209,8 @@ export default class Position extends TypeCheckable {
|
|
|
209
209
|
return 'before';
|
|
210
210
|
case 'extension':
|
|
211
211
|
return 'after';
|
|
212
|
-
/* istanbul ignore next */
|
|
213
|
-
case 'same':
|
|
214
|
-
// Already covered by `this.isEqual` above. Added so TypeScript can infer `result` as number in `default` case.
|
|
215
|
-
return 'same';
|
|
216
212
|
default:
|
|
213
|
+
// Cast to number to avoid having 'same' as a type of `result`.
|
|
217
214
|
return thisPath[result] < otherPath[result] ? 'before' : 'after';
|
|
218
215
|
}
|
|
219
216
|
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* @module engine/view/typecheckable
|
|
7
7
|
*/
|
|
8
8
|
export default class TypeCheckable {
|
|
9
|
-
/* istanbul ignore next */
|
|
9
|
+
/* istanbul ignore next -- @preserve */
|
|
10
10
|
is() {
|
|
11
11
|
// There are a lot of overloads above.
|
|
12
12
|
// Overriding method in derived classes remove them and only `is( type: string ): boolean` is visible which we don't want.
|
package/src/view/view.js
CHANGED