Remove Promotion Element at Reddit Site

Removes the promotion element from the page

当前为 2024-12-24 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Remove Promotion Element at Reddit Site
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.0.4
  5. // @description Removes the promotion element from the page
  6. // @author aspen138
  7. // @match *://www.reddit.com/*
  8. // @icon data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAQlBMVEVHcEz/RQD/RQD/QgD/RQD/RQD/RQD/RQD/RQD/RQD/////MgD/OgD/s5//z8P/a0T/5d3/VyH/iGr/qJP/mYD/+vcCA1U1AAAACnRSTlMAJP//y5WUn+ElsgVe0gAAAJFJREFUGJVtT1sOwyAMy0JpIa/C2t3/qjNQaT+zkMAmD5sIqLkwl1zpwcEPjsW3ScxMefv9m7u3WVNXdXJ9Q+BKGYRN+62miXmnMvg7WotT8SzE6ZQHHzkTL+HuIv2SKRTWkHCRC5eiJWOCSJvnNgzFWrtQ4iGuY+0wZt0jHFuWeVhPpmpwsf0PR/TaR/x9xv8CYoYGnu4Mr1kAAAAASUVORK5CYII=
  9. // @grant none
  10. // @license MIT
  11. // ==/UserScript==
  12.  
  13.  
  14.  
  15.  
  16.  
  17.  
  18. (function() {
  19. 'use strict';
  20.  
  21. /**
  22. * Recursively searches through regular DOM and Shadow DOM roots for elements
  23. * matching a given selector.
  24. * @param {string} selector - The CSS selector to look for.
  25. * @returns {Element[]} - An array of matching elements.
  26. */
  27. function deepQuerySelectorAll(selector) {
  28. const nodes = [];
  29.  
  30. /**
  31. * Searches a single node (and its children) for matching elements,
  32. * including Shadow DOM children if present.
  33. * @param {Node} node
  34. */
  35. function searchInNode(node) {
  36. // If this node has a shadow root, search within it
  37. if (node.shadowRoot) {
  38. const matches = node.shadowRoot.querySelectorAll(selector);
  39. if (matches.length > 0) {
  40. nodes.push(...matches);
  41. }
  42. Array.from(node.shadowRoot.children).forEach(searchInNode);
  43. }
  44.  
  45. // Continue searching regular child nodes
  46. Array.from(node.children).forEach(searchInNode);
  47. }
  48.  
  49. // Start the search from the document root
  50. searchInNode(document);
  51. return nodes;
  52. }
  53.  
  54. /**
  55. * Removes the error banner from the DOM if present.
  56. */
  57. function removeErrorBanner() {
  58. const banners = deepQuerySelectorAll('div.banner.error');
  59. if (banners.length > 0) {
  60. banners.forEach(banner => banner.remove());
  61. console.log("Server Error Banner has been removed.");
  62. }
  63. }
  64.  
  65. /**
  66. * Sets up a MutationObserver to detect changes in the DOM
  67. * and trigger the removeErrorBanner function.
  68. */
  69. function initErrorBannerObserver() {
  70. const observer = new MutationObserver(() => {
  71. removeErrorBanner();
  72. });
  73.  
  74. observer.observe(document, { childList: true, subtree: true });
  75. }
  76.  
  77. /**
  78. * Removes elements that match any of the given CSS selectors.
  79. * @param {string[]} selectors - Array of CSS selectors for unwanted elements.
  80. */
  81. function removePromoElements(selectors) {
  82. selectors.forEach(selector => {
  83. const promoElements = document.querySelectorAll(selector);
  84. promoElements.forEach(element => {
  85. element.remove();
  86. console.log('Promotion element removed:', selector);
  87. });
  88. });
  89. }
  90.  
  91. /**
  92. * Hides all links containing the specific rel attribute.
  93. * @param {string} relContent - The exact rel string to look for.
  94. */
  95. function hideLinksByRel(relContent) {
  96. const links = document.querySelectorAll('a');
  97. links.forEach(link => {
  98. if (link.getAttribute('rel') === relContent) {
  99. link.style.display = 'none';
  100. console.log(`Link with rel "${relContent}" hidden`);
  101. }
  102. });
  103. }
  104.  
  105. /**
  106. * Sets up a MutationObserver to detect changes in the document body
  107. * and re-run the removal/hiding functions for promotional elements.
  108. */
  109. function initPromoObserver() {
  110. const promoObserver = new MutationObserver(() => {
  111. removePromoElements(promoSelectors);
  112. hideLinksByRel('noopener nofollow sponsored');
  113. });
  114.  
  115. promoObserver.observe(document.body, {
  116. childList: true,
  117. subtree: true
  118. });
  119. }
  120.  
  121. // ==============================
  122. // MAIN EXECUTION
  123. // ==============================
  124. // Start observing the document for error banners
  125. initErrorBannerObserver();
  126.  
  127. // Initial removal of the error banner if present
  128. removeErrorBanner();
  129.  
  130. // Wait for the page to load fully before removing promotional elements
  131. window.addEventListener('load', function() {
  132. // Define your promotional selectors here
  133. const promoSelectors = [
  134. 'a.w-100.block.h-100.cursor-pointer',
  135. 'shreddit-ad-post.promotedlink',
  136. 'shreddit-dynamic-ad-link',
  137. 'shreddit-comments-page-ad.promotedlink' // Additional selector
  138. ];
  139.  
  140. // Remove or hide elements matching the promotional selectors or rel attributes
  141. removePromoElements(promoSelectors);
  142. hideLinksByRel('noopener nofollow sponsored');
  143.  
  144. // Observe for further changes to remove newly inserted promo elements
  145. initPromoObserver();
  146. });
  147. })();