Skip to content

Commit 616c25e

Browse files
committed
improve element hiding empty check to avoid potentially hiding visible content
1 parent 3b2db7d commit 616c25e

File tree

1 file changed

+16
-4
lines changed

1 file changed

+16
-4
lines changed

src/features/element-hiding.js

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,17 +137,27 @@ function isDomNodeEmpty (node) {
137137
})
138138

139139
const visibleText = parsedNode.innerText.trim().toLocaleLowerCase().replace(/:$/, '')
140-
const mediaContent = parsedNode.querySelector('video,canvas,picture')
140+
const mediaContent = parsedNode.querySelector('video,canvas,embed,object,audio,map')
141+
const formContent = parsedNode.querySelector('form,input,textarea,select,option,button')
141142
const frameElements = [...parsedNode.querySelectorAll('iframe')]
143+
// query original node instead of parsedNode for img elements since heuristic relies
144+
// on size of image elements
145+
const imageElements = [...node.querySelectorAll('img,svg')]
142146
// about:blank iframes don't count as content, return true if:
143147
// - node doesn't contain any iframes
144148
// - node contains iframes, all of which are hidden or have src='about:blank'
145149
const noFramesWithContent = frameElements.every((frame) => {
146150
return (frame.hidden || frame.src === 'about:blank')
147151
})
152+
// ad containers often contain tracking pixels and other small images (eg adchoices logo).
153+
// these should be treated as empty and hidden, but real images should not.
154+
const visibleImages = imageElements.some((image) => {
155+
return (image.getBoundingClientRect().width > 20 || image.getBoundingClientRect().height > 20)
156+
})
148157

149158
if ((visibleText === '' || adLabelStrings.includes(visibleText)) &&
150-
noFramesWithContent && mediaContent === null) {
159+
mediaContent === null && formContent === null &&
160+
noFramesWithContent && !visibleImages) {
151161
return true
152162
}
153163
return false
@@ -224,7 +234,9 @@ function extractTimeoutRules (rules) {
224234
* @param {string} rules[].type
225235
*/
226236
function injectStyleTag (rules) {
227-
const styleTag = document.createElement('style')
237+
const styleTag = document.createElement('link')
238+
styleTag.setAttribute('rel', 'stylesheet')
239+
styleTag.setAttribute('type', 'text/css')
228240
let styleTagContents = ''
229241

230242
rules.forEach((rule, i) => {
@@ -236,7 +248,7 @@ function injectStyleTag (rules) {
236248
})
237249

238250
styleTagContents = styleTagContents.concat('{display:none!important;min-height:0!important;height:0!important;}')
239-
styleTag.innerText = styleTagContents
251+
styleTag.href = 'data:text/css,' + encodeURIComponent(styleTagContents)
240252

241253
document.head.appendChild(styleTag)
242254
}

0 commit comments

Comments
 (0)