@ckeditor/ckeditor5-find-and-replace 36.0.0 → 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/build/find-and-replace.js +1 -1
- package/package.json +28 -23
- package/src/findandreplace.d.ts +45 -0
- package/src/findandreplace.js +62 -75
- package/src/findandreplaceediting.d.ts +67 -0
- package/src/findandreplaceediting.js +178 -239
- package/src/findandreplacestate.d.ts +69 -0
- package/src/findandreplacestate.js +52 -123
- package/src/findandreplaceui.d.ts +60 -0
- package/src/findandreplaceui.js +114 -188
- package/src/findandreplaceutils.d.ts +72 -0
- package/src/findandreplaceutils.js +128 -164
- package/src/findcommand.d.ts +56 -0
- package/src/findcommand.js +53 -83
- package/src/findnextcommand.d.ts +40 -0
- package/src/findnextcommand.js +32 -50
- package/src/findpreviouscommand.d.ts +24 -0
- package/src/findpreviouscommand.js +10 -16
- package/src/index.d.ts +9 -0
- package/src/index.js +0 -2
- package/src/replaceallcommand.d.ts +40 -0
- package/src/replaceallcommand.js +35 -49
- package/src/replacecommand.d.ts +27 -0
- package/src/replacecommand.js +12 -68
- package/src/replacecommandbase.d.ts +31 -0
- package/src/replacecommandbase.js +50 -0
- package/src/ui/findandreplaceformview.d.ts +288 -0
- package/src/ui/findandreplaceformview.js +440 -817
|
@@ -2,130 +2,59 @@
|
|
|
2
2
|
* @license Copyright (c) 2003-2023, 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
|
-
/**
|
|
7
|
-
* @module find-and-replace/findandreplacestate
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { ObservableMixin, mix, Collection } from 'ckeditor5/src/utils';
|
|
11
|
-
|
|
5
|
+
import { ObservableMixin, Collection } from 'ckeditor5/src/utils';
|
|
12
6
|
/**
|
|
13
7
|
* The object storing find and replace plugin state for a given editor instance.
|
|
14
|
-
*
|
|
15
|
-
* @mixes module:utils/observablemixin~ObservableMixin
|
|
16
8
|
*/
|
|
17
|
-
export default class FindAndReplaceState {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Indicates whether the matchWholeWords checkbox has been checked.
|
|
71
|
-
*
|
|
72
|
-
* @readonly
|
|
73
|
-
* @observable
|
|
74
|
-
* @member {Boolean} #matchWholeWords
|
|
75
|
-
*/
|
|
76
|
-
this.set( 'matchWholeWords', false );
|
|
77
|
-
|
|
78
|
-
this.results.on( 'change', ( eventInfo, { removed, index } ) => {
|
|
79
|
-
removed = Array.from( removed );
|
|
80
|
-
|
|
81
|
-
if ( removed.length ) {
|
|
82
|
-
let highlightedResultRemoved = false;
|
|
83
|
-
|
|
84
|
-
model.change( writer => {
|
|
85
|
-
for ( const removedResult of removed ) {
|
|
86
|
-
if ( this.highlightedResult === removedResult ) {
|
|
87
|
-
highlightedResultRemoved = true;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
if ( model.markers.has( removedResult.marker.name ) ) {
|
|
91
|
-
writer.removeMarker( removedResult.marker );
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
} );
|
|
95
|
-
|
|
96
|
-
if ( highlightedResultRemoved ) {
|
|
97
|
-
const nextHighlightedIndex = index >= this.results.length ? 0 : index;
|
|
98
|
-
this.highlightedResult = this.results.get( nextHighlightedIndex );
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
} );
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Cleans the state up and removes markers from the model.
|
|
106
|
-
*
|
|
107
|
-
* @param {module:engine/model/model~Model} model
|
|
108
|
-
*/
|
|
109
|
-
clear( model ) {
|
|
110
|
-
this.searchText = '';
|
|
111
|
-
|
|
112
|
-
model.change( writer => {
|
|
113
|
-
if ( this.highlightedResult ) {
|
|
114
|
-
const oldMatchId = this.highlightedResult.marker.name.split( ':' )[ 1 ];
|
|
115
|
-
const oldMarker = model.markers.get( `findResultHighlighted:${ oldMatchId }` );
|
|
116
|
-
|
|
117
|
-
if ( oldMarker ) {
|
|
118
|
-
writer.removeMarker( oldMarker );
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
[ ...this.results ].forEach( ( { marker } ) => {
|
|
123
|
-
writer.removeMarker( marker );
|
|
124
|
-
} );
|
|
125
|
-
} );
|
|
126
|
-
|
|
127
|
-
this.results.clear();
|
|
128
|
-
}
|
|
9
|
+
export default class FindAndReplaceState extends ObservableMixin() {
|
|
10
|
+
/**
|
|
11
|
+
* Creates an instance of the state.
|
|
12
|
+
*/
|
|
13
|
+
constructor(model) {
|
|
14
|
+
super();
|
|
15
|
+
this.set('results', new Collection());
|
|
16
|
+
this.set('highlightedResult', null);
|
|
17
|
+
this.set('searchText', '');
|
|
18
|
+
this.set('replaceText', '');
|
|
19
|
+
this.set('matchCase', false);
|
|
20
|
+
this.set('matchWholeWords', false);
|
|
21
|
+
this.results.on('change', (eventInfo, { removed, index }) => {
|
|
22
|
+
if (Array.from(removed).length) {
|
|
23
|
+
let highlightedResultRemoved = false;
|
|
24
|
+
model.change(writer => {
|
|
25
|
+
for (const removedResult of removed) {
|
|
26
|
+
if (this.highlightedResult === removedResult) {
|
|
27
|
+
highlightedResultRemoved = true;
|
|
28
|
+
}
|
|
29
|
+
if (model.markers.has(removedResult.marker.name)) {
|
|
30
|
+
writer.removeMarker(removedResult.marker);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
if (highlightedResultRemoved) {
|
|
35
|
+
const nextHighlightedIndex = index >= this.results.length ? 0 : index;
|
|
36
|
+
this.highlightedResult = this.results.get(nextHighlightedIndex);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Cleans the state up and removes markers from the model.
|
|
43
|
+
*/
|
|
44
|
+
clear(model) {
|
|
45
|
+
this.searchText = '';
|
|
46
|
+
model.change(writer => {
|
|
47
|
+
if (this.highlightedResult) {
|
|
48
|
+
const oldMatchId = this.highlightedResult.marker.name.split(':')[1];
|
|
49
|
+
const oldMarker = model.markers.get(`findResultHighlighted:${oldMatchId}`);
|
|
50
|
+
if (oldMarker) {
|
|
51
|
+
writer.removeMarker(oldMarker);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
[...this.results].forEach(({ marker }) => {
|
|
55
|
+
writer.removeMarker(marker);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
this.results.clear();
|
|
59
|
+
}
|
|
129
60
|
}
|
|
130
|
-
|
|
131
|
-
mix( FindAndReplaceState, ObservableMixin );
|
|
@@ -0,0 +1,60 @@
|
|
|
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 find-and-replace/findandreplaceui
|
|
7
|
+
*/
|
|
8
|
+
import { type Editor, Plugin } from 'ckeditor5/src/core';
|
|
9
|
+
import { type ViewWithCssTransitionDisabler } from 'ckeditor5/src/ui';
|
|
10
|
+
import FindAndReplaceFormView from './ui/findandreplaceformview';
|
|
11
|
+
/**
|
|
12
|
+
* The default find and replace UI.
|
|
13
|
+
*
|
|
14
|
+
* It registers the `'findAndReplace'` UI button in the editor's {@link module:ui/componentfactory~ComponentFactory component factory}.
|
|
15
|
+
* that uses the {@link module:find-and-replace/findandreplace~FindAndReplace FindAndReplace} plugin API.
|
|
16
|
+
*/
|
|
17
|
+
export default class FindAndReplaceUI extends Plugin {
|
|
18
|
+
/**
|
|
19
|
+
* @inheritDoc
|
|
20
|
+
*/
|
|
21
|
+
static get pluginName(): 'FindAndReplaceUI';
|
|
22
|
+
/**
|
|
23
|
+
* A reference to the find and replace form view.
|
|
24
|
+
*/
|
|
25
|
+
formView: FindAndReplaceFormView & ViewWithCssTransitionDisabler | null;
|
|
26
|
+
/**
|
|
27
|
+
* @inheritDoc
|
|
28
|
+
*/
|
|
29
|
+
constructor(editor: Editor);
|
|
30
|
+
/**
|
|
31
|
+
* @inheritDoc
|
|
32
|
+
*/
|
|
33
|
+
init(): void;
|
|
34
|
+
/**
|
|
35
|
+
* Sets up the find and replace button.
|
|
36
|
+
*/
|
|
37
|
+
private _setupDropdownButton;
|
|
38
|
+
/**
|
|
39
|
+
* Sets up the form view for the find and replace.
|
|
40
|
+
*
|
|
41
|
+
* @param formView A related form view.
|
|
42
|
+
*/
|
|
43
|
+
private _setupFormView;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Fired when the UI was reset and the search results marked in the editing root should be invalidated,
|
|
47
|
+
* for instance, because the user changed the searched phrase (or options) but didn't hit
|
|
48
|
+
* the "Find" button yet.
|
|
49
|
+
*
|
|
50
|
+
* @eventName searchReseted
|
|
51
|
+
*/
|
|
52
|
+
export type SearchResetedEvent = {
|
|
53
|
+
name: 'searchReseted';
|
|
54
|
+
args: [];
|
|
55
|
+
};
|
|
56
|
+
declare module '@ckeditor/ckeditor5-core' {
|
|
57
|
+
interface PluginsMap {
|
|
58
|
+
[FindAndReplaceUI.pluginName]: FindAndReplaceUI;
|
|
59
|
+
}
|
|
60
|
+
}
|
package/src/findandreplaceui.js
CHANGED
|
@@ -2,205 +2,131 @@
|
|
|
2
2
|
* @license Copyright (c) 2003-2023, 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 find-and-replace/findandreplaceui
|
|
8
7
|
*/
|
|
9
|
-
|
|
10
8
|
import { Plugin } from 'ckeditor5/src/core';
|
|
11
|
-
import { createDropdown } from 'ckeditor5/src/ui';
|
|
9
|
+
import { createDropdown, CssTransitionDisablerMixin } from 'ckeditor5/src/ui';
|
|
12
10
|
import FindAndReplaceFormView from './ui/findandreplaceformview';
|
|
13
|
-
|
|
14
11
|
import loupeIcon from '../theme/icons/find-replace.svg';
|
|
15
|
-
|
|
16
12
|
/**
|
|
17
13
|
* The default find and replace UI.
|
|
18
14
|
*
|
|
19
15
|
* It registers the `'findAndReplace'` UI button in the editor's {@link module:ui/componentfactory~ComponentFactory component factory}.
|
|
20
16
|
* that uses the {@link module:find-and-replace/findandreplace~FindAndReplace FindAndReplace} plugin API.
|
|
21
|
-
*
|
|
22
|
-
* @extends module:core/plugin~Plugin
|
|
23
17
|
*/
|
|
24
18
|
export default class FindAndReplaceUI extends Plugin {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
return Array.from( editingState.results )
|
|
139
|
-
.sort( ( a, b ) => sortMapping[ a.marker.getStart().compareWith( b.marker.getStart() ) ] )
|
|
140
|
-
.indexOf( highlightedResult ) + 1;
|
|
141
|
-
} );
|
|
142
|
-
|
|
143
|
-
// Let the form know how many results were found in total.
|
|
144
|
-
formView.listenTo( editingState.results, 'change', () => {
|
|
145
|
-
formView.matchCount = editingState.results.length;
|
|
146
|
-
} );
|
|
147
|
-
|
|
148
|
-
// Command states are used to enable/disable individual form controls.
|
|
149
|
-
// To keep things simple, instead of binding 4 individual observables, there's only one that combines every
|
|
150
|
-
// commands' isEnabled state. Yes, it will change more often but this simplifies the structure of the form.
|
|
151
|
-
formView.bind( '_areCommandsEnabled' ).to(
|
|
152
|
-
commands.get( 'findNext' ), 'isEnabled',
|
|
153
|
-
commands.get( 'findPrevious' ), 'isEnabled',
|
|
154
|
-
commands.get( 'replace' ), 'isEnabled',
|
|
155
|
-
commands.get( 'replaceAll' ), 'isEnabled',
|
|
156
|
-
( findNext, findPrevious, replace, replaceAll ) => ( { findNext, findPrevious, replace, replaceAll } )
|
|
157
|
-
);
|
|
158
|
-
|
|
159
|
-
// The UI plugin works as an interface between the form and the editing part of the feature.
|
|
160
|
-
formView.delegate( 'findNext', 'findPrevious', 'replace', 'replaceAll' ).to( this );
|
|
161
|
-
|
|
162
|
-
// Let the feature know that search results are no longer relevant because the user changed the searched phrase
|
|
163
|
-
// (or options) but didn't hit the "Find" button yet (e.g. still typing).
|
|
164
|
-
formView.on( 'change:isDirty', ( evt, data, isDirty ) => {
|
|
165
|
-
if ( isDirty ) {
|
|
166
|
-
this.fire( 'searchReseted' );
|
|
167
|
-
}
|
|
168
|
-
} );
|
|
169
|
-
}
|
|
19
|
+
/**
|
|
20
|
+
* @inheritDoc
|
|
21
|
+
*/
|
|
22
|
+
static get pluginName() {
|
|
23
|
+
return 'FindAndReplaceUI';
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* @inheritDoc
|
|
27
|
+
*/
|
|
28
|
+
constructor(editor) {
|
|
29
|
+
super(editor);
|
|
30
|
+
this.formView = null;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* @inheritDoc
|
|
34
|
+
*/
|
|
35
|
+
init() {
|
|
36
|
+
const editor = this.editor;
|
|
37
|
+
// Register the toolbar dropdown component.
|
|
38
|
+
editor.ui.componentFactory.add('findAndReplace', locale => {
|
|
39
|
+
const dropdown = createDropdown(locale);
|
|
40
|
+
// Dropdown should be disabled when in source editing mode. See #10001.
|
|
41
|
+
const findCommand = editor.commands.get('find');
|
|
42
|
+
dropdown.bind('isEnabled').to(findCommand);
|
|
43
|
+
dropdown.once('change:isOpen', () => {
|
|
44
|
+
this.formView = new (CssTransitionDisablerMixin(FindAndReplaceFormView))(editor.locale);
|
|
45
|
+
dropdown.panelView.children.add(this.formView);
|
|
46
|
+
this._setupFormView(this.formView);
|
|
47
|
+
});
|
|
48
|
+
// Every time a dropdown is opened, the search text field should get focused and selected for better UX.
|
|
49
|
+
// Note: Using the low priority here to make sure the following listener starts working after
|
|
50
|
+
// the default action of the drop-down is executed (i.e. the panel showed up). Otherwise,
|
|
51
|
+
// the invisible form/input cannot be focused/selected.
|
|
52
|
+
//
|
|
53
|
+
// Each time a dropdown is closed, move the focus back to the find and replace toolbar button
|
|
54
|
+
// and let the find and replace editing feature know that all search results can be invalidated
|
|
55
|
+
// and no longer should be marked in the content.
|
|
56
|
+
dropdown.on('change:isOpen', (event, name, isOpen) => {
|
|
57
|
+
if (isOpen) {
|
|
58
|
+
this.formView.disableCssTransitions();
|
|
59
|
+
this.formView.reset();
|
|
60
|
+
this.formView._findInputView.fieldView.select();
|
|
61
|
+
this.formView.enableCssTransitions();
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
this.fire('searchReseted');
|
|
65
|
+
}
|
|
66
|
+
}, { priority: 'low' });
|
|
67
|
+
this._setupDropdownButton(dropdown);
|
|
68
|
+
return dropdown;
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Sets up the find and replace button.
|
|
73
|
+
*/
|
|
74
|
+
_setupDropdownButton(dropdown) {
|
|
75
|
+
const editor = this.editor;
|
|
76
|
+
const t = editor.locale.t;
|
|
77
|
+
dropdown.buttonView.set({
|
|
78
|
+
icon: loupeIcon,
|
|
79
|
+
label: t('Find and replace'),
|
|
80
|
+
keystroke: 'CTRL+F',
|
|
81
|
+
tooltip: true
|
|
82
|
+
});
|
|
83
|
+
editor.keystrokes.set('Ctrl+F', (data, cancelEvent) => {
|
|
84
|
+
if (dropdown.isEnabled) {
|
|
85
|
+
dropdown.isOpen = true;
|
|
86
|
+
cancelEvent();
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Sets up the form view for the find and replace.
|
|
92
|
+
*
|
|
93
|
+
* @param formView A related form view.
|
|
94
|
+
*/
|
|
95
|
+
_setupFormView(formView) {
|
|
96
|
+
const editor = this.editor;
|
|
97
|
+
const commands = editor.commands;
|
|
98
|
+
const findAndReplaceEditing = this.editor.plugins.get('FindAndReplaceEditing');
|
|
99
|
+
const editingState = findAndReplaceEditing.state;
|
|
100
|
+
const sortMapping = { before: -1, same: 0, after: 1, different: 1 };
|
|
101
|
+
// Let the form know which result is being highlighted.
|
|
102
|
+
formView.bind('highlightOffset').to(editingState, 'highlightedResult', highlightedResult => {
|
|
103
|
+
if (!highlightedResult) {
|
|
104
|
+
return 0;
|
|
105
|
+
}
|
|
106
|
+
return Array.from(editingState.results)
|
|
107
|
+
.sort((a, b) => sortMapping[a.marker.getStart().compareWith(b.marker.getStart())])
|
|
108
|
+
.indexOf(highlightedResult) + 1;
|
|
109
|
+
});
|
|
110
|
+
// Let the form know how many results were found in total.
|
|
111
|
+
formView.listenTo(editingState.results, 'change', () => {
|
|
112
|
+
formView.matchCount = editingState.results.length;
|
|
113
|
+
});
|
|
114
|
+
// Command states are used to enable/disable individual form controls.
|
|
115
|
+
// To keep things simple, instead of binding 4 individual observables, there's only one that combines every
|
|
116
|
+
// commands' isEnabled state. Yes, it will change more often but this simplifies the structure of the form.
|
|
117
|
+
const findNextCommand = commands.get('findNext');
|
|
118
|
+
const findPreviousCommand = commands.get('findPrevious');
|
|
119
|
+
const replaceCommand = commands.get('replace');
|
|
120
|
+
const replaceAllCommand = commands.get('replaceAll');
|
|
121
|
+
formView.bind('_areCommandsEnabled').to(findNextCommand, 'isEnabled', findPreviousCommand, 'isEnabled', replaceCommand, 'isEnabled', replaceAllCommand, 'isEnabled', (findNext, findPrevious, replace, replaceAll) => ({ findNext, findPrevious, replace, replaceAll }));
|
|
122
|
+
// The UI plugin works as an interface between the form and the editing part of the feature.
|
|
123
|
+
formView.delegate('findNext', 'findPrevious', 'replace', 'replaceAll').to(this);
|
|
124
|
+
// Let the feature know that search results are no longer relevant because the user changed the searched phrase
|
|
125
|
+
// (or options) but didn't hit the "Find" button yet (e.g. still typing).
|
|
126
|
+
formView.on('change:isDirty', (evt, data, isDirty) => {
|
|
127
|
+
if (isDirty) {
|
|
128
|
+
this.fire('searchReseted');
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
}
|
|
170
132
|
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Fired when the find next button is triggered.
|
|
174
|
-
*
|
|
175
|
-
* @event findNext
|
|
176
|
-
* @param {String} searchText Search text.
|
|
177
|
-
*/
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Fired when the find previous button is triggered.
|
|
181
|
-
*
|
|
182
|
-
* @event findPrevious
|
|
183
|
-
* @param {String} searchText Search text.
|
|
184
|
-
*/
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Fired when the replace button is triggered.
|
|
188
|
-
*
|
|
189
|
-
* @event replace
|
|
190
|
-
* @param {String} replaceText Replacement text.
|
|
191
|
-
*/
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Fired when the replaceAll button is triggered.
|
|
195
|
-
*
|
|
196
|
-
* @event replaceAll
|
|
197
|
-
* @param {String} replaceText Replacement text.
|
|
198
|
-
*/
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* Fired when the UI was reset and the search results marked in the editing root should be invalidated,
|
|
202
|
-
* for instance, because the user changed the searched phrase (or options) but didn't hit
|
|
203
|
-
* the "Find" button yet.
|
|
204
|
-
*
|
|
205
|
-
* @event searchReseted
|
|
206
|
-
*/
|
|
@@ -0,0 +1,72 @@
|
|
|
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 find-and-replace/findandreplaceutils
|
|
7
|
+
*/
|
|
8
|
+
import type { Item, Model, Range } from 'ckeditor5/src/engine';
|
|
9
|
+
import { Plugin } from 'ckeditor5/src/core';
|
|
10
|
+
import { Collection } from 'ckeditor5/src/utils';
|
|
11
|
+
import type { ResultType } from './findandreplace';
|
|
12
|
+
/**
|
|
13
|
+
* A set of helpers related to find and replace.
|
|
14
|
+
*/
|
|
15
|
+
export default class FindAndReplaceUtils extends Plugin {
|
|
16
|
+
/**
|
|
17
|
+
* @inheritDoc
|
|
18
|
+
*/
|
|
19
|
+
static get pluginName(): 'FindAndReplaceUtils';
|
|
20
|
+
/**
|
|
21
|
+
* Executes findCallback and updates search results list.
|
|
22
|
+
*
|
|
23
|
+
* @param range The model range to scan for matches.
|
|
24
|
+
* @param model The model.
|
|
25
|
+
* @param findCallback The callback that should return `true` if provided text matches the search term.
|
|
26
|
+
* @param startResults An optional collection of find matches that the function should
|
|
27
|
+
* start with. This would be a collection returned by a previous `updateFindResultFromRange()` call.
|
|
28
|
+
* @returns A collection of objects describing find match.
|
|
29
|
+
*
|
|
30
|
+
* An example structure:
|
|
31
|
+
*
|
|
32
|
+
* ```js
|
|
33
|
+
* {
|
|
34
|
+
* id: resultId,
|
|
35
|
+
* label: foundItem.label,
|
|
36
|
+
* marker
|
|
37
|
+
* }
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
updateFindResultFromRange(range: Range, model: Model, findCallback: ({ item, text }: {
|
|
41
|
+
item: Item;
|
|
42
|
+
text: string;
|
|
43
|
+
}) => Array<ResultType>, startResults: Collection<ResultType> | null): Collection<ResultType>;
|
|
44
|
+
/**
|
|
45
|
+
* Returns text representation of a range. The returned text length should be the same as range length.
|
|
46
|
+
* In order to achieve this, this function will replace inline elements (text-line) as new line character ("\n").
|
|
47
|
+
*
|
|
48
|
+
* @param range The model range.
|
|
49
|
+
* @returns The text content of the provided range.
|
|
50
|
+
*/
|
|
51
|
+
rangeToText(range: Range): string;
|
|
52
|
+
/**
|
|
53
|
+
* Creates a text matching callback for a specified search term and matching options.
|
|
54
|
+
*
|
|
55
|
+
* @param searchTerm The search term.
|
|
56
|
+
* @param options Matching options.
|
|
57
|
+
* - options.matchCase=false If set to `true` letter casing will be ignored.
|
|
58
|
+
* - options.wholeWords=false If set to `true` only whole words that match `callbackOrText` will be matched.
|
|
59
|
+
*/
|
|
60
|
+
findByTextCallback(searchTerm: string, options: {
|
|
61
|
+
matchCase?: boolean;
|
|
62
|
+
wholeWords?: boolean;
|
|
63
|
+
}): ({ item, text }: {
|
|
64
|
+
item: Item;
|
|
65
|
+
text: string;
|
|
66
|
+
}) => Array<ResultType>;
|
|
67
|
+
}
|
|
68
|
+
declare module '@ckeditor/ckeditor5-core' {
|
|
69
|
+
interface PluginsMap {
|
|
70
|
+
[FindAndReplaceUtils.pluginName]: FindAndReplaceUtils;
|
|
71
|
+
}
|
|
72
|
+
}
|