From 98e0434077f9a83f23e4242d51751d5e023dd47a Mon Sep 17 00:00:00 2001 From: Brian Sanders Date: Wed, 13 May 2020 05:29:09 -0400 Subject: [PATCH] Alters Find in Article to escape regex characters by default --- iOS/Article/WebViewController.swift | 1 + iOS/Resources/main_ios.js | 51 ++++++++++++++--------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/iOS/Article/WebViewController.swift b/iOS/Article/WebViewController.swift index addf819a2..b8792b689 100644 --- a/iOS/Article/WebViewController.swift +++ b/iOS/Article/WebViewController.swift @@ -684,6 +684,7 @@ private extension WebViewController { private struct FindInArticleOptions: Codable { var text: String var caseSensitive = false + var regex = false } diff --git a/iOS/Resources/main_ios.js b/iOS/Resources/main_ios.js index c3d441db6..f1f057895 100644 --- a/iOS/Resources/main_ios.js +++ b/iOS/Resources/main_ios.js @@ -161,8 +161,9 @@ function makeHighlightRect({left, top, width, height}, offsetTop=0, offsetLeft=0 return overlay; } -function clearHighlightRects(container=document.getElementById('nnw:highlightContainer')) { - while (container.firstChild) container.firstChild.remove(); +function clearHighlightRects() { + let container = document.getElementById('nnw:highlightContainer') + if (container) container.remove(); } function highlightRects(rects, clearOldRects=true, makeHighlightRect=makeHighlightRect) { @@ -171,14 +172,12 @@ function highlightRects(rects, clearOldRects=true, makeHighlightRect=makeHighlig article.style.position = 'relative'; - if (container) { - if (clearOldRects) - clearHighlightRects(container); - } else { - container = document.createElement('div'); - container.id = 'nnw:highlightContainer'; - article.appendChild(container); - } + if (container && clearOldRects) + container.remove(); + + container = document.createElement('div'); + container.id = 'nnw:highlightContainer'; + article.appendChild(container); const {top, left} = article.getBoundingClientRect(); return Array.from(rects, rect => @@ -369,20 +368,6 @@ function scrollToRect({top, height}, node, pad=0) { scrollParent(node).scrollBy({ top: scrollBy }); } -function findNext() { - const result = f.next(); - const bounds = textBounds(f.node, f.offset, f.offsetEnd); - highlightRects(bounds) -} - -function getFinderCount(finder) { - let count = 0; - while (finder.next()) - ++count; - finder.reset(); - return count; -} - function withEncodedArg(fn) { return function(encodedData, ...rest) { const data = encodedData && JSON.parse(atob(encodedData)); @@ -390,9 +375,17 @@ function withEncodedArg(fn) { } } +function escapeRegex(s) { + return s.replace(/[.?*+^$\\()[\]{}]/g, '\\$&'); +} + class FindState { constructor(options) { - const { text, caseSensitive } = options; + let { text, caseSensitive, regex } = options; + + if (!regex) + text = escapeRegex(text); + const finder = new Finder(new RegExp(text, caseSensitive ? 'g' : 'ig')); this.results = Array.from(finder); this.index = -1; @@ -429,7 +422,13 @@ const ExcludeKeys = new Set(['top', 'right', 'bottom', 'left']); updateFind = withEncodedArg(options => { // TODO Start at the current result position // TODO Introduce slight delay, cap the number of results, and report results asynchronously - CurrentFindState = new FindState(options); + + try { + CurrentFindState = new FindState(options); + } catch (err) { + clearHighlightRects(); + throw err; + } CurrentFindState.selectNext() || clearHighlightRects(); return btoa(JSON.stringify(CurrentFindState, (k, v) => (ExcludeKeys.has(k) ? undefined : v))); });