Greasy Fork is available in English.

🔥🔥🔥移除页面水印🔥🔥🔥

移除常见网页的水印

  1. // ==UserScript==
  2. // @name 🔥🔥🔥移除页面水印🔥🔥🔥
  3. // @name:en Remove Page Watermark
  4. // @name:zh 🔥🔥🔥移除页面水印🔥🔥🔥
  5. // @description 移除常见网页的水印
  6. // @description:en Remove watermarks from common web pages
  7. // @description:zh 移除常见网页的水印
  8. // @namespace https://github.com/WindrunnerMax/TKScript
  9. // @version 1.0.7
  10. // @author Czy
  11. // @match http://*/*
  12. // @match https://*/*
  13. // @supportURL https://github.com/WindrunnerMax/TKScript/issues
  14. // @license GPL License
  15. // @run-at document-start
  16. // @grant GM_addStyle
  17. // @grant unsafeWindow
  18. // ==/UserScript==
  19. (function () {
  20. 'use strict';
  21.  
  22. const FALLBACK_CLASS = "__WATERMARK__";
  23. const OPACITY_PROPERTY = [
  24. "opacity: 0 !important;",
  25. "visibility: hidden !important;",
  26. "transform: translate(-999999px, -999999px) !important;"
  27. ].join("");
  28. const OPACITY_BACKGROUND_PROPERTY = [
  29. "background: transparent !important;",
  30. "background-color: transparent !important;",
  31. "background-image: linear-gradient(to right, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0)) !important;"
  32. ].join("");
  33.  
  34. const inspectWaterMarkDOM = (node) => {
  35. if (node instanceof HTMLElement === false) {
  36. return false;
  37. }
  38. if (node.classList.contains(FALLBACK_CLASS)) {
  39. return true;
  40. }
  41. if (!node.hasAttribute("style") || node.style.pointerEvents !== "none") {
  42. return false;
  43. }
  44. if (node instanceof HTMLImageElement && node.src && node.src.startsWith("data:")) {
  45. !node.classList.contains(FALLBACK_CLASS) && node.classList.add(FALLBACK_CLASS);
  46. return true;
  47. }
  48. if (node.style.background.startsWith("url") || node.style.backgroundImage.startsWith("url")) {
  49. !node.classList.contains(FALLBACK_CLASS) && node.classList.add(FALLBACK_CLASS);
  50. return true;
  51. }
  52. return false;
  53. };
  54.  
  55. const styles = {
  56. insertCSS: (id, css) => {
  57. const style = document.createElement("style");
  58. style.id = id;
  59. style.innerText = css;
  60. const [body] = document.getElementsByTagName("body");
  61. if (body) {
  62. body.appendChild(style);
  63. } else {
  64. window.addEventListener("DOMContentLoaded", () => document.body.appendChild(style));
  65. }
  66. },
  67. removeCSS: (id) => {
  68. const style = document.getElementById(id);
  69. style && style.remove();
  70. }
  71. };
  72.  
  73. const injectCSSEarly = (css) => {
  74. if (typeof GM_addStyle === "function") {
  75. GM_addStyle(css);
  76. return void 0;
  77. }
  78. const style = document.createElement("style");
  79. style.innerText = css;
  80. const head = document.head;
  81. if (head) {
  82. head.appendChild(style);
  83. return void 0;
  84. }
  85. const html = document.documentElement;
  86. if (html) {
  87. html.appendChild(style);
  88. return void 0;
  89. }
  90. styles.insertCSS(String(Math.random()), css);
  91. };
  92.  
  93. const basic = {
  94. regexp: /.*/,
  95. init: () => {
  96. const observer = MutationObserver.prototype.observe;
  97. MutationObserver.prototype.observe = function(target, options) {
  98. inspectWaterMarkDOM(target);
  99. target.childNodes.forEach(inspectWaterMarkDOM);
  100. observer.call(this, target, options);
  101. };
  102. const _MutationObserver = MutationObserver;
  103. const getMutationCallback = (callback) => {
  104. return (records, observer2) => {
  105. let isMatchedWaterMarkDOM = false;
  106. for (const record of records) {
  107. if (inspectWaterMarkDOM(record.target) && !isMatchedWaterMarkDOM) {
  108. isMatchedWaterMarkDOM = true;
  109. }
  110. }
  111. !isMatchedWaterMarkDOM && callback(records, observer2);
  112. };
  113. };
  114. unsafeWindow.MutationObserver = class extends _MutationObserver {
  115. constructor(callback) {
  116. super(getMutationCallback(callback));
  117. }
  118. };
  119. const PRESET_CLASSES = [`.${FALLBACK_CLASS}`].join(",");
  120. injectCSSEarly(`${PRESET_CLASSES}{${OPACITY_PROPERTY}}`);
  121. const PRESET_BACKGROUND = [
  122. `div[id*="watermark"]`,
  123. `div[id*="WaterMark"]`,
  124. `div[id*="Watermark"]`,
  125. `div[class*="watermark"]`,
  126. `div[class*="WaterMark"]`,
  127. `div[class*="Watermark"]`,
  128. `div[style*="pointer-events"][style*="background: url"]`,
  129. `div[style*="pointer-events"][style*="background-image: url"]`,
  130. `div[style*="pointer-events"][style*="background:url"]`,
  131. `div[style*="pointer-events"][style*="background-image:url"]`
  132. ].join(",");
  133. injectCSSEarly(`${PRESET_BACKGROUND}{${OPACITY_BACKGROUND_PROPERTY}}`);
  134. }
  135. };
  136.  
  137. const websites = [basic];
  138. const web = websites.find((item) => item.regexp.test(location.href));
  139. web && web.init();
  140.  
  141. }());