diff --git a/content.js b/content.js new file mode 100644 index 0000000..00e3f94 --- /dev/null +++ b/content.js @@ -0,0 +1,64 @@ +const DEFAULT_REPLACEMENTS = { + "consultant": "conslutant", + "AI process engineer": "algorithm inventor" +}; + +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\\]\\]/g, "\\$&"); +} + +function replaceInTextNode(node, replacements) { + let text = node.nodeValue; + let updated = text; + + for (const [search, replace] of Object.entries(replacements)) { + const regex = new RegExp(escapeRegExp(search), "gi"); + updated = updated.replace(regex, replace); + } + + if (updated !== text) { + node.nodeValue = updated; + } +} + +function walk(node, replacements) { + if ( + node.nodeType === Node.ELEMENT_NODE && + ["SCRIPT", "STYLE", "TEXTAREA", "INPUT"].includes(node.tagName) + ) { + return; + } + + if (node.nodeType === Node.TEXT_NODE) { + replaceInTextNode(node, replacements); + return; + } + + for (const child of node.childNodes) { + walk(child, replacements); + } +} + +async function getReplacements() { + return new Promise((resolve) => { + chrome.storage.sync.get(["replacements"], (result) => { + resolve(result.replacements || DEFAULT_REPLACEMENTS); + }); + }); +} + +async function runReplacement() { + const replacements = await getReplacements(); + walk(document.body, replacements); +} + +runReplacement(); + +const observer = new MutationObserver(() => { + runReplacement(); +}); + +observer.observe(document.body, { + childList: true, + subtree: true +}); \ No newline at end of file