فهرست منبع

made stats collecting less intrusive

Gildas 7 سال پیش
والد
کامیت
3751c25961
1فایلهای تغییر یافته به همراه78 افزوده شده و 82 حذف شده
  1. 78 82
      lib/single-file/single-file-core.js

+ 78 - 82
lib/single-file/single-file-core.js

@@ -220,38 +220,13 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 	// ------------
 	const ESCAPED_FRAGMENT = "_escaped_fragment_=";
 	const EMPTY_DATA_URI = "data:base64,";
-	const STATS_DEFAULT_VALUES = {
-		discarded: {
-			htmlBytes: 0,
-			hiddenElements: 0,
-			imports: 0,
-			scripts: 0,
-			objects: 0,
-			audioSource: 0,
-			videoSource: 0,
-			frames: 0,
-			cssRules: 0
-		},
-		processed: {
-			htmlBytes: 0,
-			imports: 0,
-			scripts: 0,
-			frames: 0,
-			cssRules: 0,
-			canvas: 0,
-			styleSheets: 0,
-			resources: 0
-		}
-	};
 
 	const batchRequest = new BatchRequest();
 
 	class DOMProcessor {
 		constructor(options) {
 			this.options = options;
-			if (this.options.displayStats) {
-				this.stats = JSON.parse(JSON.stringify(STATS_DEFAULT_VALUES));
-			}
+			this.stats = new Stats(options);
 			this.baseURI = options.url;
 		}
 
@@ -276,9 +251,7 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 		}
 
 		async retrieveResources(onloadListener) {
-			if (this.options.displayStats) {
-				this.stats.processed.resources = batchRequest.getMaxResources();
-			}
+			this.stats.set("processed", "resources", batchRequest.getMaxResources());
 			await batchRequest.run(onloadListener, this.options);
 		}
 
@@ -305,11 +278,12 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 			}
 			const content = DOM.serialize(this.doc, this.options.compressHTML);
 			if (this.options.displayStats) {
-				this.stats.processed.htmlBytes = DOM.getContentSize(content);
-				this.stats.discarded.htmlBytes += size - this.stats.processed.htmlBytes;
+				const contentSize = DOM.getContentSize(content);
+				this.stats.set("processed", "htmlBytes", contentSize);
+				this.stats.add("discarded", "htmlBytes", size - contentSize);
 			}
 			return {
-				stats: this.stats,
+				stats: this.stats.data,
 				title: title || (this.baseURI && matchTitle ? matchTitle[1] : (url.hostname ? url.hostname : "Untitled page")),
 				content
 			};
@@ -338,24 +312,18 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 
 		removeDiscardedResources() {
 			const objectElements = this.doc.querySelectorAll("applet, meta[http-equiv=refresh], object:not([type=\"image/svg+xml\"]):not([type=\"image/svg-xml\"]):not([type=\"text/html\"]), embed:not([src*=\".svg\"]), link[rel*=preload], link[rel*=prefetch]");
-			if (this.options.displayStats) {
-				this.stats.discarded.objects = objectElements.length;
-			}
+			this.stats.set("discarded", "objects", objectElements.length);
 			objectElements.forEach(element => element.remove());
 			this.doc.querySelectorAll("[onload]").forEach(element => element.removeAttribute("onload"));
 			this.doc.querySelectorAll("[onerror]").forEach(element => element.removeAttribute("onerror"));
 			if (this.options.removeAudioSrc) {
 				const audioSourceElements = this.doc.querySelectorAll("audio[src], audio > source[src]");
-				if (this.options.displayStats) {
-					this.stats.discarded.audioSource = objectElements.length;
-				}
+				this.stats.set("discarded", "audioSource", audioSourceElements.length);
 				audioSourceElements.forEach(element => element.removeAttribute("src"));
 			}
 			if (this.options.removeVideoSrc) {
 				const videoSourceElements = this.doc.querySelectorAll("video[src], video > source[src]");
-				if (this.options.displayStats) {
-					this.stats.discarded.videoSource = objectElements.length;
-				}
+				this.stats.set("discarded", "videoSource", videoSourceElements.length);
 				videoSourceElements.forEach(element => element.removeAttribute("src"));
 			}
 		}
@@ -373,25 +341,19 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 
 		removeScripts() {
 			const scriptElements = this.doc.querySelectorAll("script:not([type=\"application/ld+json\"])");
-			if (this.options.displayStats) {
-				this.stats.discarded.scripts = scriptElements.length;
-			}
+			this.stats.set("discarded", "scripts", scriptElements.length);
 			scriptElements.forEach(element => element.remove());
 		}
 
 		removeFrames() {
 			const frameElements = this.doc.querySelectorAll("iframe, frame, object[type=\"text/html\"][data]");
-			if (this.options.displayStats) {
-				this.stats.discarded.frames = frameElements.length;
-			}
+			this.stats.set("discarded", "frames", frameElements.length);
 			this.doc.querySelectorAll("iframe, frame, object[type=\"text/html\"][data]").forEach(element => element.remove());
 		}
 
 		removeImports() {
 			const importElements = this.doc.querySelectorAll("link[rel=import]");
-			if (this.options.displayStats) {
-				this.stats.discarded.imports = importElements.length;
-			}
+			this.stats.set("discarded", "imports", importElements.length);
 			importElements.forEach(element => element.remove());
 		}
 
@@ -423,18 +385,14 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 		}
 
 		removeUnusedCSSRules() {
-			const stats = DOM.rulesMinifier(this.doc);
-			if (this.options.displayStats) {
-				this.stats.processed.cssRules = stats.processed;
-				this.stats.discarded.cssRules = stats.discarded;
-			}
+			const removedRules = DOM.rulesMinifier(this.doc);
+			this.stats.set("processed", "cssRules", removedRules.processed);
+			this.stats.set("discarded", "cssRules", removedRules.discarded);
 		}
 
 		removeHiddenElements() {
 			const hiddenElements = this.doc.querySelectorAll("[" + DOM.removedContentAttributeName() + "]");
-			if (this.options.displayStats) {
-				this.stats.discarded.hiddenElements = hiddenElements.length;
-			}
+			this.stats.set("discarded", "hiddenElements", hiddenElements.length);
 			hiddenElements.forEach(element => element.remove());
 		}
 
@@ -446,7 +404,7 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 				}
 				DOM.htmlminiPostProcess(this.doc);
 				if (this.options.displayStats) {
-					this.stats.discarded.htmlBytes += size - DOM.getContentSize(this.doc.documentElement.outerHTML);
+					this.stats.add("discarded", "htmlBytes", size - DOM.getContentSize(this.doc.documentElement.outerHTML));
 				}
 			} else {
 				let size;
@@ -455,7 +413,7 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 				}
 				DOM.htmlminiProcess(this.doc, { preservedSpaceAttributeName: DOM.preservedSpaceAttributeName() });
 				if (this.options.displayStats) {
-					this.stats.discarded.htmlBytes += size - DOM.getContentSize(this.doc.documentElement.outerHTML);
+					this.stats.add("discarded", "htmlBytes", size - DOM.getContentSize(this.doc.documentElement.outerHTML));
 				}
 			}
 		}
@@ -484,9 +442,7 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 							imgElement.style.pixelHeight = canvasData.height;
 						}
 						canvasElement.parentElement.replaceChild(imgElement, canvasElement);
-						if (this.options.displayStats) {
-							this.stats.processed.canvas++;
-						}
+						this.stats.add("processed", "canvas", 1);
 					}
 				});
 			}
@@ -529,8 +485,8 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 
 		async inlineStylesheets(initialization) {
 			await Promise.all(Array.from(this.doc.querySelectorAll("style")).map(async styleElement => {
-				if (!initialization && this.options.displayStats) {
-					this.stats.processed.styleSheets++;
+				if (!initialization) {
+					this.stats.add("processed", "styleSheets", 1);
 				}
 				const stylesheetContent = initialization ? await DomProcessorHelper.resolveImportURLs(styleElement.textContent, this.baseURI, { maxResourceSize: this.options.maxResourceSize, maxResourceSizeEnabled: this.options.maxResourceSizeEnabled }) : await DomProcessorHelper.processStylesheet(styleElement.textContent, this.baseURI);
 				styleElement.textContent = !initialization && this.options.compressCSS ? DOM.uglifycss(stylesheetContent) : stylesheetContent;
@@ -540,9 +496,7 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 		async scripts() {
 			await Promise.all(Array.from(this.doc.querySelectorAll("script[src]")).map(async scriptElement => {
 				if (scriptElement.src) {
-					if (this.options.displayStats) {
-						this.stats.processed.scripts++;
-					}
+					this.stats.add("processed", "scripts", 1);
 					const scriptContent = await Download.getContent(scriptElement.src, { asDataURI: false, maxResourceSize: this.options.maxResourceSize, maxResourceSizeEnabled: this.options.maxResourceSizeEnabled });
 					scriptElement.textContent = scriptContent.replace(/<\/script>/gi, "<\\/script>");
 				}
@@ -578,19 +532,17 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 							}
 						} else {
 							if (frameData.processor) {
-								if (this.options.displayStats) {
-									this.stats.processed.frames++;
-								}
+								this.stats.add("processed", "frames", 1);
 								await frameData.processor.preparePageData();
 								const pageData = await frameData.processor.getPageData();
 								frameElement.removeAttribute(DOM.winIdAttributeName());
 								DomProcessorHelper.setFrameContent(frameElement, pageData.content);
 								if (this.options.displayStats) {
-									Object.keys(this.stats.discarded).forEach(key => this.stats.discarded[key] += (pageData.stats.discarded[key] || 0));
-									Object.keys(this.stats.processed).forEach(key => this.stats.processed[key] += (pageData.stats.processed[key] || 0));
+									Object.keys(this.stats.data.discarded).forEach(key => this.stats.add("discarded", key, pageData.stats.discarded[key] || 0));
+									Object.keys(this.stats.data.processed).forEach(key => this.stats.add("processed", key, pageData.stats.processed[key] || 0));
 								}
-							} else if (this.options.displayStats) {
-								this.stats.discarded.frames++;
+							} else {
+								this.stats.add("discarded", "frames", 1);
 							}
 						}
 					}
@@ -624,18 +576,16 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 					linkElement.setAttribute("href", EMPTY_DATA_URI);
 					const processor = this.relImportProcessors.get(linkElement);
 					if (processor) {
-						if (this.options.displayStats) {
-							this.stats.processed.imports++;
-						}
+						this.stats.add("processed", "imports", 1);
 						this.relImportProcessors.delete(linkElement);
 						const pageData = await processor.getPageData();
 						linkElement.setAttribute("href", "data:text/html," + pageData.content);
 						if (this.options.displayStats) {
-							Object.keys(this.stats.discarded).forEach(key => this.stats.discarded[key] += (pageData.stats.discarded[key] || 0));
-							Object.keys(this.stats.processed).forEach(key => this.stats.processed[key] += (pageData.stats.processed[key] || 0));
+							Object.keys(this.stats.data.discarded).forEach(key => this.stats.add("discarded", key, pageData.stats.discarded[key] || 0));
+							Object.keys(this.stats.data.processed).forEach(key => this.stats.add("processed", key, pageData.stats.processed[key] || 0));
 						}
-					} else if (this.options.displayStats) {
-						this.stats.discarded.imports++;
+					} else {
+						this.stats.add("discarded", "imports", 1);
 					}
 				}
 			}));
@@ -878,6 +828,52 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 
 	}
 
+	// -----
+	// Stats
+	// -----
+	const STATS_DEFAULT_VALUES = {
+		discarded: {
+			htmlBytes: 0,
+			hiddenElements: 0,
+			imports: 0,
+			scripts: 0,
+			objects: 0,
+			audioSource: 0,
+			videoSource: 0,
+			frames: 0,
+			cssRules: 0
+		},
+		processed: {
+			htmlBytes: 0,
+			imports: 0,
+			scripts: 0,
+			frames: 0,
+			cssRules: 0,
+			canvas: 0,
+			styleSheets: 0,
+			resources: 0
+		}
+	};
+
+	class Stats {
+		constructor(options) {
+			this.options = options;
+			if (options.displayStats) {
+				this.data = JSON.parse(JSON.stringify(STATS_DEFAULT_VALUES));
+			}
+		}
+		set(type, subType, value) {
+			if (this.options.displayStats) {
+				this.data[type][subType] = value;
+			}
+		}
+		add(type, subType, value) {
+			if (this.options.displayStats) {
+				this.data[type][subType] += value;
+			}
+		}
+	}
+
 	return { getClass };
 
 })();