Index: lib/content/snippets.js |
=================================================================== |
--- a/lib/content/snippets.js |
+++ b/lib/content/snippets.js |
@@ -115,16 +115,35 @@ |
{ |
element.style.setProperty("display", "none", "important"); |
} |
}) |
.observe(element, {attributes: true, attributeFilter: ["style"]}); |
} |
/** |
+ * Observes changes to a DOM node using a <code>MutationObserver</code>. |
+ * |
+ * @param {Node} target The DOM node to observe for changes. |
+ * @param {MutationObserverInit?} [options] Options that describe what DOM |
+ * mutations should be reported to the callback. |
+ * @param {function} callback A function that will be called on each DOM |
+ * mutation, taking a <code>MutationRecord</code> as its parameter. |
+ */ |
+function observe(target, options, callback) |
+{ |
+ new MutationObserver(mutations => |
+ { |
+ for (let mutation of mutations) |
+ callback(mutation); |
+ }) |
+ .observe(target, options); |
+} |
+ |
+/** |
* Logs its arguments to the console. This may be used for testing and |
* debugging. |
* |
* @param {...*} [args] The arguments to log. |
*/ |
function log(...args) |
{ |
console.log(...args); |
@@ -222,8 +241,71 @@ |
return root; |
} |
}); |
} |
exports["hide-if-shadow-contains"] = makeInjector(hideIfShadowContains, |
hideElement); |
+ |
+/** |
+ * Untrashes a document by readding removed elements that match a CSS selector. |
+ * |
+ * @param {string} selector The CSS selector that a removed element should |
+ * match for it to be added back. |
+ * @param {string?} [parentSelector] The CSS selector that a removed element's |
+ * former parent should match for it to be added back. |
+ * @param {string?} [ifContains] The string that should be found in the text |
+ * content of the removed element for it to be added back. |
+ * @param {string?} [unlessContains] The string that should not be found in the |
+ * text content of the removed element for it to be added back. |
+ */ |
+function untrash(selector, parentSelector = null, ifContains = null, |
+ unlessContains = null) |
+{ |
+ observe(document, {childList: true, subtree: true}, mutation => |
+ { |
+ if (mutation.removedNodes && |
+ (!parentSelector || (mutation.target instanceof Element && |
+ mutation.target.matches(parentSelector)))) |
+ { |
+ for (let node of mutation.removedNodes) |
+ { |
+ if (node instanceof HTMLElement && node.matches(selector) && |
+ (!ifContains || node.textContent.includes(ifContains)) && |
+ (!unlessContains || !node.textContent.includes(unlessContains))) |
+ { |
+ // We don't have the location of the element in its former parent, |
+ // but it's usually OK to just add it at the end. |
+ mutation.target.appendChild(node); |
+ } |
+ } |
+ } |
+ }); |
+} |
+ |
+exports.untrash = untrash; |
+ |
+/** |
+ * Removes any HTML element from the document if the element's text content |
+ * contains a given string. |
+ * |
+ * @param {string} search The string to look for in every HTML element. |
+ * @param {string} [selector] The CSS selector that an HTML element must match |
+ * for it to be removed from the document. |
+ */ |
+function removeIfContains(search, selector = "*") |
+{ |
+ observe(document, {childList: true, subtree: true}, mutation => |
+ { |
+ for (let node of mutation.addedNodes || []) |
+ { |
+ if (node instanceof HTMLElement && node.matches(selector) && |
+ node.textContent.includes(search)) |
+ { |
+ mutation.target.removeChild(node); |
+ } |
+ } |
+ }); |
+} |
+ |
+exports["remove-if-contains"] = removeIfContains; |