From 2f406aea83157107e36e350120618131f7c378f2 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sun, 25 May 2025 23:09:16 +0300 Subject: [PATCH] fix(client/search): broken search in read-only text --- apps/client/src/widgets/find.ts | 4 ++-- apps/client/src/widgets/find_in_html.ts | 22 ++++++++++++---------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/apps/client/src/widgets/find.ts b/apps/client/src/widgets/find.ts index 0239251cb..fc8bebb88 100644 --- a/apps/client/src/widgets/find.ts +++ b/apps/client/src/widgets/find.ts @@ -248,10 +248,10 @@ export default class FindWidget extends NoteContextAwareWidget { case "code": return this.codeHandler; case "text": - return this.textHandler; - default: const readOnly = await this.noteContext?.isReadOnly(); return readOnly ? this.htmlHandler : this.textHandler; + default: + console.warn("FindWidget: Unsupported note type for find widget", this.note?.type); } } diff --git a/apps/client/src/widgets/find_in_html.ts b/apps/client/src/widgets/find_in_html.ts index fcbc35173..304bea656 100644 --- a/apps/client/src/widgets/find_in_html.ts +++ b/apps/client/src/widgets/find_in_html.ts @@ -1,6 +1,7 @@ // ck-find-result and ck-find-result_selected are the styles ck-editor // uses for highlighting matches, use the same one on CodeMirror // for consistency +import type Mark from "mark.js"; import utils from "../services/utils.js"; import type FindWidget from "./find.js"; import type { FindResult } from "./find.js"; @@ -13,6 +14,7 @@ export default class FindInHtml { private parent: FindWidget; private currentIndex: number; private $results: JQuery | null; + private mark?: Mark; constructor(parent: FindWidget) { this.parent = parent; @@ -21,21 +23,24 @@ export default class FindInHtml { } async performFind(searchTerm: string, matchCase: boolean, wholeWord: boolean) { - await import("mark.js"); - const $content = await this.parent?.noteContext?.getContentElement(); + if (!$content || !$content.length) { + return Promise.resolve({ totalFound: 0, currentFound: 0 }); + } + + if (!this.mark) { + this.mark = new (await import("mark.js")).default($content[0]); + } const wholeWordChar = wholeWord ? "\\b" : ""; const regExp = new RegExp(wholeWordChar + utils.escapeRegExp(searchTerm) + wholeWordChar, matchCase ? "g" : "gi"); return new Promise((res) => { - $content?.unmark({ + this.mark!.unmark({ done: () => { - $content.markRegExp(regExp, { + this.mark!.markRegExp(regExp, { element: "span", className: FIND_RESULT_CSS_CLASSNAME, - separateWordSearch: false, - caseSensitive: matchCase, done: async () => { this.$results = $content.find(`.${FIND_RESULT_CSS_CLASSNAME}`); const scrollingContainer = $content[0].closest('.scrolling-container'); @@ -73,10 +78,7 @@ export default class FindInHtml { } async findBoxClosed(totalFound: number, currentFound: number) { - const $content = await this.parent?.noteContext?.getContentElement(); - if (typeof $content?.unmark === 'function') { - $content.unmark(); - } + this.mark?.unmark(); } async jumpTo() {