JMM’s notes on

Getting all text nodes in the DOM

I wanted to find a way to censor text in a page. Here’s how to do that:

Array.from(document.querySelectorAll("*"),
	   el =>
	   Array.from(el.childNodes)
	   .filter(x => x.nodeType === Node.TEXT_NODE))
    .flat()
    .forEach(x => { x.data = "░".repeat(x.data.length); })

And here’s how to censor a particular word:

Array.from(document.querySelectorAll("*"),
	   el => Array.from(el.childNodes).filter(x => x.nodeType === Node.TEXT_NODE))
    .flat()
    .forEach(x => { x.data = x.data.replace(/text/ig, match => "█".repeat(match.length)); })

Here’s how to replace all text, but leave the whitespace intact:

Array.from(document.querySelectorAll("*"),
	   el => Array.from(el.childNodes).filter(x => x.nodeType === Node.TEXT_NODE))
    .flat()
    .forEach(x => { x.data = x.data.replace(/\S+/ig, match => "█".repeat(match.length)); })

And same thing but you pick a character:

function replaceNonwhitespace(char) {
    const textnodes = Array.from(document.querySelectorAll("*"), el => Array.from(el.childNodes).filter(x => x.nodeType === Node.TEXT_NODE)).flat();
    textnodes.forEach(x => { x.data = x.data.replace(/\S+/ig, match => char.repeat(match.length)); });
}

You can see a bookmarklet that uses this function here.