@ckeditor/ckeditor5-typing 36.0.1 → 37.0.0-alpha.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 +23 -22
- package/src/delete.d.ts +37 -0
- package/src/delete.js +0 -2
- package/src/deletecommand.d.ts +90 -0
- package/src/deletecommand.js +11 -37
- package/src/deleteobserver.d.ts +51 -0
- package/src/deleteobserver.js +3 -3
- package/src/index.d.ts +22 -0
- package/src/index.js +1 -0
- package/src/input.d.ts +27 -0
- package/src/input.js +9 -7
- package/src/inserttextcommand.d.ts +81 -0
- package/src/inserttextcommand.js +2 -24
- package/src/inserttextobserver.d.ts +50 -0
- package/src/inserttextobserver.js +1 -3
- package/src/texttransformation.d.ts +38 -0
- package/src/texttransformation.js +26 -34
- package/src/textwatcher.d.ts +138 -0
- package/src/textwatcher.js +4 -54
- package/src/twostepcaretmovement.d.ts +204 -0
- package/src/twostepcaretmovement.js +80 -82
- package/src/typing.d.ts +26 -0
- package/src/typing.js +0 -2
- package/src/typingconfig.d.ts +214 -0
- package/src/utils/changebuffer.d.ts +103 -0
- package/src/utils/changebuffer.js +11 -54
- package/src/utils/findattributerange.d.ts +22 -0
- package/src/utils/findattributerange.js +15 -13
- package/src/utils/getlasttextline.d.ts +49 -0
- package/src/utils/getlasttextline.js +13 -12
- package/src/utils/inlinehighlight.d.ts +36 -0
- package/src/utils/inlinehighlight.js +10 -8
|
@@ -0,0 +1,50 @@
|
|
|
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
|
+
import { DomEventData, Observer, type View, type ViewDocumentSelection, type ViewRange, type ViewSelection } from '@ckeditor/ckeditor5-engine';
|
|
6
|
+
/**
|
|
7
|
+
* Text insertion observer introduces the {@link module:engine/view/document~Document#event:insertText} event.
|
|
8
|
+
*/
|
|
9
|
+
export default class InsertTextObserver extends Observer {
|
|
10
|
+
/**
|
|
11
|
+
* @inheritDoc
|
|
12
|
+
*/
|
|
13
|
+
constructor(view: View);
|
|
14
|
+
/**
|
|
15
|
+
* @inheritDoc
|
|
16
|
+
*/
|
|
17
|
+
observe(): void;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Event fired when the user types text, for instance presses <kbd>A</kbd> or <kbd>?</kbd> in the
|
|
21
|
+
* editing view document.
|
|
22
|
+
*
|
|
23
|
+
* **Note**: This event will **not** fire for keystrokes such as <kbd>Delete</kbd> or <kbd>Enter</kbd>.
|
|
24
|
+
* They have dedicated events, see {@link module:engine/view/document~Document#event:delete} and
|
|
25
|
+
* {@link module:engine/view/document~Document#event:enter} to learn more.
|
|
26
|
+
*
|
|
27
|
+
* **Note**: This event is fired by the {@link module:typing/inserttextobserver~InsertTextObserver input feature}.
|
|
28
|
+
*
|
|
29
|
+
* @eventName module:engine/view/document~Document#event:insertText
|
|
30
|
+
* @param data The event data.
|
|
31
|
+
*/
|
|
32
|
+
export type ViewDocumentInsertTextEvent = {
|
|
33
|
+
name: 'insertText';
|
|
34
|
+
args: [data: InsertTextEventData];
|
|
35
|
+
};
|
|
36
|
+
export interface InsertTextEventData extends DomEventData {
|
|
37
|
+
/**
|
|
38
|
+
* The text to be inserted.
|
|
39
|
+
*/
|
|
40
|
+
text: string;
|
|
41
|
+
/**
|
|
42
|
+
* The selection into which the text should be inserted.
|
|
43
|
+
* If not specified, the insertion should occur at the current view selection.
|
|
44
|
+
*/
|
|
45
|
+
selection: ViewSelection | ViewDocumentSelection;
|
|
46
|
+
/**
|
|
47
|
+
* The range that view selection should be set to after insertion.
|
|
48
|
+
*/
|
|
49
|
+
resultRange?: ViewRange;
|
|
50
|
+
}
|
|
@@ -21,8 +21,6 @@ const TYPING_INPUT_TYPES = [
|
|
|
21
21
|
];
|
|
22
22
|
/**
|
|
23
23
|
* Text insertion observer introduces the {@link module:engine/view/document~Document#event:insertText} event.
|
|
24
|
-
*
|
|
25
|
-
* @extends module:engine/view/observer/observer~Observer
|
|
26
24
|
*/
|
|
27
25
|
export default class InsertTextObserver extends Observer {
|
|
28
26
|
/**
|
|
@@ -68,7 +66,7 @@ export default class InsertTextObserver extends Observer {
|
|
|
68
66
|
if (!data) {
|
|
69
67
|
return;
|
|
70
68
|
}
|
|
71
|
-
// @if CK_DEBUG_TYPING // if ( window.logCKETyping ) {
|
|
69
|
+
// @if CK_DEBUG_TYPING // if ( ( window as any ).logCKETyping ) {
|
|
72
70
|
// @if CK_DEBUG_TYPING // console.log( `%c[InsertTextObserver]%c Fire insertText event, text: ${ JSON.stringify( data ) }`,
|
|
73
71
|
// @if CK_DEBUG_TYPING // 'font-weight: bold; color: green;', ''
|
|
74
72
|
// @if CK_DEBUG_TYPING // );
|
|
@@ -0,0 +1,38 @@
|
|
|
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/texttransformation
|
|
7
|
+
*/
|
|
8
|
+
import { Plugin, type Editor, type PluginDependencies } from '@ckeditor/ckeditor5-core';
|
|
9
|
+
/**
|
|
10
|
+
* The text transformation plugin.
|
|
11
|
+
*/
|
|
12
|
+
export default class TextTransformation extends Plugin {
|
|
13
|
+
/**
|
|
14
|
+
* @inheritDoc
|
|
15
|
+
*/
|
|
16
|
+
static get requires(): PluginDependencies;
|
|
17
|
+
/**
|
|
18
|
+
* @inheritDoc
|
|
19
|
+
*/
|
|
20
|
+
static get pluginName(): 'TextTransformation';
|
|
21
|
+
/**
|
|
22
|
+
* @inheritDoc
|
|
23
|
+
*/
|
|
24
|
+
constructor(editor: Editor);
|
|
25
|
+
/**
|
|
26
|
+
* @inheritDoc
|
|
27
|
+
*/
|
|
28
|
+
init(): void;
|
|
29
|
+
/**
|
|
30
|
+
* Create new TextWatcher listening to the editor for typing and selection events.
|
|
31
|
+
*/
|
|
32
|
+
private _enableTransformationWatchers;
|
|
33
|
+
}
|
|
34
|
+
declare module '@ckeditor/ckeditor5-core' {
|
|
35
|
+
interface PluginsMap {
|
|
36
|
+
[TextTransformation.pluginName]: TextTransformation;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -60,8 +60,6 @@ const DEFAULT_TRANSFORMATIONS = [
|
|
|
60
60
|
];
|
|
61
61
|
/**
|
|
62
62
|
* The text transformation plugin.
|
|
63
|
-
*
|
|
64
|
-
* @extends module:core/plugin~Plugin
|
|
65
63
|
*/
|
|
66
64
|
export default class TextTransformation extends Plugin {
|
|
67
65
|
/**
|
|
@@ -101,8 +99,6 @@ export default class TextTransformation extends Plugin {
|
|
|
101
99
|
}
|
|
102
100
|
/**
|
|
103
101
|
* Create new TextWatcher listening to the editor for typing and selection events.
|
|
104
|
-
*
|
|
105
|
-
* @private
|
|
106
102
|
*/
|
|
107
103
|
_enableTransformationWatchers() {
|
|
108
104
|
const editor = this.editor;
|
|
@@ -150,12 +146,11 @@ export default class TextTransformation extends Plugin {
|
|
|
150
146
|
watcher.bind('isEnabled').to(this);
|
|
151
147
|
}
|
|
152
148
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
// @returns {RegExp}
|
|
149
|
+
/**
|
|
150
|
+
* Normalizes the configuration `from` parameter value.
|
|
151
|
+
* The normalized value for the `from` parameter is a RegExp instance. If the passed `from` is already a RegExp instance,
|
|
152
|
+
* it is returned unchanged.
|
|
153
|
+
*/
|
|
159
154
|
function normalizeFrom(from) {
|
|
160
155
|
if (typeof from == 'string') {
|
|
161
156
|
return new RegExp(`(${escapeRegExp(from)})$`);
|
|
@@ -163,12 +158,11 @@ function normalizeFrom(from) {
|
|
|
163
158
|
// `from` is already a regular expression.
|
|
164
159
|
return from;
|
|
165
160
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
// @returns {Function}
|
|
161
|
+
/**
|
|
162
|
+
* Normalizes the configuration `to` parameter value.
|
|
163
|
+
* The normalized value for the `to` parameter is a function that takes an array and returns an array. See more in the
|
|
164
|
+
* configuration description. If the passed `to` is already a function, it is returned unchanged.
|
|
165
|
+
*/
|
|
172
166
|
function normalizeTo(to) {
|
|
173
167
|
if (typeof to == 'string') {
|
|
174
168
|
return () => [to];
|
|
@@ -179,26 +173,25 @@ function normalizeTo(to) {
|
|
|
179
173
|
// `to` is already a function.
|
|
180
174
|
return to;
|
|
181
175
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
// @returns {Iterable.<*>}
|
|
176
|
+
/**
|
|
177
|
+
* For given `position` returns attributes for the text that is after that position.
|
|
178
|
+
* The text can be in the same text node as the position (`foo[]bar`) or in the next text node (`foo[]<$text bold="true">bar</$text>`).
|
|
179
|
+
*/
|
|
187
180
|
function getTextAttributesAfterPosition(position) {
|
|
188
181
|
const textNode = position.textNode ? position.textNode : position.nodeAfter;
|
|
189
182
|
return textNode.getAttributes();
|
|
190
183
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
184
|
+
/**
|
|
185
|
+
* Returns a RegExp pattern string that detects a sentence inside a quote.
|
|
186
|
+
*
|
|
187
|
+
* @param quoteCharacter The character to create a pattern for.
|
|
188
|
+
*/
|
|
195
189
|
function buildQuotesRegExp(quoteCharacter) {
|
|
196
190
|
return new RegExp(`(^|\\s)(${quoteCharacter})([^${quoteCharacter}]*)(${quoteCharacter})$`);
|
|
197
191
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
// @returns {Array.<{from:String,to:Function}>}
|
|
192
|
+
/**
|
|
193
|
+
* Reads text transformation config and returns normalized array of transformations objects.
|
|
194
|
+
*/
|
|
202
195
|
function normalizeTransformations(config) {
|
|
203
196
|
const extra = config.extra || [];
|
|
204
197
|
const remove = config.remove || [];
|
|
@@ -214,11 +207,10 @@ function normalizeTransformations(config) {
|
|
|
214
207
|
to: normalizeTo(transformation.to)
|
|
215
208
|
}));
|
|
216
209
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
// @returns {Array.<String|Object>}
|
|
210
|
+
/**
|
|
211
|
+
* Reads definitions and expands named groups if needed to transformation names.
|
|
212
|
+
* This method also removes duplicated named transformations if any.
|
|
213
|
+
*/
|
|
222
214
|
function expandGroupsAndRemoveDuplicates(definitions) {
|
|
223
215
|
// Set is using to make sure that transformation names are not duplicated.
|
|
224
216
|
const definedTransformations = new Set();
|
|
@@ -0,0 +1,138 @@
|
|
|
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
|
+
import type { Batch, Model, Range } from '@ckeditor/ckeditor5-engine';
|
|
6
|
+
declare const TextWatcher_base: {
|
|
7
|
+
new (): import("@ckeditor/ckeditor5-utils").Observable;
|
|
8
|
+
prototype: import("@ckeditor/ckeditor5-utils").Observable;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* The text watcher feature.
|
|
12
|
+
*
|
|
13
|
+
* Fires the {@link module:typing/textwatcher~TextWatcher#event:matched:data `matched:data`},
|
|
14
|
+
* {@link module:typing/textwatcher~TextWatcher#event:matched:selection `matched:selection`} and
|
|
15
|
+
* {@link module:typing/textwatcher~TextWatcher#event:unmatched `unmatched`} events on typing or selection changes.
|
|
16
|
+
*/
|
|
17
|
+
export default class TextWatcher extends TextWatcher_base {
|
|
18
|
+
/**
|
|
19
|
+
* The editor's model.
|
|
20
|
+
*/
|
|
21
|
+
readonly model: Model;
|
|
22
|
+
/**
|
|
23
|
+
* The function used to match the text.
|
|
24
|
+
*
|
|
25
|
+
* The test callback can return 3 values:
|
|
26
|
+
*
|
|
27
|
+
* * `false` if there is no match,
|
|
28
|
+
* * `true` if there is a match,
|
|
29
|
+
* * an object if there is a match and we want to pass some additional information to the {@link #event:matched:data} event.
|
|
30
|
+
*/
|
|
31
|
+
testCallback: (text: string) => unknown;
|
|
32
|
+
/**
|
|
33
|
+
* Whether there is a match currently.
|
|
34
|
+
*/
|
|
35
|
+
private _hasMatch;
|
|
36
|
+
/**
|
|
37
|
+
* Flag indicating whether the `TextWatcher` instance is enabled or disabled.
|
|
38
|
+
* A disabled TextWatcher will not evaluate text.
|
|
39
|
+
*
|
|
40
|
+
* To disable TextWatcher:
|
|
41
|
+
*
|
|
42
|
+
* ```ts
|
|
43
|
+
* const watcher = new TextWatcher( editor.model, testCallback );
|
|
44
|
+
*
|
|
45
|
+
* // After this a testCallback will not be called.
|
|
46
|
+
* watcher.isEnabled = false;
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
isEnabled: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Creates a text watcher instance.
|
|
52
|
+
*
|
|
53
|
+
* @param testCallback See {@link module:typing/textwatcher~TextWatcher#testCallback}.
|
|
54
|
+
*/
|
|
55
|
+
constructor(model: Model, testCallback: (text: string) => unknown);
|
|
56
|
+
/**
|
|
57
|
+
* Flag indicating whether there is a match currently.
|
|
58
|
+
*/
|
|
59
|
+
get hasMatch(): boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Starts listening to the editor for typing and selection events.
|
|
62
|
+
*/
|
|
63
|
+
private _startListening;
|
|
64
|
+
/**
|
|
65
|
+
* Checks the editor content for matched text.
|
|
66
|
+
*
|
|
67
|
+
* @fires matched:data
|
|
68
|
+
* @fires matched:selection
|
|
69
|
+
* @fires unmatched
|
|
70
|
+
*
|
|
71
|
+
* @param suffix A suffix used for generating the event name.
|
|
72
|
+
* @param data Data object for event.
|
|
73
|
+
*/
|
|
74
|
+
private _evaluateTextBeforeSelection;
|
|
75
|
+
}
|
|
76
|
+
export type TextWatcherMatchedEvent<TCallbackResult extends Record<string, unknown> = Record<string, unknown>> = {
|
|
77
|
+
name: 'matched' | 'matched:data' | 'matched:selection';
|
|
78
|
+
args: [
|
|
79
|
+
{
|
|
80
|
+
text: string;
|
|
81
|
+
range: Range;
|
|
82
|
+
batch?: Batch;
|
|
83
|
+
} & TCallbackResult
|
|
84
|
+
];
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* Fired whenever the text watcher found a match for data changes.
|
|
88
|
+
*
|
|
89
|
+
* @eventName matched:data
|
|
90
|
+
* @param data Event data.
|
|
91
|
+
* @param data.testResult The additional data returned from the {@link module:typing/textwatcher~TextWatcher#testCallback}.
|
|
92
|
+
*/
|
|
93
|
+
export type TextWatcherMatchedDataEvent<TCallbackResult extends Record<string, unknown>> = {
|
|
94
|
+
name: 'matched:data';
|
|
95
|
+
args: [data: TextWatcherMatchedDataEventData & TCallbackResult];
|
|
96
|
+
};
|
|
97
|
+
export interface TextWatcherMatchedDataEventData {
|
|
98
|
+
/**
|
|
99
|
+
* The full text before selection to which the regexp was applied.
|
|
100
|
+
*/
|
|
101
|
+
text: string;
|
|
102
|
+
/**
|
|
103
|
+
* The range representing the position of the `data.text`.
|
|
104
|
+
*/
|
|
105
|
+
range: Range;
|
|
106
|
+
batch: Batch;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Fired whenever the text watcher found a match for selection changes.
|
|
110
|
+
*
|
|
111
|
+
* @eventName matched:selection
|
|
112
|
+
* @param data Event data.
|
|
113
|
+
* @param data.testResult The additional data returned from the {@link module:typing/textwatcher~TextWatcher#testCallback}.
|
|
114
|
+
*/
|
|
115
|
+
export type TextWatcherMatchedSelectionEvent<TCallbackResult extends Record<string, unknown>> = {
|
|
116
|
+
name: 'matched:selection';
|
|
117
|
+
args: [data: TextWatcherMatchedSelectionEventData & TCallbackResult];
|
|
118
|
+
};
|
|
119
|
+
export interface TextWatcherMatchedSelectionEventData {
|
|
120
|
+
/**
|
|
121
|
+
* The full text before selection.
|
|
122
|
+
*/
|
|
123
|
+
text: string;
|
|
124
|
+
/**
|
|
125
|
+
* The range representing the position of the `data.text`.
|
|
126
|
+
*/
|
|
127
|
+
range: Range;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Fired whenever the text does not match anymore. Fired only when the text watcher found a match.
|
|
131
|
+
*
|
|
132
|
+
* @eventName unmatched
|
|
133
|
+
*/
|
|
134
|
+
export type TextWatcherUnmatchedEvent = {
|
|
135
|
+
name: 'unmatched';
|
|
136
|
+
args: [];
|
|
137
|
+
};
|
|
138
|
+
export {};
|
package/src/textwatcher.js
CHANGED
|
@@ -13,60 +13,18 @@ import getLastTextLine from './utils/getlasttextline';
|
|
|
13
13
|
* Fires the {@link module:typing/textwatcher~TextWatcher#event:matched:data `matched:data`},
|
|
14
14
|
* {@link module:typing/textwatcher~TextWatcher#event:matched:selection `matched:selection`} and
|
|
15
15
|
* {@link module:typing/textwatcher~TextWatcher#event:unmatched `unmatched`} events on typing or selection changes.
|
|
16
|
-
*
|
|
17
|
-
* @private
|
|
18
|
-
* @mixes module:utils/observablemixin~ObservableMixin
|
|
19
16
|
*/
|
|
20
17
|
export default class TextWatcher extends ObservableMixin() {
|
|
21
18
|
/**
|
|
22
19
|
* Creates a text watcher instance.
|
|
23
20
|
*
|
|
24
|
-
* @param {module:
|
|
25
|
-
* @param {Function} testCallback See {@link module:typing/textwatcher~TextWatcher#testCallback}.
|
|
21
|
+
* @param testCallback See {@link module:typing/textwatcher~TextWatcher#testCallback}.
|
|
26
22
|
*/
|
|
27
23
|
constructor(model, testCallback) {
|
|
28
24
|
super();
|
|
29
|
-
/**
|
|
30
|
-
* The editor's model.
|
|
31
|
-
*
|
|
32
|
-
* @readonly
|
|
33
|
-
* @member {module:engine/model/model~Model}
|
|
34
|
-
*/
|
|
35
25
|
this.model = model;
|
|
36
|
-
/**
|
|
37
|
-
* The function used to match the text.
|
|
38
|
-
*
|
|
39
|
-
* The test callback can return 3 values:
|
|
40
|
-
*
|
|
41
|
-
* * `false` if there is no match,
|
|
42
|
-
* * `true` if there is a match,
|
|
43
|
-
* * an object if there is a match and we want to pass some additional information to the {@link #event:matched:data} event.
|
|
44
|
-
*
|
|
45
|
-
* @member {Function} #testCallback
|
|
46
|
-
* @returns {Object} testResult
|
|
47
|
-
*/
|
|
48
26
|
this.testCallback = testCallback;
|
|
49
|
-
/**
|
|
50
|
-
* Whether there is a match currently.
|
|
51
|
-
*
|
|
52
|
-
* @readonly
|
|
53
|
-
* @member {Boolean}
|
|
54
|
-
*/
|
|
55
27
|
this._hasMatch = false;
|
|
56
|
-
/**
|
|
57
|
-
* Flag indicating whether the `TextWatcher` instance is enabled or disabled.
|
|
58
|
-
* A disabled TextWatcher will not evaluate text.
|
|
59
|
-
*
|
|
60
|
-
* To disable TextWatcher:
|
|
61
|
-
*
|
|
62
|
-
* const watcher = new TextWatcher( editor.model, testCallback );
|
|
63
|
-
*
|
|
64
|
-
* // After this a testCallback will not be called.
|
|
65
|
-
* watcher.isEnabled = false;
|
|
66
|
-
*
|
|
67
|
-
* @observable
|
|
68
|
-
* @member {Boolean} #isEnabled
|
|
69
|
-
*/
|
|
70
28
|
this.set('isEnabled', true);
|
|
71
29
|
// Toggle text watching on isEnabled state change.
|
|
72
30
|
this.on('change:isEnabled', () => {
|
|
@@ -81,15 +39,13 @@ export default class TextWatcher extends ObservableMixin() {
|
|
|
81
39
|
this._startListening();
|
|
82
40
|
}
|
|
83
41
|
/**
|
|
84
|
-
*
|
|
42
|
+
* Flag indicating whether there is a match currently.
|
|
85
43
|
*/
|
|
86
44
|
get hasMatch() {
|
|
87
45
|
return this._hasMatch;
|
|
88
46
|
}
|
|
89
47
|
/**
|
|
90
48
|
* Starts listening to the editor for typing and selection events.
|
|
91
|
-
*
|
|
92
|
-
* @private
|
|
93
49
|
*/
|
|
94
50
|
_startListening() {
|
|
95
51
|
const model = this.model;
|
|
@@ -123,9 +79,8 @@ export default class TextWatcher extends ObservableMixin() {
|
|
|
123
79
|
* @fires matched:selection
|
|
124
80
|
* @fires unmatched
|
|
125
81
|
*
|
|
126
|
-
* @
|
|
127
|
-
* @param
|
|
128
|
-
* @param {Object} data Data object for event.
|
|
82
|
+
* @param suffix A suffix used for generating the event name.
|
|
83
|
+
* @param data Data object for event.
|
|
129
84
|
*/
|
|
130
85
|
_evaluateTextBeforeSelection(suffix, data = {}) {
|
|
131
86
|
const model = this.model;
|
|
@@ -148,8 +103,3 @@ export default class TextWatcher extends ObservableMixin() {
|
|
|
148
103
|
}
|
|
149
104
|
}
|
|
150
105
|
}
|
|
151
|
-
/**
|
|
152
|
-
* Fired whenever the text does not match anymore. Fired only when the text watcher found a match.
|
|
153
|
-
*
|
|
154
|
-
* @event unmatched
|
|
155
|
-
*/
|
|
@@ -0,0 +1,204 @@
|
|
|
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/twostepcaretmovement
|
|
7
|
+
*/
|
|
8
|
+
import { Plugin, type Editor } from '@ckeditor/ckeditor5-core';
|
|
9
|
+
/**
|
|
10
|
+
* This plugin enables the two-step caret (phantom) movement behavior for
|
|
11
|
+
* {@link module:typing/twostepcaretmovement~TwoStepCaretMovement#registerAttribute registered attributes}
|
|
12
|
+
* on arrow right (<kbd>→</kbd>) and left (<kbd>←</kbd>) key press.
|
|
13
|
+
*
|
|
14
|
+
* Thanks to this (phantom) caret movement the user is able to type before/after as well as at the
|
|
15
|
+
* beginning/end of an attribute.
|
|
16
|
+
*
|
|
17
|
+
* **Note:** This plugin support right–to–left (Arabic, Hebrew, etc.) content by mirroring its behavior
|
|
18
|
+
* but for the sake of simplicity examples showcase only left–to–right use–cases.
|
|
19
|
+
*
|
|
20
|
+
* # Forward movement
|
|
21
|
+
*
|
|
22
|
+
* ## "Entering" an attribute:
|
|
23
|
+
*
|
|
24
|
+
* When this plugin is enabled and registered for the `a` attribute and the selection is right before it
|
|
25
|
+
* (at the attribute boundary), pressing the right arrow key will not move the selection but update its
|
|
26
|
+
* attributes accordingly:
|
|
27
|
+
*
|
|
28
|
+
* * When enabled:
|
|
29
|
+
*
|
|
30
|
+
* ```xml
|
|
31
|
+
* foo{}<$text a="true">bar</$text>
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* <kbd>→</kbd>
|
|
35
|
+
*
|
|
36
|
+
* ```xml
|
|
37
|
+
* foo<$text a="true">{}bar</$text>
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* * When disabled:
|
|
41
|
+
*
|
|
42
|
+
* ```xml
|
|
43
|
+
* foo{}<$text a="true">bar</$text>
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* <kbd>→</kbd>
|
|
47
|
+
*
|
|
48
|
+
* ```xml
|
|
49
|
+
* foo<$text a="true">b{}ar</$text>
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
*
|
|
53
|
+
* ## "Leaving" an attribute:
|
|
54
|
+
*
|
|
55
|
+
* * When enabled:
|
|
56
|
+
*
|
|
57
|
+
* ```xml
|
|
58
|
+
* <$text a="true">bar{}</$text>baz
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* <kbd>→</kbd>
|
|
62
|
+
*
|
|
63
|
+
* ```xml
|
|
64
|
+
* <$text a="true">bar</$text>{}baz
|
|
65
|
+
* ```
|
|
66
|
+
*
|
|
67
|
+
* * When disabled:
|
|
68
|
+
*
|
|
69
|
+
* ```xml
|
|
70
|
+
* <$text a="true">bar{}</$text>baz
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
* <kbd>→</kbd>
|
|
74
|
+
*
|
|
75
|
+
* ```xml
|
|
76
|
+
* <$text a="true">bar</$text>b{}az
|
|
77
|
+
* ```
|
|
78
|
+
*
|
|
79
|
+
* # Backward movement
|
|
80
|
+
*
|
|
81
|
+
* * When enabled:
|
|
82
|
+
*
|
|
83
|
+
* ```xml
|
|
84
|
+
* <$text a="true">bar</$text>{}baz
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* <kbd>←</kbd>
|
|
88
|
+
*
|
|
89
|
+
* ```xml
|
|
90
|
+
* <$text a="true">bar{}</$text>baz
|
|
91
|
+
* ```
|
|
92
|
+
*
|
|
93
|
+
* * When disabled:
|
|
94
|
+
*
|
|
95
|
+
* ```xml
|
|
96
|
+
* <$text a="true">bar</$text>{}baz
|
|
97
|
+
* ```
|
|
98
|
+
*
|
|
99
|
+
* <kbd>←</kbd>
|
|
100
|
+
*
|
|
101
|
+
* ```xml
|
|
102
|
+
* <$text a="true">ba{}r</$text>b{}az
|
|
103
|
+
* ```
|
|
104
|
+
*
|
|
105
|
+
* # Multiple attributes
|
|
106
|
+
*
|
|
107
|
+
* * When enabled and many attributes starts or ends at the same position:
|
|
108
|
+
*
|
|
109
|
+
* ```xml
|
|
110
|
+
* <$text a="true" b="true">bar</$text>{}baz
|
|
111
|
+
* ```
|
|
112
|
+
*
|
|
113
|
+
* <kbd>←</kbd>
|
|
114
|
+
*
|
|
115
|
+
* ```xml
|
|
116
|
+
* <$text a="true" b="true">bar{}</$text>baz
|
|
117
|
+
* ```
|
|
118
|
+
*
|
|
119
|
+
* * When enabled and one procedes another:
|
|
120
|
+
*
|
|
121
|
+
* ```xml
|
|
122
|
+
* <$text a="true">bar</$text><$text b="true">{}bar</$text>
|
|
123
|
+
* ```
|
|
124
|
+
*
|
|
125
|
+
* <kbd>←</kbd>
|
|
126
|
+
*
|
|
127
|
+
* ```xml
|
|
128
|
+
* <$text a="true">bar{}</$text><$text b="true">bar</$text>
|
|
129
|
+
* ```
|
|
130
|
+
*
|
|
131
|
+
*/
|
|
132
|
+
export default class TwoStepCaretMovement extends Plugin {
|
|
133
|
+
/**
|
|
134
|
+
* A set of attributes to handle.
|
|
135
|
+
*/
|
|
136
|
+
private attributes;
|
|
137
|
+
/**
|
|
138
|
+
* The current UID of the overridden gravity, as returned by
|
|
139
|
+
* {@link module:engine/model/writer~Writer#overrideSelectionGravity}.
|
|
140
|
+
*/
|
|
141
|
+
private _overrideUid;
|
|
142
|
+
/**
|
|
143
|
+
* A flag indicating that the automatic gravity restoration should not happen upon the next
|
|
144
|
+
* gravity restoration.
|
|
145
|
+
* {@link module:engine/model/selection~Selection#event:change:range} event.
|
|
146
|
+
*/
|
|
147
|
+
private _isNextGravityRestorationSkipped;
|
|
148
|
+
/**
|
|
149
|
+
* @inheritDoc
|
|
150
|
+
*/
|
|
151
|
+
static get pluginName(): 'TwoStepCaretMovement';
|
|
152
|
+
/**
|
|
153
|
+
* @inheritDoc
|
|
154
|
+
*/
|
|
155
|
+
constructor(editor: Editor);
|
|
156
|
+
/**
|
|
157
|
+
* @inheritDoc
|
|
158
|
+
*/
|
|
159
|
+
init(): void;
|
|
160
|
+
/**
|
|
161
|
+
* Registers a given attribute for the two-step caret movement.
|
|
162
|
+
*
|
|
163
|
+
* @param attribute Name of the attribute to handle.
|
|
164
|
+
*/
|
|
165
|
+
registerAttribute(attribute: string): void;
|
|
166
|
+
/**
|
|
167
|
+
* Updates the document selection and the view according to the two–step caret movement state
|
|
168
|
+
* when moving **forwards**. Executed upon `keypress` in the {@link module:engine/view/view~View}.
|
|
169
|
+
*
|
|
170
|
+
* @param data Data of the key press.
|
|
171
|
+
* @returns `true` when the handler prevented caret movement.
|
|
172
|
+
*/
|
|
173
|
+
private _handleForwardMovement;
|
|
174
|
+
/**
|
|
175
|
+
* Updates the document selection and the view according to the two–step caret movement state
|
|
176
|
+
* when moving **backwards**. Executed upon `keypress` in the {@link module:engine/view/view~View}.
|
|
177
|
+
*
|
|
178
|
+
* @param data Data of the key press.
|
|
179
|
+
* @returns `true` when the handler prevented caret movement
|
|
180
|
+
*/
|
|
181
|
+
private _handleBackwardMovement;
|
|
182
|
+
/**
|
|
183
|
+
* `true` when the gravity is overridden for the plugin.
|
|
184
|
+
*/
|
|
185
|
+
private get _isGravityOverridden();
|
|
186
|
+
/**
|
|
187
|
+
* Overrides the gravity using the {@link module:engine/model/writer~Writer model writer}
|
|
188
|
+
* and stores the information about this fact in the {@link #_overrideUid}.
|
|
189
|
+
*
|
|
190
|
+
* A shorthand for {@link module:engine/model/writer~Writer#overrideSelectionGravity}.
|
|
191
|
+
*/
|
|
192
|
+
private _overrideGravity;
|
|
193
|
+
/**
|
|
194
|
+
* Restores the gravity using the {@link module:engine/model/writer~Writer model writer}.
|
|
195
|
+
*
|
|
196
|
+
* A shorthand for {@link module:engine/model/writer~Writer#restoreSelectionGravity}.
|
|
197
|
+
*/
|
|
198
|
+
private _restoreGravity;
|
|
199
|
+
}
|
|
200
|
+
declare module '@ckeditor/ckeditor5-core' {
|
|
201
|
+
interface PluginsMap {
|
|
202
|
+
[TwoStepCaretMovement.pluginName]: TwoStepCaretMovement;
|
|
203
|
+
}
|
|
204
|
+
}
|