@ckeditor/ckeditor5-typing 39.0.2 → 40.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.
- package/package.json +4 -4
- package/src/augmentation.d.ts +27 -27
- package/src/augmentation.js +5 -5
- package/src/delete.d.ts +32 -32
- package/src/delete.js +82 -82
- package/src/deletecommand.d.ts +83 -83
- package/src/deletecommand.js +201 -201
- package/src/deleteobserver.d.ts +55 -55
- package/src/deleteobserver.js +261 -261
- package/src/index.d.ts +24 -24
- package/src/index.js +18 -18
- package/src/input.d.ts +21 -21
- package/src/input.js +141 -141
- package/src/inserttextcommand.d.ts +76 -76
- package/src/inserttextcommand.js +80 -80
- package/src/inserttextobserver.d.ts +59 -59
- package/src/inserttextobserver.js +108 -108
- package/src/texttransformation.d.ts +33 -33
- package/src/texttransformation.js +228 -228
- package/src/textwatcher.d.ts +138 -138
- package/src/textwatcher.js +105 -105
- package/src/twostepcaretmovement.d.ts +199 -199
- package/src/twostepcaretmovement.js +435 -435
- package/src/typing.d.ts +23 -23
- package/src/typing.js +27 -27
- package/src/typingconfig.d.ts +204 -204
- package/src/typingconfig.js +5 -5
- package/src/utils/changebuffer.d.ts +103 -103
- package/src/utils/changebuffer.js +123 -123
- package/src/utils/findattributerange.d.ts +33 -33
- package/src/utils/findattributerange.js +41 -41
- package/src/utils/getlasttextline.d.ts +49 -49
- package/src/utils/getlasttextline.js +43 -43
- package/src/utils/inlinehighlight.d.ts +33 -33
- package/src/utils/inlinehighlight.js +74 -74
package/src/input.d.ts
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
|
-
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* @module typing/input
|
|
7
|
-
*/
|
|
8
|
-
import { Plugin } from '@ckeditor/ckeditor5-core';
|
|
9
|
-
/**
|
|
10
|
-
* Handles text input coming from the keyboard or other input methods.
|
|
11
|
-
*/
|
|
12
|
-
export default class Input extends Plugin {
|
|
13
|
-
/**
|
|
14
|
-
* @inheritDoc
|
|
15
|
-
*/
|
|
16
|
-
static get pluginName(): "Input";
|
|
17
|
-
/**
|
|
18
|
-
* @inheritDoc
|
|
19
|
-
*/
|
|
20
|
-
init(): void;
|
|
21
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* @module typing/input
|
|
7
|
+
*/
|
|
8
|
+
import { Plugin } from '@ckeditor/ckeditor5-core';
|
|
9
|
+
/**
|
|
10
|
+
* Handles text input coming from the keyboard or other input methods.
|
|
11
|
+
*/
|
|
12
|
+
export default class Input extends Plugin {
|
|
13
|
+
/**
|
|
14
|
+
* @inheritDoc
|
|
15
|
+
*/
|
|
16
|
+
static get pluginName(): "Input";
|
|
17
|
+
/**
|
|
18
|
+
* @inheritDoc
|
|
19
|
+
*/
|
|
20
|
+
init(): void;
|
|
21
|
+
}
|
package/src/input.js
CHANGED
|
@@ -1,141 +1,141 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
|
-
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* @module typing/input
|
|
7
|
-
*/
|
|
8
|
-
import { Plugin } from '@ckeditor/ckeditor5-core';
|
|
9
|
-
import { env } from '@ckeditor/ckeditor5-utils';
|
|
10
|
-
import InsertTextCommand from './inserttextcommand';
|
|
11
|
-
import InsertTextObserver from './inserttextobserver';
|
|
12
|
-
/**
|
|
13
|
-
* Handles text input coming from the keyboard or other input methods.
|
|
14
|
-
*/
|
|
15
|
-
export default class Input extends Plugin {
|
|
16
|
-
/**
|
|
17
|
-
* @inheritDoc
|
|
18
|
-
*/
|
|
19
|
-
static get pluginName() {
|
|
20
|
-
return 'Input';
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* @inheritDoc
|
|
24
|
-
*/
|
|
25
|
-
init() {
|
|
26
|
-
const editor = this.editor;
|
|
27
|
-
const model = editor.model;
|
|
28
|
-
const view = editor.editing.view;
|
|
29
|
-
const modelSelection = model.document.selection;
|
|
30
|
-
view.addObserver(InsertTextObserver);
|
|
31
|
-
// TODO The above default configuration value should be defined using editor.config.define() once it's fixed.
|
|
32
|
-
const insertTextCommand = new InsertTextCommand(editor, editor.config.get('typing.undoStep') || 20);
|
|
33
|
-
// Register `insertText` command and add `input` command as an alias for backward compatibility.
|
|
34
|
-
editor.commands.add('insertText', insertTextCommand);
|
|
35
|
-
editor.commands.add('input', insertTextCommand);
|
|
36
|
-
this.listenTo(view.document, 'insertText', (evt, data) => {
|
|
37
|
-
// Rendering is disabled while composing so prevent events that will be rendered by the engine
|
|
38
|
-
// and should not be applied by the browser.
|
|
39
|
-
if (!view.document.isComposing) {
|
|
40
|
-
data.preventDefault();
|
|
41
|
-
}
|
|
42
|
-
const { text, selection: viewSelection, resultRange: viewResultRange } = data;
|
|
43
|
-
// If view selection was specified, translate it to model selection.
|
|
44
|
-
const modelRanges = Array.from(viewSelection.getRanges()).map(viewRange => {
|
|
45
|
-
return editor.editing.mapper.toModelRange(viewRange);
|
|
46
|
-
});
|
|
47
|
-
let insertText = text;
|
|
48
|
-
// Typing in English on Android is firing composition events for the whole typed word.
|
|
49
|
-
// We need to check the target range text to only apply the difference.
|
|
50
|
-
if (env.isAndroid) {
|
|
51
|
-
const selectedText = Array.from(modelRanges[0].getItems()).reduce((rangeText, node) => {
|
|
52
|
-
return rangeText + (node.is('$textProxy') ? node.data : '');
|
|
53
|
-
}, '');
|
|
54
|
-
if (selectedText) {
|
|
55
|
-
if (selectedText.length <= insertText.length) {
|
|
56
|
-
if (insertText.startsWith(selectedText)) {
|
|
57
|
-
insertText = insertText.substring(selectedText.length);
|
|
58
|
-
modelRanges[0].start = modelRanges[0].start.getShiftedBy(selectedText.length);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
if (selectedText.startsWith(insertText)) {
|
|
63
|
-
// TODO this should be mapped as delete?
|
|
64
|
-
modelRanges[0].start = modelRanges[0].start.getShiftedBy(insertText.length);
|
|
65
|
-
insertText = '';
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
const insertTextCommandData = {
|
|
71
|
-
text: insertText,
|
|
72
|
-
selection: model.createSelection(modelRanges)
|
|
73
|
-
};
|
|
74
|
-
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
75
|
-
// @if CK_DEBUG_TYPING // console.log( '%c[Input]%c Execute insertText:',
|
|
76
|
-
// @if CK_DEBUG_TYPING // 'font-weight: bold; color: green;', '',
|
|
77
|
-
// @if CK_DEBUG_TYPING // insertText,
|
|
78
|
-
// @if CK_DEBUG_TYPING // `[${ modelRanges[ 0 ].start.path }]-[${ modelRanges[ 0 ].end.path }]`
|
|
79
|
-
// @if CK_DEBUG_TYPING // );
|
|
80
|
-
// @if CK_DEBUG_TYPING // }
|
|
81
|
-
if (viewResultRange) {
|
|
82
|
-
insertTextCommandData.resultRange = editor.editing.mapper.toModelRange(viewResultRange);
|
|
83
|
-
}
|
|
84
|
-
editor.execute('insertText', insertTextCommandData);
|
|
85
|
-
view.scrollToTheSelection();
|
|
86
|
-
});
|
|
87
|
-
if (env.isAndroid) {
|
|
88
|
-
// On Android with English keyboard, the composition starts just by putting caret
|
|
89
|
-
// at the word end or by selecting a table column. This is not a real composition started.
|
|
90
|
-
// Trigger delete content on first composition key pressed.
|
|
91
|
-
this.listenTo(view.document, 'keydown', (evt, data) => {
|
|
92
|
-
if (modelSelection.isCollapsed || data.keyCode != 229 || !view.document.isComposing) {
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
96
|
-
// @if CK_DEBUG_TYPING // const firstPositionPath = modelSelection.getFirstPosition()!.path;
|
|
97
|
-
// @if CK_DEBUG_TYPING // const lastPositionPath = modelSelection.getLastPosition()!.path;
|
|
98
|
-
// @if CK_DEBUG_TYPING // console.log( '%c[Input]%c KeyDown 229 -> model.deleteContent()',
|
|
99
|
-
// @if CK_DEBUG_TYPING // 'font-weight: bold; color: green;', '',
|
|
100
|
-
// @if CK_DEBUG_TYPING // `[${ firstPositionPath }]-[${ lastPositionPath }]`
|
|
101
|
-
// @if CK_DEBUG_TYPING // );
|
|
102
|
-
// @if CK_DEBUG_TYPING // }
|
|
103
|
-
deleteSelectionContent(model, insertTextCommand);
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
else {
|
|
107
|
-
// Note: The priority must precede the CompositionObserver handler to call it before
|
|
108
|
-
// the renderer is blocked, because we want to render this change.
|
|
109
|
-
this.listenTo(view.document, 'compositionstart', () => {
|
|
110
|
-
if (modelSelection.isCollapsed) {
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
114
|
-
// @if CK_DEBUG_TYPING // const firstPositionPath = modelSelection.getFirstPosition()!.path;
|
|
115
|
-
// @if CK_DEBUG_TYPING // const lastPositionPath = modelSelection.getLastPosition()!.path;
|
|
116
|
-
// @if CK_DEBUG_TYPING // console.log( '%c[Input]%c Composition start -> model.deleteContent()',
|
|
117
|
-
// @if CK_DEBUG_TYPING // 'font-weight: bold; color: green;', '',
|
|
118
|
-
// @if CK_DEBUG_TYPING // `[${ firstPositionPath }]-[${ lastPositionPath }]`
|
|
119
|
-
// @if CK_DEBUG_TYPING // );
|
|
120
|
-
// @if CK_DEBUG_TYPING // }
|
|
121
|
-
deleteSelectionContent(model, insertTextCommand);
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
function deleteSelectionContent(model, insertTextCommand) {
|
|
127
|
-
// By relying on the state of the input command we allow disabling the entire input easily
|
|
128
|
-
// by just disabling the input command. We could’ve used here the delete command but that
|
|
129
|
-
// would mean requiring the delete feature which would block loading one without the other.
|
|
130
|
-
// We could also check the editor.isReadOnly property, but that wouldn't allow to block
|
|
131
|
-
// the input without blocking other features.
|
|
132
|
-
if (!insertTextCommand.isEnabled) {
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
const buffer = insertTextCommand.buffer;
|
|
136
|
-
buffer.lock();
|
|
137
|
-
model.enqueueChange(buffer.batch, () => {
|
|
138
|
-
model.deleteContent(model.document.selection);
|
|
139
|
-
});
|
|
140
|
-
buffer.unlock();
|
|
141
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* @module typing/input
|
|
7
|
+
*/
|
|
8
|
+
import { Plugin } from '@ckeditor/ckeditor5-core';
|
|
9
|
+
import { env } from '@ckeditor/ckeditor5-utils';
|
|
10
|
+
import InsertTextCommand from './inserttextcommand';
|
|
11
|
+
import InsertTextObserver from './inserttextobserver';
|
|
12
|
+
/**
|
|
13
|
+
* Handles text input coming from the keyboard or other input methods.
|
|
14
|
+
*/
|
|
15
|
+
export default class Input extends Plugin {
|
|
16
|
+
/**
|
|
17
|
+
* @inheritDoc
|
|
18
|
+
*/
|
|
19
|
+
static get pluginName() {
|
|
20
|
+
return 'Input';
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* @inheritDoc
|
|
24
|
+
*/
|
|
25
|
+
init() {
|
|
26
|
+
const editor = this.editor;
|
|
27
|
+
const model = editor.model;
|
|
28
|
+
const view = editor.editing.view;
|
|
29
|
+
const modelSelection = model.document.selection;
|
|
30
|
+
view.addObserver(InsertTextObserver);
|
|
31
|
+
// TODO The above default configuration value should be defined using editor.config.define() once it's fixed.
|
|
32
|
+
const insertTextCommand = new InsertTextCommand(editor, editor.config.get('typing.undoStep') || 20);
|
|
33
|
+
// Register `insertText` command and add `input` command as an alias for backward compatibility.
|
|
34
|
+
editor.commands.add('insertText', insertTextCommand);
|
|
35
|
+
editor.commands.add('input', insertTextCommand);
|
|
36
|
+
this.listenTo(view.document, 'insertText', (evt, data) => {
|
|
37
|
+
// Rendering is disabled while composing so prevent events that will be rendered by the engine
|
|
38
|
+
// and should not be applied by the browser.
|
|
39
|
+
if (!view.document.isComposing) {
|
|
40
|
+
data.preventDefault();
|
|
41
|
+
}
|
|
42
|
+
const { text, selection: viewSelection, resultRange: viewResultRange } = data;
|
|
43
|
+
// If view selection was specified, translate it to model selection.
|
|
44
|
+
const modelRanges = Array.from(viewSelection.getRanges()).map(viewRange => {
|
|
45
|
+
return editor.editing.mapper.toModelRange(viewRange);
|
|
46
|
+
});
|
|
47
|
+
let insertText = text;
|
|
48
|
+
// Typing in English on Android is firing composition events for the whole typed word.
|
|
49
|
+
// We need to check the target range text to only apply the difference.
|
|
50
|
+
if (env.isAndroid) {
|
|
51
|
+
const selectedText = Array.from(modelRanges[0].getItems()).reduce((rangeText, node) => {
|
|
52
|
+
return rangeText + (node.is('$textProxy') ? node.data : '');
|
|
53
|
+
}, '');
|
|
54
|
+
if (selectedText) {
|
|
55
|
+
if (selectedText.length <= insertText.length) {
|
|
56
|
+
if (insertText.startsWith(selectedText)) {
|
|
57
|
+
insertText = insertText.substring(selectedText.length);
|
|
58
|
+
modelRanges[0].start = modelRanges[0].start.getShiftedBy(selectedText.length);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
if (selectedText.startsWith(insertText)) {
|
|
63
|
+
// TODO this should be mapped as delete?
|
|
64
|
+
modelRanges[0].start = modelRanges[0].start.getShiftedBy(insertText.length);
|
|
65
|
+
insertText = '';
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const insertTextCommandData = {
|
|
71
|
+
text: insertText,
|
|
72
|
+
selection: model.createSelection(modelRanges)
|
|
73
|
+
};
|
|
74
|
+
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
75
|
+
// @if CK_DEBUG_TYPING // console.log( '%c[Input]%c Execute insertText:',
|
|
76
|
+
// @if CK_DEBUG_TYPING // 'font-weight: bold; color: green;', '',
|
|
77
|
+
// @if CK_DEBUG_TYPING // insertText,
|
|
78
|
+
// @if CK_DEBUG_TYPING // `[${ modelRanges[ 0 ].start.path }]-[${ modelRanges[ 0 ].end.path }]`
|
|
79
|
+
// @if CK_DEBUG_TYPING // );
|
|
80
|
+
// @if CK_DEBUG_TYPING // }
|
|
81
|
+
if (viewResultRange) {
|
|
82
|
+
insertTextCommandData.resultRange = editor.editing.mapper.toModelRange(viewResultRange);
|
|
83
|
+
}
|
|
84
|
+
editor.execute('insertText', insertTextCommandData);
|
|
85
|
+
view.scrollToTheSelection();
|
|
86
|
+
});
|
|
87
|
+
if (env.isAndroid) {
|
|
88
|
+
// On Android with English keyboard, the composition starts just by putting caret
|
|
89
|
+
// at the word end or by selecting a table column. This is not a real composition started.
|
|
90
|
+
// Trigger delete content on first composition key pressed.
|
|
91
|
+
this.listenTo(view.document, 'keydown', (evt, data) => {
|
|
92
|
+
if (modelSelection.isCollapsed || data.keyCode != 229 || !view.document.isComposing) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
96
|
+
// @if CK_DEBUG_TYPING // const firstPositionPath = modelSelection.getFirstPosition()!.path;
|
|
97
|
+
// @if CK_DEBUG_TYPING // const lastPositionPath = modelSelection.getLastPosition()!.path;
|
|
98
|
+
// @if CK_DEBUG_TYPING // console.log( '%c[Input]%c KeyDown 229 -> model.deleteContent()',
|
|
99
|
+
// @if CK_DEBUG_TYPING // 'font-weight: bold; color: green;', '',
|
|
100
|
+
// @if CK_DEBUG_TYPING // `[${ firstPositionPath }]-[${ lastPositionPath }]`
|
|
101
|
+
// @if CK_DEBUG_TYPING // );
|
|
102
|
+
// @if CK_DEBUG_TYPING // }
|
|
103
|
+
deleteSelectionContent(model, insertTextCommand);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
// Note: The priority must precede the CompositionObserver handler to call it before
|
|
108
|
+
// the renderer is blocked, because we want to render this change.
|
|
109
|
+
this.listenTo(view.document, 'compositionstart', () => {
|
|
110
|
+
if (modelSelection.isCollapsed) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
114
|
+
// @if CK_DEBUG_TYPING // const firstPositionPath = modelSelection.getFirstPosition()!.path;
|
|
115
|
+
// @if CK_DEBUG_TYPING // const lastPositionPath = modelSelection.getLastPosition()!.path;
|
|
116
|
+
// @if CK_DEBUG_TYPING // console.log( '%c[Input]%c Composition start -> model.deleteContent()',
|
|
117
|
+
// @if CK_DEBUG_TYPING // 'font-weight: bold; color: green;', '',
|
|
118
|
+
// @if CK_DEBUG_TYPING // `[${ firstPositionPath }]-[${ lastPositionPath }]`
|
|
119
|
+
// @if CK_DEBUG_TYPING // );
|
|
120
|
+
// @if CK_DEBUG_TYPING // }
|
|
121
|
+
deleteSelectionContent(model, insertTextCommand);
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
function deleteSelectionContent(model, insertTextCommand) {
|
|
127
|
+
// By relying on the state of the input command we allow disabling the entire input easily
|
|
128
|
+
// by just disabling the input command. We could’ve used here the delete command but that
|
|
129
|
+
// would mean requiring the delete feature which would block loading one without the other.
|
|
130
|
+
// We could also check the editor.isReadOnly property, but that wouldn't allow to block
|
|
131
|
+
// the input without blocking other features.
|
|
132
|
+
if (!insertTextCommand.isEnabled) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const buffer = insertTextCommand.buffer;
|
|
136
|
+
buffer.lock();
|
|
137
|
+
model.enqueueChange(buffer.batch, () => {
|
|
138
|
+
model.deleteContent(model.document.selection);
|
|
139
|
+
});
|
|
140
|
+
buffer.unlock();
|
|
141
|
+
}
|
|
@@ -1,76 +1,76 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
|
-
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* @module typing/inserttextcommand
|
|
7
|
-
*/
|
|
8
|
-
import { Command, type Editor } from '@ckeditor/ckeditor5-core';
|
|
9
|
-
import ChangeBuffer from './utils/changebuffer';
|
|
10
|
-
import type { DocumentSelection, Range, Selection } from '@ckeditor/ckeditor5-engine';
|
|
11
|
-
/**
|
|
12
|
-
* The insert text command. Used by the {@link module:typing/input~Input input feature} to handle typing.
|
|
13
|
-
*/
|
|
14
|
-
export default class InsertTextCommand extends Command {
|
|
15
|
-
/**
|
|
16
|
-
* Typing's change buffer used to group subsequent changes into batches.
|
|
17
|
-
*/
|
|
18
|
-
private readonly _buffer;
|
|
19
|
-
/**
|
|
20
|
-
* Creates an instance of the command.
|
|
21
|
-
*
|
|
22
|
-
* @param undoStepSize The maximum number of atomic changes
|
|
23
|
-
* which can be contained in one batch in the command buffer.
|
|
24
|
-
*/
|
|
25
|
-
constructor(editor: Editor, undoStepSize: number);
|
|
26
|
-
/**
|
|
27
|
-
* The current change buffer.
|
|
28
|
-
*/
|
|
29
|
-
get buffer(): ChangeBuffer;
|
|
30
|
-
/**
|
|
31
|
-
* @inheritDoc
|
|
32
|
-
*/
|
|
33
|
-
destroy(): void;
|
|
34
|
-
/**
|
|
35
|
-
* Executes the input command. It replaces the content within the given range with the given text.
|
|
36
|
-
* Replacing is a two step process, first the content within the range is removed and then the new text is inserted
|
|
37
|
-
* at the beginning of the range (which after the removal is a collapsed range).
|
|
38
|
-
*
|
|
39
|
-
* @fires execute
|
|
40
|
-
* @param options The command options.
|
|
41
|
-
*/
|
|
42
|
-
execute(options?: InsertTextCommandOptions): void;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Interface with parameters for executing InsertTextCommand.
|
|
46
|
-
*
|
|
47
|
-
* Both `range` and `selection` parameters are used for defining selection but should not be used together.
|
|
48
|
-
* If both are defined, only `selection` will be considered.
|
|
49
|
-
*/
|
|
50
|
-
export interface InsertTextCommandOptions {
|
|
51
|
-
/**
|
|
52
|
-
* The text to be inserted.
|
|
53
|
-
*/
|
|
54
|
-
text?: string;
|
|
55
|
-
/**
|
|
56
|
-
* The selection in which the text is inserted.
|
|
57
|
-
* Inserting a text into a selection deletes the current content within selection ranges. If the selection is not specified,
|
|
58
|
-
* the current selection in the model will be used instead.
|
|
59
|
-
*/
|
|
60
|
-
selection?: Selection | DocumentSelection;
|
|
61
|
-
/**
|
|
62
|
-
* The range in which the text is inserted. Defaults to the first range in the current selection.
|
|
63
|
-
*/
|
|
64
|
-
range?: Range;
|
|
65
|
-
/**
|
|
66
|
-
* The range where the selection should be placed after the insertion.
|
|
67
|
-
* If not specified, the selection will be placed right after the inserted text.
|
|
68
|
-
*/
|
|
69
|
-
resultRange?: Range;
|
|
70
|
-
}
|
|
71
|
-
export interface InsertTextCommandExecuteEvent {
|
|
72
|
-
name: 'execute';
|
|
73
|
-
args: [
|
|
74
|
-
data: [options: InsertTextCommandOptions]
|
|
75
|
-
];
|
|
76
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* @module typing/inserttextcommand
|
|
7
|
+
*/
|
|
8
|
+
import { Command, type Editor } from '@ckeditor/ckeditor5-core';
|
|
9
|
+
import ChangeBuffer from './utils/changebuffer';
|
|
10
|
+
import type { DocumentSelection, Range, Selection } from '@ckeditor/ckeditor5-engine';
|
|
11
|
+
/**
|
|
12
|
+
* The insert text command. Used by the {@link module:typing/input~Input input feature} to handle typing.
|
|
13
|
+
*/
|
|
14
|
+
export default class InsertTextCommand extends Command {
|
|
15
|
+
/**
|
|
16
|
+
* Typing's change buffer used to group subsequent changes into batches.
|
|
17
|
+
*/
|
|
18
|
+
private readonly _buffer;
|
|
19
|
+
/**
|
|
20
|
+
* Creates an instance of the command.
|
|
21
|
+
*
|
|
22
|
+
* @param undoStepSize The maximum number of atomic changes
|
|
23
|
+
* which can be contained in one batch in the command buffer.
|
|
24
|
+
*/
|
|
25
|
+
constructor(editor: Editor, undoStepSize: number);
|
|
26
|
+
/**
|
|
27
|
+
* The current change buffer.
|
|
28
|
+
*/
|
|
29
|
+
get buffer(): ChangeBuffer;
|
|
30
|
+
/**
|
|
31
|
+
* @inheritDoc
|
|
32
|
+
*/
|
|
33
|
+
destroy(): void;
|
|
34
|
+
/**
|
|
35
|
+
* Executes the input command. It replaces the content within the given range with the given text.
|
|
36
|
+
* Replacing is a two step process, first the content within the range is removed and then the new text is inserted
|
|
37
|
+
* at the beginning of the range (which after the removal is a collapsed range).
|
|
38
|
+
*
|
|
39
|
+
* @fires execute
|
|
40
|
+
* @param options The command options.
|
|
41
|
+
*/
|
|
42
|
+
execute(options?: InsertTextCommandOptions): void;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Interface with parameters for executing InsertTextCommand.
|
|
46
|
+
*
|
|
47
|
+
* Both `range` and `selection` parameters are used for defining selection but should not be used together.
|
|
48
|
+
* If both are defined, only `selection` will be considered.
|
|
49
|
+
*/
|
|
50
|
+
export interface InsertTextCommandOptions {
|
|
51
|
+
/**
|
|
52
|
+
* The text to be inserted.
|
|
53
|
+
*/
|
|
54
|
+
text?: string;
|
|
55
|
+
/**
|
|
56
|
+
* The selection in which the text is inserted.
|
|
57
|
+
* Inserting a text into a selection deletes the current content within selection ranges. If the selection is not specified,
|
|
58
|
+
* the current selection in the model will be used instead.
|
|
59
|
+
*/
|
|
60
|
+
selection?: Selection | DocumentSelection;
|
|
61
|
+
/**
|
|
62
|
+
* The range in which the text is inserted. Defaults to the first range in the current selection.
|
|
63
|
+
*/
|
|
64
|
+
range?: Range;
|
|
65
|
+
/**
|
|
66
|
+
* The range where the selection should be placed after the insertion.
|
|
67
|
+
* If not specified, the selection will be placed right after the inserted text.
|
|
68
|
+
*/
|
|
69
|
+
resultRange?: Range;
|
|
70
|
+
}
|
|
71
|
+
export interface InsertTextCommandExecuteEvent {
|
|
72
|
+
name: 'execute';
|
|
73
|
+
args: [
|
|
74
|
+
data: [options: InsertTextCommandOptions]
|
|
75
|
+
];
|
|
76
|
+
}
|
package/src/inserttextcommand.js
CHANGED
|
@@ -1,80 +1,80 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
|
-
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* @module typing/inserttextcommand
|
|
7
|
-
*/
|
|
8
|
-
import { Command } from '@ckeditor/ckeditor5-core';
|
|
9
|
-
import ChangeBuffer from './utils/changebuffer';
|
|
10
|
-
/**
|
|
11
|
-
* The insert text command. Used by the {@link module:typing/input~Input input feature} to handle typing.
|
|
12
|
-
*/
|
|
13
|
-
export default class InsertTextCommand extends Command {
|
|
14
|
-
/**
|
|
15
|
-
* Creates an instance of the command.
|
|
16
|
-
*
|
|
17
|
-
* @param undoStepSize The maximum number of atomic changes
|
|
18
|
-
* which can be contained in one batch in the command buffer.
|
|
19
|
-
*/
|
|
20
|
-
constructor(editor, undoStepSize) {
|
|
21
|
-
super(editor);
|
|
22
|
-
this._buffer = new ChangeBuffer(editor.model, undoStepSize);
|
|
23
|
-
// Since this command may execute on different selectable than selection, it should be checked directly in execute block.
|
|
24
|
-
this._isEnabledBasedOnSelection = false;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* The current change buffer.
|
|
28
|
-
*/
|
|
29
|
-
get buffer() {
|
|
30
|
-
return this._buffer;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* @inheritDoc
|
|
34
|
-
*/
|
|
35
|
-
destroy() {
|
|
36
|
-
super.destroy();
|
|
37
|
-
this._buffer.destroy();
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Executes the input command. It replaces the content within the given range with the given text.
|
|
41
|
-
* Replacing is a two step process, first the content within the range is removed and then the new text is inserted
|
|
42
|
-
* at the beginning of the range (which after the removal is a collapsed range).
|
|
43
|
-
*
|
|
44
|
-
* @fires execute
|
|
45
|
-
* @param options The command options.
|
|
46
|
-
*/
|
|
47
|
-
execute(options = {}) {
|
|
48
|
-
const model = this.editor.model;
|
|
49
|
-
const doc = model.document;
|
|
50
|
-
const text = options.text || '';
|
|
51
|
-
const textInsertions = text.length;
|
|
52
|
-
let selection = doc.selection;
|
|
53
|
-
if (options.selection) {
|
|
54
|
-
selection = options.selection;
|
|
55
|
-
}
|
|
56
|
-
else if (options.range) {
|
|
57
|
-
selection = model.createSelection(options.range);
|
|
58
|
-
}
|
|
59
|
-
// Stop executing if selectable is in non-editable place.
|
|
60
|
-
if (!model.canEditAt(selection)) {
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
const resultRange = options.resultRange;
|
|
64
|
-
model.enqueueChange(this._buffer.batch, writer => {
|
|
65
|
-
this._buffer.lock();
|
|
66
|
-
model.deleteContent(selection);
|
|
67
|
-
if (text) {
|
|
68
|
-
model.insertContent(writer.createText(text, doc.selection.getAttributes()), selection);
|
|
69
|
-
}
|
|
70
|
-
if (resultRange) {
|
|
71
|
-
writer.setSelection(resultRange);
|
|
72
|
-
}
|
|
73
|
-
else if (!selection.is('documentSelection')) {
|
|
74
|
-
writer.setSelection(selection);
|
|
75
|
-
}
|
|
76
|
-
this._buffer.unlock();
|
|
77
|
-
this._buffer.input(textInsertions);
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* @module typing/inserttextcommand
|
|
7
|
+
*/
|
|
8
|
+
import { Command } from '@ckeditor/ckeditor5-core';
|
|
9
|
+
import ChangeBuffer from './utils/changebuffer';
|
|
10
|
+
/**
|
|
11
|
+
* The insert text command. Used by the {@link module:typing/input~Input input feature} to handle typing.
|
|
12
|
+
*/
|
|
13
|
+
export default class InsertTextCommand extends Command {
|
|
14
|
+
/**
|
|
15
|
+
* Creates an instance of the command.
|
|
16
|
+
*
|
|
17
|
+
* @param undoStepSize The maximum number of atomic changes
|
|
18
|
+
* which can be contained in one batch in the command buffer.
|
|
19
|
+
*/
|
|
20
|
+
constructor(editor, undoStepSize) {
|
|
21
|
+
super(editor);
|
|
22
|
+
this._buffer = new ChangeBuffer(editor.model, undoStepSize);
|
|
23
|
+
// Since this command may execute on different selectable than selection, it should be checked directly in execute block.
|
|
24
|
+
this._isEnabledBasedOnSelection = false;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The current change buffer.
|
|
28
|
+
*/
|
|
29
|
+
get buffer() {
|
|
30
|
+
return this._buffer;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* @inheritDoc
|
|
34
|
+
*/
|
|
35
|
+
destroy() {
|
|
36
|
+
super.destroy();
|
|
37
|
+
this._buffer.destroy();
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Executes the input command. It replaces the content within the given range with the given text.
|
|
41
|
+
* Replacing is a two step process, first the content within the range is removed and then the new text is inserted
|
|
42
|
+
* at the beginning of the range (which after the removal is a collapsed range).
|
|
43
|
+
*
|
|
44
|
+
* @fires execute
|
|
45
|
+
* @param options The command options.
|
|
46
|
+
*/
|
|
47
|
+
execute(options = {}) {
|
|
48
|
+
const model = this.editor.model;
|
|
49
|
+
const doc = model.document;
|
|
50
|
+
const text = options.text || '';
|
|
51
|
+
const textInsertions = text.length;
|
|
52
|
+
let selection = doc.selection;
|
|
53
|
+
if (options.selection) {
|
|
54
|
+
selection = options.selection;
|
|
55
|
+
}
|
|
56
|
+
else if (options.range) {
|
|
57
|
+
selection = model.createSelection(options.range);
|
|
58
|
+
}
|
|
59
|
+
// Stop executing if selectable is in non-editable place.
|
|
60
|
+
if (!model.canEditAt(selection)) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const resultRange = options.resultRange;
|
|
64
|
+
model.enqueueChange(this._buffer.batch, writer => {
|
|
65
|
+
this._buffer.lock();
|
|
66
|
+
model.deleteContent(selection);
|
|
67
|
+
if (text) {
|
|
68
|
+
model.insertContent(writer.createText(text, doc.selection.getAttributes()), selection);
|
|
69
|
+
}
|
|
70
|
+
if (resultRange) {
|
|
71
|
+
writer.setSelection(resultRange);
|
|
72
|
+
}
|
|
73
|
+
else if (!selection.is('documentSelection')) {
|
|
74
|
+
writer.setSelection(selection);
|
|
75
|
+
}
|
|
76
|
+
this._buffer.unlock();
|
|
77
|
+
this._buffer.input(textInsertions);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|