| 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; |
| } |