Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Replace all instances of one word with another in a web page
// ### Replace words in document
//
// Update all instances of `fromWord` to `toWord` within the text
// in the current document.
//
function replaceWordsInDocument(fromWord, toWord) {
if (/\s/.test(fromWord)) {
throw new Error('You must enter a single word without whitespace');
}
const textNodes = iterAllTextNodes();
replaceInNodes(fromWord, toWord, textNodes);
}
// ### Iterate all text nodes
//
// Returns a generator that yields all the text nodes within a
// document (excluding those within link, style, and script tags)
//
function* iterAllTextNodes() {
const ignoreNodes = new Set(['LINK', 'STYLE', 'SCRIPT']);
for (const elt of document.querySelectorAll('*')) {
if (!ignoreNodes.has(elt.nodeName)) {
for (const node of elt.childNodes) {
if (node.nodeType === 3) {
yield node;
}
}
}
}
}
// ### Replace in nodes
//
// Replaces all instances of fromText with toText within
// the textNodes. Matches whole words and expects
// `fromText` to have no whitespaces. Matches are also
// case-insensitve, and replacements attempt to replicate
// the original capitalization found in the node.
//
// - fromText (string) representing one word with no spaces
// - toText (string)
// - textNodes (nodeList of text nodes)
//
function replaceInNodes(fromText, toText, textNodes) {
const fromLower = fromText.toLowerCase();
const replacements = {
[fromLower]: toText.toLowerCase(),
[fromText.toUpperCase()]: toText.toUpperCase(),
[capitalize(fromText)]: capitalize(toText)
}
for (const node of textNodes) {
const newText = node.nodeValue.split(/(\s+)/).map((token, i) => {
if (i % 2 === 0) {
const tokenLower = token.toLowerCase();
if (tokenLower === fromLower) {
return replacements[token] || toText;
}
}
return token;
}).join('');
// looks faster to only set if changed https://jsperf.com/node-nodevalue
if (newText !== node.nodeValue) {
node.nodeValue = newText;
}
}
}
// ### Helpers
//
const capitalize = (text) => text.substring(0, 1).toUpperCase() + text.toLowerCase().substring(1);
// ### Run it
//
replaceWordsInDocument('you', 'y\'all');
@mrcoles

This comment has been minimized.

Copy link
Owner Author

mrcoles commented Dec 14, 2017

This uses some es6 features like generators, arrow functions, and computed property keys, which may not work in some older browsers.

Usage:

replaceWordsInDocument('you', 'y\'all');

😉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.