From 22ebbff7554126742e5934404e202f2a09bfeef9 Mon Sep 17 00:00:00 2001 From: Gigi Date: Tue, 14 Oct 2025 00:25:18 +0200 Subject: [PATCH] fix(highlights): add text validation before applying highlights - Validate extracted range text matches search text before highlighting - Check single-node matches are not empty or whitespace-only - Compare both exact and normalized text to handle whitespace variations - Prevent broken/corrupted highlights from being applied to DOM - Add detailed logging for validation failures to aid debugging --- src/utils/highlightMatching/domUtils.ts | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/utils/highlightMatching/domUtils.ts b/src/utils/highlightMatching/domUtils.ts index 00fe3454..b5755c29 100644 --- a/src/utils/highlightMatching/domUtils.ts +++ b/src/utils/highlightMatching/domUtils.ts @@ -74,6 +74,13 @@ export function tryMarkInTextNodes( const before = text.substring(0, actualIndex) const match = text.substring(actualIndex, actualIndex + searchText.length) const after = text.substring(actualIndex + searchText.length) + + // Validate the match makes sense (not just whitespace or empty) + if (!match || match.trim().length === 0) { + console.warn('Invalid match (empty or whitespace only)') + continue + } + const mark = createMarkElement(highlight, match, highlightStyle) replaceTextWithMark(textNode, before, after, mark) @@ -202,6 +209,24 @@ function tryMultiNodeMatch( return false } + // Get the text content before extraction to verify it matches + const rangeText = range.toString() + const normalizedRangeText = normalizeWhitespace(rangeText) + const normalizedSearchText = normalizeWhitespace(searchText) + + // Validate that the extracted text matches what we're searching for + if (!rangeText.includes(searchText) && + !normalizedRangeText.includes(normalizedSearchText) && + normalizedRangeText !== normalizedSearchText) { + console.warn('Range text does not match search text:', { + rangeText: rangeText.substring(0, 100), + searchText: searchText.substring(0, 100), + rangeLength: rangeText.length, + searchLength: searchText.length + }) + return false + } + // Extract the content from the range const extractedContent = range.extractContents()