Search code examples
javascriptjsonregexreplaceuserscripts

JavaScript Regex to replace VISIBLE text in webpages


I'm looking to match strings in a .json list called "mylist" with visible strings only on any webpage any time they appear. Matching strings would be replaced with the term "REPLACED!" below in the script.

The most important thing is that the script should work on modern browsers and not degrade page loading performance. So I'd appreciate any optimization tips!

Here's what I have got so far:

@resource      mylist https://example.com/mylist.json

(function(){
var mylist = JSON.parse(GM_getResourceText("mylist"));
var regexp = new RegExp('\\b(' + mylist.join('|') + ')\\b(?!\\)\\))', "gi");
 
function walk(node) {
    var child, next;
 
    switch ( node.nodeType )
    {
        case 1:
        case 9:
        case 11:
            child = node.firstChild;
            while ( child )
            {
                next = child.nextSibling;
                walk(child);
                child = next;
            }
            break;
 
        case 3:
            handleText(node);
            break;
    }
}
 
function handleText(textNode) {
    textNode.nodeValue = textNode.nodeValue.replace(regexp, 'REPLACED!');
}
 
walk(document.body);
})();

I've made a sample here: https://jsfiddle.net/xgnocwbq/

The biggest issue I am facing is that on some pages, the script works. On others, it does not work at all. For example, on Qwant search results, my code doesn't work at all. Yet on Google search results, it does.


Solution

  • Fixing @AztecCodes work, the only issue is using the querySelector() function, where instead you should use childNodes attribute.

    (function() {
      var mylist = JSON.parse(GM_getResourceText("mylist"));
      var regexp = new RegExp('\\b(' + mylist.join('|') + ')\\b(?!\\)\\))', "gi");
    
      function handleText(textNode) {
          console.log("Replacing text")
          textNode.nodeValue = textNode.nodeValue.replace(regexp, 'REPLACED!');
      }
    
      function processNode(node) {
          if (node.nodeType === 3) {
              handleText(node);
          } else {
              node.childNodes.forEach(processNode);
          }
      }
    
      // Processes the initial page content
      processNode(document.body);
    
      // Observes the changes in the DOM to handle dynamic content
      const observer = new MutationObserver((mutations) => {
          mutations.forEach((mutation) => {
              mutation.addedNodes.forEach(processNode);
          });
      });
    
      observer.observe(document.body, {
          childList: true,
          subtree: true
      });
    })();