|
|
@@ -18,15 +18,13 @@
|
|
|
* along with SingleFile. If not, see <http://www.gnu.org/licenses/>.
|
|
|
*/
|
|
|
|
|
|
-/* global browser, window, top, document, HTMLHtmlElement, addEventListener */
|
|
|
+/* global browser, window, top, document, HTMLHtmlElement, addEventListener, common */
|
|
|
|
|
|
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 };
|
|
|
|
|
|
@@ -46,7 +44,7 @@ this.FrameTree = this.FrameTree || (() => {
|
|
|
}
|
|
|
browser.runtime.onMessage.addListener(message => {
|
|
|
if (message.method == "FrameTree.getDataRequest" && FrameTree.windowId == message.windowId) {
|
|
|
- preProcessDoc(document, window, message.options);
|
|
|
+ common.preProcessDoc(document, window, message.options);
|
|
|
browser.runtime.sendMessage({
|
|
|
method: "FrameTree.getDataResponse",
|
|
|
windowId: message.windowId,
|
|
|
@@ -57,7 +55,7 @@ this.FrameTree = this.FrameTree || (() => {
|
|
|
baseURI: document.baseURI,
|
|
|
title: document.title
|
|
|
}).catch(() => {/* ignored */ });
|
|
|
- postProcessDoc(document, message.options);
|
|
|
+ common.postProcessDoc(document, message.options);
|
|
|
}
|
|
|
});
|
|
|
addEventListener("message", event => {
|
|
|
@@ -165,12 +163,12 @@ this.FrameTree = this.FrameTree || (() => {
|
|
|
const message = JSON.parse(event.data.substring(MESSAGE_PREFIX.length + 2));
|
|
|
if (message.method == "getDataRequest" && message.windowId == frameWinId) {
|
|
|
topWindow.removeEventListener("message", onMessage, false);
|
|
|
- preProcessDoc(frameDoc, frameWindow, message.options);
|
|
|
+ common.preProcessDoc(frameDoc, frameWindow, message.options);
|
|
|
const content = getDoctype(frameDoc) + frameDoc.documentElement.outerHTML;
|
|
|
const emptyStyleRulesText = getEmptyStyleRulesText(frameDoc);
|
|
|
const canvasData = getCanvasData(frameDoc);
|
|
|
top.postMessage(MESSAGE_PREFIX + "::" + JSON.stringify({ method: "getDataResponse", windowId: message.windowId, content, baseURI: frameDoc.baseURI, title: document.title, emptyStyleRulesText, canvasData }), "*");
|
|
|
- postProcessDoc(frameDoc, frameWindow, message.options);
|
|
|
+ common.postProcessDoc(frameDoc, frameWindow, message.options);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -236,46 +234,4 @@ this.FrameTree = this.FrameTree || (() => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- function preProcessDoc(doc, win, options) {
|
|
|
- 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);
|
|
|
- if (options.removeHiddenElements) {
|
|
|
- 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, "");
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- if (options.compressHTML) {
|
|
|
- doc.querySelectorAll("*").forEach(element => {
|
|
|
- const style = win.getComputedStyle(element);
|
|
|
- if (style.whiteSpace.startsWith("pre")) {
|
|
|
- element.setAttribute(PRESERVED_SPACE_ELEMENT_ATTRIBUTE_NAME, "");
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- function postProcessDoc(doc, options) {
|
|
|
- doc.head.querySelectorAll("disabled-noscript").forEach(element => {
|
|
|
- const noscriptElement = 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"));
|
|
|
- if (options.removeHiddenElements) {
|
|
|
- doc.querySelectorAll("[" + REMOVED_CONTENT_ATTRIBUTE_NAME + "]").forEach(element => element.removeAttribute(REMOVED_CONTENT_ATTRIBUTE_NAME));
|
|
|
- }
|
|
|
- if (options.compressHTML) {
|
|
|
- doc.querySelectorAll("[" + PRESERVED_SPACE_ELEMENT_ATTRIBUTE_NAME + "]").forEach(element => element.removeAttribute(PRESERVED_SPACE_ELEMENT_ATTRIBUTE_NAME));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
})();
|