Skip to content
This repository was archived by the owner on Jun 24, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions apps/client/src/stylesheets/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,14 @@ body .CodeMirror {
background-color: #eeeeee;
}

.cm-matchhighlight.ck-find-result{
background: var(--ck-color-highlight-background);
}

.cm-matchhighlight.ck-find-result_selected {
background-color: #ff9633;
}

.CodeMirror pre.CodeMirror-placeholder {
color: #999 !important;
}
Expand Down
25 changes: 18 additions & 7 deletions apps/client/src/widgets/find.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,9 @@ export default class FindWidget extends NoteContextAwareWidget {
this.$currentFound = this.$widget.find(".find-widget-current-found");
this.$totalFound = this.$widget.find(".find-widget-total-found");
this.$caseSensitiveCheckbox = this.$widget.find(".find-widget-case-sensitive-checkbox");
this.$caseSensitiveCheckbox.change(() => this.performFind());
this.$caseSensitiveCheckbox.on("change", () => this.performFind());
this.$matchWordsCheckbox = this.$widget.find(".find-widget-match-words-checkbox");
this.$matchWordsCheckbox.change(() => this.performFind());
this.$matchWordsCheckbox.on("change", () => this.performFind());
this.$previousButton = this.$widget.find(".find-widget-previous-button");
this.$previousButton.on("click", () => this.findNext(-1));
this.$nextButton = this.$widget.find(".find-widget-next-button");
Expand All @@ -160,7 +160,7 @@ export default class FindWidget extends NoteContextAwareWidget {
this.$replaceButton = this.$widget.find(".replace-widget-replace-button");
this.$replaceButton.on("click", () => this.replace());

this.$input.keydown(async (e) => {
this.$input.on("keydown", async (e) => {
if ((e.metaKey || e.ctrlKey) && (e.key === "F" || e.key === "f")) {
// If ctrl+f is pressed when the findbox is shown, select the
// whole input to find
Expand All @@ -172,7 +172,7 @@ export default class FindWidget extends NoteContextAwareWidget {
}
});

this.$widget.keydown(async (e) => {
this.$widget.on("keydown", async (e) => {
if (e.key === "Escape") {
await this.closeSearch();
}
Expand All @@ -197,9 +197,14 @@ export default class FindWidget extends NoteContextAwareWidget {
const isReadOnly = await this.noteContext?.isReadOnly();

let selectedText = "";
if (this.note?.type === "code" && !isReadOnly && this.noteContext) {
const codeEditor = await this.noteContext.getCodeEditor();
selectedText = codeEditor.getSelection();
if (this.note?.type === "code" && this.noteContext) {
if (isReadOnly){
const $content = await this.noteContext.getContentElement();
selectedText = $content.find('.cm-matchhighlight').first().text();
} else {
const codeEditor = await this.noteContext.getCodeEditor();
selectedText = codeEditor.getSelection();
}
} else {
selectedText = window.getSelection()?.toString() || "";
}
Expand Down Expand Up @@ -235,6 +240,12 @@ export default class FindWidget extends NoteContextAwareWidget {
}
}

async readOnlyTemporarilyDisabledEvent({ noteContext }: EventData<"readOnlyTemporarilyDisabled">) {
if (this.isNoteContext(noteContext.ntxId)) {
await this.closeSearch();
}
}

async getHandler() {
if (this.note?.type === "render") {
return this.htmlHandler;
Expand Down
25 changes: 9 additions & 16 deletions apps/client/src/widgets/find_in_html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// uses for highlighting matches, use the same one on CodeMirror
// for consistency
import utils from "../services/utils.js";
import appContext from "../components/app_context.js";
import type FindWidget from "./find.js";
import type { FindResult } from "./find.js";

Expand Down Expand Up @@ -39,12 +38,16 @@ export default class FindInHtml {
caseSensitive: matchCase,
done: async () => {
this.$results = $content.find(`.${FIND_RESULT_CSS_CLASSNAME}`);
this.currentIndex = 0;
const scrollingContainer = $content[0].closest('.scrolling-container');
const containerTop = scrollingContainer?.getBoundingClientRect().top ?? 0;
const closestIndex = this.$results.toArray().findIndex(el => el.getBoundingClientRect().top >= containerTop);
this.currentIndex = closestIndex >= 0 ? closestIndex : 0;

await this.jumpTo();

res({
totalFound: this.$results.length,
currentFound: Math.min(1, this.$results.length)
currentFound: this.$results.length > 0 ? this.currentIndex + 1 : 0
});
}
});
Expand All @@ -71,27 +74,17 @@ export default class FindInHtml {

async findBoxClosed(totalFound: number, currentFound: number) {
const $content = await this.parent?.noteContext?.getContentElement();
if ($content) {
if (typeof $content?.unmark === 'function') {
$content.unmark();
}
}

async jumpTo() {
if (this.$results?.length) {
const offsetTop = 100;
const $current = this.$results.eq(this.currentIndex);
this.$results.removeClass(FIND_RESULT_SELECTED_CSS_CLASSNAME);

if ($current.length) {
$current.addClass(FIND_RESULT_SELECTED_CSS_CLASSNAME);
const position = $current.position().top - offsetTop;

const $content = await this.parent.noteContext?.getContentElement();
if ($content) {
const $contentWidget = appContext.getComponentByEl($content[0]);
$contentWidget.triggerCommand("scrollContainerTo", { position });
}
}
$current[0].scrollIntoView();
$current.addClass(FIND_RESULT_SELECTED_CSS_CLASSNAME);
}
}
}
27 changes: 19 additions & 8 deletions apps/client/src/widgets/find_in_text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,26 @@ export default class FindInText {
const options = { matchCase: matchCase, wholeWords: wholeWord };
findResult = textEditor.execute("find", searchTerm, options);
totalFound = findResult.results.length;
// Find the result beyond the cursor
const cursorPos = model.document.selection.getLastPosition();
for (let i = 0; i < findResult.results.length; ++i) {
const marker = findResult.results.get(i)?.marker;
const fromPos = marker?.getStart();
if (cursorPos && fromPos && fromPos.compareWith(cursorPos) !== "before") {
currentFound = i;
break;
const selection = model.document.selection;
// If text is selected, highlight the corresponding result;
// otherwise, highlight the first visible result in the scrolling container.
if (!selection.isCollapsed) {
const cursorPos = selection.getFirstPosition();
for (let i = 0; i < findResult.results.length; ++i) {
const marker = findResult.results.get(i)?.marker;
const fromPos = marker?.getStart();
if (cursorPos && fromPos?.compareWith(cursorPos) !== "before") {
currentFound = i;
break;
}
}
} else {
const editorEl = textEditor?.sourceElement;
const findResultElement = editorEl?.querySelectorAll(".ck-find-result");
const scrollingContainer = editorEl?.closest('.scrolling-container');
const containerTop = scrollingContainer?.getBoundingClientRect().top ?? 0;
const closestIndex = Array.from(findResultElement ?? []).findIndex((el) => el.getBoundingClientRect().top >= containerTop);
currentFound = closestIndex >= 0 ? closestIndex : 0;
}
}

Expand Down
Loading