Replaces text based on a mapping with exact matching and site-specific filtering
// ==UserScript==
// @name Pattern Mapping Replacer - Multi-Site
// @namespace http://tampermonkey.net/
// @version 1.2
// @description Replaces text based on a mapping with exact matching and site-specific filtering
// @author Kreezxil
// @match *://*/*
// @grant none
// @license MIT; explicity from MIT license, you must link back to this script.
// ==/UserScript==
(function() {
'use strict';
// 1. Define your site lists as variables
const bibleSites = ["sefaria.org", "chabad.org", "biblegateway.com"];
const allSites = [];
/**
* MAPPING CONFIGURATION
*/
const mapping = {
// 2. Use the variable name instead of typing the array
"The Lord": [true, bibleSites, "Yahweh"],
"the Lord": [false, bibleSites, "Yahweh"],
"THE LORD": [false, bibleSites, "Yahweh"],
"thou": [false, allSites, "you"],
"shalt": [false, allSites, "shall"],
"hallow": [false, bibleSites, "sanctify"],
"candlestick": [false, bibleSites, "menorah"],
"didst": [false, bibleSites, "did"],
"God": [false, bibleSites, "Elohim"],
"thereat": [false, bibleSites, "there"]
};
const currentHost = window.location.hostname;
function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
function applyReplacements(text) {
let newText = text;
for (const [pattern, [exactMatch, allowedSites, replacement]] of Object.entries(mapping)) {
// Check if current site is in the allowed list or if the list is empty
const isSiteAllowed = allowedSites.length === 0 || allowedSites.some(site => currentHost.includes(site));
if (!isSiteAllowed) continue;
const escapedPattern = escapeRegExp(pattern);
const flags = exactMatch ? 'g' : 'gi';
const regex = new RegExp(`\\b${escapedPattern}\\b`, flags);
newText = newText.replace(regex, replacement);
}
return newText;
}
function walkNodes(node) {
if (node.nodeType === Node.TEXT_NODE) {
const processed = applyReplacements(node.nodeValue);
if (processed !== node.nodeValue) {
node.nodeValue = processed;
}
} else if (node.nodeType === Node.ELEMENT_NODE &&
!['SCRIPT', 'STYLE', 'TEXTAREA', 'INPUT'].includes(node.tagName)) {
for (let i = 0; i < node.childNodes.length; i++) {
walkNodes(node.childNodes[i]);
}
}
}
walkNodes(document.body);
const observer = new MutationObserver((mutations) => {
for (const mutation of mutations) {
for (const node of mutation.addedNodes) {
walkNodes(node);
}
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
})();