Kaynağa Gözat

added pre and post frame processing

Gildas 7 yıl önce
ebeveyn
işleme
c6ff756cb3
1 değiştirilmiş dosya ile 38 ekleme ve 0 silme
  1. 38 0
      lib/frame-tree/content/frame-tree.js

+ 38 - 0
lib/frame-tree/content/frame-tree.js

@@ -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));
+	}
+
 })();