From fefa7b51d783b3e945e7358094978945aaf03bcb Mon Sep 17 00:00:00 2001 From: KoloMl Date: Sat, 8 Feb 2025 05:30:01 +0400 Subject: [PATCH] Finding the active line in textarea, treating each line as different queries --- assets/js/autocomplete.ts | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/assets/js/autocomplete.ts b/assets/js/autocomplete.ts index c83a8705..e546c410 100644 --- a/assets/js/autocomplete.ts +++ b/assets/js/autocomplete.ts @@ -111,9 +111,34 @@ function findSelectedTerm(targetInput: InputFieldElement, searchQuery: string): if (targetInput.selectionStart === null || targetInput.selectionEnd === null) return null; const selectionIndex = Math.min(targetInput.selectionStart, targetInput.selectionEnd); - const terms = getTermContexts(searchQuery); + const isMultiline = targetInput instanceof HTMLTextAreaElement; - return terms.find(([range]) => range[0] < selectionIndex && range[1] >= selectionIndex) ?? null; + let lineOffset = 0; + let targetQuery = searchQuery; + + // Multi-line textarea elements should treat each line as the different search queries. Here we're looking for the + // actively edited line and use it instead of the whole value. + if (isMultiline) { + const activeLineStart = searchQuery.slice(0, selectionIndex).lastIndexOf('\n') + 1; + const lengthAfterSelectionIndex = Math.max(searchQuery.slice(selectionIndex).indexOf('\n'), 0); + + targetQuery = searchQuery.slice(activeLineStart, selectionIndex + lengthAfterSelectionIndex); + lineOffset = activeLineStart; + } + + const terms = getTermContexts(targetQuery); + const searchIndex = selectionIndex - lineOffset; + const term = terms.find(([range]) => range[0] < searchIndex && range[1] >= searchIndex) ?? null; + + // Converting line-specific indexes back to absolute ones. + if (isMultiline && term) { + const [range] = term; + + range[0] += lineOffset; + range[1] += lineOffset; + } + + return term; } function toggleSearchAutocomplete() {