Skip to content

Instantly share code, notes, and snippets.

@WFreelandEcon
Forked from mrcoles/replace_words.js
Created January 31, 2018 09:10
Show Gist options
  • Save WFreelandEcon/8a368fdf0516057efed4135aee3bbcf0 to your computer and use it in GitHub Desktop.
Save WFreelandEcon/8a368fdf0516057efed4135aee3bbcf0 to your computer and use it in GitHub Desktop.
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');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment