feat(browser-extension): move backdrops to database and improve code/documentation

This commit is contained in:
wanhose 2024-08-10 15:42:08 +02:00
parent acb6243412
commit 9a12e46796
2 changed files with 46 additions and 45 deletions

View File

@ -834,6 +834,7 @@
] ]
}, },
"tokens": { "tokens": {
"backdrops": [".modal-backdrop", ".offcanvas-backdrop", ".overlay"],
"classes": [ "classes": [
"appconsent_noscroll", "appconsent_noscroll",
"b-modal-banner--disabled", "b-modal-banner--disabled",

View File

@ -1,28 +1,28 @@
/** /**
* @typedef {Object} ExtensionData * @typedef {Object} ExtensionData
* @property {string[] | undefined} commonWords * @property {string[]} commonWords
* @property {Fix[] | undefined} fixes * @property {Fix[]} fixes
* @property {{ domains: string[] | undefined, tags: string[] | undefined } | undefined} skips * @property {{ domains: string[], tags: string[] }} skips
* @property {{ classes: string[] | undefined, selectors: string[] | undefined } | undefined} tokens * @property {{ backdrops: string[], classes: string[], selectors: string[] }} tokens
*/ */
/** /**
* @typedef {Object} Fix * @typedef {Object} Fix
* @property {string} action * @property {string} action
* @property {string} domain * @property {string} domain
* @property {string | undefined} property * @property {string} [property]
* @property {string} selector * @property {string} selector
*/ */
/** /**
* @typedef {Object} RunParams * @typedef {Object} RunParams
* @property {HTMLElement[] | undefined} elements * @property {HTMLElement[]} [elements]
* @property {boolean | undefined} skipMatch * @property {boolean} [skipMatch]
*/ */
/** /**
* @typedef {Object} SetUpParams * @typedef {Object} SetUpParams
* @property {boolean | undefined} skipRunFn * @property {boolean} [skipRunFn]
*/ */
if (typeof browser === 'undefined') { if (typeof browser === 'undefined') {
@ -39,7 +39,19 @@ let count = 0;
* @description Data properties * @description Data properties
* @type {ExtensionData} * @type {ExtensionData}
*/ */
let { commonWords, fixes = [], skips, tokens } = {}; let { commonWords, fixes, skips, tokens } = {
commonWords: [],
fixes: [],
skips: {
domains: [],
tags: [],
},
tokens: {
backdrops: [],
classes: [],
selectors: [],
},
};
/** /**
* @description Attribute name * @description Attribute name
@ -98,7 +110,7 @@ let state = { enabled: true };
/** /**
* @description Clean DOM * @description Clean DOM
* @param {Element[]} elements * @param {Element[]} elements
* @param {boolean?} skipMatch * @param {boolean} [skipMatch]
* @returns {void} * @returns {void}
*/ */
function clean(elements, skipMatch) { function clean(elements, skipMatch) {
@ -156,7 +168,7 @@ function containsCommonWord(element) {
*/ */
function forceClean(element) { function forceClean(element) {
const nodes = [...element.querySelectorAll(tokens.selectors)]; const nodes = [...element.querySelectorAll(tokens.selectors)];
const elements = nodes.flatMap((node) => filterMapEarly(node)); const elements = nodes.flatMap((node) => filterNodeEarly(node));
if (elements.length) { if (elements.length) {
fix(); fix();
@ -220,16 +232,11 @@ function isInViewport(element) {
/** /**
* @description Check if element element is removable * @description Check if element element is removable
* @param {Element} element * @param {Element} element
* @param {boolean?} skipMatch * @param {boolean} [skipMatch]
* @returns {boolean} * @returns {boolean}
*/ */
function match(element, skipMatch) { function match(element, skipMatch) {
if ( if (!tokens.selectors.length || !skips.tags.length) {
!commonWords.length ||
!tokens?.classes?.length ||
!tokens?.selectors?.length ||
!skips?.tags?.length
) {
return false; return false;
} }
@ -245,7 +252,7 @@ function match(element, skipMatch) {
return false; return false;
} }
const tagName = element.tagName?.toUpperCase?.(); const tagName = element.tagName.toUpperCase();
if (skips.tags.includes(tagName)) { if (skips.tags.includes(tagName)) {
return false; return false;
@ -283,13 +290,13 @@ function match(element, skipMatch) {
* @param {Node} node * @param {Node} node
* @param {boolean} stopRecursion * @param {boolean} stopRecursion
*/ */
function filterMapEarly(node, stopRecursion) { function filterNodeEarly(node, stopRecursion) {
if (node.nodeType !== Node.ELEMENT_NODE || !(node instanceof HTMLElement)) { if (node.nodeType !== Node.ELEMENT_NODE || !(node instanceof HTMLElement)) {
return []; return [];
} }
if (commonWords && containsCommonWord(node) && !stopRecursion) { if (commonWords && containsCommonWord(node) && !stopRecursion) {
return [node, ...[...node.children].flatMap((node) => filterMapEarly(node, true))]; return [node, ...[...node.children].flatMap((node) => filterNodeEarly(node, true))];
} }
return [node]; return [node];
@ -300,12 +307,8 @@ function filterMapEarly(node, stopRecursion) {
* @returns {void} * @returns {void}
*/ */
function fix() { function fix() {
const backdrops = document.querySelectorAll([ const backdrops = tokens.backdrops.length ? [...document.querySelectorAll(tokens.backdrops)] : [];
'.modal-backdrop', const domains = skips.domains.map((x) => (x.split('.').length < 3 ? `*${x}` : x));
'.offcanvas-backdrop',
'.overlay',
]);
const domains = (skips?.domains ?? []).map((x) => (x.split('.').length < 3 ? `*${x}` : x));
for (const backdrop of backdrops) { for (const backdrop of backdrops) {
if (backdrop.children.length === 0 && backdrop.style.display !== 'none') { if (backdrop.children.length === 0 && backdrop.style.display !== 'none') {
@ -349,7 +352,7 @@ function fix() {
if (domains.every((x) => !hostname.match(x.replaceAll(/\*/g, '[^ ]*')))) { if (domains.every((x) => !hostname.match(x.replaceAll(/\*/g, '[^ ]*')))) {
for (const element of [document.body, document.documentElement]) { for (const element of [document.body, document.documentElement]) {
element?.classList.remove(...(tokens?.classes ?? [])); element?.classList.remove(...(tokens.classes ?? []));
element?.style.setProperty('position', 'initial', 'important'); element?.style.setProperty('position', 'initial', 'important');
element?.style.setProperty('overflow-y', 'initial', 'important'); element?.style.setProperty('overflow-y', 'initial', 'important');
} }
@ -361,11 +364,13 @@ function fix() {
* @returns {void} * @returns {void}
*/ */
function restoreDOM() { function restoreDOM() {
const backdrop = document.getElementsByClassName('modal-backdrop')[0]; const backdrops = tokens.backdrops.length ? [...document.querySelectorAll(tokens.backdrops)] : [];
if (backdrop?.children.length === 0) { for (const backdrop of backdrops) {
if (backdrop.children.length === 0 && backdrop.hasAttribute(dataAttributeName)) {
backdrop.style.removeProperty('display'); backdrop.style.removeProperty('display');
} }
}
const elements = [...document.querySelectorAll(`[${dataAttributeName}]`)]; const elements = [...document.querySelectorAll(`[${dataAttributeName}]`)];
@ -384,11 +389,11 @@ function restoreDOM() {
/** /**
* @description Clean DOM when this function is called * @description Clean DOM when this function is called
* @param {RunParams} params * @param {RunParams} [params]
* @returns {void} * @returns {void}
*/ */
function run(params = {}) { function run(params = {}) {
if (document.body?.children.length && !preview && state.enabled && tokens?.selectors?.length) { if (document.body?.children.length && !preview && state.enabled && tokens.selectors.length) {
fix(); fix();
if (params.elements?.length) { if (params.elements?.length) {
@ -408,7 +413,7 @@ function run(params = {}) {
...[...(document.getElementById('app')?.children ?? [])], ...[...(document.getElementById('app')?.children ?? [])],
...[...(document.getElementById('main')?.children ?? [])], ...[...(document.getElementById('main')?.children ?? [])],
...[...(document.getElementById('root')?.children ?? [])], ...[...(document.getElementById('root')?.children ?? [])],
].flatMap((node) => filterMapEarly(node)) ].flatMap((node) => filterNodeEarly(node))
); );
} }
} }
@ -417,19 +422,14 @@ function run(params = {}) {
/** /**
* @async * @async
* @description Set up the extension * @description Set up the extension
* @param {SetUpParams | undefined} params * @param {SetUpParams} [params]
*/ */
async function setUp(params) { async function setUp(params = {}) {
state = (await dispatch({ hostname, type: 'GET_HOSTNAME_STATE' })) ?? state; state = (await dispatch({ hostname, type: 'GET_HOSTNAME_STATE' })) ?? state;
dispatch({ type: 'ENABLE_POPUP' }); dispatch({ type: 'ENABLE_POPUP' });
if (state.enabled) { if (state.enabled) {
const data = await dispatch({ hostname, type: 'GET_DATA' }); data = await dispatch({ hostname, type: 'GET_DATA' });
commonWords = data?.commonWords;
fixes = data?.fixes;
skips = data?.skips;
tokens = data?.tokens;
if (count > 0) { if (count > 0) {
dispatch({ type: 'SET_BADGE', value: `${count}` }); dispatch({ type: 'SET_BADGE', value: `${count}` });
@ -438,7 +438,7 @@ async function setUp(params) {
dispatch({ type: 'ENABLE_ICON' }); dispatch({ type: 'ENABLE_ICON' });
observer.observe(document.body ?? document.documentElement, options); observer.observe(document.body ?? document.documentElement, options);
if (!params?.skipRunFn) { if (!params.skipRunFn) {
run(); run();
} }
} else { } else {
@ -452,12 +452,12 @@ async function setUp(params) {
* @type {MutationObserver} * @type {MutationObserver}
*/ */
const observer = new MutationObserver((mutations) => { const observer = new MutationObserver((mutations) => {
if (preview || !state.enabled || !tokens?.selectors.length) { if (preview || !state.enabled || !tokens.selectors.length) {
return; return;
} }
const nodes = mutations.flatMap((mutation) => [...mutation.addedNodes]); const nodes = mutations.flatMap((mutation) => [...mutation.addedNodes]);
const elements = nodes.flatMap((node) => filterMapEarly(node)); const elements = nodes.flatMap((node) => filterNodeEarly(node));
run({ elements }); run({ elements });
}); });