mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-11-04 15:11:31 +08:00 
			
		
		
		
	chore(client/ts): port find_in_html/text
This commit is contained in:
		
							parent
							
								
									ef59b636b1
								
							
						
					
					
						commit
						7c805eb427
					
				
							
								
								
									
										25
									
								
								src/public/app/types.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										25
									
								
								src/public/app/types.d.ts
									
									
									
									
										vendored
									
									
								
							@ -227,6 +227,7 @@ declare global {
 | 
				
			|||||||
        focus();
 | 
					        focus();
 | 
				
			||||||
        getCursor(): { line: number, col: number, ch: number };
 | 
					        getCursor(): { line: number, col: number, ch: number };
 | 
				
			||||||
        setCursor(line: number, col: number);
 | 
					        setCursor(line: number, col: number);
 | 
				
			||||||
 | 
					        getSelection(): string;
 | 
				
			||||||
        lineCount(): number;
 | 
					        lineCount(): number;
 | 
				
			||||||
        on(event: string, callback: () => void);
 | 
					        on(event: string, callback: () => void);
 | 
				
			||||||
        operation(callback: () => void);
 | 
					        operation(callback: () => void);
 | 
				
			||||||
@ -254,7 +255,7 @@ declare global {
 | 
				
			|||||||
    interface Writer {
 | 
					    interface Writer {
 | 
				
			||||||
        setAttribute(name: string, value: string, el: TextEditorElement);
 | 
					        setAttribute(name: string, value: string, el: TextEditorElement);
 | 
				
			||||||
        createPositionAt(el: TextEditorElement, opt?: "end");
 | 
					        createPositionAt(el: TextEditorElement, opt?: "end");
 | 
				
			||||||
        setSelection(pos: number);
 | 
					        setSelection(pos: number, pos?: number);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    interface TextNode {
 | 
					    interface TextNode {
 | 
				
			||||||
        previousSibling?: TextNode;
 | 
					        previousSibling?: TextNode;
 | 
				
			||||||
@ -270,6 +271,7 @@ declare global {
 | 
				
			|||||||
    interface TextPosition {
 | 
					    interface TextPosition {
 | 
				
			||||||
        textNode: TextNode;
 | 
					        textNode: TextNode;
 | 
				
			||||||
        offset: number;
 | 
					        offset: number;
 | 
				
			||||||
 | 
					        compareWith(pos: TextPosition): string;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    interface TextEditor {
 | 
					    interface TextEditor {
 | 
				
			||||||
        model: {
 | 
					        model: {
 | 
				
			||||||
@ -306,15 +308,34 @@ declare global {
 | 
				
			|||||||
                scrollToTheSelection(): void;
 | 
					                scrollToTheSelection(): void;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        plugins: {
 | 
				
			||||||
 | 
					            get(command: string)
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        getData(): string;
 | 
					        getData(): string;
 | 
				
			||||||
        setData(data: string): void;
 | 
					        setData(data: string): void;
 | 
				
			||||||
        getSelectedHtml(): string;
 | 
					        getSelectedHtml(): string;
 | 
				
			||||||
        removeSelection(): void;
 | 
					        removeSelection(): void;
 | 
				
			||||||
        execute(action: string, ...args: unknown[]): void;
 | 
					        execute<T>(action: string, ...args: unknown[]): T;
 | 
				
			||||||
        focus(): void;
 | 
					        focus(): void;
 | 
				
			||||||
        sourceElement: HTMLElement;
 | 
					        sourceElement: HTMLElement;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    interface EditingState {
 | 
				
			||||||
 | 
					        highlightedResult: string;
 | 
				
			||||||
 | 
					        results: unknown[];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    interface CKFindResult {
 | 
				
			||||||
 | 
					        results: {
 | 
				
			||||||
 | 
					            get(number): {
 | 
				
			||||||
 | 
					                marker: {
 | 
				
			||||||
 | 
					                    getStart(): TextPosition;
 | 
				
			||||||
 | 
					                    getRange(): number;
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } & [];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    interface MentionItem {
 | 
					    interface MentionItem {
 | 
				
			||||||
        action?: string;
 | 
					        action?: string;
 | 
				
			||||||
        noteTitle?: string;
 | 
					        noteTitle?: string;
 | 
				
			||||||
 | 
				
			|||||||
@ -9,10 +9,16 @@ import attributeService from "../services/attributes.js";
 | 
				
			|||||||
import FindInText from "./find_in_text.js";
 | 
					import FindInText from "./find_in_text.js";
 | 
				
			||||||
import FindInCode from "./find_in_code.js";
 | 
					import FindInCode from "./find_in_code.js";
 | 
				
			||||||
import FindInHtml from "./find_in_html.js";
 | 
					import FindInHtml from "./find_in_html.js";
 | 
				
			||||||
 | 
					import type { EventData } from "../components/app_context.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const findWidgetDelayMillis = 200;
 | 
					const findWidgetDelayMillis = 200;
 | 
				
			||||||
const waitForEnter = findWidgetDelayMillis < 0;
 | 
					const waitForEnter = findWidgetDelayMillis < 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface FindResult {
 | 
				
			||||||
 | 
					    totalFound: number;
 | 
				
			||||||
 | 
					    currentFound: number;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// tabIndex=-1 on the checkbox labels is necessary, so when clicking on the label,
 | 
					// tabIndex=-1 on the checkbox labels is necessary, so when clicking on the label,
 | 
				
			||||||
// the focusout handler is called with relatedTarget equal to the label instead
 | 
					// the focusout handler is called with relatedTarget equal to the label instead
 | 
				
			||||||
// of undefined. It's -1 instead of > 0, so they don't tabstop
 | 
					// of undefined. It's -1 instead of > 0, so they don't tabstop
 | 
				
			||||||
@ -92,6 +98,28 @@ const TPL = `
 | 
				
			|||||||
</div>`;
 | 
					</div>`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class FindWidget extends NoteContextAwareWidget {
 | 
					export default class FindWidget extends NoteContextAwareWidget {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private searchTerm: string | null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private textHandler: FindInText;
 | 
				
			||||||
 | 
					    private codeHandler: FindInCode;
 | 
				
			||||||
 | 
					    private htmlHandler: FindInHtml;
 | 
				
			||||||
 | 
					    private handler?: FindInText | FindInCode | FindInHtml;
 | 
				
			||||||
 | 
					    private timeoutId?: number | null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private $input!: JQuery<HTMLElement>;
 | 
				
			||||||
 | 
					    private $currentFound!: JQuery<HTMLElement>;
 | 
				
			||||||
 | 
					    private $totalFound!: JQuery<HTMLElement>;
 | 
				
			||||||
 | 
					    private $caseSensitiveCheckbox!: JQuery<HTMLElement>;
 | 
				
			||||||
 | 
					    private $matchWordsCheckbox!: JQuery<HTMLElement>;
 | 
				
			||||||
 | 
					    private $previousButton!: JQuery<HTMLElement>;
 | 
				
			||||||
 | 
					    private $nextButton!: JQuery<HTMLElement>;
 | 
				
			||||||
 | 
					    private $closeButton!: JQuery<HTMLElement>;
 | 
				
			||||||
 | 
					    private $replaceWidgetBox!: JQuery<HTMLElement>;
 | 
				
			||||||
 | 
					    private $replaceTextInput!: JQuery<HTMLElement>;
 | 
				
			||||||
 | 
					    private $replaceAllButton!: JQuery<HTMLElement>;
 | 
				
			||||||
 | 
					    private $replaceButton!: JQuery<HTMLElement>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor() {
 | 
					    constructor() {
 | 
				
			||||||
        super();
 | 
					        super();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -160,24 +188,24 @@ export default class FindWidget extends NoteContextAwareWidget {
 | 
				
			|||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!["text", "code", "render"].includes(this.note.type)) {
 | 
					        if (!["text", "code", "render"].includes(this.note?.type ?? "")) {
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.handler = await this.getHandler();
 | 
					        this.handler = await this.getHandler();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const isReadOnly = await this.noteContext.isReadOnly();
 | 
					        const isReadOnly = await this.noteContext?.isReadOnly();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let selectedText = "";
 | 
					        let selectedText = "";
 | 
				
			||||||
        if (this.note.type === "code" && !isReadOnly) {
 | 
					        if (this.note?.type === "code" && !isReadOnly && this.noteContext) {
 | 
				
			||||||
            const codeEditor = await this.noteContext.getCodeEditor();
 | 
					            const codeEditor = await this.noteContext.getCodeEditor();
 | 
				
			||||||
            selectedText = codeEditor.getSelection();
 | 
					            selectedText = codeEditor.getSelection();
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            selectedText = window.getSelection().toString() || "";
 | 
					            selectedText = window.getSelection()?.toString() || "";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        this.$widget.show();
 | 
					        this.$widget.show();
 | 
				
			||||||
        this.$input.focus();
 | 
					        this.$input.focus();
 | 
				
			||||||
        if (["text", "code"].includes(this.note.type) && !isReadOnly) {
 | 
					        if (["text", "code"].includes(this.note?.type ?? "") && !isReadOnly) {
 | 
				
			||||||
            this.$replaceWidgetBox.show();
 | 
					            this.$replaceWidgetBox.show();
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            this.$replaceWidgetBox.hide();
 | 
					            this.$replaceWidgetBox.hide();
 | 
				
			||||||
@ -208,16 +236,16 @@ export default class FindWidget extends NoteContextAwareWidget {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async getHandler() {
 | 
					    async getHandler() {
 | 
				
			||||||
        if (this.note.type === "render") {
 | 
					        if (this.note?.type === "render") {
 | 
				
			||||||
            return this.htmlHandler;
 | 
					            return this.htmlHandler;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const readOnly = await this.noteContext.isReadOnly();
 | 
					        const readOnly = await this.noteContext?.isReadOnly();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (readOnly) {
 | 
					        if (readOnly) {
 | 
				
			||||||
            return this.htmlHandler;
 | 
					            return this.htmlHandler;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            return this.note.type === "code" ? this.codeHandler : this.textHandler;
 | 
					            return this.note?.type === "code" ? this.codeHandler : this.textHandler;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -228,7 +256,7 @@ export default class FindWidget extends NoteContextAwareWidget {
 | 
				
			|||||||
        if (!waitForEnter) {
 | 
					        if (!waitForEnter) {
 | 
				
			||||||
            // Clear the previous timeout if any, it's ok if timeoutId is
 | 
					            // Clear the previous timeout if any, it's ok if timeoutId is
 | 
				
			||||||
            // null or undefined
 | 
					            // null or undefined
 | 
				
			||||||
            clearTimeout(this.timeoutId);
 | 
					            clearTimeout(this.timeoutId as unknown as NodeJS.Timeout); // TODO: Fix once client is separated from Node.js types.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Defer the search a few millis so the search doesn't start
 | 
					            // Defer the search a few millis so the search doesn't start
 | 
				
			||||||
            // immediately, as this can cause search word typing lag with
 | 
					            // immediately, as this can cause search word typing lag with
 | 
				
			||||||
@ -237,15 +265,14 @@ export default class FindWidget extends NoteContextAwareWidget {
 | 
				
			|||||||
            this.timeoutId = setTimeout(async () => {
 | 
					            this.timeoutId = setTimeout(async () => {
 | 
				
			||||||
                this.timeoutId = null;
 | 
					                this.timeoutId = null;
 | 
				
			||||||
                await this.performFind();
 | 
					                await this.performFind();
 | 
				
			||||||
            }, findWidgetDelayMillis);
 | 
					            }, findWidgetDelayMillis) as unknown as number; // TODO: Fix once client is separated from Node.js types.
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @param direction +1 for next, -1 for previous
 | 
					     * @param direction +1 for next, -1 for previous
 | 
				
			||||||
     * @returns {Promise<void>}
 | 
					 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    async findNext(direction) {
 | 
					    async findNext(direction: 1 | -1) {
 | 
				
			||||||
        if (this.$totalFound.text() == "?") {
 | 
					        if (this.$totalFound.text() == "?") {
 | 
				
			||||||
            await this.performFind();
 | 
					            await this.performFind();
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
@ -268,17 +295,17 @@ export default class FindWidget extends NoteContextAwareWidget {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            this.$currentFound.text(nextFound + 1);
 | 
					            this.$currentFound.text(nextFound + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            await this.handler.findNext(direction, currentFound, nextFound);
 | 
					            await this.handler?.findNext(direction, currentFound, nextFound);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** Perform the find and highlight the find results. */
 | 
					    /** Perform the find and highlight the find results. */
 | 
				
			||||||
    async performFind() {
 | 
					    async performFind() {
 | 
				
			||||||
        const searchTerm = this.$input.val();
 | 
					        const searchTerm = String(this.$input.val());
 | 
				
			||||||
        const matchCase = this.$caseSensitiveCheckbox.prop("checked");
 | 
					        const matchCase = this.$caseSensitiveCheckbox.prop("checked");
 | 
				
			||||||
        const wholeWord = this.$matchWordsCheckbox.prop("checked");
 | 
					        const wholeWord = this.$matchWordsCheckbox.prop("checked");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const { totalFound, currentFound } = await this.handler.performFind(searchTerm, matchCase, wholeWord);
 | 
					        const { totalFound, currentFound } = await this.handler?.performFind(searchTerm, matchCase, wholeWord);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.$totalFound.text(totalFound);
 | 
					        this.$totalFound.text(totalFound);
 | 
				
			||||||
        this.$currentFound.text(currentFound);
 | 
					        this.$currentFound.text(currentFound);
 | 
				
			||||||
@ -297,28 +324,34 @@ export default class FindWidget extends NoteContextAwareWidget {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            this.searchTerm = null;
 | 
					            this.searchTerm = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            await this.handler.findBoxClosed(totalFound, currentFound);
 | 
					            await this.handler?.findBoxClosed(totalFound, currentFound);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async replace() {
 | 
					    async replace() {
 | 
				
			||||||
        const replaceText = this.$replaceTextInput.val();
 | 
					        const replaceText = String(this.$replaceTextInput.val());
 | 
				
			||||||
        await this.handler.replace(replaceText);
 | 
					        if (this.handler && "replace" in this.handler) {
 | 
				
			||||||
 | 
					            await this.handler.replace(replaceText);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async replaceAll() {
 | 
					    async replaceAll() {
 | 
				
			||||||
        const replaceText = this.$replaceTextInput.val();
 | 
					        const replaceText = String(this.$replaceTextInput.val());
 | 
				
			||||||
        await this.handler.replaceAll(replaceText);
 | 
					        if (this.handler && "replace" in this.handler) {
 | 
				
			||||||
 | 
					            await this.handler.replaceAll(replaceText);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    isEnabled() {
 | 
					    isEnabled() {
 | 
				
			||||||
        return super.isEnabled() && ["text", "code", "render"].includes(this.note.type);
 | 
					        return super.isEnabled() && ["text", "code", "render"].includes(this.note?.type ?? "");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async entitiesReloadedEvent({ loadResults }) {
 | 
					    async entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) {
 | 
				
			||||||
        if (loadResults.isNoteContentReloaded(this.noteId)) {
 | 
					        if (this.noteId && loadResults.isNoteContentReloaded(this.noteId)) {
 | 
				
			||||||
            this.$totalFound.text("?");
 | 
					            this.$totalFound.text("?");
 | 
				
			||||||
        } else if (loadResults.getAttributeRows().find((attr) => attr.type === "label" && attr.name.toLowerCase().includes("readonly") && attributeService.isAffecting(attr, this.note))) {
 | 
					        } else if (loadResults.getAttributeRows().find((attr) => attr.type === "label"
 | 
				
			||||||
 | 
					                && (attr.name?.toLowerCase() ?? "").includes("readonly")
 | 
				
			||||||
 | 
					                && attributeService.isAffecting(attr, this.note))) {
 | 
				
			||||||
            this.closeSearch();
 | 
					            this.closeSearch();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -5,6 +5,7 @@ import libraryLoader from "../services/library_loader.js";
 | 
				
			|||||||
import utils from "../services/utils.js";
 | 
					import utils from "../services/utils.js";
 | 
				
			||||||
import appContext from "../components/app_context.js";
 | 
					import appContext from "../components/app_context.js";
 | 
				
			||||||
import type FindWidget from "./find.js";
 | 
					import type FindWidget from "./find.js";
 | 
				
			||||||
 | 
					import type { FindResult } from "./find.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const FIND_RESULT_SELECTED_CSS_CLASSNAME = "ck-find-result_selected";
 | 
					const FIND_RESULT_SELECTED_CSS_CLASSNAME = "ck-find-result_selected";
 | 
				
			||||||
const FIND_RESULT_CSS_CLASSNAME = "ck-find-result";
 | 
					const FIND_RESULT_CSS_CLASSNAME = "ck-find-result";
 | 
				
			||||||
@ -29,7 +30,7 @@ export default class FindInHtml {
 | 
				
			|||||||
        const wholeWordChar = wholeWord ? "\\b" : "";
 | 
					        const wholeWordChar = wholeWord ? "\\b" : "";
 | 
				
			||||||
        const regExp = new RegExp(wholeWordChar + utils.escapeRegExp(searchTerm) + wholeWordChar, matchCase ? "g" : "gi");
 | 
					        const regExp = new RegExp(wholeWordChar + utils.escapeRegExp(searchTerm) + wholeWordChar, matchCase ? "g" : "gi");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return new Promise((res) => {
 | 
					        return new Promise<FindResult>((res) => {
 | 
				
			||||||
            $content?.unmark({
 | 
					            $content?.unmark({
 | 
				
			||||||
                done: () => {
 | 
					                done: () => {
 | 
				
			||||||
                    $content.markRegExp(regExp, {
 | 
					                    $content.markRegExp(regExp, {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					import type { FindResult } from "./find.js";
 | 
				
			||||||
import type FindWidget from "./find.js";
 | 
					import type FindWidget from "./find.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO: Deduplicate.
 | 
					// TODO: Deduplicate.
 | 
				
			||||||
@ -13,7 +14,8 @@ interface Match {
 | 
				
			|||||||
export default class FindInText {
 | 
					export default class FindInText {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private parent: FindWidget;
 | 
					    private parent: FindWidget;
 | 
				
			||||||
    private findResult?: Match[] | null;
 | 
					    private findResult?: CKFindResult | null;
 | 
				
			||||||
 | 
					    private editingState?: EditingState;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(parent: FindWidget) {
 | 
					    constructor(parent: FindWidget) {
 | 
				
			||||||
        this.parent = parent;
 | 
					        this.parent = parent;
 | 
				
			||||||
@ -23,10 +25,14 @@ export default class FindInText {
 | 
				
			|||||||
        return this.parent?.noteContext?.getTextEditor();
 | 
					        return this.parent?.noteContext?.getTextEditor();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async performFind(searchTerm: string, matchCase: boolean, wholeWord: boolean) {
 | 
					    async performFind(searchTerm: string, matchCase: boolean, wholeWord: boolean): Promise<FindResult> {
 | 
				
			||||||
        // Do this even if the searchTerm is empty so the markers are cleared and
 | 
					        // Do this even if the searchTerm is empty so the markers are cleared and
 | 
				
			||||||
        // the counters updated
 | 
					        // the counters updated
 | 
				
			||||||
        const textEditor = await this.getTextEditor();
 | 
					        const textEditor = await this.getTextEditor();
 | 
				
			||||||
 | 
					        if (!textEditor) {
 | 
				
			||||||
 | 
					            return { currentFound: 0, totalFound: 0 };
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const model = textEditor.model;
 | 
					        const model = textEditor.model;
 | 
				
			||||||
        let findResult = null;
 | 
					        let findResult = null;
 | 
				
			||||||
        let totalFound = 0;
 | 
					        let totalFound = 0;
 | 
				
			||||||
@ -46,14 +52,14 @@ export default class FindInText {
 | 
				
			|||||||
            // let m = text.match(re);
 | 
					            // let m = text.match(re);
 | 
				
			||||||
            // totalFound = m ? m.length : 0;
 | 
					            // totalFound = m ? m.length : 0;
 | 
				
			||||||
            const options = { matchCase: matchCase, wholeWords: wholeWord };
 | 
					            const options = { matchCase: matchCase, wholeWords: wholeWord };
 | 
				
			||||||
            findResult = textEditor.execute("find", searchTerm, options);
 | 
					            findResult = textEditor.execute<CKFindResult>("find", searchTerm, options);
 | 
				
			||||||
            totalFound = findResult.results.length;
 | 
					            totalFound = findResult.results.length;
 | 
				
			||||||
            // Find the result beyond the cursor
 | 
					            // Find the result beyond the cursor
 | 
				
			||||||
            const cursorPos = model.document.selection.getLastPosition();
 | 
					            const cursorPos = model.document.selection.getLastPosition();
 | 
				
			||||||
            for (let i = 0; i < findResult.results.length; ++i) {
 | 
					            for (let i = 0; i < findResult.results.length; ++i) {
 | 
				
			||||||
                const marker = findResult.results.get(i).marker;
 | 
					                const marker = findResult.results.get(i).marker;
 | 
				
			||||||
                const fromPos = marker.getStart();
 | 
					                const fromPos = marker.getStart();
 | 
				
			||||||
                if (fromPos.compareWith(cursorPos) !== "before") {
 | 
					                if (cursorPos && fromPos.compareWith(cursorPos) !== "before") {
 | 
				
			||||||
                    currentFound = i;
 | 
					                    currentFound = i;
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@ -111,9 +117,11 @@ export default class FindInText {
 | 
				
			|||||||
            let findAndReplaceEditing = textEditor.plugins.get("FindAndReplaceEditing");
 | 
					            let findAndReplaceEditing = textEditor.plugins.get("FindAndReplaceEditing");
 | 
				
			||||||
            findAndReplaceEditing.state.clear(model);
 | 
					            findAndReplaceEditing.state.clear(model);
 | 
				
			||||||
            findAndReplaceEditing.stop();
 | 
					            findAndReplaceEditing.stop();
 | 
				
			||||||
            model.change((writer) => {
 | 
					            if (range) {
 | 
				
			||||||
                writer.setSelection(range, 0);
 | 
					                model.change((writer) => {
 | 
				
			||||||
            });
 | 
					                    writer.setSelection(range, 0);
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            textEditor.editing.view.scrollToTheSelection();
 | 
					            textEditor.editing.view.scrollToTheSelection();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user