|
|
@@ -42,261 +42,263 @@ this.singlefile.lib.util = this.singlefile.lib.util || (() => {
|
|
|
const singlefile = this.singlefile;
|
|
|
|
|
|
return {
|
|
|
- getInstance(utilOptions) {
|
|
|
- const modules = singlefile.lib.modules;
|
|
|
- const vendor = singlefile.lib.vendor;
|
|
|
- const helper = singlefile.lib.helper;
|
|
|
+ getInstance
|
|
|
+ };
|
|
|
|
|
|
- if (modules.serializer === undefined) {
|
|
|
- modules.serializer = {
|
|
|
- process(doc) {
|
|
|
- const docType = doc.doctype;
|
|
|
- let docTypeString = "";
|
|
|
- if (docType) {
|
|
|
- docTypeString = "<!DOCTYPE " + docType.nodeName;
|
|
|
- if (docType.publicId) {
|
|
|
- docTypeString += " PUBLIC \"" + docType.publicId + "\"";
|
|
|
- if (docType.systemId)
|
|
|
- docTypeString += " \"" + docType.systemId + "\"";
|
|
|
- } else if (docType.systemId)
|
|
|
- docTypeString += " SYSTEM \"" + docType.systemId + "\"";
|
|
|
- if (docType.internalSubset)
|
|
|
- docTypeString += " [" + docType.internalSubset + "]";
|
|
|
- docTypeString += "> ";
|
|
|
- }
|
|
|
- return docTypeString + doc.documentElement.outerHTML;
|
|
|
- }
|
|
|
- };
|
|
|
- }
|
|
|
+ function getInstance(utilOptions) {
|
|
|
+ const modules = singlefile.lib.modules;
|
|
|
+ const vendor = singlefile.lib.vendor;
|
|
|
+ const helper = singlefile.lib.helper;
|
|
|
|
|
|
- utilOptions = utilOptions || {};
|
|
|
- utilOptions.fetch = utilOptions.fetch || fetch;
|
|
|
- utilOptions.frameFetch = utilOptions.frameFetch || utilOptions.fetch || fetch;
|
|
|
- return {
|
|
|
- getContent,
|
|
|
- parseURL(resourceURL, baseURI) {
|
|
|
- if (baseURI === undefined) {
|
|
|
- return new URL(resourceURL);
|
|
|
- } else {
|
|
|
- return new URL(resourceURL, baseURI);
|
|
|
- }
|
|
|
- },
|
|
|
- resolveURL(resourceURL, baseURI) {
|
|
|
- return this.parseURL(resourceURL, baseURI).href;
|
|
|
- },
|
|
|
- getValidFilename(filename, replacedCharacters = DEFAULT_REPLACED_CHARACTERS, replacementCharacter = DEFAULT_REPLACEMENT_CHARACTER) {
|
|
|
- replacedCharacters.forEach(replacedCharacter => filename = filename.replace(new RegExp("[" + replacedCharacter + "]+", "g"), replacementCharacter));
|
|
|
- filename = filename
|
|
|
- .replace(/\.\.\//g, "")
|
|
|
- .replace(/^\/+/, "")
|
|
|
- .replace(/\/+/g, "/")
|
|
|
- .replace(/\/$/, "")
|
|
|
- .replace(/\.$/, "")
|
|
|
- .replace(/\.\//g, "." + replacementCharacter)
|
|
|
- .replace(/\/\./g, "/" + replacementCharacter);
|
|
|
- return filename;
|
|
|
- },
|
|
|
- parseDocContent(content, baseURI) {
|
|
|
- const doc = (new DOMParser()).parseFromString(content, "text/html");
|
|
|
- if (!doc.head) {
|
|
|
- doc.documentElement.insertBefore(doc.createElement("HEAD"), doc.body);
|
|
|
- }
|
|
|
- let baseElement = doc.querySelector("base");
|
|
|
- if (!baseElement || !baseElement.getAttribute("href")) {
|
|
|
- if (baseElement) {
|
|
|
- baseElement.remove();
|
|
|
- }
|
|
|
- baseElement = doc.createElement("base");
|
|
|
- baseElement.setAttribute("href", baseURI);
|
|
|
- doc.head.insertBefore(baseElement, doc.head.firstChild);
|
|
|
+ if (modules.serializer === undefined) {
|
|
|
+ modules.serializer = {
|
|
|
+ process(doc) {
|
|
|
+ const docType = doc.doctype;
|
|
|
+ let docTypeString = "";
|
|
|
+ if (docType) {
|
|
|
+ docTypeString = "<!DOCTYPE " + docType.nodeName;
|
|
|
+ if (docType.publicId) {
|
|
|
+ docTypeString += " PUBLIC \"" + docType.publicId + "\"";
|
|
|
+ if (docType.systemId)
|
|
|
+ docTypeString += " \"" + docType.systemId + "\"";
|
|
|
+ } else if (docType.systemId)
|
|
|
+ docTypeString += " SYSTEM \"" + docType.systemId + "\"";
|
|
|
+ if (docType.internalSubset)
|
|
|
+ docTypeString += " [" + docType.internalSubset + "]";
|
|
|
+ docTypeString += "> ";
|
|
|
}
|
|
|
- return doc;
|
|
|
- },
|
|
|
- parseXMLContent(content) {
|
|
|
- return (new DOMParser()).parseFromString(content, "text/xml");
|
|
|
- },
|
|
|
- parseSVGContent(content) {
|
|
|
- return (new DOMParser()).parseFromString(content, "image/svg+xml");
|
|
|
- },
|
|
|
- async digest(algo, text) {
|
|
|
- try {
|
|
|
- const hash = await crypto.subtle.digest(algo, new TextEncoder("utf-8").encode(text));
|
|
|
- return hex(hash);
|
|
|
- } catch (error) {
|
|
|
- return "";
|
|
|
- }
|
|
|
- },
|
|
|
- getContentSize(content) {
|
|
|
- return new Blob([content]).size;
|
|
|
- },
|
|
|
- truncateText(content, maxSize) {
|
|
|
- const blob = new Blob([content]);
|
|
|
- const reader = new FileReader();
|
|
|
- reader.readAsText(blob.slice(0, maxSize));
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
- reader.addEventListener("load", () => {
|
|
|
- if (content.startsWith(reader.result)) {
|
|
|
- resolve(reader.result);
|
|
|
- } else {
|
|
|
- this.truncateText(content, maxSize - 1).then(resolve).catch(reject);
|
|
|
- }
|
|
|
- }, false);
|
|
|
- reader.addEventListener("error", reject, false);
|
|
|
- });
|
|
|
- },
|
|
|
- minifyHTML(doc, options) {
|
|
|
- return modules.htmlMinifier.process(doc, options);
|
|
|
- },
|
|
|
- minifyCSSRules(stylesheets, styles, mediaAllInfo) {
|
|
|
- return modules.cssRulesMinifier.process(stylesheets, styles, mediaAllInfo);
|
|
|
- },
|
|
|
- removeUnusedFonts(doc, stylesheets, styles, options) {
|
|
|
- return modules.fontsMinifier.process(doc, stylesheets, styles, options);
|
|
|
- },
|
|
|
- removeAlternativeFonts(doc, stylesheets, fontURLs, fontTests) {
|
|
|
- return modules.fontsAltMinifier.process(doc, stylesheets, fontURLs, fontTests);
|
|
|
- },
|
|
|
- getMediaAllInfo(doc, stylesheets, styles) {
|
|
|
- return modules.matchedRules.getMediaAllInfo(doc, stylesheets, styles);
|
|
|
- },
|
|
|
- compressCSS(content, options) {
|
|
|
- return vendor.cssMinifier.processString(content, options);
|
|
|
- },
|
|
|
- minifyMedias(stylesheets) {
|
|
|
- return modules.mediasAltMinifier.process(stylesheets);
|
|
|
- },
|
|
|
- removeAlternativeImages(doc) {
|
|
|
- return modules.imagesAltMinifier.process(doc);
|
|
|
- },
|
|
|
- parseSrcset(srcset) {
|
|
|
- return vendor.srcsetParser.process(srcset);
|
|
|
- },
|
|
|
- preProcessDoc(doc, win, options) {
|
|
|
- return helper.preProcessDoc(doc, win, options);
|
|
|
- },
|
|
|
- postProcessDoc(doc, markedElements) {
|
|
|
- helper.postProcessDoc(doc, markedElements);
|
|
|
- },
|
|
|
- serialize(doc, compressHTML) {
|
|
|
- return modules.serializer.process(doc, compressHTML);
|
|
|
- },
|
|
|
- removeQuotes(string) {
|
|
|
- return helper.removeQuotes(string);
|
|
|
- },
|
|
|
- waitForUserScript(eventPrefixName) {
|
|
|
- if (helper.waitForUserScript) {
|
|
|
- return helper.waitForUserScript(eventPrefixName);
|
|
|
- }
|
|
|
- },
|
|
|
- ON_BEFORE_CAPTURE_EVENT_NAME: helper.ON_BEFORE_CAPTURE_EVENT_NAME,
|
|
|
- ON_AFTER_CAPTURE_EVENT_NAME: helper.ON_AFTER_CAPTURE_EVENT_NAME,
|
|
|
- WIN_ID_ATTRIBUTE_NAME: helper.WIN_ID_ATTRIBUTE_NAME,
|
|
|
- REMOVED_CONTENT_ATTRIBUTE_NAME: helper.REMOVED_CONTENT_ATTRIBUTE_NAME,
|
|
|
- HIDDEN_CONTENT_ATTRIBUTE_NAME: helper.HIDDEN_CONTENT_ATTRIBUTE_NAME,
|
|
|
- HIDDEN_FRAME_ATTRIBUTE_NAME: helper.HIDDEN_FRAME_ATTRIBUTE_NAME,
|
|
|
- IMAGE_ATTRIBUTE_NAME: helper.IMAGE_ATTRIBUTE_NAME,
|
|
|
- POSTER_ATTRIBUTE_NAME: helper.POSTER_ATTRIBUTE_NAME,
|
|
|
- CANVAS_ATTRIBUTE_NAME: helper.CANVAS_ATTRIBUTE_NAME,
|
|
|
- HTML_IMPORT_ATTRIBUTE_NAME: helper.HTML_IMPORT_ATTRIBUTE_NAME,
|
|
|
- INPUT_VALUE_ATTRIBUTE_NAME: helper.INPUT_VALUE_ATTRIBUTE_NAME,
|
|
|
- SHADOW_ROOT_ATTRIBUTE_NAME: helper.SHADOW_ROOT_ATTRIBUTE_NAME,
|
|
|
- PRESERVED_SPACE_ELEMENT_ATTRIBUTE_NAME: helper.PRESERVED_SPACE_ELEMENT_ATTRIBUTE_NAME,
|
|
|
- STYLESHEET_ATTRIBUTE_NAME: helper.STYLESHEET_ATTRIBUTE_NAME,
|
|
|
- SELECTED_CONTENT_ATTRIBUTE_NAME: helper.SELECTED_CONTENT_ATTRIBUTE_NAME,
|
|
|
- COMMENT_HEADER: helper.COMMENT_HEADER,
|
|
|
- COMMENT_HEADER_LEGACY: helper.COMMENT_HEADER_LEGACY,
|
|
|
- SINGLE_FILE_UI_ELEMENT_CLASS: helper.SINGLE_FILE_UI_ELEMENT_CLASS
|
|
|
+ return docTypeString + doc.documentElement.outerHTML;
|
|
|
+ }
|
|
|
};
|
|
|
+ }
|
|
|
|
|
|
- async function getContent(resourceURL, options) {
|
|
|
- let response, startTime;
|
|
|
- const fetchResource = utilOptions.fetch;
|
|
|
- const fetchFrameResource = utilOptions.frameFetch;
|
|
|
- if (DEBUG) {
|
|
|
- startTime = Date.now();
|
|
|
- log(" // STARTED download url =", resourceURL, "asBinary =", options.asBinary);
|
|
|
+ utilOptions = utilOptions || {};
|
|
|
+ utilOptions.fetch = utilOptions.fetch || fetch;
|
|
|
+ utilOptions.frameFetch = utilOptions.frameFetch || utilOptions.fetch || fetch;
|
|
|
+ return {
|
|
|
+ getContent,
|
|
|
+ parseURL(resourceURL, baseURI) {
|
|
|
+ if (baseURI === undefined) {
|
|
|
+ return new URL(resourceURL);
|
|
|
+ } else {
|
|
|
+ return new URL(resourceURL, baseURI);
|
|
|
}
|
|
|
- try {
|
|
|
- if (options.frameId) {
|
|
|
- try {
|
|
|
- response = await fetchFrameResource(resourceURL, { frameId: options.frameId, referrer: options.resourceReferrer });
|
|
|
- } catch (error) {
|
|
|
- response = await fetchResource(resourceURL);
|
|
|
- }
|
|
|
- } else {
|
|
|
- response = await fetchResource(resourceURL, { referrer: options.resourceReferrer });
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- return { data: options.asBinary ? "data:null;base64," : "", resourceURL };
|
|
|
+ },
|
|
|
+ resolveURL(resourceURL, baseURI) {
|
|
|
+ return this.parseURL(resourceURL, baseURI).href;
|
|
|
+ },
|
|
|
+ getValidFilename(filename, replacedCharacters = DEFAULT_REPLACED_CHARACTERS, replacementCharacter = DEFAULT_REPLACEMENT_CHARACTER) {
|
|
|
+ replacedCharacters.forEach(replacedCharacter => filename = filename.replace(new RegExp("[" + replacedCharacter + "]+", "g"), replacementCharacter));
|
|
|
+ filename = filename
|
|
|
+ .replace(/\.\.\//g, "")
|
|
|
+ .replace(/^\/+/, "")
|
|
|
+ .replace(/\/+/g, "/")
|
|
|
+ .replace(/\/$/, "")
|
|
|
+ .replace(/\.$/, "")
|
|
|
+ .replace(/\.\//g, "." + replacementCharacter)
|
|
|
+ .replace(/\/\./g, "/" + replacementCharacter);
|
|
|
+ return filename;
|
|
|
+ },
|
|
|
+ parseDocContent(content, baseURI) {
|
|
|
+ const doc = (new DOMParser()).parseFromString(content, "text/html");
|
|
|
+ if (!doc.head) {
|
|
|
+ doc.documentElement.insertBefore(doc.createElement("HEAD"), doc.body);
|
|
|
}
|
|
|
- let buffer;
|
|
|
- try {
|
|
|
- buffer = await response.arrayBuffer();
|
|
|
- } catch (error) {
|
|
|
- return { data: options.asBinary ? "data:null;base64," : "", resourceURL };
|
|
|
+ let baseElement = doc.querySelector("base");
|
|
|
+ if (!baseElement || !baseElement.getAttribute("href")) {
|
|
|
+ if (baseElement) {
|
|
|
+ baseElement.remove();
|
|
|
+ }
|
|
|
+ baseElement = doc.createElement("base");
|
|
|
+ baseElement.setAttribute("href", baseURI);
|
|
|
+ doc.head.insertBefore(baseElement, doc.head.firstChild);
|
|
|
}
|
|
|
- resourceURL = response.url || resourceURL;
|
|
|
- let contentType = "", charset;
|
|
|
+ return doc;
|
|
|
+ },
|
|
|
+ parseXMLContent(content) {
|
|
|
+ return (new DOMParser()).parseFromString(content, "text/xml");
|
|
|
+ },
|
|
|
+ parseSVGContent(content) {
|
|
|
+ return (new DOMParser()).parseFromString(content, "image/svg+xml");
|
|
|
+ },
|
|
|
+ async digest(algo, text) {
|
|
|
try {
|
|
|
- const mimeType = new vendor.MIMEType(response.headers.get("content-type"));
|
|
|
- contentType = mimeType.type + "/" + mimeType.subtype;
|
|
|
- charset = mimeType.parameters.get("charset");
|
|
|
+ const hash = await crypto.subtle.digest(algo, new TextEncoder("utf-8").encode(text));
|
|
|
+ return hex(hash);
|
|
|
} catch (error) {
|
|
|
- // ignored
|
|
|
+ return "";
|
|
|
}
|
|
|
- if (!contentType) {
|
|
|
- contentType = guessMIMEType(options.expectedType, buffer);
|
|
|
- }
|
|
|
- if (!charset && options.charset) {
|
|
|
- charset = options.charset;
|
|
|
- }
|
|
|
- if (options.asBinary) {
|
|
|
- try {
|
|
|
- if (DEBUG) {
|
|
|
- log(" // ENDED download url =", resourceURL, "delay =", Date.now() - startTime);
|
|
|
- }
|
|
|
- if (options.maxResourceSizeEnabled && buffer.byteLength > options.maxResourceSize * ONE_MB) {
|
|
|
- return { data: "data:null;base64,", resourceURL };
|
|
|
+ },
|
|
|
+ getContentSize(content) {
|
|
|
+ return new Blob([content]).size;
|
|
|
+ },
|
|
|
+ truncateText(content, maxSize) {
|
|
|
+ const blob = new Blob([content]);
|
|
|
+ const reader = new FileReader();
|
|
|
+ reader.readAsText(blob.slice(0, maxSize));
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ reader.addEventListener("load", () => {
|
|
|
+ if (content.startsWith(reader.result)) {
|
|
|
+ resolve(reader.result);
|
|
|
} else {
|
|
|
- const reader = new FileReader();
|
|
|
- reader.readAsDataURL(new Blob([buffer], { type: contentType + (options.charset ? ";charset=" + options.charset : "") }));
|
|
|
- const dataUri = await new Promise((resolve, reject) => {
|
|
|
- reader.addEventListener("load", () => resolve(reader.result), false);
|
|
|
- reader.addEventListener("error", reject, false);
|
|
|
- });
|
|
|
- return { data: dataUri, resourceURL };
|
|
|
+ this.truncateText(content, maxSize - 1).then(resolve).catch(reject);
|
|
|
}
|
|
|
+ }, false);
|
|
|
+ reader.addEventListener("error", reject, false);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ minifyHTML(doc, options) {
|
|
|
+ return modules.htmlMinifier.process(doc, options);
|
|
|
+ },
|
|
|
+ minifyCSSRules(stylesheets, styles, mediaAllInfo) {
|
|
|
+ return modules.cssRulesMinifier.process(stylesheets, styles, mediaAllInfo);
|
|
|
+ },
|
|
|
+ removeUnusedFonts(doc, stylesheets, styles, options) {
|
|
|
+ return modules.fontsMinifier.process(doc, stylesheets, styles, options);
|
|
|
+ },
|
|
|
+ removeAlternativeFonts(doc, stylesheets, fontURLs, fontTests) {
|
|
|
+ return modules.fontsAltMinifier.process(doc, stylesheets, fontURLs, fontTests);
|
|
|
+ },
|
|
|
+ getMediaAllInfo(doc, stylesheets, styles) {
|
|
|
+ return modules.matchedRules.getMediaAllInfo(doc, stylesheets, styles);
|
|
|
+ },
|
|
|
+ compressCSS(content, options) {
|
|
|
+ return vendor.cssMinifier.processString(content, options);
|
|
|
+ },
|
|
|
+ minifyMedias(stylesheets) {
|
|
|
+ return modules.mediasAltMinifier.process(stylesheets);
|
|
|
+ },
|
|
|
+ removeAlternativeImages(doc) {
|
|
|
+ return modules.imagesAltMinifier.process(doc);
|
|
|
+ },
|
|
|
+ parseSrcset(srcset) {
|
|
|
+ return vendor.srcsetParser.process(srcset);
|
|
|
+ },
|
|
|
+ preProcessDoc(doc, win, options) {
|
|
|
+ return helper.preProcessDoc(doc, win, options);
|
|
|
+ },
|
|
|
+ postProcessDoc(doc, markedElements) {
|
|
|
+ helper.postProcessDoc(doc, markedElements);
|
|
|
+ },
|
|
|
+ serialize(doc, compressHTML) {
|
|
|
+ return modules.serializer.process(doc, compressHTML);
|
|
|
+ },
|
|
|
+ removeQuotes(string) {
|
|
|
+ return helper.removeQuotes(string);
|
|
|
+ },
|
|
|
+ waitForUserScript(eventPrefixName) {
|
|
|
+ if (helper.waitForUserScript) {
|
|
|
+ return helper.waitForUserScript(eventPrefixName);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ ON_BEFORE_CAPTURE_EVENT_NAME: helper.ON_BEFORE_CAPTURE_EVENT_NAME,
|
|
|
+ ON_AFTER_CAPTURE_EVENT_NAME: helper.ON_AFTER_CAPTURE_EVENT_NAME,
|
|
|
+ WIN_ID_ATTRIBUTE_NAME: helper.WIN_ID_ATTRIBUTE_NAME,
|
|
|
+ REMOVED_CONTENT_ATTRIBUTE_NAME: helper.REMOVED_CONTENT_ATTRIBUTE_NAME,
|
|
|
+ HIDDEN_CONTENT_ATTRIBUTE_NAME: helper.HIDDEN_CONTENT_ATTRIBUTE_NAME,
|
|
|
+ HIDDEN_FRAME_ATTRIBUTE_NAME: helper.HIDDEN_FRAME_ATTRIBUTE_NAME,
|
|
|
+ IMAGE_ATTRIBUTE_NAME: helper.IMAGE_ATTRIBUTE_NAME,
|
|
|
+ POSTER_ATTRIBUTE_NAME: helper.POSTER_ATTRIBUTE_NAME,
|
|
|
+ CANVAS_ATTRIBUTE_NAME: helper.CANVAS_ATTRIBUTE_NAME,
|
|
|
+ HTML_IMPORT_ATTRIBUTE_NAME: helper.HTML_IMPORT_ATTRIBUTE_NAME,
|
|
|
+ INPUT_VALUE_ATTRIBUTE_NAME: helper.INPUT_VALUE_ATTRIBUTE_NAME,
|
|
|
+ SHADOW_ROOT_ATTRIBUTE_NAME: helper.SHADOW_ROOT_ATTRIBUTE_NAME,
|
|
|
+ PRESERVED_SPACE_ELEMENT_ATTRIBUTE_NAME: helper.PRESERVED_SPACE_ELEMENT_ATTRIBUTE_NAME,
|
|
|
+ STYLESHEET_ATTRIBUTE_NAME: helper.STYLESHEET_ATTRIBUTE_NAME,
|
|
|
+ SELECTED_CONTENT_ATTRIBUTE_NAME: helper.SELECTED_CONTENT_ATTRIBUTE_NAME,
|
|
|
+ COMMENT_HEADER: helper.COMMENT_HEADER,
|
|
|
+ COMMENT_HEADER_LEGACY: helper.COMMENT_HEADER_LEGACY,
|
|
|
+ SINGLE_FILE_UI_ELEMENT_CLASS: helper.SINGLE_FILE_UI_ELEMENT_CLASS
|
|
|
+ };
|
|
|
+
|
|
|
+ async function getContent(resourceURL, options) {
|
|
|
+ let response, startTime;
|
|
|
+ const fetchResource = utilOptions.fetch;
|
|
|
+ const fetchFrameResource = utilOptions.frameFetch;
|
|
|
+ if (DEBUG) {
|
|
|
+ startTime = Date.now();
|
|
|
+ log(" // STARTED download url =", resourceURL, "asBinary =", options.asBinary);
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ if (options.frameId) {
|
|
|
+ try {
|
|
|
+ response = await fetchFrameResource(resourceURL, { frameId: options.frameId, referrer: options.resourceReferrer });
|
|
|
} catch (error) {
|
|
|
- return { data: "data:null;base64,", resourceURL };
|
|
|
+ response = await fetchResource(resourceURL);
|
|
|
}
|
|
|
} else {
|
|
|
- if (response.status >= 400 || (options.validateTextContentType && contentType && !contentType.startsWith(PREFIX_CONTENT_TYPE_TEXT))) {
|
|
|
- return { data: "", resourceURL };
|
|
|
- }
|
|
|
- if (!charset) {
|
|
|
- charset = "utf-8";
|
|
|
- }
|
|
|
+ response = await fetchResource(resourceURL, { referrer: options.resourceReferrer });
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ return { data: options.asBinary ? "data:null;base64," : "", resourceURL };
|
|
|
+ }
|
|
|
+ let buffer;
|
|
|
+ try {
|
|
|
+ buffer = await response.arrayBuffer();
|
|
|
+ } catch (error) {
|
|
|
+ return { data: options.asBinary ? "data:null;base64," : "", resourceURL };
|
|
|
+ }
|
|
|
+ resourceURL = response.url || resourceURL;
|
|
|
+ let contentType = "", charset;
|
|
|
+ try {
|
|
|
+ const mimeType = new vendor.MIMEType(response.headers.get("content-type"));
|
|
|
+ contentType = mimeType.type + "/" + mimeType.subtype;
|
|
|
+ charset = mimeType.parameters.get("charset");
|
|
|
+ } catch (error) {
|
|
|
+ // ignored
|
|
|
+ }
|
|
|
+ if (!contentType) {
|
|
|
+ contentType = guessMIMEType(options.expectedType, buffer);
|
|
|
+ }
|
|
|
+ if (!charset && options.charset) {
|
|
|
+ charset = options.charset;
|
|
|
+ }
|
|
|
+ if (options.asBinary) {
|
|
|
+ try {
|
|
|
if (DEBUG) {
|
|
|
log(" // ENDED download url =", resourceURL, "delay =", Date.now() - startTime);
|
|
|
}
|
|
|
if (options.maxResourceSizeEnabled && buffer.byteLength > options.maxResourceSize * ONE_MB) {
|
|
|
- return { data: "", resourceURL, charset };
|
|
|
+ return { data: "data:null;base64,", resourceURL };
|
|
|
} else {
|
|
|
+ const reader = new FileReader();
|
|
|
+ reader.readAsDataURL(new Blob([buffer], { type: contentType + (options.charset ? ";charset=" + options.charset : "") }));
|
|
|
+ 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:null;base64,", resourceURL };
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (response.status >= 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 && 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) {
|
|
|
- try {
|
|
|
- charset = "utf-8";
|
|
|
- return { data: new TextDecoder(charset).decode(buffer), resourceURL, charset };
|
|
|
- } catch (error) {
|
|
|
- return { data: "", resourceURL, charset };
|
|
|
- }
|
|
|
+ return { data: "", resourceURL, charset };
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- };
|
|
|
+ }
|
|
|
|
|
|
function guessMIMEType(expectedType, buffer) {
|
|
|
if (expectedType == "image") {
|