NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name BambooSimplifyErrorFilter
// @author ole.goebbels@dtn.com, after Profanity Filter by adisib (https://github.com/adisib/Profanity-Filter)
// @namespace namespace_dtn
// @description Simple filtering for ^error on Bamboo log website text to make searching for errors simpler.
// @version 2020-08-11
// @license MIT
// @include /.*bamboo.*\.log$/
// @grant none
// ==/UserScript==
(function() {
"use strict";
// --- SETTINGS --------
// The string that replaces offending words.
const replaceString = "stderr";
// Display performance and debugging information to the console.
const DEBUG = false;
// --------------------
let wordString = "^error";
const wordsFilter = new RegExp(wordString, "gm");
wordString = null;
const findText = document.createExpression(".//text()[string-length() > 2 and not(parent::script or parent::code)]", null);
// Initial slow filter pass that handles static text
function filterStaticText()
{
let startTime, endTime;
if (DEBUG)
{
startTime = performance.now();
}
filterNodeTree(document.body);
if (DEBUG)
{
endTime = performance.now();
console.log("PF | Static Text Run-Time (ms): " + (endTime - startTime).toString());
}
}
// --------------------
// filters dynamic text, and handles things such as AJAX Youtube comments
function filterDynamicText()
{
let textMutationObserver = new MutationObserver(filterMutations);
let TxMOInitOps = { characterData: true, childList: true, subtree: true };
textMutationObserver.observe(document.body, TxMOInitOps);
}
// --------------------
// Handler for mutation observer from filterDynamicText()
function filterMutations(mutations)
{
let startTime, endTime;
if (DEBUG)
{
startTime = performance.now();
}
for (let i = 0; i < mutations.length; ++i)
{
let mutation = mutations[i];
if (mutation.type === "childList")
{
let nodes = mutation.addedNodes;
for (let j = 0; j < nodes.length; ++j)
{
filterNodeTree(nodes[j]);
}
}
else if (mutation.type === "characterData" && !mutation.target.parentNode.isContentEditable)
{
filterNode(mutation.target);
}
}
if (DEBUG)
{
endTime = performance.now();
console.log("PF | Dynamic Text Run-Time (ms): " + (endTime - startTime).toString());
}
}
// --------------------
// Filters a textNode
function filterNode(node)
{
if (DEBUG) {
console.log(node.nodeName, node.nodeType);
}
if (wordsFilter.test(node.data))
{
node.data = node.data.replace(wordsFilter, replaceString);
}
}
// --------------------
// Filters all of the text from a node and its decendants
function filterNodeTree(node)
{
if (!node || (node.nodeType !== Node.ELEMENT_NODE && node.nodeType !== Node.TEXT_NODE))
{
return;
}
if (node.nodeType === Node.TEXT_NODE)
{
filterNode(node);
return; // text nodes don't have children
}
let textNodes = findText.evaluate(node, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
const l = textNodes.snapshotLength;
for (let i = 0; i < l; ++i)
{
filterNode(textNodes.snapshotItem(i));
}
}
// --------------------
// Runs the different filter types
function filterPage()
{
filterStaticText();
filterDynamicText();
}
// --- MAIN -----------
filterPage();
})();