Browse Source

moved common code of getContent into DocUtilCore

Gildas 7 years ago
parent
commit
39205213b3

+ 33 - 91
lib/single-file/single-file-browser.js

@@ -36,9 +36,6 @@
 
 this.SingleFileBrowser = this.SingleFileBrowser || (() => {
 
-	const ONE_MB = 1024 * 1024;
-	const DEBUG = false;
-	const PREFIX_CONTENT_TYPE_TEXT = "text/";
 	const FONT_FACE_TEST_MAX_DELAY = 1000;
 
 	const modules = {
@@ -55,7 +52,12 @@ this.SingleFileBrowser = this.SingleFileBrowser || (() => {
 		imagesAltMinifier: this.imagesAltMinifier.getInstance(this.srcsetParser)
 	};
 	const domUtil = {
-		getContent, parseDocContent, parseSVGContent, isValidFontUrl, getContentSize, digestText
+		getResourceContent,
+		parseDocContent,
+		parseSVGContent,
+		isValidFontUrl,
+		getContentSize,
+		digestText
 	};
 	let fetchResource;
 	return {
@@ -65,93 +67,37 @@ this.SingleFileBrowser = this.SingleFileBrowser || (() => {
 		}
 	};
 
-	async function getContent(resourceURL, options) {
-		let resourceContent, startTime;
-		if (DEBUG) {
-			startTime = Date.now();
-			log("  // STARTED download url =", resourceURL, "asDataURI =", options.asDataURI);
-		}
+	async function getResourceContent(resourceURL) {
 		if (!fetchResource) {
 			fetchResource = typeof superFetch == "undefined" ? fetch : superFetch.fetch;
 		}
-		try {
-			resourceContent = await fetchResource(resourceURL);
-			if (resourceContent.url) {
-				resourceURL = resourceContent.url;
-			}
-		} catch (error) {
-			return { data: options.asDataURI ? "data:base64," : "", resourceURL };
-		}
-		let contentType = resourceContent.headers && resourceContent.headers.get("content-type");
-		let charset;
-		if (contentType) {
-			const matchContentType = contentType.toLowerCase().split(";");
-			contentType = matchContentType[0].trim();
-			if (!contentType.includes("/")) {
-				contentType = null;
-			}
-			const charsetValue = matchContentType[1] && matchContentType[1].trim();
-			if (charsetValue) {
-				const matchCharset = charsetValue.match(/^charset=(.*)/);
-				if (matchCharset && matchCharset[1]) {
-					charset = docHelper.removeQuotes(matchCharset[1].trim());
-				}
-			}
-		}
-		if (!charset && options.charset) {
-			charset = options.charset;
-		}
-		if (options.asDataURI) {
-			try {
-				if (DEBUG) {
-					log("  // ENDED   download url =", resourceURL, "delay =", Date.now() - startTime);
-				}
-				const buffer = await resourceContent.arrayBuffer();
-				if (options.maxResourceSizeEnabled && buffer.byteLength > options.maxResourceSize * ONE_MB) {
-					return { data: "data:base64,", resourceURL };
-				} else {
-					const reader = new FileReader();
-					reader.readAsDataURL(new Blob([buffer], { type: contentType }));
-					const dataURI = await new Promise((resolve, reject) => {
-						reader.addEventListener("load", () => resolve(reader.result), false);
-						reader.addEventListener("error", reject, false);
-					});
-					return { data: dataURI, resourceURL };
-				}
-			} catch (error) {
-				return { data: "data:base64,", resourceURL };
+		const resourceContent = await fetchResource(resourceURL);
+		const buffer = await resourceContent.arrayBuffer();
+		return {
+			getUrl() {
+				return resourceContent.url || resourceURL;
+			},
+			getContentType() {
+				return resourceContent.headers && resourceContent.headers.get("content-type");
+			},
+			getStatusCode() {
+				return resourceContent.status;
+			},
+			getSize() {
+				return buffer.byteLength;
+			},
+			getText(charset) {
+				return new TextDecoder(charset).decode(buffer);
+			},
+			async getDataUri(contentType) {
+				const reader = new FileReader();
+				reader.readAsDataURL(new Blob([buffer], { type: contentType || this.getContentType() }));
+				return await new Promise((resolve, reject) => {
+					reader.addEventListener("load", () => resolve(reader.result), false);
+					reader.addEventListener("error", reject, false);
+				});
 			}
-		} else {
-			if (resourceContent.status >= 400 || (options.validateTextContentType && contentType && !contentType.startsWith(PREFIX_CONTENT_TYPE_TEXT))) {
-				return { data: "", resourceURL };
-			}
-			if (!charset) {
-				charset = "utf-8";
-			}
-			let buffer;
-			try {
-				buffer = await resourceContent.arrayBuffer();
-			} catch (error) {
-				return { data: "", resourceURL, charset };
-			}
-			if (DEBUG) {
-				log("  // ENDED   download url =", resourceURL, "delay =", Date.now() - startTime);
-			}
-			if (options.maxResourceSizeEnabled && buffer.byteLength > options.maxResourceSize * ONE_MB) {
-				return { data: "", resourceURL, charset };
-			} else {
-				try {
-					return { data: new TextDecoder(charset).decode(buffer), resourceURL, charset };
-				} catch (error) {
-					try {
-						charset = "utf-8";
-						return { data: new TextDecoder(charset).decode(buffer), resourceURL, charset };
-					} catch (error) {
-						return { data: "", resourceURL, charset };
-					}
-				}
-			}
-		}
+		};
 	}
 
 	// https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest
@@ -205,8 +151,4 @@ this.SingleFileBrowser = this.SingleFileBrowser || (() => {
 		}
 	}
 
-	function log(...args) {
-		console.log("S-File <browser>", ...args); // eslint-disable-line no-console
-	}
-
 })();

+ 77 - 1
lib/single-file/util/doc-util-core.js

@@ -22,6 +22,10 @@
 
 this.DocUtilCore = this.DocUtilCore || (() => {
 
+	const DEBUG = false;
+	const ONE_MB = 1024 * 1024;
+	const PREFIX_CONTENT_TYPE_TEXT = "text/";
+
 	return {
 		getClass: (modules, domUtil) => {
 			if (modules.serializer === undefined) {
@@ -48,7 +52,75 @@ this.DocUtilCore = this.DocUtilCore || (() => {
 
 			return class DocUtil {
 				static async getContent(resourceURL, options) {
-					return domUtil.getContent(resourceURL, options);
+					let resourceContent, startTime;
+					if (DEBUG) {
+						startTime = Date.now();
+						log("  // STARTED download url =", resourceURL, "asDataURI =", options.asDataURI);
+					}
+					try {
+						resourceContent = await domUtil.getResourceContent(resourceURL, options);
+					} catch (error) {
+						return { data: options.asDataURI ? "data:base64," : "", resourceURL };
+					}
+					resourceURL = resourceContent.getUrl();
+					let contentType = resourceContent.getContentType();
+					let charset;
+					if (contentType) {
+						const matchContentType = contentType.toLowerCase().split(";");
+						contentType = matchContentType[0].trim();
+						if (!contentType.includes("/")) {
+							contentType = null;
+						}
+						const charsetValue = matchContentType[1] && matchContentType[1].trim();
+						if (charsetValue) {
+							const matchCharset = charsetValue.match(/^charset=(.*)/);
+							if (matchCharset && matchCharset[1]) {
+								charset = modules.docHelper.removeQuotes(matchCharset[1].trim());
+							}
+						}
+					}
+					if (!charset && options.charset) {
+						charset = options.charset;
+					}
+					if (options.asDataURI) {
+						try {
+							if (DEBUG) {
+								log("  // ENDED   download url =", resourceURL, "delay =", Date.now() - startTime);
+							}
+							if (options.maxResourceSizeEnabled && resourceContent.getSize() > options.maxResourceSize * ONE_MB) {
+								return { data: "data:base64,", resourceURL };
+							} else {
+								const dataUri = await resourceContent.getDataUri(contentType);
+								return { data: dataUri, resourceURL };
+							}
+						} catch (error) {
+							return { data: "data:base64,", resourceURL };
+						}
+					} else {
+						if (resourceContent.getStatusCode() >= 400 || (options.validateTextContentType && contentType && !contentType.startsWith(PREFIX_CONTENT_TYPE_TEXT))) {
+							return { data: "", resourceURL };
+						}
+						if (!charset) {
+							charset = "utf-8";
+						}
+						if (DEBUG) {
+							log("  // ENDED   download url =", resourceURL, "delay =", Date.now() - startTime);
+						}
+						if (options.maxResourceSizeEnabled && resourceContent.getSize() > options.maxResourceSize * ONE_MB) {
+							return { data: "", resourceURL, charset };
+						} else {
+							try {
+								return { data: resourceContent.getText(charset), resourceURL, charset };
+							} catch (error) {
+								try {
+									charset = "utf-8";
+									return { data: resourceContent.getText(charset), resourceURL, charset };
+								} catch (error) {
+									return { data: "", resourceURL, charset };
+								}
+							}
+						}
+					}
 				}
 
 				static parseURL(resourceURL, baseURI) {
@@ -162,4 +234,8 @@ this.DocUtilCore = this.DocUtilCore || (() => {
 		}
 	};
 
+	function log(...args) {
+		console.log("S-File <browser>", ...args); // eslint-disable-line no-console
+	}
+
 })();

+ 25 - 54
node-jsdom/single-file-jsdom.js

@@ -32,8 +32,6 @@ const iconv = require("iconv-lite");
 const request = require("request-promise-native");
 const { JSDOM } = jsdom;
 
-const ONE_MB = 1024 * 1024;
-const PREFIX_CONTENT_TYPE_TEXT = "text/";
 const SCRIPTS = [
 	"./lib/single-file/util/doc-util-core.js",
 	"./lib/single-file/util/doc-helper.js",
@@ -69,7 +67,7 @@ const modules = {
 	imagesAltMinifier: this.imagesAltMinifier.getInstance(this.srcsetParser)
 };
 const domUtil = {
-	getContent,
+	getResourceContent,
 	parseDocContent,
 	parseSVGContent,
 	isValidFontUrl,
@@ -119,8 +117,9 @@ function isValidFontUrl(/* urlFunction */) {
 	return true;
 }
 
-async function getContent(resourceURL, options) {
-	const requestOptions = {
+async function getResourceContent(resourceURL, options) {
+	let resourceContent;
+	resourceContent = await request({
 		method: "GET",
 		uri: resourceURL,
 		resolveWithFullResponse: true,
@@ -128,54 +127,26 @@ async function getContent(resourceURL, options) {
 		headers: {
 			"User-Agent": options.userAgent
 		}
-	};
-	let resourceContent;
-	try {
-		resourceContent = await request(requestOptions);
-	} catch (e) {
-		return options.asDataURI ? "data:base64," : "";
-	}
-	let contentType = resourceContent.headers["content-type"];
-	let charset;
-	if (contentType) {
-		const matchContentType = contentType.toLowerCase().split(";");
-		contentType = matchContentType[0].trim();
-		if (!contentType.includes("/")) {
-			contentType = null;
+	});
+	return {
+		getUrl() {
+			// TODO
+			return resourceURL;
+		},
+		getContentType() {
+			return resourceContent.headers["content-type"];
+		},
+		getStatusCode() {
+			return resourceContent.statusCode;
+		},
+		getSize() {
+			return resourceContent.body.byteLength;
+		},
+		getText(charset) {
+			return iconv.decode(resourceContent.body, charset);
+		},
+		async getDataUri(contentType) {
+			return dataUri.encode(resourceContent.body, contentType || this.getContentType());
 		}
-		const charsetValue = matchContentType[1] && matchContentType[1].trim();
-		if (charsetValue) {
-			const matchCharset = charsetValue.match(/^charset=(.*)/);
-			if (matchCharset && matchCharset[1]) {
-				charset = docHelper.removeQuotes(matchCharset[1].trim());
-			}
-		}
-	}
-	if (!charset && options.charset) {
-		charset = options.charset;
-	}
-	if (options && options.asDataURI) {
-		try {
-			const buffer = resourceContent.body;
-			if (options.maxResourceSizeEnabled && buffer.byteLength > options.maxResourceSize * ONE_MB) {
-				return { data: "data:base64,", resourceURL };
-			} else {
-				return { data: dataUri.encode(buffer, contentType), resourceURL };
-			}
-		} catch (e) {
-			return { data: "data:base64,", resourceURL };
-		}
-	} else {
-		if (resourceContent.statusCode >= 400 || (options.validateTextContentType && contentType && !contentType.startsWith(PREFIX_CONTENT_TYPE_TEXT))) {
-			return { data: "", resourceURL };
-		}
-		if (!charset) {
-			charset = "utf-8";
-		}
-		try {
-			return { data: iconv.decode(resourceContent.body, charset), charset };
-		} catch (e) {
-			return { data: resourceContent.body.toString("utf8"), charset: "utf8" };
-		}
-	}
+	};
 }