Skip to content

Commit

Permalink
Merge pull request #12 from horihiro/fix-performance
Browse files Browse the repository at this point in the history
improve performance
  • Loading branch information
horihiro authored Sep 21, 2023
2 parents e298b74 + fcea6c8 commit 8a06bc1
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 37 deletions.
72 changes: 48 additions & 24 deletions content/js/main.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,40 @@
(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) : '';
};

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}`.includes(blurredClassName));
}).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(blurredClassName)) return;
const size = Math.floor(parseFloat(getComputedStyle(n).fontSize) / 4);
n.childNodes.forEach((c) => {
if (c.nodeName !== "#text" || !pattern.test(c.nodeValue)) return;
Expand All @@ -37,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);
Expand All @@ -46,43 +54,59 @@
});
})
});
console.debug(`Took ${Date.now() - now} ms`)
};

const blur = (keywords) => {
if (w.__observer) return;
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 = () => {
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();
m.forEach((n) => {
const p = n.parentNode;
n.childNodes.forEach((c) => {
p.insertBefore(c, n);
if (c.nodeName !== '#text') {
p.insertBefore(c, n);
return;
}

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);
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) => {
Expand Down
29 changes: 16 additions & 13 deletions popup/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -83,12 +87,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;
Expand All @@ -108,13 +115,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 ? 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;
}
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;
}
Expand All @@ -123,15 +130,15 @@ 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);
}

document.querySelector('head > style').innerHTML = `
textarea#${patternInput.id} {
background: linear-gradient(
${bgColors.join(',\n ')}
) 0 8px no-repeat, #444;
) 0 8px no-repeat, ${COLOR_DEFAULT};
}`;
}

Expand Down Expand Up @@ -169,14 +176,10 @@ textarea#${patternInput.id} {
});
regexpCheckbox.addEventListener('change', async (e) => {
patternInput.focus();
patternInput.style.background = '#444';
patternInput.style.background = COLOR_DEFAULT;

patternInput.style.background = '';
await renderBackground();
if (e.target.checked) {
return;
}
document.querySelector('head > style').innerHTML = '';
});
caseCheckbox.addEventListener('change', async (e) => {
await renderBackground();
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 8a06bc1

Please sign in to comment.