mostlynew
mostlynew

Reputation: 7

Chrome extension breaks DOM

I'm making a Chrome extension that replaces certain text on a page with new text and a link. To do this I'm using document.body.innerHTML, which I've read breaks the DOM. When the extension is enabled it seems to break the loading of YouTube videos and pages at codepen.io. I've tried to fix this by excluding YouTube and codepen in the manifest, and by filtering them out in the code below, but it doesn't seem to be working.

Can anyone suggest an alternative to using document.body.innerHTML or see other problems in my code that may be breaking page loads? Thanks.

var texts=["some text","more text"];
if(!window.location.href.includes("www.google.com")||!window.location.href.includes("youtube.com")||!window.location.href.includes("codepen.io")){
for(var i=0;i<texts.length;i++){
    if(document.documentElement.textContent || document.documentElement.innerText.includes(texts[i])){

        var regex = new RegExp(texts[i],'g');

        document.body.innerHTML = document.body.innerHTML.replace(regex, 
 "<a href='https://www.somesite.org'>replacement text</a>");
         }
     }
}

Upvotes: 0

Views: 117

Answers (1)

Matti Virkkunen
Matti Virkkunen

Reputation: 65166

Using innerHTML to do this is like using a shotgun to do brain surgery. Not to mention that this can even result in invalid HTML. You will end up having to whitelist every single website that uses any JavaScript at this rate, which is obviously not feasible.

The correct way to do it is to not touch innerHTML at all. Recursively iterate through all the DOM nodes (using firstChild, nextSibling) on the page and look for matches in text nodes. When you find one, replace that single node (replaceChild) with your link (createElement), and new text nodes (createTextNode, appendChild, insertBefore) for any leftover bits.

Essentially you will want to look for a node like:

Text: this is some text that should be linked

And programmatically replace it with nodes like:

Text: this is
Element: a href="..."
    Text: replacement text
Text: that should be linked

Additionally if you want to support websites that generate content with JavaScript you'll have to run this replacement process on dynamically inserted content as well. A MutationObserver would be one way to do that, but bear in mind this will probably slow down websites.

Upvotes: 1

Related Questions