Gildas 7 лет назад
Родитель
Сommit
34a0f33ea1
1 измененных файлов с 75 добавлено и 88 удалено
  1. 75 88
      lib/single-file/single-file-core.js

+ 75 - 88
lib/single-file/single-file-core.js

@@ -317,7 +317,10 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 	// ---------
 	// Processor
 	// ---------
-	const EMPTY_DATA_URI = "data:base64,";
+	const PREFIX_DATA_URI_IMAGE = "data:image/";
+	const PREFIX_DATA_URI_AUDIO = "data:audio/";
+	const PREFIX_DATA_URI_VIDEO = "data:video/";
+	const PREFIX_DATA_URI_IMAGE_SVG = "data:image/svg+xml";
 	const EMPTY_IMAGE = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
 	const SCRIPT_TAG_FOUND = /<script/gi;
 	const NOSCRIPT_TAG_FOUND = /<noscript/gi;
@@ -522,7 +525,34 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 		}
 
 		removeUnselectedElements() {
-			ProcessorHelper.removeUnselectedElements(this.doc);
+			removeUnmarkedElements(this.doc.body);
+			this.doc.body.removeAttribute(SELECTED_CONTENT_ATTRIBUTE_NAME);
+
+			function removeUnmarkedElements(element) {
+				let selectedElementFound = false;
+				Array.from(element.childNodes).forEach(node => {
+					if (node.nodeType == 1) {
+						const isSelectedElement = node.getAttribute(SELECTED_CONTENT_ATTRIBUTE_NAME) == "";
+						selectedElementFound = selectedElementFound || isSelectedElement;
+						if (isSelectedElement) {
+							node.removeAttribute(SELECTED_CONTENT_ATTRIBUTE_NAME);
+							removeUnmarkedElements(node);
+						} else if (selectedElementFound) {
+							removeNode(node);
+						} else {
+							node.style.setProperty("display", "none", "important");
+							Array.from(node.childNodes).forEach(removeNode);
+						}
+					}
+				});
+			}
+
+			function removeNode(node) {
+				const tagName = node.tagName && node.tagName.toLowerCase();
+				if (tagName != "svg" && tagName != "style" && tagName != "link") {
+					node.remove();
+				}
+			}
 		}
 
 		insertVideoPosters() {
@@ -794,7 +824,12 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 			if (!this.options.saveRawPage && this.options.framesData) {
 				const frameElements = Array.from(this.doc.querySelectorAll("iframe, frame, object[type=\"text/html\"][data]"));
 				await Promise.all(frameElements.map(async frameElement => {
-					ProcessorHelper.setFrameEmptySrc(frameElement);
+					if (frameElement.tagName == "OBJECT") {
+						frameElement.setAttribute("data", "data:text/html,");
+					} else {
+						frameElement.removeAttribute("src");
+						frameElement.removeAttribute("srcdoc");
+					}
 					const frameWindowId = frameElement.getAttribute(docUtil.WIN_ID_ATTRIBUTE_NAME);
 					if (frameWindowId) {
 						const frameData = this.options.framesData.find(frame => frame.windowId == frameWindowId);
@@ -954,7 +989,16 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 								} else {
 									frameElement.setAttribute("sandbox", "");
 								}
-								ProcessorHelper.setFrameContent(frameElement, pageData.content);
+								if (frameElement.tagName == "OBJECT") {
+									frameElement.setAttribute("data", "data:text/html," + pageData.content);
+								} else {
+									if (frameElement.tagName == "FRAME") {
+										frameElement.setAttribute("src", "data:text/html," + pageData.content.replace(/#/g, "%23"));
+									} else {
+										frameElement.setAttribute("srcdoc", pageData.content);
+										frameElement.removeAttribute("src");
+									}
+								}
 								this.stats.addAll(pageData);
 							} else {
 								this.stats.add("discarded", "frames", 1);
@@ -1057,15 +1101,14 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 	// ---------------
 	// ProcessorHelper
 	// ---------------
+	const DATA_URI_PREFIX = "data:";
+	const ABOUT_BLANK_URI = "about:blank";
+	const EMPTY_DATA_URI = "data:base64,";
 	const REGEXP_AMP = /&/g;
 	const REGEXP_NBSP = /\u00a0/g;
 	const REGEXP_START_TAG = /</g;
 	const REGEXP_END_TAG = />/g;
 	const REGEXP_URL_HASH = /(#.+?)$/;
-	const PREFIX_DATA_URI_IMAGE = "data:image/";
-	const PREFIX_DATA_URI_AUDIO = "data:audio/";
-	const PREFIX_DATA_URI_VIDEO = "data:video/";
-	const PREFIX_DATA_URI_IMAGE_SVG = "data:image/svg+xml";
 	const PREFIX_DATA_URI_NO_MIMETYPE = "data:;";
 	const PREFIX_DATA_URI_OCTET_STREAM = /^data:(application|binary)\/octet-stream/;
 	const PREFIX_DATA_URI_NULL_STREAM = /^data:null;/;
@@ -1155,59 +1198,6 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 			}
 		}
 
-		static setFrameEmptySrc(frameElement) {
-			if (frameElement.tagName == "OBJECT") {
-				frameElement.setAttribute("data", "data:text/html,");
-			} else {
-				frameElement.removeAttribute("src");
-				frameElement.removeAttribute("srcdoc");
-			}
-		}
-
-		static setFrameContent(frameElement, content) {
-			if (frameElement.tagName == "OBJECT") {
-				frameElement.setAttribute("data", "data:text/html," + content);
-			} else {
-				if (frameElement.tagName == "FRAME") {
-					frameElement.setAttribute("src", "data:text/html," + content.replace(/#/g, "%23"));
-				} else {
-					frameElement.setAttribute("srcdoc", content);
-					frameElement.removeAttribute("src");
-				}
-			}
-		}
-
-		static removeUnselectedElements(doc) {
-			removeUnmarkedElements(doc.body);
-			doc.body.removeAttribute(SELECTED_CONTENT_ATTRIBUTE_NAME);
-
-			function removeUnmarkedElements(element) {
-				let selectedElementFound = false;
-				Array.from(element.childNodes).forEach(node => {
-					if (node.nodeType == 1) {
-						const isSelectedElement = node.getAttribute(SELECTED_CONTENT_ATTRIBUTE_NAME) == "";
-						selectedElementFound = selectedElementFound || isSelectedElement;
-						if (isSelectedElement) {
-							node.removeAttribute(SELECTED_CONTENT_ATTRIBUTE_NAME);
-							removeUnmarkedElements(node);
-						} else if (selectedElementFound) {
-							removeNode(node);
-						} else {
-							node.style.setProperty("display", "none", "important");
-							Array.from(node.childNodes).forEach(removeNode);
-						}
-					}
-				});
-			}
-
-			function removeNode(node) {
-				const tagName = node.tagName && node.tagName.toLowerCase();
-				if (tagName != "svg" && tagName != "style" && tagName != "link") {
-					node.remove();
-				}
-			}
-		}
-
 		static removeSingleLineCssComments(stylesheet) {
 			const removedRules = [];
 			for (let cssRule = stylesheet.children.head; cssRule; cssRule = cssRule.next) {
@@ -1430,7 +1420,7 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 								if (content.startsWith(prefixDataURI) || content.startsWith(PREFIX_DATA_URI_NO_MIMETYPE) || content.match(PREFIX_DATA_URI_OCTET_STREAM) || content.match(PREFIX_DATA_URI_NULL_STREAM)) {
 									const isSVG = content.startsWith(PREFIX_DATA_URI_IMAGE_SVG);
 									if (processDuplicates && duplicate && options.groupDuplicateImages && !isSVG) {
-										if (Util.replaceImageSource(resourceElement, SINGLE_FILE_VARIABLE_NAME_PREFIX + indexResource, options)) {
+										if (ProcessorHelper.replaceImageSource(resourceElement, SINGLE_FILE_VARIABLE_NAME_PREFIX + indexResource, options)) {
 											cssVariables.set(indexResource, content);
 											const declarationList = cssTree.parse(resourceElement.getAttribute("style"), { context: "declarationList" });
 											styles.set(resourceElement, declarationList);
@@ -1516,17 +1506,38 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 			}));
 		}
 
+		static replaceImageSource(imgElement, variableName, options) {
+			const dataAttributeName = docUtil.IMAGE_ATTRIBUTE_NAME;
+			if (imgElement.getAttribute(dataAttributeName) != null) {
+				const imgData = options.imageData[Number(imgElement.getAttribute(dataAttributeName))];
+				if (imgData.replaceable) {
+					imgElement.setAttribute("src", `${PREFIX_DATA_URI_IMAGE_SVG},<svg xmlns="http://www.w3.org/2000/svg" width="${imgData.size.pxWidth}" height="${imgData.size.pxHeight}"><rect fill-opacity="0"/></svg>`);
+					const backgroundStyle = {};
+					const backgroundSize = (imgData.objectFit == "content" || imgData.objectFit == "cover") && imgData.objectFit;
+					if (backgroundSize) {
+						backgroundStyle["background-size"] = imgData.objectFit;
+					}
+					if (imgData.objectPosition) {
+						backgroundStyle["background-position"] = imgData.objectPosition;
+					}
+					if (imgData.backgroundColor) {
+						backgroundStyle["background-color"] = imgData.backgroundColor;
+					}
+					ProcessorHelper.setBackgroundImage(imgElement, "var(" + variableName + ")", backgroundStyle);
+					imgElement.removeAttribute(dataAttributeName);
+					return true;
+				}
+			}
+		}
 	}
 
 	// ----
 	// Util
 	// ----
-	const DATA_URI_PREFIX = "data:";
 	const BLOB_URI_PREFIX = "blob:";
 	const HTTP_URI_PREFIX = /^https?:\/\//;
 	const FILE_URI_PREFIX = /^file:\/\//;
 	const EMPTY_URL = /^https?:\/\/+\s*$/;
-	const ABOUT_BLANK_URI = "about:blank";
 	const NOT_EMPTY_URL = /^(https?:\/\/|file:\/\/|blob:).+/;
 	const REGEXP_URL_FN = /(url\s*\(\s*'(.*?)'\s*\))|(url\s*\(\s*"(.*?)"\s*\))|(url\s*\(\s*(.*?)\s*\))/gi;
 	const REGEXP_URL_SIMPLE_QUOTES_FN = /^url\s*\(\s*'(.*?)'\s*\)$/i;
@@ -1673,30 +1684,6 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 				return stylesheetContent;
 			}
 		}
-
-		static replaceImageSource(imgElement, variableName, options) {
-			const dataAttributeName = docUtil.IMAGE_ATTRIBUTE_NAME;
-			if (imgElement.getAttribute(dataAttributeName) != null) {
-				const imgData = options.imageData[Number(imgElement.getAttribute(dataAttributeName))];
-				if (imgData.replaceable) {
-					imgElement.setAttribute("src", `${PREFIX_DATA_URI_IMAGE_SVG},<svg xmlns="http://www.w3.org/2000/svg" width="${imgData.size.pxWidth}" height="${imgData.size.pxHeight}"><rect fill-opacity="0"/></svg>`);
-					const backgroundStyle = {};
-					const backgroundSize = (imgData.objectFit == "content" || imgData.objectFit == "cover") && imgData.objectFit;
-					if (backgroundSize) {
-						backgroundStyle["background-size"] = imgData.objectFit;
-					}
-					if (imgData.objectPosition) {
-						backgroundStyle["background-position"] = imgData.objectPosition;
-					}
-					if (imgData.backgroundColor) {
-						backgroundStyle["background-color"] = imgData.backgroundColor;
-					}
-					ProcessorHelper.setBackgroundImage(imgElement, "var(" + variableName + ")", backgroundStyle);
-					imgElement.removeAttribute(dataAttributeName);
-					return true;
-				}
-			}
-		}
 	}
 
 	function log(...args) {