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