mirror of
https://github.com/TriliumNext/Notes.git
synced 2025-07-27 10:02:59 +08:00
chore(code/find): jump to first result
This commit is contained in:
parent
f2745d546b
commit
c4863dec50
@ -1,8 +1,13 @@
|
||||
import { EditorView, Decoration, MatchDecorator, ViewPlugin, ViewUpdate } from "@codemirror/view";
|
||||
import { StateEffect, Compartment } from "@codemirror/state";
|
||||
import { StateEffect, Compartment, EditorSelection, RangeSet } from "@codemirror/state";
|
||||
|
||||
const searchMatchDecoration = Decoration.mark({ class: "cm-searchMatch" });
|
||||
|
||||
interface Match {
|
||||
from: number;
|
||||
to: number;
|
||||
}
|
||||
|
||||
export function createSearchHighlighter(view: EditorView, searchTerm: string, matchCase: boolean, wholeWord: boolean) {
|
||||
// Escape the search term for use in RegExp
|
||||
const escapedTerm = searchTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
@ -16,17 +21,49 @@ export function createSearchHighlighter(view: EditorView, searchTerm: string, ma
|
||||
});
|
||||
|
||||
return ViewPlugin.fromClass(class SearchHighlighter {
|
||||
matches = matcher.createDeco(view);
|
||||
totalFound = this.matches.size;
|
||||
matches!: RangeSet<Decoration>;
|
||||
totalFound: number;
|
||||
private parsedMatches: Match[];
|
||||
|
||||
constructor(public view: EditorView) { }
|
||||
constructor(public view: EditorView) {
|
||||
this.parsedMatches = [];
|
||||
this.totalFound = 0;
|
||||
this.updateSearchData(view);
|
||||
}
|
||||
|
||||
updateSearchData(view: EditorView) {
|
||||
const matches = matcher.createDeco(view);
|
||||
const cursor = matches.iter();
|
||||
while (cursor.value) {
|
||||
this.parsedMatches.push({
|
||||
from: cursor.from,
|
||||
to: cursor.to
|
||||
});
|
||||
cursor.next();
|
||||
}
|
||||
|
||||
this.matches = matches;
|
||||
this.totalFound = this.parsedMatches.length;
|
||||
}
|
||||
|
||||
update(update: ViewUpdate) {
|
||||
if (update.docChanged || update.viewportChanged) {
|
||||
this.matches = matcher.createDeco(update.view);
|
||||
this.updateSearchData(update.view);
|
||||
}
|
||||
}
|
||||
|
||||
scrollToMatch(matchIndex: number) {
|
||||
if (this.parsedMatches.length <= matchIndex) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pos = this.parsedMatches[matchIndex];
|
||||
this.view.dispatch({
|
||||
effects: EditorView.scrollIntoView(pos.from, { y: "center" }),
|
||||
scrollIntoView: true
|
||||
});
|
||||
}
|
||||
|
||||
destroy() {
|
||||
// Do nothing.
|
||||
}
|
||||
|
@ -176,9 +176,13 @@ export default class CodeMirror extends EditorView {
|
||||
this.dispatch({
|
||||
effects: this.searchHighlightCompartment.reconfigure(plugin)
|
||||
});
|
||||
|
||||
// Wait for the plugin to activate in the next render cycle
|
||||
await new Promise(requestAnimationFrame);
|
||||
const instance = this.plugin(plugin); // TS workaround
|
||||
const instance = this.plugin(plugin);
|
||||
if (instance) {
|
||||
instance.scrollToMatch(0);
|
||||
}
|
||||
|
||||
return {
|
||||
totalFound: instance?.totalFound ?? 0
|
||||
|
Loading…
x
Reference in New Issue
Block a user