Index: lib/content/elemHideEmulation.js |
=================================================================== |
--- a/lib/content/elemHideEmulation.js |
+++ b/lib/content/elemHideEmulation.js |
@@ -337,40 +337,104 @@ |
if (testInfo) |
testInfo.lastProcessedElements.add(element); |
} |
} |
} |
} |
+/** |
+ * Determine if the text inside the element is visible. |
+ * @param {Element} element the leaf element we are checking. |
+ * @returns {bool} whether the text is visible. |
+ */ |
+function isTextVisible(element) |
+{ |
+ let style = window.getComputedStyle(element); |
hub
2019/03/06 16:34:11
I wonder if it is worth complexifying the code to
Manish Jethani
2019/03/12 12:24:09
If you have `<div style="display: none"><div>Spons
hub
2019/03/14 10:12:40
I think we can constrain to "visible within the sp
Manish Jethani
2019/03/14 11:36:33
OK, perhaps I can change my example to this: `<art
hub
2019/03/20 14:19:55
Actually I believe it should not hide it. But it d
hub
2019/03/20 16:31:11
This is handled properly now.
|
+ |
+ if (style.getPropertyValue("opacity") == "0") |
+ return false; |
+ if (style.getPropertyValue("font-size") == "0px") |
+ return false; |
+ let visibility = style.getPropertyValue("visibility"); |
+ if (visibility == "hidden" || visibility == "collapse") |
+ return false; |
+ if (style.getPropertyValue("display") == "none") |
+ return false; |
+ if (style.getPropertyValue("color") == |
+ style.getPropertyValue("background-color")) |
+ return false; |
+ |
+ return true; |
+} |
+ |
+/** |
+ * Returns the visible text content from an element and its children. |
+ * @param {Element} element the element whose visible text we want. |
+ * @returns {String} the text that is visible. |
+ */ |
+function getVisibleContent(element) |
Manish Jethani
2019/03/12 08:44:01
Instead of doing all this, why not just use the `i
hub
2019/03/12 09:29:29
innerText doesn't know about opacity, 0 sized font
Manish Jethani
2019/03/12 12:24:09
Acknowledged.
|
+{ |
+ let text = ""; |
+ for (let node of element.childNodes) |
+ { |
+ switch (node.nodeType) |
+ { |
+ case Node.ELEMENT_NODE: |
+ text += getVisibleContent(node); |
+ break; |
+ case Node.TEXT_NODE: |
+ if (isTextVisible(element)) |
+ text += node.nodeValue; |
+ break; |
+ } |
+ } |
+ return text; |
+} |
+ |
class ContainsSelector |
{ |
- constructor(textContent) |
+ constructor(textContent, onlyVisible = false) |
{ |
this.dependsOnDOM = true; |
this.dependsOnCharacterData = true; |
+ this._onlyVisible = onlyVisible; |
this._regexp = makeRegExpParameter(textContent); |
} |
*getSelectors(prefix, subtree, styles, targets) |
{ |
for (let element of this.getElements(prefix, subtree, styles, targets)) |
yield [makeSelector(element), subtree]; |
} |
*getElements(prefix, subtree, styles, targets) |
{ |
let actualPrefix = (!prefix || incompletePrefixRegexp.test(prefix)) ? |
prefix + "*" : prefix; |
let elements = scopedQuerySelectorAll(subtree, actualPrefix); |
- if (elements) |
+ if (!elements) |
+ return; |
+ |
+ if (this._onlyVisible) |
+ { |
+ for (let element of elements) |
+ { |
+ let visibleContent = getVisibleContent(element); |
+ if (this._regexp && this._regexp.test(visibleContent)) |
+ yield element; |
+ else |
+ yield null; |
+ } |
+ } |
+ else |
{ |
let lastRoot = null; |
for (let element of elements) |
{ |
// For a filter like div:-abp-contains(Hello) and a subtree like |
// <div id="a"><div id="b"><div id="c">Hello</div></div></div> |
// we're only interested in div#a |
if (lastRoot && lastRoot.contains(element)) |
@@ -661,16 +725,18 @@ |
{ |
let hasSelectors = this.parseSelector(content.text); |
if (hasSelectors == null) |
return null; |
selectors.push(new HasSelector(hasSelectors)); |
} |
else if (match[1] == "contains") |
selectors.push(new ContainsSelector(content.text)); |
+ else if (match[1] == "contains-visible") |
+ selectors.push(new ContainsSelector(content.text, true)); |
else |
{ |
// this is an error, can't parse selector. |
console.error(new SyntaxError("Failed to parse Adblock Plus " + |
`selector ${selector}, invalid ` + |
`pseudo-class :-abp-${match[1]}().`)); |
return null; |
} |