Generic Watermark Remover

Generic Watermark Remover by ihciah

  1. // ==UserScript==
  2. // @name Generic Watermark Remover
  3. // @name:zh-CN 通用水印移除器
  4. // @namespace https://github.com/ihciah/
  5. // @version 0.1.0
  6. // @description Generic Watermark Remover by ihciah
  7. // @description:zh-CN 通用水印移除器 by ihciah
  8. // @author ihciah
  9. // @match https://*.example.com/*
  10. // @grant none
  11. // ==/UserScript==
  12.  
  13. function traverseByDFS(domRoot) {
  14. var child = domRoot.firstElementChild;
  15. while(child) {
  16. setNodeTransparent(child);
  17. traverseByDFS(child);
  18. child = child.nextElementSibling;
  19. }
  20. }
  21.  
  22. function setNodeTransparent(node) {
  23. if (validateNode(node)) {
  24. //node.background = '';
  25. let classes = node.className.split(" ")
  26. for (let i = 0; i < classes.length; i++) {
  27. if (classes[i].length == 0) {continue;}
  28. let sheet = new CSSStyleSheet();
  29. sheet.replaceSync(`.${classes[i]} {opacity: 0}`);
  30. document.adoptedStyleSheets = [sheet];
  31. console.log(`[NoWatermark] Element .${classes[i]} has been set transparent!`);
  32. }
  33. }
  34. }
  35.  
  36.  
  37. function validateNode(node) {
  38. let ret = false;
  39. // Only process nodes with className.
  40. if (!node || typeof(node.className) != 'string'){
  41. return false;
  42. }
  43.  
  44. // Do not process avatar and icon nodes.
  45. const whiteList = ['avatar', 'icon', 'lode-more', 'suite-body', 'flex', 'layout-column', 'banner'];
  46. for (let i = 0; i < whiteList.length; i++) {
  47. if (node.className.includes(whiteList[i])) {return false;}
  48. }
  49.  
  50. // Images start with 'url("data:image/png' or 'url("data:image/svg+xml' is treated as watermark.
  51. let bgImg = getComputedStyle(node).backgroundImage;
  52. if (typeof(bgImg) === 'string' && bgImg.startsWith('url("data:image/png') || bgImg.startsWith('url("data:image/svg+xml')) {
  53. ret = true;
  54. }
  55.  
  56. // Images with repeat property is treated as watermark.
  57. let bg = getComputedStyle(node).background;
  58. if (typeof(bg) === 'string' && bg.includes('repeat') && !bg.includes('none repeat') && !bg.includes('banner')) {
  59. ret = true;
  60. }
  61. return ret;
  62. }
  63.  
  64. (function() {
  65. 'use strict';
  66.  
  67. const callback = function(mutationsList, observer) {
  68. traverseByDFS(document.body);
  69. }
  70. const observer = new MutationObserver(callback);
  71.  
  72. const config = { attributes: true, childList: true, subtree: true };
  73. observer.observe(document.body, config);
  74. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址