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

+ 135 - 145
lib/single-file/single-file-core.js

@@ -68,58 +68,6 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 	// -------------
 	// PageProcessor
 	// -------------
-	const STAGES = [{
-		sync: [
-			{ action: "removeUIElements" },
-			{ action: "replaceStyleContents" },
-			{ option: "removeFrames", action: "removeFrames" },
-			{ option: "removeImports", action: "removeImports" },
-			{ option: "removeScripts", action: "removeScripts" },
-			{ action: "removeDiscardedResources" },
-			{ action: "resetCharsetMeta" },
-			{ option: "compressHTML", action: "compressHTML" },
-			{ action: "insertFaviconLink" },
-			{ action: "resolveHrefs" },
-			{ action: "replaceCanvasElements" },
-			{ option: "removeHiddenElements", action: "removeHiddenElements" }
-		],
-		async: [
-			{ action: "inlineStylesheets" },
-			{ action: "linkStylesheets" },
-			{ action: "attributeStyles" },
-			{ option: "!removeFrames", action: "frames" },
-			{ option: "!removeImports", action: "htmlImports" }
-		]
-	}, {
-		sync: [
-			{ option: "removeUnusedStyles", action: "removeUnusedStyles" },
-			{ option: "compressHTML", action: "compressHTML" },
-			{ option: "removeAlternativeFonts", action: "removeAlternativeFonts" },
-			{ option: "compressCSS", action: "compressCSS" },
-		],
-		async: [
-			{ action: "inlineStylesheets" },
-			{ action: "attributeStyles" },
-			{ action: "pageResources" },
-			{ option: "!removeScripts", action: "scripts" }
-		]
-	}, {
-		sync: [
-			{ option: "lazyLoadImages", action: "lazyLoadImages" },
-			{ option: "removeAlternativeFonts", action: "postRemoveAlternativeFonts" }
-		],
-		async: [
-			{ option: "!removeFrames", action: "frames" },
-			{ option: "!removeImports", action: "htmlImports" },
-		]
-	}, {
-		sync: [
-			{ option: "compressHTML", action: "postCompressHTML" },
-			{ option: "insertSingleFileComment", action: "insertSingleFileComment" },
-			{ action: "removeDefaultHeadTags" }
-		]
-	}];
-
 	class PageProcessor {
 		constructor(options) {
 			this.options = options;
@@ -142,8 +90,54 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 
 		async initialize() {
 			this.onprogress(new ProgressEvent(RESOURCES_INITIALIZING, { pageURL: this.options.url }));
-			await this.executeStage(0);
-			this.pendingPromises = this.executeStage(1);
+			this.processor.removeUIElements();
+			this.processor.replaceStyleContents();
+			if (this.options.removeFrames) {
+				this.processor.removeFrames();
+			}
+			if (this.options.removeImports) {
+				this.processor.removeImports();
+			}
+			if (this.options.removeScripts) {
+				this.processor.removeScripts();
+			}
+			this.processor.removeDiscardedResources();
+			this.processor.resetCharsetMeta();
+			if (this.options.compressHTML) {
+				this.processor.compressHTML();
+			}
+			if (this.options.insertFaviconLink) {
+				this.processor.insertFaviconLink();
+			}
+			this.processor.resolveHrefs();
+			this.processor.replaceCanvasElements();
+			if (this.options.removeHiddenElements) {
+				this.processor.removeHiddenElements(this.options.sessionId);
+			}
+			const initializationPromises = [this.processor.inlineStylesheets(true), this.processor.linkStylesheets(), this.processor.attributeStyles(true)];
+			if (!this.options.removeFrames && this.options.framesData) {
+				initializationPromises.push(this.processor.frames(true));
+			}
+			await Promise.all(initializationPromises);
+			if (this.options.removeUnusedStyles) {
+				this.processor.removeUnusedStyles();
+			}
+			if (!this.options.removeImports) {
+				initializationPromises.push(this.processor.htmlImports(true));
+			}
+			if (this.options.compressHTML) {
+				this.processor.compressHTML();
+			}
+			if (this.options.removeAlternativeFonts) {
+				this.processor.removeAlternativeFonts();
+			}
+			if (this.options.compressCSS) {
+				this.processor.compressCSS();
+			}
+			this.pendingPromises = [this.processor.inlineStylesheets(), this.processor.attributeStyles(), this.processor.pageResources()];
+			if (!this.options.removeScripts) {
+				this.pendingPromises.push(this.processor.scripts());
+			}
 			if (this.options.doc) {
 				DOM.postProcessDoc(this.options.doc, this.options);
 				this.options.doc = null;
@@ -153,35 +147,40 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 		}
 
 		async preparePageData() {
-			if (!this.options.windowId) {
-				this.processor.retrieveResources(
-					details => {
-						details.pageURL = this.options.url;
-						this.onprogress(new ProgressEvent(RESOURCE_LOADED, details));
-					});
-			}
+			await this.processor.retrieveResources(
+				details => {
+					details.pageURL = this.options.url;
+					this.onprogress(new ProgressEvent(RESOURCE_LOADED, details));
+				});
 			await this.pendingPromises;
-			await this.executeStage(2);
-			await this.executeStage(3);
+			if (this.options.lazyLoadImages) {
+				this.processor.lazyLoadImages();
+			}
+			if (this.options.removeAlternativeFonts) {
+				this.processor.removeAlternativeFonts(true);
+				if (this.options.compressCSS) {
+					this.processor.compressCSS();
+				}
+			}
+			if (!this.options.removeFrames && this.options.framesData) {
+				await this.processor.frames();
+			}
+			if (!this.options.removeImports) {
+				await this.processor.htmlImports();
+			}
+			if (this.options.compressHTML) {
+				this.processor.compressHTML(true);
+			}
+			if (this.options.insertSingleFileComment) {
+				this.processor.insertSingleFileCommentNode();
+			}
+			this.processor.removeDefaultHeadTags();
 		}
 
 		getPageData() {
 			this.onprogress(new ProgressEvent(PAGE_ENDED, { pageURL: this.options.url }));
 			return this.processor.getPageData();
 		}
-
-		async executeStage(step) {
-			STAGES[step].sync.forEach(task => this.executeTask(task, !step));
-			if (STAGES[step].async) {
-				return Promise.all(STAGES[step].async.map(task => this.executeTask(task, !step)));
-			}
-		}
-
-		executeTask(task, initialization) {
-			if (!task.option || ((task.option.startsWith("!") && !this.options[task.option]) || this.options[task.option])) {
-				return this.processor[task.action](initialization);
-			}
-		}
 	}
 
 	// --------
@@ -389,42 +388,35 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 			this.stats.set("discarded", "cssRules", stats.discarded);
 		}
 
-		removeAlternativeFonts() {
-			DOM.minifyFonts(this.doc);
-		}
-
-		postRemoveAlternativeFonts() {
-			DOM.minifyFonts(this.doc, true);
-			if (this.options.compressCSS) {
-				this.compressCSS();
-			}
+		removeAlternativeFonts(secondPass) {
+			DOM.minifyFonts(this.doc, secondPass);
 		}
 
-		removeHiddenElements() {
-			const hiddenElements = this.doc.querySelectorAll("[" + DOM.removedContentAttributeName(this.options.sessionId) + "]");
+		removeHiddenElements(sessionId) {
+			const hiddenElements = this.doc.querySelectorAll("[" + DOM.removedContentAttributeName(sessionId) + "]");
 			this.stats.set("discarded", "hiddenElements", hiddenElements.length);
 			hiddenElements.forEach(element => element.remove());
 		}
 
-		compressHTML() {
-			let size;
-			if (this.options.displayStats) {
-				size = DOM.getContentSize(this.doc.documentElement.outerHTML);
-			}
-			DOM.minifyHTML(this.doc, { preservedSpaceAttributeName: DOM.preservedSpaceAttributeName(this.options.sessionId) });
-			if (this.options.displayStats) {
-				this.stats.add("discarded", "htmlBytes", size - DOM.getContentSize(this.doc.documentElement.outerHTML));
-			}
-		}
-
-		postCompressHTML() {
-			let size;
-			if (this.options.displayStats) {
-				size = DOM.getContentSize(this.doc.documentElement.outerHTML);
-			}
-			DOM.postMinifyHTML(this.doc);
-			if (this.options.displayStats) {
-				this.stats.add("discarded", "htmlBytes", size - DOM.getContentSize(this.doc.documentElement.outerHTML));
+		compressHTML(postProcess) {
+			if (postProcess) {
+				let size;
+				if (this.options.displayStats) {
+					size = DOM.getContentSize(this.doc.documentElement.outerHTML);
+				}
+				DOM.postMinifyHTML(this.doc);
+				if (this.options.displayStats) {
+					this.stats.add("discarded", "htmlBytes", size - DOM.getContentSize(this.doc.documentElement.outerHTML));
+				}
+			} else {
+				let size;
+				if (this.options.displayStats) {
+					size = DOM.getContentSize(this.doc.documentElement.outerHTML);
+				}
+				DOM.minifyHTML(this.doc, { preservedSpaceAttributeName: DOM.preservedSpaceAttributeName(this.options.sessionId) });
+				if (this.options.displayStats) {
+					this.stats.add("discarded", "htmlBytes", size - DOM.getContentSize(this.doc.documentElement.outerHTML));
+				}
 			}
 		}
 
@@ -439,7 +431,7 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 			});
 		}
 
-		insertSingleFileComment() {
+		insertSingleFileCommentNode() {
 			const commentNode = this.doc.createComment("\n Archive processed by SingleFile \n url: " + this.baseURI + " \n saved date: " + new Date() + " \n");
 			this.doc.documentElement.insertBefore(commentNode, this.doc.documentElement.firstChild);
 		}
@@ -530,48 +522,46 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 		}
 
 		async frames(initialization) {
-			if (this.options.framesData) {
-				const frameElements = Array.from(this.doc.querySelectorAll("iframe, frame, object[type=\"text/html\"][data]"));
-				await Promise.all(frameElements.map(async frameElement => {
-					DomProcessorHelper.setFrameEmptySrc(frameElement);
-					frameElement.setAttribute("sandbox", "");
-					const frameWindowId = frameElement.getAttribute(DOM.windowIdAttributeName(this.options.sessionId));
-					if (frameWindowId) {
-						const frameData = this.options.framesData.find(frame => frame.windowId == frameWindowId);
-						if (frameData) {
-							if (initialization) {
-								const options = Object.create(this.options);
-								options.insertSingleFileComment = false;
-								options.insertFaviconLink = false;
-								options.doc = null;
-								options.win = null;
-								options.url = frameData.baseURI;
-								options.windowId = frameWindowId;
-								if (frameData.content) {
-									options.content = frameData.content;
-									options.canvasData = frameData.canvasData;
-									options.stylesheetContents = frameData.stylesheetContents;
-									frameData.processor = new PageProcessor(options);
-									frameData.frameElement = frameElement;
-									await frameData.processor.loadPage();
-									return frameData.processor.initialize();
-								}
+			const frameElements = Array.from(this.doc.querySelectorAll("iframe, frame, object[type=\"text/html\"][data]"));
+			await Promise.all(frameElements.map(async frameElement => {
+				DomProcessorHelper.setFrameEmptySrc(frameElement);
+				frameElement.setAttribute("sandbox", "");
+				const frameWindowId = frameElement.getAttribute(DOM.windowIdAttributeName(this.options.sessionId));
+				if (frameWindowId) {
+					const frameData = this.options.framesData.find(frame => frame.windowId == frameWindowId);
+					if (frameData) {
+						if (initialization) {
+							const options = Object.create(this.options);
+							options.insertSingleFileComment = false;
+							options.insertFaviconLink = false;
+							options.doc = null;
+							options.win = null;
+							options.url = frameData.baseURI;
+							options.windowId = frameWindowId;
+							if (frameData.content) {
+								options.content = frameData.content;
+								options.canvasData = frameData.canvasData;
+								options.stylesheetContents = frameData.stylesheetContents;
+								frameData.processor = new PageProcessor(options);
+								frameData.frameElement = frameElement;
+								await frameData.processor.loadPage();
+								return frameData.processor.initialize();
+							}
+						} else {
+							if (frameData.processor) {
+								this.stats.add("processed", "frames", 1);
+								await frameData.processor.preparePageData();
+								const pageData = await frameData.processor.getPageData();
+								frameElement.removeAttribute(DOM.windowIdAttributeName(this.options.sessionId));
+								DomProcessorHelper.setFrameContent(frameElement, pageData.content);
+								this.stats.addAll(pageData);
 							} else {
-								if (frameData.processor) {
-									this.stats.add("processed", "frames", 1);
-									await frameData.processor.preparePageData();
-									const pageData = await frameData.processor.getPageData();
-									frameElement.removeAttribute(DOM.windowIdAttributeName(this.options.sessionId));
-									DomProcessorHelper.setFrameContent(frameElement, pageData.content);
-									this.stats.addAll(pageData);
-								} else {
-									this.stats.add("discarded", "frames", 1);
-								}
+								this.stats.add("discarded", "frames", 1);
 							}
 						}
 					}
-				}));
-			}
+				}
+			}));
 		}
 
 		async htmlImports(initialization) {