@ckeditor/ckeditor5-typing 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.
Files changed (2) hide show
  1. package/package.json +21 -21
  2. package/src/deleteobserver.js +45 -8
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ckeditor/ckeditor5-typing",
3
- "version": "37.0.0",
3
+ "version": "37.1.0",
4
4
  "description": "Typing feature for CKEditor 5.",
5
5
  "keywords": [
6
6
  "ckeditor",
@@ -12,29 +12,29 @@
12
12
  ],
13
13
  "main": "src/index.js",
14
14
  "dependencies": {
15
- "@ckeditor/ckeditor5-core": "^37.0.0",
16
- "@ckeditor/ckeditor5-engine": "^37.0.0",
17
- "@ckeditor/ckeditor5-utils": "^37.0.0",
15
+ "@ckeditor/ckeditor5-core": "^37.1.0",
16
+ "@ckeditor/ckeditor5-engine": "^37.1.0",
17
+ "@ckeditor/ckeditor5-utils": "^37.1.0",
18
18
  "lodash-es": "^4.17.15"
19
19
  },
20
20
  "devDependencies": {
21
- "@ckeditor/ckeditor5-autoformat": "^37.0.0",
22
- "@ckeditor/ckeditor5-basic-styles": "^37.0.0",
23
- "@ckeditor/ckeditor5-block-quote": "^37.0.0",
24
- "@ckeditor/ckeditor5-code-block": "^37.0.0",
25
- "@ckeditor/ckeditor5-editor-classic": "^37.0.0",
26
- "@ckeditor/ckeditor5-enter": "^37.0.0",
27
- "@ckeditor/ckeditor5-essentials": "^37.0.0",
28
- "@ckeditor/ckeditor5-heading": "^37.0.0",
29
- "@ckeditor/ckeditor5-image": "^37.0.0",
30
- "@ckeditor/ckeditor5-indent": "^37.0.0",
31
- "@ckeditor/ckeditor5-link": "^37.0.0",
32
- "@ckeditor/ckeditor5-list": "^37.0.0",
33
- "@ckeditor/ckeditor5-media-embed": "^37.0.0",
34
- "@ckeditor/ckeditor5-mention": "^37.0.0",
35
- "@ckeditor/ckeditor5-paragraph": "^37.0.0",
36
- "@ckeditor/ckeditor5-table": "^37.0.0",
37
- "@ckeditor/ckeditor5-undo": "^37.0.0",
21
+ "@ckeditor/ckeditor5-autoformat": "^37.1.0",
22
+ "@ckeditor/ckeditor5-basic-styles": "^37.1.0",
23
+ "@ckeditor/ckeditor5-block-quote": "^37.1.0",
24
+ "@ckeditor/ckeditor5-code-block": "^37.1.0",
25
+ "@ckeditor/ckeditor5-editor-classic": "^37.1.0",
26
+ "@ckeditor/ckeditor5-enter": "^37.1.0",
27
+ "@ckeditor/ckeditor5-essentials": "^37.1.0",
28
+ "@ckeditor/ckeditor5-heading": "^37.1.0",
29
+ "@ckeditor/ckeditor5-image": "^37.1.0",
30
+ "@ckeditor/ckeditor5-indent": "^37.1.0",
31
+ "@ckeditor/ckeditor5-link": "^37.1.0",
32
+ "@ckeditor/ckeditor5-list": "^37.1.0",
33
+ "@ckeditor/ckeditor5-media-embed": "^37.1.0",
34
+ "@ckeditor/ckeditor5-mention": "^37.1.0",
35
+ "@ckeditor/ckeditor5-paragraph": "^37.1.0",
36
+ "@ckeditor/ckeditor5-table": "^37.1.0",
37
+ "@ckeditor/ckeditor5-undo": "^37.1.0",
38
38
  "typescript": "^4.8.4",
39
39
  "webpack": "^5.58.1",
40
40
  "webpack-cli": "^4.9.0"
@@ -5,7 +5,7 @@
5
5
  /**
6
6
  * @module typing/deleteobserver
7
7
  */
8
- import { env, keyCodes } from '@ckeditor/ckeditor5-utils';
8
+ import { env, keyCodes, isInsideCombinedSymbol, isInsideEmojiSequence, isInsideSurrogatePair } from '@ckeditor/ckeditor5-utils';
9
9
  import { BubblingEventInfo, DomEventData, Observer } from '@ckeditor/ckeditor5-engine';
10
10
  const DELETE_CHARACTER = 'character';
11
11
  const DELETE_WORD = 'word';
@@ -133,14 +133,14 @@ export default class DeleteObserver extends Observer {
133
133
  deleteData.selectionToRemove = view.createSelection(targetRanges[0]);
134
134
  }
135
135
  // The default deletion unit for deleteContentBackward is a single code point
136
- // but on Android it sometimes passes a wider target range, so we need to change
137
- // the unit of deletion to include the whole range to be removed and not a single code point.
138
- if (env.isAndroid && inputType === 'deleteContentBackward') {
136
+ // but if the browser provides a wider target range then we should use it.
137
+ if (inputType === 'deleteContentBackward') {
139
138
  // On Android, deleteContentBackward has sequence 1 by default.
140
- deleteData.sequence = 1;
141
- // IME wants more than a single character to be removed.
142
- if (targetRanges.length == 1 && (targetRanges[0].start.parent != targetRanges[0].end.parent ||
143
- targetRanges[0].start.offset + 1 != targetRanges[0].end.offset)) {
139
+ if (env.isAndroid) {
140
+ deleteData.sequence = 1;
141
+ }
142
+ // The beforeInput event wants more than a single character to be removed.
143
+ if (shouldUseTargetRanges(targetRanges)) {
144
144
  deleteData.unit = DELETE_SELECTION;
145
145
  deleteData.selectionToRemove = view.createSelection(targetRanges);
146
146
  }
@@ -222,3 +222,40 @@ function enableChromeWorkaround(observer) {
222
222
  return keyCode == keyCodes.backspace ? DELETE_BACKWARD : DELETE_FORWARD;
223
223
  }
224
224
  }
225
+ /**
226
+ * Verifies if the given target ranges cover more than a single character and should be used instead of single code-point deletion.
227
+ */
228
+ function shouldUseTargetRanges(targetRanges) {
229
+ // The collapsed target range could happen for example while deleting inside an inline filler
230
+ // (it's mapped to collapsed position before an inline filler).
231
+ if (targetRanges.length != 1 || targetRanges[0].isCollapsed) {
232
+ return false;
233
+ }
234
+ const walker = targetRanges[0].getWalker({
235
+ direction: 'backward',
236
+ singleCharacters: true,
237
+ ignoreElementEnd: true
238
+ });
239
+ let count = 0;
240
+ for (const { nextPosition } of walker) {
241
+ // There is some element in the range so count it as a single character.
242
+ if (!nextPosition.parent.is('$text')) {
243
+ count++;
244
+ }
245
+ else {
246
+ const data = nextPosition.parent.data;
247
+ const offset = nextPosition.offset;
248
+ // Count combined symbols and emoji sequences as a single character.
249
+ if (isInsideSurrogatePair(data, offset) ||
250
+ isInsideCombinedSymbol(data, offset) ||
251
+ isInsideEmojiSequence(data, offset)) {
252
+ continue;
253
+ }
254
+ count++;
255
+ }
256
+ if (count > 1) {
257
+ return true;
258
+ }
259
+ }
260
+ return false;
261
+ }