Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Delta Between Two Patch Sets: lib/content/snippets.js

Issue 30024560: Issue 7450 - Implement hide-if-contains-visible-text snippet (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore/
Left Patch Set: Rework snippet Created April 17, 2019, 5:11 p.m.
Right Patch Set: Updated patch for real Created May 9, 2019, 12:04 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « no previous file | test/browser/snippets.js » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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 392 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 } 403 }
404 404
405 exports["hide-if-shadow-contains"] = makeInjector(hideIfShadowContains, 405 exports["hide-if-shadow-contains"] = makeInjector(hideIfShadowContains,
406 toRegExp, regexEscape, 406 toRegExp, regexEscape,
407 hideElement); 407 hideElement);
408 408
409 /** 409 /**
410 * Hides any HTML element or one of its ancestors matching a CSS selector if 410 * Hides any HTML element or one of its ancestors matching a CSS selector if
411 * it matches the provided condition. 411 * it matches the provided condition.
412 * 412 *
413 * @param {function} match The function that match the element. 413 * @param {function} match The function that provides the matching condition.
414 * @param {string} selector The CSS selector that an HTML element must match 414 * @param {string} selector The CSS selector that an HTML element must match
415 * for it to be hidden. 415 * for it to be hidden.
416 * @param {string?} [searchSelector] The CSS selector that an HTML element 416 * @param {?string} [searchSelector] The CSS selector that an HTML element
417 * containing the given string must match. Defaults to the value of the 417 * containing the given string must match. Defaults to the value of the
418 * <code>selector</code> argument. 418 * <code>selector</code> argument.
419 */ 419 */
420 function hideIfMatch(match, selector = "*", searchSelector = null) 420 function hideIfMatches(match, selector, searchSelector)
421 { 421 {
422 if (searchSelector == null) 422 if (searchSelector == null)
423 searchSelector = selector; 423 searchSelector = selector;
424 424
425 new MutationObserver(() => 425 let callback = () =>
426 { 426 {
427 for (let element of document.querySelectorAll(searchSelector)) 427 for (let element of document.querySelectorAll(searchSelector))
428 { 428 {
429 if (match(element)) 429 let closest = element.closest(selector);
430 { 430 if (closest && match(element, closest))
431 let closest = element.closest(selector); 431 hideElement(closest);
432 if (closest) 432 }
433 hideElement(closest); 433 };
434 } 434 new MutationObserver(callback)
435 } 435 .observe(document, {childList: true, characterData: true, subtree: true});
436 }) 436 callback();
437 .observe(document, {childList: true, characterData: true, subtree: true});
438 } 437 }
439 438
440 /** 439 /**
441 * Hides any HTML element or one of its ancestors matching a CSS selector if 440 * Hides any HTML element or one of its ancestors matching a CSS selector if
442 * the text content of the element contains a given string. 441 * the text content of the element contains a given string.
443 * 442 *
444 * @param {string} search The string to look for in HTML elements. If the 443 * @param {string} search The string to look for in HTML elements. If the
445 * string begins and ends with a slash (<code>/</code>), the text in between 444 * string begins and ends with a slash (<code>/</code>), the text in between
446 * is treated as a regular expression. 445 * is treated as a regular expression.
447 * @param {string} selector The CSS selector that an HTML element must match 446 * @param {string} selector The CSS selector that an HTML element must match
448 * for it to be hidden. 447 * for it to be hidden.
449 * @param {string?} [searchSelector] The CSS selector that an HTML element 448 * @param {?string} [searchSelector] The CSS selector that an HTML element
450 * containing the given string must match. Defaults to the value of the 449 * containing the given string must match. Defaults to the value of the
451 * <code>selector</code> argument. 450 * <code>selector</code> argument.
452 */ 451 */
453 function hideIfContains(search, selector = "*", searchSelector = null) 452 function hideIfContains(search, selector = "*", searchSelector = null)
454 { 453 {
455 let re = toRegExp(search); 454 let re = toRegExp(search);
456 455
457 hideIfMatch(element => re.test(element.textContent), 456 hideIfMatches(element => re.test(element.textContent),
458 selector, searchSelector); 457 selector, searchSelector);
459 } 458 }
460 459
461 exports["hide-if-contains"] = hideIfContains; 460 exports["hide-if-contains"] = hideIfContains;
462 461
463 /** 462 /**
464 * Hides any HTML element matching a CSS selector if the visible text content 463 * Hides any HTML element matching a CSS selector if the visible text content
465 * of the element contains a given string. 464 * of the element contains a given string.
466 * 465 *
467 * @param {string} search The text to match to the visible text. Is considered 466 * @param {string} search The string to match to the visible text. Is considered
468 * visible text that isn't hidden by CSS properties or other means. 467 * visible text that isn't hidden by CSS properties or other means.
469 * If the string begins and ends with a slash (<code>/</code>), the 468 * If the string begins and ends with a slash (<code>/</code>), the
470 * text in between is treated as a regular expression. 469 * text in between is treated as a regular expression.
471 * @param {string} selector The CSS selector that an HTML element must match 470 * @param {string} selector The CSS selector that an HTML element must match
472 * for it to be hidden. 471 * for it to be hidden.
473 * @param {string?} [searchSelector] The CSS selector that an HTML element 472 * @param {?string} [searchSelector] The CSS selector that an HTML element
474 * containing the given string must match. Defaults to the value of the 473 * containing the given string must match. Defaults to the value of the
475 * <code>selector</code> argument. 474 * <code>selector</code> argument.
476 */ 475 */
477 function hideIfContainsVisibleText(search, selector, searchSelector = null) 476 function hideIfContainsVisibleText(search, selector, searchSelector = null)
478 { 477 {
479 /** 478 /**
480 * Determines if the text inside the element is visible. 479 * Determines if the text inside the element is visible.
481 * @param {Element} element The leaf element we are checking. 480 * @param {Element} element The element we are checking.
482 * @param {?CSSStyleDeclaration} [style] The computed style of element. If 481 * @param {?CSSStyleDeclaration} style The computed style of element. If
483 * falsey it will be queried. 482 * falsey it will be queried.
484 * @returns {bool} Whether the text is visible. 483 * @returns {bool} Whether the text is visible.
485 */ 484 */
486 function isTextVisible(element, style) 485 function isTextVisible(element, style)
487 { 486 {
488 if (!style) 487 if (!style)
489 style = window.getComputedStyle(element); 488 style = window.getComputedStyle(element);
490 489
491 if (style.getPropertyValue("opacity") == "0") 490 if (style.getPropertyValue("opacity") == "0")
492 return false; 491 return false;
493 if (style.getPropertyValue("font-size") == "0px") 492 if (style.getPropertyValue("font-size") == "0px")
494 return false; 493 return false;
495 if (style.getPropertyValue("color") == 494
496 style.getPropertyValue("background-color")) 495 let color = style.getPropertyValue("color");
496 // if color is transparent...
497 if (color == "rgba(0, 0, 0, 0)")
497 return false; 498 return false;
499 if (style.getPropertyValue("background-color") == color)
500 return false;
498 501
499 return true; 502 return true;
500 } 503 }
501 504
502 /** 505 /**
503 * Returns the visible text content from an element and its children. 506 * Check if an element is visible
507 * @param {Element} element The element to check visibility of.
508 * @param {?CSSStyleDeclaration} style The computed style of element. If
509 * falsey it will be queried.
510 * @param {?Element} closest The closest parent to reach.
511 * @return {bool} Whether the element is visible.
512 */
513 function isVisible(element, style, closest)
514 {
515 if (!style)
516 style = window.getComputedStyle(element);
517
518 if (style.getPropertyValue("display") == "none")
519 return false;
520 let visibility = style.getPropertyValue("visibility");
521 if (visibility == "hidden" || visibility == "collapse")
522 return false;
523
524 if (!closest || element == closest)
525 return true;
526
527 let parent = element.parentElement;
528 if (!parent)
529 return true;
530
531 return isVisible(parent, null, closest);
532 }
533
534 /**
535 * Returns the visible text content from an element and its descendants.
504 * @param {Element} element The element whose visible text we want. 536 * @param {Element} element The element whose visible text we want.
537 * @param {Element} closest The closest parent to reach while checking
538 * for visibility.
505 * @returns {string} The text that is visible. 539 * @returns {string} The text that is visible.
506 */ 540 */
507 function getVisibleContent(element) 541 function getVisibleContent(element, closest)
508 { 542 {
509 let style = window.getComputedStyle(element); 543 let style = window.getComputedStyle(element);
510 if (style.getPropertyValue("display") == "none") 544 if (!isVisible(element, style, closest))
511 return "";
512 let visibility = style.getPropertyValue("visibility");
513 if (visibility == "hidden" || visibility == "collapse")
514 return ""; 545 return "";
515 546
516 let text = ""; 547 let text = "";
517 for (let node of element.childNodes) 548 for (let node of element.childNodes)
518 { 549 {
519 switch (node.nodeType) 550 switch (node.nodeType)
520 { 551 {
521 case Node.ELEMENT_NODE: 552 case Node.ELEMENT_NODE:
522 text += getVisibleContent(node); 553 text += getVisibleContent(node, element);
523 break; 554 break;
524 case Node.TEXT_NODE: 555 case Node.TEXT_NODE:
525 if (isTextVisible(element, style)) 556 if (isTextVisible(element, style))
526 text += node.nodeValue; 557 text += node.nodeValue;
527 break; 558 break;
528 } 559 }
529 } 560 }
530 return text; 561 return text;
531 } 562 }
532 563
533 let re = toRegExp(search); 564 let re = toRegExp(search);
534 565
535 hideIfMatch(element => 566 hideIfMatches(
536 { 567 (element, closest) => re.test(getVisibleContent(element, closest)),
537 let content = getVisibleContent(element); 568 selector, searchSelector);
538 return re.test(content); 569 }
539 }, selector, searchSelector); 570
540 } 571 exports["hide-if-contains-visible-text"] = hideIfContainsVisibleText;
541
542 exports["hide-if-contains-visible-text"] =
543 makeInjector(hideIfContainsVisibleText, hideIfMatch, hideElement);
544 572
545 /** 573 /**
546 * Hides any HTML element or one of its ancestors matching a CSS selector if 574 * Hides any HTML element or one of its ancestors matching a CSS selector if
547 * the text content of the element contains a given string and, optionally, if 575 * the text content of the element contains a given string and, optionally, if
548 * the element's computed style contains a given string. 576 * the element's computed style contains a given string.
549 * 577 *
550 * @param {string} search The string to look for in HTML elements. If the 578 * @param {string} search The string to look for in HTML elements. If the
551 * string begins and ends with a slash (<code>/</code>), the text in between 579 * string begins and ends with a slash (<code>/</code>), the text in between
552 * is treated as a regular expression. 580 * is treated as a regular expression.
553 * @param {string} selector The CSS selector that an HTML element must match 581 * @param {string} selector The CSS selector that an HTML element must match
(...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after
992 1020
993 args[0] = url.href; 1021 args[0] = url.href;
994 } 1022 }
995 1023
996 return fetch_.apply(this, args); 1024 return fetch_.apply(this, args);
997 }; 1025 };
998 } 1026 }
999 1027
1000 exports["strip-fetch-query-parameter"] = makeInjector(stripFetchQueryParameter, 1028 exports["strip-fetch-query-parameter"] = makeInjector(stripFetchQueryParameter,
1001 toRegExp, regexEscape); 1029 toRegExp, regexEscape);
LEFTRIGHT

Powered by Google App Engine
This is Rietveld