Replaces all occurences of "Microsoft" in text nodes and page titles with "Microslop".
// ==UserScript==
// @name μSlop
// @match *://*/*
// @run-at document-end
// @grant none
// @description Replaces all occurences of "Microsoft" in text nodes and page titles with "Microslop".
// @license Public Domain
// @version 0.2
// @namespace https://greasyfork.org/users/1593905
// ==/UserScript==
(function() {
'use strict';
const TARGET = "microsoft";
const REPLACEMENT_BASE = "microslop";
const MAX_EXEC_TIME_MS = 50;
const IGNORE_TAGS = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEMPLATE'];
function applyCasing(match, replacement) {
if (!match || !replacement) return match;
const firstChar = match[0];
const isUpperFirst = firstChar === firstChar.toUpperCase() && firstChar !== firstChar.toLowerCase();
const isAllUpper = match === match.toUpperCase();
let result = "";
if (isAllUpper) {
result = replacement.toUpperCase();
} else if (isUpperFirst) {
result = replacement.charAt(0).toUpperCase() + replacement.slice(1).toLowerCase();
} else {
// All lowercase (or mixed that isn't title/upper)
result = replacement.toLowerCase();
}
return result;
}
function processNode(node) {
if (node.nodeType === Node.TEXT_NODE) {
const text = node.nodeValue;
if (!text.toLowerCase().includes(TARGET.toLowerCase())) return;
const regex = new RegExp(
TARGET.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'),
'gi'
);
node.nodeValue = text.replace(regex, (match) => {
return applyCasing(match, REPLACEMENT_BASE);
});
}
}
function fixTitle() {
if (document.title && document.title.toLowerCase().includes(TARGET.toLowerCase())) {
const regex = new RegExp(
TARGET.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'),
'gi'
);
document.title = document.title.replace(regex, (match) => {
return applyCasing(match, REPLACEMENT_BASE);
});
}
}
function processQueue(queue) {
const startTime = performance.now();
while (queue.length > 0) {
const node = queue.shift();
processNode(node);
if (node.childNodes) {
for (let j = 0; j < node.childNodes.length; j++) {
const child = node.childNodes[j];
if (!IGNORE_TAGS.includes(child.tagName)) {
queue.push(child);
}
}
}
if (performance.now() - startTime > MAX_EXEC_TIME_MS) {
setTimeout(() => processQueue(queue), 0);
return;
}
}
}
fixTitle();
setInterval(() => {fixTitle();}, 2000);
const initialQueue = [document.body];
processQueue(initialQueue);
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
mutation.addedNodes.forEach(node => {
if (!IGNORE_TAGS.includes(node.tagName)) {
const queue = [node];
processQueue(queue);
}
});
});
});
observer.observe(document.body, { childList: true, subtree: true });
})();