|
|
@@ -25,6 +25,8 @@ this.FrameTree = this.FrameTree || (() => {
|
|
|
const MESSAGE_PREFIX = "__FrameTree__";
|
|
|
const TIMEOUT_INIT_REQUEST_MESSAGE = 1000;
|
|
|
const TIMEOUT_DATA_RESPONSE_MESSAGE = 1000;
|
|
|
+ const REMOVED_CONTENT_ATTRIBUTE_NAME = "data-single-file-removed-content";
|
|
|
+ const PRESERVED_SPACE_ELEMENT_ATTRIBUTE_NAME = "data-single-file-preserved-space-element";
|
|
|
|
|
|
const FrameTree = { getFramesData };
|
|
|
|
|
|
@@ -44,6 +46,7 @@ this.FrameTree = this.FrameTree || (() => {
|
|
|
}
|
|
|
browser.runtime.onMessage.addListener(message => {
|
|
|
if (message.method == "FrameTree.getDataRequest" && FrameTree.windowId == message.windowId) {
|
|
|
+ preProcessDoc(document, window);
|
|
|
browser.runtime.sendMessage({
|
|
|
method: "FrameTree.getDataResponse",
|
|
|
windowId: message.windowId,
|
|
|
@@ -54,6 +57,7 @@ this.FrameTree = this.FrameTree || (() => {
|
|
|
baseURI: document.baseURI,
|
|
|
title: document.title
|
|
|
}).catch(() => {/* ignored */ });
|
|
|
+ postProcessDoc(document);
|
|
|
}
|
|
|
});
|
|
|
addEventListener("message", event => {
|
|
|
@@ -229,4 +233,38 @@ this.FrameTree = this.FrameTree || (() => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ function preProcessDoc(doc, win) {
|
|
|
+ doc.querySelectorAll("script").forEach(element => element.textContent = element.textContent.replace(/<\/script>/gi, "<\\/script>"));
|
|
|
+ doc.head.querySelectorAll("noscript").forEach(element => {
|
|
|
+ const disabledNoscriptElement = doc.createElement("disabled-noscript");
|
|
|
+ Array.from(element.childNodes).forEach(node => disabledNoscriptElement.appendChild(node));
|
|
|
+ disabledNoscriptElement.hidden = true;
|
|
|
+ element.parentElement.replaceChild(disabledNoscriptElement, element);
|
|
|
+ });
|
|
|
+ doc.head.querySelectorAll("*:not(base):not(link):not(meta):not(noscript):not(script):not(style):not(template):not(title)").forEach(element => element.hidden = true);
|
|
|
+ doc.querySelectorAll("html > body *:not(style):not(script):not(link):not(frame):not(iframe):not(object)").forEach(element => {
|
|
|
+ const style = win.getComputedStyle(element);
|
|
|
+ if (element instanceof win.HTMLElement && (element.hidden || style.display == "none" || ((style.opacity === 0 || style.visibility == "hidden") && !element.clientWidth && !element.clientHeight)) && !element.querySelector("iframe, frame, object[type=\"text/html\"][data]")) {
|
|
|
+ element.setAttribute(REMOVED_CONTENT_ATTRIBUTE_NAME, "");
|
|
|
+ }
|
|
|
+ });
|
|
|
+ doc.querySelectorAll("*").forEach(element => {
|
|
|
+ const style = win.getComputedStyle(element);
|
|
|
+ if (style.whiteSpace.startsWith("pre")) {
|
|
|
+ element.setAttribute(PRESERVED_SPACE_ELEMENT_ATTRIBUTE_NAME, "");
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ function postProcessDoc(doc) {
|
|
|
+ doc.head.querySelectorAll("disabled-noscript").forEach(element => {
|
|
|
+ const noscriptElement = this.options.doc.createElement("noscript");
|
|
|
+ Array.from(element.childNodes).forEach(node => noscriptElement.appendChild(node));
|
|
|
+ element.parentElement.replaceChild(noscriptElement, element);
|
|
|
+ });
|
|
|
+ doc.head.querySelectorAll("*:not(base):not(link):not(meta):not(noscript):not(script):not(style):not(template):not(title)").forEach(element => element.removeAttribute("hidden"));
|
|
|
+ doc.querySelectorAll("[" + REMOVED_CONTENT_ATTRIBUTE_NAME + "]").forEach(element => element.removeAttribute(REMOVED_CONTENT_ATTRIBUTE_NAME));
|
|
|
+ doc.querySelectorAll("[" + PRESERVED_SPACE_ELEMENT_ATTRIBUTE_NAME + "]").forEach(element => element.removeAttribute(PRESERVED_SPACE_ELEMENT_ATTRIBUTE_NAME));
|
|
|
+ }
|
|
|
+
|
|
|
})();
|