-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathhide-in-shadow-dom.js
102 lines (90 loc) · 2.74 KB
/
hide-in-shadow-dom.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import {
hit,
observeDOMChanges,
findHostElements,
pierceShadowDom,
flatten,
throttle,
} from '../helpers';
/**
* @scriptlet hide-in-shadow-dom
*
* @description
* Hides elements inside open shadow DOM elements.
*
* ### Syntax
*
* ```text
* example.org#%#//scriptlet('hide-in-shadow-dom', selector[, baseSelector])
* ```
*
* - `selector` — required, CSS selector of element in shadow-dom to hide
* - `baseSelector` — optional, selector of specific page DOM element,
* narrows down the part of the page DOM where shadow-dom host supposed to be,
* defaults to document.documentElement
*
* > `baseSelector` should match element of the page DOM, but not of shadow DOM.
*
* ### Examples
*
* ```adblock
* ! hides menu bar
* example.com#%#//scriptlet('hide-in-shadow-dom', '.storyAd', '#app')
*
* ! hides floating element
* example.com#%#//scriptlet('hide-in-shadow-dom', '.contact-fab')
* ```
*
* @added v1.3.0.
*/
export function hideInShadowDom(source, selector, baseSelector) {
// do nothing if browser does not support ShadowRoot
// https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot
if (!Element.prototype.attachShadow) {
return;
}
const hideElement = (targetElement) => {
const DISPLAY_NONE_CSS = 'display:none!important;';
targetElement.style.cssText = DISPLAY_NONE_CSS;
};
/**
* Handles shadow-dom piercing and hiding of found elements
*/
const hideHandler = () => {
// start value of shadow-dom hosts for the page dom
let hostElements = !baseSelector ? findHostElements(document.documentElement)
: document.querySelectorAll(baseSelector);
// if there is shadow-dom host, they should be explored
while (hostElements.length !== 0) {
let isHidden = false;
const { targets, innerHosts } = pierceShadowDom(selector, hostElements);
targets.forEach((targetEl) => {
hideElement(targetEl);
isHidden = true;
});
if (isHidden) {
hit(source);
}
// continue to pierce for inner shadow-dom hosts
// and search inside them while the next iteration
hostElements = innerHosts;
}
};
hideHandler();
observeDOMChanges(hideHandler, true);
}
export const hideInShadowDomNames = [
'hide-in-shadow-dom',
];
// eslint-disable-next-line prefer-destructuring
hideInShadowDom.primaryName = hideInShadowDomNames[0];
hideInShadowDom.injections = [
hit,
observeDOMChanges,
findHostElements,
pierceShadowDom,
// following helpers should be imported and injected
// because they are used by helpers above
flatten,
throttle,
];