From 1432f86bae96be14a7604a96a86460c308bfb610 Mon Sep 17 00:00:00 2001 From: horihiro Date: Sun, 10 Sep 2023 08:18:13 +0900 Subject: [PATCH 1/7] add warning for one character matching --- popup/js/main.js | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/popup/js/main.js b/popup/js/main.js index 41789b0..0bf127b 100644 --- a/popup/js/main.js +++ b/popup/js/main.js @@ -83,12 +83,15 @@ document.addEventListener('DOMContentLoaded', async (e) => { isValid: true }; if (onlyLineCounting) { + // if (curr.length == 1) result.reason = 'Warning:\n One character matching might cause performance issue.'; } else if (!(await validateRegExp(curr))) { result.isValid = false; - result.reason = 'Failed to create RegExp object.\nCheck if this is a valid regular expression string.'; + result.reason = 'Error:\n Failed to create RegExp object.\n Check if this is a valid regular expression string.'; } else if (await hasCaptureGroups(curr)) { result.isValid = false; - result.reason = 'This string might contain capture-group that should be non-capture-group.\nReplace a pair of `(` and `)` to `(?:` and `)`.'; + result.reason = 'Error:\n This string might contain capture-group that should be non-capture-group.\n Replace a pair of `(` and `)` to `(?:` and `)`.'; + } else if (/^(?:\.|(?:\\[^\\])|(?:\[[^\]]+\]))(?:\?|\*|\+|\{,?1\}|\{1,(?:\d+)?\})?$/.test(curr)) { + result.reason = 'Warning:\n One character matching might cause performance issue.'; } array.push(result); return array; @@ -108,13 +111,13 @@ document.addEventListener('DOMContentLoaded', async (e) => { applyButton.disabled = !validationResults.every(r => r.isValid) || (patternInput.value === savedKeywords && caseCheckbox.checked === savedMatchCase && regexpCheckbox.checked === savedMode); const re = /\*(\d+)( - [\d.]+px\))$/; const bgColors = validationResults.reduce((prev, curr, pos, array) => { - const backgroundColor = curr.isValid ? '#444' : '#FF4500'; + const backgroundColor = curr.isValid ? (!curr.reason ? '#444' : '#FFA500') : '#FF4500'; if (pos == 0) { prev.push(`${backgroundColor} calc(var(--l)*0 - ${patternInput.scrollTop}px) calc(var(--l)*${curr.numOfLine} - ${patternInput.scrollTop}px)`); return prev; } const start = parseInt(prev[prev.length - 1].match(re)[1]); - if (curr.isValid == array[pos - 1].isValid) { + if (curr.isValid == array[pos - 1].isValid && !!curr.reason == !!array[pos - 1].reason) { prev[prev.length - 1] = prev[prev.length - 1].replace(re, `*${start + curr.numOfLine}$2`); return prev; } @@ -173,10 +176,10 @@ textarea#${patternInput.id} { patternInput.style.background = ''; await renderBackground(); - if (e.target.checked) { - return; - } - document.querySelector('head > style').innerHTML = ''; + // if (e.target.checked) { + // return; + // } + // document.querySelector('head > style').innerHTML = ''; }); caseCheckbox.addEventListener('change', async (e) => { await renderBackground(); @@ -222,7 +225,7 @@ textarea#${patternInput.id} { applyButton.disabled = !statusCheckbox.checked; patternInput.focus(); - if (statusCheckbox.checked && regexpCheckbox.checked) { + if (statusCheckbox.checked) { await renderBackground(patternInput.value.split(/\n/)); } applyButton.disabled = true; From b080f642279a39b10ce5e1da38463ed44645973d Mon Sep 17 00:00:00 2001 From: horihiro Date: Sun, 10 Sep 2023 15:43:30 +0900 Subject: [PATCH 2/7] fix color definition --- popup/js/main.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/popup/js/main.js b/popup/js/main.js index 0bf127b..e7b5b96 100644 --- a/popup/js/main.js +++ b/popup/js/main.js @@ -6,7 +6,11 @@ document.addEventListener('DOMContentLoaded', async (e) => { const statusCheckbox = document.querySelector('#statusCheckbox'); const caseCheckbox = document.querySelector('#caseCheckbox'); const regexpCheckbox = document.querySelector('#regexpCheckbox'); - const _bufferTextArea = document.querySelector('#_bufferTextArea') + const _bufferTextArea = document.querySelector('#_bufferTextArea'); + + const COLOR_DEFAULT = getComputedStyle(_bufferTextArea).getPropertyValue('background-color'); + const COLOR_WARNING = '#FFA500'; + const COLOR_ERROR = '#FF4500'; const minRowTextArea = 10; const styleTextArea = getComputedStyle(patternInput); @@ -111,7 +115,7 @@ document.addEventListener('DOMContentLoaded', async (e) => { applyButton.disabled = !validationResults.every(r => r.isValid) || (patternInput.value === savedKeywords && caseCheckbox.checked === savedMatchCase && regexpCheckbox.checked === savedMode); const re = /\*(\d+)( - [\d.]+px\))$/; const bgColors = validationResults.reduce((prev, curr, pos, array) => { - const backgroundColor = curr.isValid ? (!curr.reason ? '#444' : '#FFA500') : '#FF4500'; + const backgroundColor = curr.isValid ? (!curr.reason ? COLOR_DEFAULT : COLOR_WARNING) : COLOR_ERROR; if (pos == 0) { prev.push(`${backgroundColor} calc(var(--l)*0 - ${patternInput.scrollTop}px) calc(var(--l)*${curr.numOfLine} - ${patternInput.scrollTop}px)`); return prev; @@ -126,7 +130,7 @@ document.addEventListener('DOMContentLoaded', async (e) => { }, []); if (bgColors.length > 0) { const start = parseInt(bgColors[bgColors.length - 1].match(re)[1]); - bgColors.push(`#444 calc(var(--l)*${start} - ${patternInput.scrollTop}px) calc(var(--l)*${start + 1} - ${patternInput.scrollTop}px)`); + bgColors.push(`${COLOR_DEFAULT} calc(var(--l)*${start} - ${patternInput.scrollTop}px) calc(var(--l)*${start + 1} - ${patternInput.scrollTop}px)`); patternInput.setAttribute('rows', start > minRowTextArea ? start : minRowTextArea); } @@ -134,7 +138,7 @@ document.addEventListener('DOMContentLoaded', async (e) => { textarea#${patternInput.id} { background: linear-gradient( ${bgColors.join(',\n ')} - ) 0 8px no-repeat, #444; + ) 0 8px no-repeat, ${COLOR_DEFAULT}; }`; } @@ -172,7 +176,7 @@ textarea#${patternInput.id} { }); regexpCheckbox.addEventListener('change', async (e) => { patternInput.focus(); - patternInput.style.background = '#444'; + patternInput.style.background = COLOR_DEFAULT; patternInput.style.background = ''; await renderBackground(); From ece34bbeb3da5ba0539e372e6b78ce279504f3bd Mon Sep 17 00:00:00 2001 From: horihiro Date: Thu, 21 Sep 2023 21:18:01 +0900 Subject: [PATCH 3/7] improve performance --- content/js/main.js | 45 ++++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/content/js/main.js b/content/js/main.js index f897e14..2ed9f5e 100644 --- a/content/js/main.js +++ b/content/js/main.js @@ -8,25 +8,32 @@ const getElementsByNodeValue = (value, target) => { const nodes = []; - (target || document).childNodes.forEach((n) => { + Array.prototype.filter.call((target || document).childNodes, (n) => { + return n.nodeName.toLowerCase() !== 'span' || n.className !== 'blurred'; + }).forEach((n) => { !n.nodeValue && nodes.push(...getElementsByNodeValue(value, n)); - (value.constructor.name === 'RegExp' && value.test(n.nodeValue)) && nodes.push(n.parentNode); + value.test(n.nodeValue) && nodes.push(n.parentNode); }); return nodes; }; const blurByRegExpPatterns = (patterns) => { if (patterns.length === 0) return; + const now = Date.now(); patterns.forEach((pattern) => { console.debug(`Searching pattern ${pattern}`); - getElementsByNodeValue(pattern, document.body).filter((n) => { - return !exElmList.includes(n.nodeName.toLowerCase()) + getElementsByNodeValue(pattern, document.body) + .reduce((prev, n) => { + if (!prev.includes(n) + && !exElmList.includes(n.nodeName.toLowerCase()) && Array.prototype.filter.call(n.childNodes, (c) => { return c.nodeName === '#text' && pattern.test(c.nodeValue); }).length > 0 - && getStateOfContentEditable(n) !== 'true'; - }).forEach((n) => { - if (n.className && n.className.includes('blurred')) return; + && getStateOfContentEditable(n) !== 'true' + ) prev.push(n); + return prev; + }, []).forEach((n) => { + if (n.className && `${n.className}`.includes('blurred')) return; const size = Math.floor(parseFloat(getComputedStyle(n).fontSize) / 4); n.childNodes.forEach((c) => { if (c.nodeName !== "#text" || !pattern.test(c.nodeValue)) return; @@ -46,6 +53,7 @@ }); }) }); + console.debug(`Took ${Date.now() - now} ms`) }; const blur = (keywords) => { @@ -69,20 +77,27 @@ const m = w.document.querySelectorAll('.blurred'); if (m.length === 0) return; + const now = Date.now(); m.forEach((n) => { const p = n.parentNode; + p.childNodes.forEach((c) => { + if (c.nodeName !== '#text' || c.nodeValue !== '' || c === p.firstChild) return + p.removeChild(c); + }); n.childNodes.forEach((c) => { - p.insertBefore(c, n); + if (n.previousSibling.nodeName === '#text' && c.nodeName === '#text') { + n.previousSibling.nodeValue += c.nodeValue; + if (n.nextSibling?.nodeName === '#text') { + n.previousSibling.nodeValue += n.nextSibling.nodeValue; + p.removeChild(n.nextSibling); + } + } else { + p.insertBefore(c, n); + } }); p.removeChild(n); - for (let i = p.childNodes.length - 1; i >= 1; i--) { - const c = p.childNodes[i]; - const s = p.childNodes[i - 1]; - if (!s || c.nodeName !== '#text' || s.nodeName !== '#text') continue; - s.nodeValue += c.nodeValue; - c.nodeValue = ""; - } }); + console.debug(`Took ${Date.now() - now} ms`) }; const escapeRegExp = (str) => { From 20ca1337a946939be667908a85ef9302a9cd4d1f Mon Sep 17 00:00:00 2001 From: horihiro Date: Thu, 21 Sep 2023 21:34:14 +0900 Subject: [PATCH 4/7] chore: reduce indent --- content/js/main.js | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/content/js/main.js b/content/js/main.js index 2ed9f5e..da7dcef 100644 --- a/content/js/main.js +++ b/content/js/main.js @@ -61,13 +61,11 @@ w.__observer = new MutationObserver(() => { blurByRegExpPatterns(keywords); }); - w.__observer.observe(w.document, - { - childList: true, - subtree: true, - characterData: true - } - ); + w.__observer.observe(w.document, { + childList: true, + subtree: true, + characterData: true + }); blurByRegExpPatterns(keywords); }; const unblur = () => { @@ -85,15 +83,15 @@ p.removeChild(c); }); n.childNodes.forEach((c) => { - if (n.previousSibling.nodeName === '#text' && c.nodeName === '#text') { - n.previousSibling.nodeValue += c.nodeValue; - if (n.nextSibling?.nodeName === '#text') { - n.previousSibling.nodeValue += n.nextSibling.nodeValue; - p.removeChild(n.nextSibling); - } - } else { + if (n.previousSibling.nodeName !== '#text' || c.nodeName !== '#text') { p.insertBefore(c, n); + return; } + n.previousSibling.nodeValue += c.nodeValue; + + if (n.nextSibling?.nodeName !== '#text') return; + n.previousSibling.nodeValue += n.nextSibling.nodeValue; + p.removeChild(n.nextSibling); }); p.removeChild(n); }); From 0f20ca4d34ea9d9fcf0b7e7406ed7d4f07a14b4c Mon Sep 17 00:00:00 2001 From: horihiro Date: Fri, 22 Sep 2023 06:36:33 +0900 Subject: [PATCH 5/7] improve performance on unblurring --- content/js/main.js | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/content/js/main.js b/content/js/main.js index da7dcef..421df84 100644 --- a/content/js/main.js +++ b/content/js/main.js @@ -78,20 +78,30 @@ const now = Date.now(); m.forEach((n) => { const p = n.parentNode; - p.childNodes.forEach((c) => { - if (c.nodeName !== '#text' || c.nodeValue !== '' || c === p.firstChild) return - p.removeChild(c); - }); n.childNodes.forEach((c) => { - if (n.previousSibling.nodeName !== '#text' || c.nodeName !== '#text') { + if (c.nodeName !== '#text') { p.insertBefore(c, n); return; } - n.previousSibling.nodeValue += c.nodeValue; - if (n.nextSibling?.nodeName !== '#text') return; - n.previousSibling.nodeValue += n.nextSibling.nodeValue; - p.removeChild(n.nextSibling); + let textContainer = n.previousSibling; + do { + if (textContainer.nodeName !== '#text') { + p.insertBefore(c, n); + break; + } + if (textContainer.previousSibling && textContainer.nodeValue === '') { + textContainer = textContainer.previousSibling; + continue; + } + textContainer.nodeValue += c.nodeValue; + + if (n.nextSibling?.nodeName === '#text') { + n.previousSibling.nodeValue += n.nextSibling.nodeValue; + p.removeChild(n.nextSibling); + } + break; + } while (true); }); p.removeChild(n); }); From 8e1c0bb32b94ffa4facbd2e54a32105a1fc3eeff Mon Sep 17 00:00:00 2001 From: horihiro Date: Fri, 22 Sep 2023 07:11:47 +0900 Subject: [PATCH 6/7] define classname --- content/js/main.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/content/js/main.js b/content/js/main.js index 421df84..08f08d7 100644 --- a/content/js/main.js +++ b/content/js/main.js @@ -1,6 +1,7 @@ (async () => { const w = window; const exElmList = ['html', 'title', 'script', 'noscript', 'style', 'meta', 'link', 'head', 'textarea']; + const blurredClassName = 'blurred'; const getStateOfContentEditable = (element) => { if (element.contentEditable && element.contentEditable !== 'inherit') return element.contentEditable; return element.parentNode ? getStateOfContentEditable(element.parentNode) : ''; @@ -9,7 +10,7 @@ const getElementsByNodeValue = (value, target) => { const nodes = []; Array.prototype.filter.call((target || document).childNodes, (n) => { - return n.nodeName.toLowerCase() !== 'span' || n.className !== 'blurred'; + return n.nodeName.toLowerCase() !== 'span' || !(`${n.className}`.includes(blurredClassName)); }).forEach((n) => { !n.nodeValue && nodes.push(...getElementsByNodeValue(value, n)); value.test(n.nodeValue) && nodes.push(n.parentNode); @@ -33,7 +34,7 @@ ) prev.push(n); return prev; }, []).forEach((n) => { - if (n.className && `${n.className}`.includes('blurred')) return; + if (n.className && `${n.className}`.includes(blurredClassName)) return; const size = Math.floor(parseFloat(getComputedStyle(n).fontSize) / 4); n.childNodes.forEach((c) => { if (c.nodeName !== "#text" || !pattern.test(c.nodeValue)) return; @@ -44,7 +45,7 @@ textArray.forEach((t) => { const blurredSpan = document.createElement('span'); - blurredSpan.className = 'blurred'; + blurredSpan.className = blurredClassName; blurredSpan.innerText = matched.shift(); if (size > 5) blurredSpan.style.filter = `blur(${size}px)`; c.parentNode.insertBefore(blurredSpan, referenceNode); @@ -72,7 +73,7 @@ if (!w.__observer) return; w.__observer.disconnect(); delete w.__observer - const m = w.document.querySelectorAll('.blurred'); + const m = w.document.querySelectorAll(`.${blurredClassName}`); if (m.length === 0) return; const now = Date.now(); From fcea6c88b8d5ade42630c38b0b237bfeabc09eb2 Mon Sep 17 00:00:00 2001 From: horihiro Date: Fri, 22 Sep 2023 07:16:55 +0900 Subject: [PATCH 7/7] remove lines commented out --- popup/js/main.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/popup/js/main.js b/popup/js/main.js index e7b5b96..a734d02 100644 --- a/popup/js/main.js +++ b/popup/js/main.js @@ -180,10 +180,6 @@ textarea#${patternInput.id} { patternInput.style.background = ''; await renderBackground(); - // if (e.target.checked) { - // return; - // } - // document.querySelector('head > style').innerHTML = ''; }); caseCheckbox.addEventListener('change', async (e) => { await renderBackground();