@ckeditor/ckeditor5-typing 35.2.1 → 35.3.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.
@@ -2,15 +2,11 @@
2
2
  * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
-
6
5
  /**
7
6
  * @module typing/textwatcher
8
7
  */
9
-
10
- import mix from '@ckeditor/ckeditor5-utils/src/mix';
11
- import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';
8
+ import { Observable } from '@ckeditor/ckeditor5-utils/src/observablemixin';
12
9
  import getLastTextLine from './utils/getlasttextline';
13
-
14
10
  /**
15
11
  * The text watcher feature.
16
12
  *
@@ -21,173 +17,137 @@ import getLastTextLine from './utils/getlasttextline';
21
17
  * @private
22
18
  * @mixes module:utils/observablemixin~ObservableMixin
23
19
  */
24
- export default class TextWatcher {
25
- /**
26
- * Creates a text watcher instance.
27
- *
28
- * @param {module:engine/model/model~Model} model
29
- * @param {Function} testCallback See {@link module:typing/textwatcher~TextWatcher#testCallback}.
30
- */
31
- constructor( model, testCallback ) {
32
- /**
33
- * The editor's model.
34
- *
35
- * @readonly
36
- * @member {module:engine/model/model~Model}
37
- */
38
- this.model = model;
39
-
40
- /**
41
- * The function used to match the text.
42
- *
43
- * The test callback can return 3 values:
44
- *
45
- * * `false` if there is no match,
46
- * * `true` if there is a match,
47
- * * an object if there is a match and we want to pass some additional information to the {@link #event:matched:data} event.
48
- *
49
- * @member {Function} #testCallback
50
- * @returns {Object} testResult
51
- */
52
- this.testCallback = testCallback;
53
-
54
- /**
55
- * Whether there is a match currently.
56
- *
57
- * @readonly
58
- * @member {Boolean}
59
- */
60
- this.hasMatch = false;
61
-
62
- /**
63
- * Flag indicating whether the `TextWatcher` instance is enabled or disabled.
64
- * A disabled TextWatcher will not evaluate text.
65
- *
66
- * To disable TextWatcher:
67
- *
68
- * const watcher = new TextWatcher( editor.model, testCallback );
69
- *
70
- * // After this a testCallback will not be called.
71
- * watcher.isEnabled = false;
72
- *
73
- * @observable
74
- * @member {Boolean} #isEnabled
75
- */
76
- this.set( 'isEnabled', true );
77
-
78
- // Toggle text watching on isEnabled state change.
79
- this.on( 'change:isEnabled', () => {
80
- if ( this.isEnabled ) {
81
- this._startListening();
82
- } else {
83
- this.stopListening( model.document.selection );
84
- this.stopListening( model.document );
85
- }
86
- } );
87
-
88
- this._startListening();
89
- }
90
-
91
- /**
92
- * Starts listening to the editor for typing and selection events.
93
- *
94
- * @private
95
- */
96
- _startListening() {
97
- const model = this.model;
98
- const document = model.document;
99
-
100
- this.listenTo( document.selection, 'change:range', ( evt, { directChange } ) => {
101
- // Indirect changes (i.e. when the user types or external changes are applied) are handled in the document's change event.
102
- if ( !directChange ) {
103
- return;
104
- }
105
-
106
- // Act only on collapsed selection.
107
- if ( !document.selection.isCollapsed ) {
108
- if ( this.hasMatch ) {
109
- this.fire( 'unmatched' );
110
- this.hasMatch = false;
111
- }
112
-
113
- return;
114
- }
115
-
116
- this._evaluateTextBeforeSelection( 'selection' );
117
- } );
118
-
119
- this.listenTo( document, 'change:data', ( evt, batch ) => {
120
- if ( batch.isUndo || !batch.isLocal ) {
121
- return;
122
- }
123
-
124
- this._evaluateTextBeforeSelection( 'data', { batch } );
125
- } );
126
- }
127
-
128
- /**
129
- * Checks the editor content for matched text.
130
- *
131
- * @fires matched:data
132
- * @fires matched:selection
133
- * @fires unmatched
134
- *
135
- * @private
136
- * @param {'data'|'selection'} suffix A suffix used for generating the event name.
137
- * @param {Object} data Data object for event.
138
- */
139
- _evaluateTextBeforeSelection( suffix, data = {} ) {
140
- const model = this.model;
141
- const document = model.document;
142
- const selection = document.selection;
143
-
144
- const rangeBeforeSelection = model.createRange( model.createPositionAt( selection.focus.parent, 0 ), selection.focus );
145
-
146
- const { text, range } = getLastTextLine( rangeBeforeSelection, model );
147
-
148
- const testResult = this.testCallback( text );
149
-
150
- if ( !testResult && this.hasMatch ) {
151
- this.fire( 'unmatched' );
152
- }
153
-
154
- this.hasMatch = !!testResult;
155
-
156
- if ( testResult ) {
157
- const eventData = Object.assign( data, { text, range } );
158
-
159
- // If the test callback returns an object with additional data, assign the data as well.
160
- if ( typeof testResult == 'object' ) {
161
- Object.assign( eventData, testResult );
162
- }
163
-
164
- this.fire( `matched:${ suffix }`, eventData );
165
- }
166
- }
20
+ export default class TextWatcher extends Observable {
21
+ /**
22
+ * Creates a text watcher instance.
23
+ *
24
+ * @param {module:engine/model/model~Model} model
25
+ * @param {Function} testCallback See {@link module:typing/textwatcher~TextWatcher#testCallback}.
26
+ */
27
+ constructor(model, testCallback) {
28
+ super();
29
+ /**
30
+ * The editor's model.
31
+ *
32
+ * @readonly
33
+ * @member {module:engine/model/model~Model}
34
+ */
35
+ 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
+ this.testCallback = testCallback;
49
+ /**
50
+ * Whether there is a match currently.
51
+ *
52
+ * @readonly
53
+ * @member {Boolean}
54
+ */
55
+ 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
+ this.set('isEnabled', true);
71
+ // Toggle text watching on isEnabled state change.
72
+ this.on('change:isEnabled', () => {
73
+ if (this.isEnabled) {
74
+ this._startListening();
75
+ }
76
+ else {
77
+ this.stopListening(model.document.selection);
78
+ this.stopListening(model.document);
79
+ }
80
+ });
81
+ this._startListening();
82
+ }
83
+ /**
84
+ * TODO
85
+ */
86
+ get hasMatch() {
87
+ return this._hasMatch;
88
+ }
89
+ /**
90
+ * Starts listening to the editor for typing and selection events.
91
+ *
92
+ * @private
93
+ */
94
+ _startListening() {
95
+ const model = this.model;
96
+ const document = model.document;
97
+ this.listenTo(document.selection, 'change:range', (evt, { directChange }) => {
98
+ // Indirect changes (i.e. when the user types or external changes are applied) are handled in the document's change event.
99
+ if (!directChange) {
100
+ return;
101
+ }
102
+ // Act only on collapsed selection.
103
+ if (!document.selection.isCollapsed) {
104
+ if (this.hasMatch) {
105
+ this.fire('unmatched');
106
+ this._hasMatch = false;
107
+ }
108
+ return;
109
+ }
110
+ this._evaluateTextBeforeSelection('selection');
111
+ });
112
+ this.listenTo(document, 'change:data', (evt, batch) => {
113
+ if (batch.isUndo || !batch.isLocal) {
114
+ return;
115
+ }
116
+ this._evaluateTextBeforeSelection('data', { batch });
117
+ });
118
+ }
119
+ /**
120
+ * Checks the editor content for matched text.
121
+ *
122
+ * @fires matched:data
123
+ * @fires matched:selection
124
+ * @fires unmatched
125
+ *
126
+ * @private
127
+ * @param {'data'|'selection'} suffix A suffix used for generating the event name.
128
+ * @param {Object} data Data object for event.
129
+ */
130
+ _evaluateTextBeforeSelection(suffix, data = {}) {
131
+ const model = this.model;
132
+ const document = model.document;
133
+ const selection = document.selection;
134
+ const rangeBeforeSelection = model.createRange(model.createPositionAt(selection.focus.parent, 0), selection.focus);
135
+ const { text, range } = getLastTextLine(rangeBeforeSelection, model);
136
+ const testResult = this.testCallback(text);
137
+ if (!testResult && this.hasMatch) {
138
+ this.fire('unmatched');
139
+ }
140
+ this._hasMatch = !!testResult;
141
+ if (testResult) {
142
+ const eventData = Object.assign(data, { text, range });
143
+ // If the test callback returns an object with additional data, assign the data as well.
144
+ if (typeof testResult == 'object') {
145
+ Object.assign(eventData, testResult);
146
+ }
147
+ this.fire(`matched:${suffix}`, eventData);
148
+ }
149
+ }
167
150
  }
168
-
169
- mix( TextWatcher, ObservableMixin );
170
-
171
- /**
172
- * Fired whenever the text watcher found a match for data changes.
173
- *
174
- * @event matched:data
175
- * @param {Object} data Event data.
176
- * @param {String} data.text The full text before selection to which the regexp was applied.
177
- * @param {module:engine/model/range~Range} data.range The range representing the position of the `data.text`.
178
- * @param {Object} [data.testResult] The additional data returned from the {@link module:typing/textwatcher~TextWatcher#testCallback}.
179
- */
180
-
181
- /**
182
- * Fired whenever the text watcher found a match for selection changes.
183
- *
184
- * @event matched:selection
185
- * @param {Object} data Event data.
186
- * @param {String} data.text The full text before selection.
187
- * @param {module:engine/model/range~Range} data.range The range representing the position of the `data.text`.
188
- * @param {Object} [data.testResult] The additional data returned from the {@link module:typing/textwatcher~TextWatcher#testCallback}.
189
- */
190
-
191
151
  /**
192
152
  * Fired whenever the text does not match anymore. Fired only when the text watcher found a match.
193
153
  *