@univerjs/docs-find-replace 1.0.0-insiders.20260727-46ed76c
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/README.md +13 -0
- package/lib/cjs/index.js +519 -0
- package/lib/es/index.js +513 -0
- package/lib/index.js +513 -0
- package/lib/types/commands/commands/docs-replace.command.d.ts +24 -0
- package/lib/types/config/config.d.ts +20 -0
- package/lib/types/controllers/docs-find-replace.controller.d.ts +22 -0
- package/lib/types/controllers/utils.d.ts +23 -0
- package/lib/types/index.d.ts +29 -0
- package/lib/types/menu/find-replace.menu.d.ts +18 -0
- package/lib/types/menu/schema.d.ts +17 -0
- package/lib/types/models/docs-find.model.d.ts +61 -0
- package/lib/types/services/docs-find-replace.provider.d.ts +39 -0
- package/lib/umd/index.js +1 -0
- package/package.json +79 -0
package/lib/index.js
ADDED
|
@@ -0,0 +1,513 @@
|
|
|
1
|
+
import { BuildTextUtils, ColorKit, CommandType, DependentOn, Disposable, FOCUSING_DOC, ICommandService, IConfigService, IContextService, IUniverInstanceService, Inject, Injector, JSONX, MemoryCursor, Plugin, TextX, ThemeService, UniverInstanceType, fromCallback, getRichTextEditPath, merge, regexp, toDisposable } from "@univerjs/core";
|
|
2
|
+
import { DocSelectionManagerService, DocSkeletonManagerService, RichTextEditingMutation, UniverDocsPlugin } from "@univerjs/docs";
|
|
3
|
+
import { DocBackScrollRenderController, UniverDocsUIPlugin, getTextRangeFromCharIndex } from "@univerjs/docs-ui";
|
|
4
|
+
import { IRenderManagerService, UniverRenderEnginePlugin } from "@univerjs/engine-render";
|
|
5
|
+
import { FindModel, IFindReplaceService, OpenFindDialogOperation, UniverFindReplacePlugin } from "@univerjs/find-replace";
|
|
6
|
+
import { IMenuManagerService, MenuItemType, RibbonStartGroup } from "@univerjs/ui";
|
|
7
|
+
import { Subject, debounceTime, filter, map } from "rxjs";
|
|
8
|
+
|
|
9
|
+
//#region package.json
|
|
10
|
+
var name = "@univerjs/docs-find-replace";
|
|
11
|
+
var version = "1.0.0-insiders.20260727-46ed76c";
|
|
12
|
+
|
|
13
|
+
//#endregion
|
|
14
|
+
//#region src/config/config.ts
|
|
15
|
+
/**
|
|
16
|
+
* Copyright 2023-present DreamNum Co., Ltd.
|
|
17
|
+
*
|
|
18
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
19
|
+
* you may not use this file except in compliance with the License.
|
|
20
|
+
* You may obtain a copy of the License at
|
|
21
|
+
*
|
|
22
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
23
|
+
*
|
|
24
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
25
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
26
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
27
|
+
* See the License for the specific language governing permissions and
|
|
28
|
+
* limitations under the License.
|
|
29
|
+
*/
|
|
30
|
+
const DOCS_FIND_REPLACE_PLUGIN_CONFIG_KEY = "docs-find-replace.config";
|
|
31
|
+
const configSymbol = Symbol(DOCS_FIND_REPLACE_PLUGIN_CONFIG_KEY);
|
|
32
|
+
const defaultPluginConfig = {};
|
|
33
|
+
|
|
34
|
+
//#endregion
|
|
35
|
+
//#region src/controllers/utils.ts
|
|
36
|
+
function findDocRanges(body, query, disabled) {
|
|
37
|
+
if (!query.findString) return [];
|
|
38
|
+
const expression = regexp.createLiteralRegExp(query.findString, query.caseSensitive ? "gu" : "giu");
|
|
39
|
+
const wordRanges = query.matchesTheWholeWord ? new Set(Array.from(new Intl.Segmenter(void 0, { granularity: "word" }).segment(body.dataStream)).filter((item) => item.isWordLike).map((item) => `${item.index}:${item.index + item.segment.length}`)) : null;
|
|
40
|
+
return Array.from(body.dataStream.matchAll(expression)).filter((match) => {
|
|
41
|
+
var _wordRanges$has;
|
|
42
|
+
return (_wordRanges$has = wordRanges === null || wordRanges === void 0 ? void 0 : wordRanges.has(`${match.index}:${match.index + match[0].length}`)) !== null && _wordRanges$has !== void 0 ? _wordRanges$has : true;
|
|
43
|
+
}).map((match) => {
|
|
44
|
+
var _body$customRanges$so, _body$customRanges;
|
|
45
|
+
const startOffset = match.index;
|
|
46
|
+
const endOffset = startOffset + match[0].length;
|
|
47
|
+
const overlapsWholeEntity = (_body$customRanges$so = (_body$customRanges = body.customRanges) === null || _body$customRanges === void 0 ? void 0 : _body$customRanges.some((range) => range.wholeEntity && range.startIndex < endOffset && range.endIndex + 1 > startOffset)) !== null && _body$customRanges$so !== void 0 ? _body$customRanges$so : false;
|
|
48
|
+
return {
|
|
49
|
+
startOffset,
|
|
50
|
+
endOffset,
|
|
51
|
+
replaceable: !disabled && !overlapsWholeEntity
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
//#endregion
|
|
57
|
+
//#region src/commands/commands/docs-replace.command.ts
|
|
58
|
+
const DocsReplaceCommand = {
|
|
59
|
+
id: "docs.command.replace",
|
|
60
|
+
type: CommandType.COMMAND,
|
|
61
|
+
handler: (accessor, params) => {
|
|
62
|
+
if (!params) return {
|
|
63
|
+
success: 0,
|
|
64
|
+
failure: 0
|
|
65
|
+
};
|
|
66
|
+
const instanceService = accessor.get(IUniverInstanceService);
|
|
67
|
+
const commandService = accessor.get(ICommandService);
|
|
68
|
+
const doc = instanceService.getUnit(params.unitId, UniverInstanceType.UNIVER_DOC);
|
|
69
|
+
const body = doc === null || doc === void 0 ? void 0 : doc.getBody();
|
|
70
|
+
if (!doc || !body) return {
|
|
71
|
+
success: 0,
|
|
72
|
+
failure: params.range ? 1 : 0
|
|
73
|
+
};
|
|
74
|
+
const matches = findDocRanges(body, params.query, !!doc.getSnapshot().disabled);
|
|
75
|
+
const candidates = params.range ? matches.filter((match) => match.startOffset === params.range.startOffset && match.endOffset === params.range.endOffset) : matches;
|
|
76
|
+
const replaceable = candidates.filter((match) => match.replaceable);
|
|
77
|
+
const failure = (params.range && candidates.length === 0 ? 1 : candidates.length) - replaceable.length;
|
|
78
|
+
if (!replaceable.length) return {
|
|
79
|
+
success: 0,
|
|
80
|
+
failure
|
|
81
|
+
};
|
|
82
|
+
const textX = new TextX();
|
|
83
|
+
const memoryCursor = new MemoryCursor();
|
|
84
|
+
for (const match of replaceable) {
|
|
85
|
+
var _slice$textRuns, _slice$customRanges;
|
|
86
|
+
const slice = doc.sliceBody(match.startOffset, match.endOffset);
|
|
87
|
+
const insertBody = params.replaceString ? {
|
|
88
|
+
dataStream: params.replaceString,
|
|
89
|
+
textRuns: (slice === null || slice === void 0 || (_slice$textRuns = slice.textRuns) === null || _slice$textRuns === void 0 ? void 0 : _slice$textRuns.length) ? [{
|
|
90
|
+
...slice.textRuns[0],
|
|
91
|
+
st: 0,
|
|
92
|
+
ed: params.replaceString.length
|
|
93
|
+
}] : void 0,
|
|
94
|
+
customRanges: (slice === null || slice === void 0 || (_slice$customRanges = slice.customRanges) === null || _slice$customRanges === void 0 ? void 0 : _slice$customRanges.length) ? [{
|
|
95
|
+
...slice.customRanges[0],
|
|
96
|
+
startIndex: 0,
|
|
97
|
+
endIndex: params.replaceString.length - 1
|
|
98
|
+
}] : void 0
|
|
99
|
+
} : null;
|
|
100
|
+
textX.push(...BuildTextUtils.selection.delete([{
|
|
101
|
+
startOffset: match.startOffset,
|
|
102
|
+
endOffset: match.endOffset,
|
|
103
|
+
collapsed: false
|
|
104
|
+
}], body, memoryCursor.cursor, insertBody, false));
|
|
105
|
+
memoryCursor.moveCursorTo(match.endOffset);
|
|
106
|
+
}
|
|
107
|
+
const actions = JSONX.getInstance().editOp(textX.serialize(), getRichTextEditPath(doc));
|
|
108
|
+
return commandService.syncExecuteCommand(RichTextEditingMutation.id, {
|
|
109
|
+
unitId: params.unitId,
|
|
110
|
+
actions,
|
|
111
|
+
textRanges: []
|
|
112
|
+
}) ? {
|
|
113
|
+
success: replaceable.length,
|
|
114
|
+
failure
|
|
115
|
+
} : {
|
|
116
|
+
success: 0,
|
|
117
|
+
failure: failure + replaceable.length
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
//#endregion
|
|
123
|
+
//#region src/menu/find-replace.menu.ts
|
|
124
|
+
function DocsFindReplaceMenuItemFactory(accessor) {
|
|
125
|
+
const contextService = accessor.get(IContextService);
|
|
126
|
+
return {
|
|
127
|
+
id: OpenFindDialogOperation.id,
|
|
128
|
+
icon: "SearchIcon",
|
|
129
|
+
tooltip: "find-replace.toolbar",
|
|
130
|
+
type: MenuItemType.BUTTON,
|
|
131
|
+
disabled$: contextService.subscribeContextValue$(FOCUSING_DOC).pipe(map((focused) => !focused))
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
//#endregion
|
|
136
|
+
//#region src/menu/schema.ts
|
|
137
|
+
const menuSchema = { [RibbonStartGroup.OTHERS]: { [OpenFindDialogOperation.id]: {
|
|
138
|
+
order: 3,
|
|
139
|
+
menuItemFactory: DocsFindReplaceMenuItemFactory
|
|
140
|
+
} } };
|
|
141
|
+
|
|
142
|
+
//#endregion
|
|
143
|
+
//#region \0@oxc-project+runtime@0.140.0/helpers/esm/typeof.js
|
|
144
|
+
function _typeof(o) {
|
|
145
|
+
"@babel/helpers - typeof";
|
|
146
|
+
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
|
|
147
|
+
return typeof o;
|
|
148
|
+
} : function(o) {
|
|
149
|
+
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
|
|
150
|
+
}, _typeof(o);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
//#endregion
|
|
154
|
+
//#region \0@oxc-project+runtime@0.140.0/helpers/esm/toPrimitive.js
|
|
155
|
+
function toPrimitive(t, r) {
|
|
156
|
+
if ("object" != _typeof(t) || !t) return t;
|
|
157
|
+
var e = t[Symbol.toPrimitive];
|
|
158
|
+
if (void 0 !== e) {
|
|
159
|
+
var i = e.call(t, r || "default");
|
|
160
|
+
if ("object" != _typeof(i)) return i;
|
|
161
|
+
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
162
|
+
}
|
|
163
|
+
return ("string" === r ? String : Number)(t);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
//#endregion
|
|
167
|
+
//#region \0@oxc-project+runtime@0.140.0/helpers/esm/toPropertyKey.js
|
|
168
|
+
function toPropertyKey(t) {
|
|
169
|
+
var i = toPrimitive(t, "string");
|
|
170
|
+
return "symbol" == _typeof(i) ? i : i + "";
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
//#endregion
|
|
174
|
+
//#region \0@oxc-project+runtime@0.140.0/helpers/esm/defineProperty.js
|
|
175
|
+
function _defineProperty(e, r, t) {
|
|
176
|
+
return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
177
|
+
value: t,
|
|
178
|
+
enumerable: !0,
|
|
179
|
+
configurable: !0,
|
|
180
|
+
writable: !0
|
|
181
|
+
}) : e[r] = t, e;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
//#endregion
|
|
185
|
+
//#region \0@oxc-project+runtime@0.140.0/helpers/esm/decorateParam.js
|
|
186
|
+
function __decorateParam(paramIndex, decorator) {
|
|
187
|
+
return function(target, key) {
|
|
188
|
+
decorator(target, key, paramIndex);
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
//#endregion
|
|
193
|
+
//#region \0@oxc-project+runtime@0.140.0/helpers/esm/decorate.js
|
|
194
|
+
function __decorate(decorators, target, key, desc) {
|
|
195
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
196
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
197
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
198
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
//#endregion
|
|
202
|
+
//#region src/models/docs-find.model.ts
|
|
203
|
+
const DOCS_FIND_REPLACE_PROVIDER = "docs-find-replace-provider";
|
|
204
|
+
let DocsFindModel = class DocsFindModel extends FindModel {
|
|
205
|
+
constructor(_doc, _skeletonManager, _selectionManager, _renderManagerService, _commandService, _themeService) {
|
|
206
|
+
super();
|
|
207
|
+
this._doc = _doc;
|
|
208
|
+
this._skeletonManager = _skeletonManager;
|
|
209
|
+
this._selectionManager = _selectionManager;
|
|
210
|
+
this._renderManagerService = _renderManagerService;
|
|
211
|
+
this._commandService = _commandService;
|
|
212
|
+
this._themeService = _themeService;
|
|
213
|
+
_defineProperty(this, "_matchesUpdate$", new Subject());
|
|
214
|
+
_defineProperty(this, "matchesUpdate$", this._matchesUpdate$.asObservable());
|
|
215
|
+
_defineProperty(this, "_activelyChangingMatch$", new Subject());
|
|
216
|
+
_defineProperty(this, "activelyChangingMatch$", this._activelyChangingMatch$.asObservable());
|
|
217
|
+
_defineProperty(this, "_matches", []);
|
|
218
|
+
_defineProperty(this, "_position", -1);
|
|
219
|
+
_defineProperty(this, "_query", null);
|
|
220
|
+
_defineProperty(this, "_highlights", []);
|
|
221
|
+
_defineProperty(this, "unitId", void 0);
|
|
222
|
+
this.unitId = _doc.getUnitId();
|
|
223
|
+
this.disposeWithMe(toDisposable(fromCallback(this._commandService.onCommandExecuted.bind(this._commandService)).pipe(filter(([command]) => {
|
|
224
|
+
var _command$params;
|
|
225
|
+
return command.id === RichTextEditingMutation.id && ((_command$params = command.params) === null || _command$params === void 0 ? void 0 : _command$params.unitId) === this.unitId;
|
|
226
|
+
}), debounceTime(220)).subscribe(() => this._scan(true))));
|
|
227
|
+
this.disposeWithMe(toDisposable(this._skeletonManager.currentSkeleton$.subscribe(() => this._refreshHighlights())));
|
|
228
|
+
}
|
|
229
|
+
get currentMatch() {
|
|
230
|
+
var _this$_matches$this$_;
|
|
231
|
+
return this._position < 0 ? null : (_this$_matches$this$_ = this._matches[this._position]) !== null && _this$_matches$this$_ !== void 0 ? _this$_matches$this$_ : null;
|
|
232
|
+
}
|
|
233
|
+
dispose() {
|
|
234
|
+
super.dispose();
|
|
235
|
+
this._disposeHighlights();
|
|
236
|
+
this._matchesUpdate$.complete();
|
|
237
|
+
this._activelyChangingMatch$.complete();
|
|
238
|
+
}
|
|
239
|
+
getMatches() {
|
|
240
|
+
return this._matches;
|
|
241
|
+
}
|
|
242
|
+
start(query) {
|
|
243
|
+
this._query = query;
|
|
244
|
+
this._position = -1;
|
|
245
|
+
this._scan(false);
|
|
246
|
+
}
|
|
247
|
+
moveToNextMatch(params) {
|
|
248
|
+
if (!this._matches.length) return null;
|
|
249
|
+
if ((params === null || params === void 0 ? void 0 : params.stayIfOnMatch) && this.currentMatch) return this._activate(this._position, params.noFocus);
|
|
250
|
+
let index;
|
|
251
|
+
if (params === null || params === void 0 ? void 0 : params.ignoreSelection) index = 0;
|
|
252
|
+
else if (this._position >= 0) index = this._position + 1;
|
|
253
|
+
else {
|
|
254
|
+
const selection = this._selectionManager.getActiveTextRange();
|
|
255
|
+
const selectedMatch = (params === null || params === void 0 ? void 0 : params.stayIfOnMatch) ? this._selectionMatchIndex() : -1;
|
|
256
|
+
index = selectedMatch >= 0 ? selectedMatch : this._matches.findIndex((match) => {
|
|
257
|
+
var _selection$endOffset;
|
|
258
|
+
return match.range.startOffset >= ((_selection$endOffset = selection === null || selection === void 0 ? void 0 : selection.endOffset) !== null && _selection$endOffset !== void 0 ? _selection$endOffset : 0);
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
if (index < 0 || index >= this._matches.length) index = (params === null || params === void 0 ? void 0 : params.loop) ? 0 : -1;
|
|
262
|
+
if (index < 0) {
|
|
263
|
+
this._position = -1;
|
|
264
|
+
this._refreshHighlights();
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
return this._activate(index, params === null || params === void 0 ? void 0 : params.noFocus);
|
|
268
|
+
}
|
|
269
|
+
moveToPreviousMatch(params) {
|
|
270
|
+
if (!this._matches.length) return null;
|
|
271
|
+
if ((params === null || params === void 0 ? void 0 : params.stayIfOnMatch) && this.currentMatch) return this._activate(this._position, params.noFocus);
|
|
272
|
+
let index;
|
|
273
|
+
if (params === null || params === void 0 ? void 0 : params.ignoreSelection) index = this._matches.length - 1;
|
|
274
|
+
else if (this._position >= 0) index = this._position - 1;
|
|
275
|
+
else {
|
|
276
|
+
const selection = this._selectionManager.getActiveTextRange();
|
|
277
|
+
const selectedMatch = (params === null || params === void 0 ? void 0 : params.stayIfOnMatch) ? this._selectionMatchIndex() : -1;
|
|
278
|
+
index = selectedMatch >= 0 ? selectedMatch : this._matches.findLastIndex((match) => {
|
|
279
|
+
var _selection$startOffse;
|
|
280
|
+
return match.range.endOffset <= ((_selection$startOffse = selection === null || selection === void 0 ? void 0 : selection.startOffset) !== null && _selection$startOffse !== void 0 ? _selection$startOffse : 0);
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
if (index < 0) index = (params === null || params === void 0 ? void 0 : params.loop) ? this._matches.length - 1 : -1;
|
|
284
|
+
if (index < 0) {
|
|
285
|
+
this._position = -1;
|
|
286
|
+
this._refreshHighlights();
|
|
287
|
+
return null;
|
|
288
|
+
}
|
|
289
|
+
return this._activate(index, params === null || params === void 0 ? void 0 : params.noFocus);
|
|
290
|
+
}
|
|
291
|
+
async replace(replaceString) {
|
|
292
|
+
const current = this.currentMatch;
|
|
293
|
+
if (!(current === null || current === void 0 ? void 0 : current.replaceable) || !this._query) return false;
|
|
294
|
+
const result = await this._commandService.executeCommand(DocsReplaceCommand.id, {
|
|
295
|
+
unitId: this.unitId,
|
|
296
|
+
query: this._query,
|
|
297
|
+
replaceString,
|
|
298
|
+
range: current.range
|
|
299
|
+
});
|
|
300
|
+
return (result === null || result === void 0 ? void 0 : result.success) === 1;
|
|
301
|
+
}
|
|
302
|
+
async replaceAll(replaceString) {
|
|
303
|
+
var _await$this$_commandS;
|
|
304
|
+
if (!this._query) return {
|
|
305
|
+
success: 0,
|
|
306
|
+
failure: 0
|
|
307
|
+
};
|
|
308
|
+
return (_await$this$_commandS = await this._commandService.executeCommand(DocsReplaceCommand.id, {
|
|
309
|
+
unitId: this.unitId,
|
|
310
|
+
query: this._query,
|
|
311
|
+
replaceString
|
|
312
|
+
})) !== null && _await$this$_commandS !== void 0 ? _await$this$_commandS : {
|
|
313
|
+
success: 0,
|
|
314
|
+
failure: this._matches.length
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
focusSelection() {
|
|
318
|
+
if (this.currentMatch) this._focusMatch(this.currentMatch);
|
|
319
|
+
}
|
|
320
|
+
_scan(emit) {
|
|
321
|
+
var _this$currentMatch;
|
|
322
|
+
if (!this._query) return;
|
|
323
|
+
const body = this._doc.getBody();
|
|
324
|
+
if (!body) {
|
|
325
|
+
this._matches = [];
|
|
326
|
+
this._position = -1;
|
|
327
|
+
this._disposeHighlights();
|
|
328
|
+
if (emit) this._matchesUpdate$.next([]);
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
const previousStart = (_this$currentMatch = this.currentMatch) === null || _this$currentMatch === void 0 ? void 0 : _this$currentMatch.range.startOffset;
|
|
332
|
+
this._matches = findDocRanges(body, this._query, !!this._doc.getSnapshot().disabled).map((range) => ({
|
|
333
|
+
provider: DOCS_FIND_REPLACE_PROVIDER,
|
|
334
|
+
unitId: this.unitId,
|
|
335
|
+
range: {
|
|
336
|
+
...range,
|
|
337
|
+
collapsed: false
|
|
338
|
+
},
|
|
339
|
+
replaceable: range.replaceable
|
|
340
|
+
}));
|
|
341
|
+
this._position = previousStart == null ? -1 : this._matches.findIndex((match) => match.range.startOffset >= previousStart);
|
|
342
|
+
this._refreshHighlights();
|
|
343
|
+
if (emit) this._matchesUpdate$.next(this._matches);
|
|
344
|
+
}
|
|
345
|
+
_selectionMatchIndex() {
|
|
346
|
+
const selection = this._selectionManager.getActiveTextRange();
|
|
347
|
+
if (!selection) return -1;
|
|
348
|
+
return this._matches.findIndex((match) => match.range.startOffset <= selection.startOffset && match.range.endOffset >= selection.endOffset);
|
|
349
|
+
}
|
|
350
|
+
_activate(index, noFocus = false) {
|
|
351
|
+
const match = this._matches[index];
|
|
352
|
+
if (!match) return null;
|
|
353
|
+
this._position = index;
|
|
354
|
+
if (!noFocus) this._focusMatch(match);
|
|
355
|
+
else this._refreshHighlights();
|
|
356
|
+
return match;
|
|
357
|
+
}
|
|
358
|
+
_focusMatch(match) {
|
|
359
|
+
var _this$_renderManagerS;
|
|
360
|
+
this._selectionManager.replaceDocRanges([match.range], {
|
|
361
|
+
unitId: this.unitId,
|
|
362
|
+
subUnitId: this.unitId
|
|
363
|
+
}, true, { shouldFocus: false });
|
|
364
|
+
(_this$_renderManagerS = this._renderManagerService.getRenderUnitById(this.unitId)) === null || _this$_renderManagerS === void 0 || _this$_renderManagerS.with(DocBackScrollRenderController).scrollToRange(match.range);
|
|
365
|
+
this._activelyChangingMatch$.next(match);
|
|
366
|
+
this._refreshHighlights();
|
|
367
|
+
}
|
|
368
|
+
_refreshHighlights() {
|
|
369
|
+
this._disposeHighlights();
|
|
370
|
+
const render = this._renderManagerService.getRenderUnitById(this.unitId);
|
|
371
|
+
const skeleton = this._skeletonManager.getSkeleton();
|
|
372
|
+
const document = render === null || render === void 0 ? void 0 : render.mainComponent;
|
|
373
|
+
if (!render || !skeleton || !document) return;
|
|
374
|
+
const color = this._themeService.getColorFromTheme("yellow.400");
|
|
375
|
+
const passiveStyle = {
|
|
376
|
+
strokeWidth: 0,
|
|
377
|
+
stroke: "rgba(0,0,0,0)",
|
|
378
|
+
strokeActive: "rgba(0,0,0,0)",
|
|
379
|
+
fill: new ColorKit(color).setAlpha(.3).toRgbString()
|
|
380
|
+
};
|
|
381
|
+
const activeStyle = {
|
|
382
|
+
...passiveStyle,
|
|
383
|
+
fill: new ColorKit(color).setAlpha(.65).toRgbString()
|
|
384
|
+
};
|
|
385
|
+
this._matches.forEach((match, index) => {
|
|
386
|
+
const range = getTextRangeFromCharIndex(match.range.startOffset, match.range.endOffset, render.scene, document, skeleton, index === this._position ? activeStyle : passiveStyle, "", -1);
|
|
387
|
+
if (range) this._highlights.push(range);
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
_disposeHighlights() {
|
|
391
|
+
this._highlights.forEach((highlight) => highlight.dispose());
|
|
392
|
+
this._highlights = [];
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
DocsFindModel = __decorate([
|
|
396
|
+
__decorateParam(2, Inject(DocSelectionManagerService)),
|
|
397
|
+
__decorateParam(3, IRenderManagerService),
|
|
398
|
+
__decorateParam(4, ICommandService),
|
|
399
|
+
__decorateParam(5, Inject(ThemeService))
|
|
400
|
+
], DocsFindModel);
|
|
401
|
+
|
|
402
|
+
//#endregion
|
|
403
|
+
//#region src/services/docs-find-replace.provider.ts
|
|
404
|
+
let DocsFindReplaceProvider = class DocsFindReplaceProvider extends Disposable {
|
|
405
|
+
constructor(_instanceService, _renderManagerService, _injector) {
|
|
406
|
+
super();
|
|
407
|
+
this._instanceService = _instanceService;
|
|
408
|
+
this._renderManagerService = _renderManagerService;
|
|
409
|
+
this._injector = _injector;
|
|
410
|
+
_defineProperty(this, "capabilities", {
|
|
411
|
+
caseSensitive: true,
|
|
412
|
+
matchesTheWholeWord: true,
|
|
413
|
+
matchesTheWholeCell: false,
|
|
414
|
+
findDirection: false,
|
|
415
|
+
findScope: false,
|
|
416
|
+
findBy: false
|
|
417
|
+
});
|
|
418
|
+
_defineProperty(this, "_model", null);
|
|
419
|
+
}
|
|
420
|
+
isSupported(unit) {
|
|
421
|
+
return unit.type === UniverInstanceType.UNIVER_DOC;
|
|
422
|
+
}
|
|
423
|
+
async find(query) {
|
|
424
|
+
var _this$_renderManagerS;
|
|
425
|
+
this.terminate();
|
|
426
|
+
const doc = this._instanceService.getCurrentUnitOfType(UniverInstanceType.UNIVER_DOC);
|
|
427
|
+
if (!doc) return [];
|
|
428
|
+
const skeleton = (_this$_renderManagerS = this._renderManagerService.getRenderUnitById(doc.getUnitId())) === null || _this$_renderManagerS === void 0 ? void 0 : _this$_renderManagerS.with(DocSkeletonManagerService);
|
|
429
|
+
if (!skeleton) return [];
|
|
430
|
+
this._model = this._injector.createInstance(DocsFindModel, doc, skeleton);
|
|
431
|
+
this._model.start(query);
|
|
432
|
+
return [this._model];
|
|
433
|
+
}
|
|
434
|
+
terminate() {
|
|
435
|
+
var _this$_model;
|
|
436
|
+
(_this$_model = this._model) === null || _this$_model === void 0 || _this$_model.dispose();
|
|
437
|
+
this._model = null;
|
|
438
|
+
}
|
|
439
|
+
dispose() {
|
|
440
|
+
this.terminate();
|
|
441
|
+
super.dispose();
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
DocsFindReplaceProvider = __decorate([
|
|
445
|
+
__decorateParam(0, IUniverInstanceService),
|
|
446
|
+
__decorateParam(1, IRenderManagerService),
|
|
447
|
+
__decorateParam(2, Inject(Injector))
|
|
448
|
+
], DocsFindReplaceProvider);
|
|
449
|
+
|
|
450
|
+
//#endregion
|
|
451
|
+
//#region src/controllers/docs-find-replace.controller.ts
|
|
452
|
+
/**
|
|
453
|
+
* Copyright 2023-present DreamNum Co., Ltd.
|
|
454
|
+
*
|
|
455
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
456
|
+
* you may not use this file except in compliance with the License.
|
|
457
|
+
* You may obtain a copy of the License at
|
|
458
|
+
*
|
|
459
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
460
|
+
*
|
|
461
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
462
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
463
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
464
|
+
* See the License for the specific language governing permissions and
|
|
465
|
+
* limitations under the License.
|
|
466
|
+
*/
|
|
467
|
+
let DocsFindReplaceController = class DocsFindReplaceController extends Disposable {
|
|
468
|
+
constructor(provider, findReplaceService, commandService, menuManagerService) {
|
|
469
|
+
super();
|
|
470
|
+
this.disposeWithMe(provider);
|
|
471
|
+
this.disposeWithMe(findReplaceService.registerFindReplaceProvider(provider));
|
|
472
|
+
this.disposeWithMe(commandService.registerCommand(DocsReplaceCommand));
|
|
473
|
+
menuManagerService.mergeMenu(menuSchema);
|
|
474
|
+
}
|
|
475
|
+
};
|
|
476
|
+
DocsFindReplaceController = __decorate([
|
|
477
|
+
__decorateParam(0, Inject(DocsFindReplaceProvider)),
|
|
478
|
+
__decorateParam(1, IFindReplaceService),
|
|
479
|
+
__decorateParam(2, ICommandService),
|
|
480
|
+
__decorateParam(3, IMenuManagerService)
|
|
481
|
+
], DocsFindReplaceController);
|
|
482
|
+
|
|
483
|
+
//#endregion
|
|
484
|
+
//#region src/index.ts
|
|
485
|
+
let UniverDocsFindReplacePlugin = class UniverDocsFindReplacePlugin extends Plugin {
|
|
486
|
+
constructor(_config = defaultPluginConfig, _injector, _configService) {
|
|
487
|
+
super();
|
|
488
|
+
this._config = _config;
|
|
489
|
+
this._injector = _injector;
|
|
490
|
+
this._configService = _configService;
|
|
491
|
+
const { ...rest } = merge({}, defaultPluginConfig, this._config);
|
|
492
|
+
this._configService.setConfig(DOCS_FIND_REPLACE_PLUGIN_CONFIG_KEY, rest);
|
|
493
|
+
}
|
|
494
|
+
onStarting() {
|
|
495
|
+
this._injector.add([DocsFindReplaceProvider]);
|
|
496
|
+
this._injector.add([DocsFindReplaceController]);
|
|
497
|
+
}
|
|
498
|
+
onSteady() {
|
|
499
|
+
this._injector.get(DocsFindReplaceController);
|
|
500
|
+
}
|
|
501
|
+
};
|
|
502
|
+
_defineProperty(UniverDocsFindReplacePlugin, "pluginName", "DOCS_FIND_REPLACE_PLUGIN");
|
|
503
|
+
_defineProperty(UniverDocsFindReplacePlugin, "packageName", name);
|
|
504
|
+
_defineProperty(UniverDocsFindReplacePlugin, "version", version);
|
|
505
|
+
_defineProperty(UniverDocsFindReplacePlugin, "type", UniverInstanceType.UNIVER_DOC);
|
|
506
|
+
UniverDocsFindReplacePlugin = __decorate([
|
|
507
|
+
DependentOn(UniverDocsPlugin, UniverRenderEnginePlugin, UniverDocsUIPlugin, UniverFindReplacePlugin),
|
|
508
|
+
__decorateParam(1, Inject(Injector)),
|
|
509
|
+
__decorateParam(2, IConfigService)
|
|
510
|
+
], UniverDocsFindReplacePlugin);
|
|
511
|
+
|
|
512
|
+
//#endregion
|
|
513
|
+
export { UniverDocsFindReplacePlugin };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2023-present DreamNum Co., Ltd.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import type { ICommand, ITextRange } from '@univerjs/core';
|
|
17
|
+
import type { IFindQuery, IReplaceAllResult } from '@univerjs/find-replace';
|
|
18
|
+
export interface IDocsReplaceCommandParams {
|
|
19
|
+
unitId: string;
|
|
20
|
+
query: IFindQuery;
|
|
21
|
+
replaceString: string;
|
|
22
|
+
range?: ITextRange;
|
|
23
|
+
}
|
|
24
|
+
export declare const DocsReplaceCommand: ICommand<IDocsReplaceCommandParams, IReplaceAllResult>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2023-present DreamNum Co., Ltd.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
export declare const DOCS_FIND_REPLACE_PLUGIN_CONFIG_KEY = "docs-find-replace.config";
|
|
17
|
+
export declare const configSymbol: unique symbol;
|
|
18
|
+
export interface IUniverDocsFindReplaceConfig {
|
|
19
|
+
}
|
|
20
|
+
export declare const defaultPluginConfig: IUniverDocsFindReplaceConfig;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2023-present DreamNum Co., Ltd.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import { Disposable, ICommandService } from '@univerjs/core';
|
|
17
|
+
import { IFindReplaceService } from '@univerjs/find-replace';
|
|
18
|
+
import { IMenuManagerService } from '@univerjs/ui';
|
|
19
|
+
import { DocsFindReplaceProvider } from '../services/docs-find-replace.provider';
|
|
20
|
+
export declare class DocsFindReplaceController extends Disposable {
|
|
21
|
+
constructor(provider: DocsFindReplaceProvider, findReplaceService: IFindReplaceService, commandService: ICommandService, menuManagerService: IMenuManagerService);
|
|
22
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2023-present DreamNum Co., Ltd.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import type { IDocumentBody } from '@univerjs/core';
|
|
17
|
+
import type { IFindQuery } from '@univerjs/find-replace';
|
|
18
|
+
export interface IDocFindRange {
|
|
19
|
+
startOffset: number;
|
|
20
|
+
endOffset: number;
|
|
21
|
+
replaceable: boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare function findDocRanges(body: IDocumentBody, query: IFindQuery, disabled: boolean): IDocFindRange[];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2023-present DreamNum Co., Ltd.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import type { IUniverDocsFindReplaceConfig } from './config/config';
|
|
17
|
+
import { IConfigService, Injector, Plugin, UniverInstanceType } from '@univerjs/core';
|
|
18
|
+
export declare class UniverDocsFindReplacePlugin extends Plugin {
|
|
19
|
+
private readonly _config;
|
|
20
|
+
protected readonly _injector: Injector;
|
|
21
|
+
private readonly _configService;
|
|
22
|
+
static pluginName: string;
|
|
23
|
+
static packageName: string;
|
|
24
|
+
static version: string;
|
|
25
|
+
static type: UniverInstanceType;
|
|
26
|
+
constructor(_config: Partial<IUniverDocsFindReplaceConfig> | undefined, _injector: Injector, _configService: IConfigService);
|
|
27
|
+
onStarting(): void;
|
|
28
|
+
onSteady(): void;
|
|
29
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2023-present DreamNum Co., Ltd.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import type { IAccessor } from '@univerjs/core';
|
|
17
|
+
import type { IMenuButtonItem } from '@univerjs/ui';
|
|
18
|
+
export declare function DocsFindReplaceMenuItemFactory(accessor: IAccessor): IMenuButtonItem;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2023-present DreamNum Co., Ltd.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import type { MenuSchemaType } from '@univerjs/ui';
|
|
17
|
+
export declare const menuSchema: MenuSchemaType;
|