Left: | ||
Right: |
OLD | NEW |
---|---|
1 /* | 1 /* |
2 * This file is part of Adblock Plus <https://adblockplus.org/>, | 2 * This file is part of Adblock Plus <https://adblockplus.org/>, |
3 * Copyright (C) 2006-present eyeo GmbH | 3 * Copyright (C) 2006-present eyeo GmbH |
4 * | 4 * |
5 * Adblock Plus is free software: you can redistribute it and/or modify | 5 * Adblock Plus is free software: you can redistribute it and/or modify |
6 * it under the terms of the GNU General Public License version 3 as | 6 * it under the terms of the GNU General Public License version 3 as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
8 * | 8 * |
9 * Adblock Plus is distributed in the hope that it will be useful, | 9 * Adblock Plus is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
335 } | 335 } |
336 yield null; | 336 yield null; |
337 | 337 |
338 if (testInfo) | 338 if (testInfo) |
339 testInfo.lastProcessedElements.add(element); | 339 testInfo.lastProcessedElements.add(element); |
340 } | 340 } |
341 } | 341 } |
342 } | 342 } |
343 } | 343 } |
344 | 344 |
345 /** | |
346 * Determine if the text inside the element is visible. | |
347 * @param {Element} element the leaf element we are checking. | |
348 * @returns {bool} whether the text is visible. | |
349 */ | |
350 function isTextVisible(element) | |
351 { | |
352 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.
| |
353 | |
354 if (style.getPropertyValue("opacity") == "0") | |
355 return false; | |
356 if (style.getPropertyValue("font-size") == "0px") | |
357 return false; | |
358 let visibility = style.getPropertyValue("visibility"); | |
359 if (visibility == "hidden" || visibility == "collapse") | |
360 return false; | |
361 if (style.getPropertyValue("display") == "none") | |
362 return false; | |
363 if (style.getPropertyValue("color") == | |
364 style.getPropertyValue("background-color")) | |
365 return false; | |
366 | |
367 return true; | |
368 } | |
369 | |
370 /** | |
371 * Returns the visible text content from an element and its children. | |
372 * @param {Element} element the element whose visible text we want. | |
373 * @returns {String} the text that is visible. | |
374 */ | |
375 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.
| |
376 { | |
377 let text = ""; | |
378 for (let node of element.childNodes) | |
379 { | |
380 switch (node.nodeType) | |
381 { | |
382 case Node.ELEMENT_NODE: | |
383 text += getVisibleContent(node); | |
384 break; | |
385 case Node.TEXT_NODE: | |
386 if (isTextVisible(element)) | |
387 text += node.nodeValue; | |
388 break; | |
389 } | |
390 } | |
391 return text; | |
392 } | |
393 | |
345 class ContainsSelector | 394 class ContainsSelector |
346 { | 395 { |
347 constructor(textContent) | 396 constructor(textContent, onlyVisible = false) |
348 { | 397 { |
349 this.dependsOnDOM = true; | 398 this.dependsOnDOM = true; |
350 this.dependsOnCharacterData = true; | 399 this.dependsOnCharacterData = true; |
351 | 400 |
401 this._onlyVisible = onlyVisible; | |
352 this._regexp = makeRegExpParameter(textContent); | 402 this._regexp = makeRegExpParameter(textContent); |
353 } | 403 } |
354 | 404 |
355 *getSelectors(prefix, subtree, styles, targets) | 405 *getSelectors(prefix, subtree, styles, targets) |
356 { | 406 { |
357 for (let element of this.getElements(prefix, subtree, styles, targets)) | 407 for (let element of this.getElements(prefix, subtree, styles, targets)) |
358 yield [makeSelector(element), subtree]; | 408 yield [makeSelector(element), subtree]; |
359 } | 409 } |
360 | 410 |
361 *getElements(prefix, subtree, styles, targets) | 411 *getElements(prefix, subtree, styles, targets) |
362 { | 412 { |
363 let actualPrefix = (!prefix || incompletePrefixRegexp.test(prefix)) ? | 413 let actualPrefix = (!prefix || incompletePrefixRegexp.test(prefix)) ? |
364 prefix + "*" : prefix; | 414 prefix + "*" : prefix; |
365 | 415 |
366 let elements = scopedQuerySelectorAll(subtree, actualPrefix); | 416 let elements = scopedQuerySelectorAll(subtree, actualPrefix); |
367 | 417 |
368 if (elements) | 418 if (!elements) |
419 return; | |
420 | |
421 if (this._onlyVisible) | |
422 { | |
423 for (let element of elements) | |
424 { | |
425 let visibleContent = getVisibleContent(element); | |
426 if (this._regexp && this._regexp.test(visibleContent)) | |
427 yield element; | |
428 else | |
429 yield null; | |
430 } | |
431 } | |
432 else | |
369 { | 433 { |
370 let lastRoot = null; | 434 let lastRoot = null; |
371 for (let element of elements) | 435 for (let element of elements) |
372 { | 436 { |
373 // For a filter like div:-abp-contains(Hello) and a subtree like | 437 // For a filter like div:-abp-contains(Hello) and a subtree like |
374 // <div id="a"><div id="b"><div id="c">Hello</div></div></div> | 438 // <div id="a"><div id="b"><div id="c">Hello</div></div></div> |
375 // we're only interested in div#a | 439 // we're only interested in div#a |
376 if (lastRoot && lastRoot.contains(element)) | 440 if (lastRoot && lastRoot.contains(element)) |
377 { | 441 { |
378 yield null; | 442 yield null; |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
659 selectors.push(new PropsSelector(content.text)); | 723 selectors.push(new PropsSelector(content.text)); |
660 else if (match[1] == "has") | 724 else if (match[1] == "has") |
661 { | 725 { |
662 let hasSelectors = this.parseSelector(content.text); | 726 let hasSelectors = this.parseSelector(content.text); |
663 if (hasSelectors == null) | 727 if (hasSelectors == null) |
664 return null; | 728 return null; |
665 selectors.push(new HasSelector(hasSelectors)); | 729 selectors.push(new HasSelector(hasSelectors)); |
666 } | 730 } |
667 else if (match[1] == "contains") | 731 else if (match[1] == "contains") |
668 selectors.push(new ContainsSelector(content.text)); | 732 selectors.push(new ContainsSelector(content.text)); |
733 else if (match[1] == "contains-visible") | |
734 selectors.push(new ContainsSelector(content.text, true)); | |
669 else | 735 else |
670 { | 736 { |
671 // this is an error, can't parse selector. | 737 // this is an error, can't parse selector. |
672 console.error(new SyntaxError("Failed to parse Adblock Plus " + | 738 console.error(new SyntaxError("Failed to parse Adblock Plus " + |
673 `selector ${selector}, invalid ` + | 739 `selector ${selector}, invalid ` + |
674 `pseudo-class :-abp-${match[1]}().`)); | 740 `pseudo-class :-abp-${match[1]}().`)); |
675 return null; | 741 return null; |
676 } | 742 } |
677 | 743 |
678 let suffix = this.parseSelector(selector.substring(content.end + 1)); | 744 let suffix = this.parseSelector(selector.substring(content.end + 1)); |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
964 characterData: shouldObserveCharacterData(this.patterns), | 1030 characterData: shouldObserveCharacterData(this.patterns), |
965 subtree: true | 1031 subtree: true |
966 } | 1032 } |
967 ); | 1033 ); |
968 this.document.addEventListener("load", this.onLoad.bind(this), true); | 1034 this.document.addEventListener("load", this.onLoad.bind(this), true); |
969 } | 1035 } |
970 } | 1036 } |
971 } | 1037 } |
972 | 1038 |
973 exports.ElemHideEmulation = ElemHideEmulation; | 1039 exports.ElemHideEmulation = ElemHideEmulation; |
OLD | NEW |