Add MIME type to the generated .epub file

This commit is contained in:
Alex Adam 2020-12-24 15:52:14 +02:00
parent 03dd484827
commit 12a4cbb081
4 changed files with 173 additions and 186 deletions

View file

@ -66,6 +66,9 @@ in Chrome:
3. Click on Keyboard shortcuts 3. Click on Keyboard shortcuts
``` ```
## Added in 1.4.2
- Added MIME type to the generated .epub file
## Added in 1.4.1 ## Added in 1.4.1
- Remove unnecessary permissions - Remove unnecessary permissions
- Detect image type if the URL doesn't have a file extension (jpg, gif, png) - Detect image type if the URL doesn't have a file extension (jpg, gif, png)

View file

@ -1,188 +1,171 @@
/* FileSaver.js /*
* A saveAs() FileSaver implementation. * FileSaver.js
* 1.3.2 * A saveAs() FileSaver implementation.
* 2016-06-16 18:25:19 *
* * By Eli Grey, http://eligrey.com
* By Eli Grey, http://eligrey.com *
* License: MIT * License : https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md (MIT)
* See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md * source : http://purl.eligrey.com/github/FileSaver.js
*/ */
/*global self */ // The one and only way of getting global scope in all environments
/*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */ // https://stackoverflow.com/q/3277182/1008999
var _global = typeof window === 'object' && window.window === window
? window : typeof self === 'object' && self.self === self
? self : typeof global === 'object' && global.global === global
? global
: this
/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ function bom (blob, opts) {
if (typeof opts === 'undefined') opts = { autoBom: false }
else if (typeof opts !== 'object') {
console.warn('Deprecated: Expected third argument to be a object')
opts = { autoBom: !opts }
}
var saveAs = saveAs || (function(view) { // prepend BOM for UTF-8 XML and text/* types (including HTML)
"use strict"; // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
// IE <10 is explicitly unsupported if (opts.autoBom && /^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
if (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) { return new Blob([String.fromCharCode(0xFEFF), blob], { type: blob.type })
return; }
} return blob
var }
doc = view.document
// only get URL when necessary in case Blob.js hasn't overridden it yet function download (url, name, opts) {
, get_URL = function() { var xhr = new XMLHttpRequest()
return view.URL || view.webkitURL || view; xhr.open('GET', url)
} xhr.responseType = 'blob'
, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a") xhr.onload = function () {
, can_use_save_link = "download" in save_link saveAs(xhr.response, name, opts)
, click = function(node) { }
var event = new MouseEvent("click"); xhr.onerror = function () {
node.dispatchEvent(event); console.error('could not download file')
} }
, is_safari = /constructor/i.test(view.HTMLElement) xhr.send()
, is_chrome_ios =/CriOS\/[\d]+/.test(navigator.userAgent) }
, throw_outside = function(ex) {
(view.setImmediate || view.setTimeout)(function() { function corsEnabled (url) {
throw ex; var xhr = new XMLHttpRequest()
}, 0); // use sync to avoid popup blocker
} xhr.open('HEAD', url, false)
, force_saveable_type = "application/octet-stream" try {
// the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to xhr.send()
, arbitrary_revoke_timeout = 1000 * 40 // in ms } catch (e) {}
, revoke = function(file) { return xhr.status >= 200 && xhr.status <= 299
var revoker = function() { }
if (typeof file === "string") { // file is an object URL
get_URL().revokeObjectURL(file); // `a.click()` doesn't work for all browsers (#465)
} else { // file is a File function click (node) {
file.remove(); try {
} node.dispatchEvent(new MouseEvent('click'))
}; } catch (e) {
setTimeout(revoker, arbitrary_revoke_timeout); var evt = document.createEvent('MouseEvents')
} evt.initMouseEvent('click', true, true, window, 0, 0, 0, 80,
, dispatch = function(filesaver, event_types, event) { 20, false, false, false, false, 0, null)
event_types = [].concat(event_types); node.dispatchEvent(evt)
var i = event_types.length; }
while (i--) { }
var listener = filesaver["on" + event_types[i]];
if (typeof listener === "function") { // Detect WebView inside a native macOS app by ruling out all browsers
try { // We just need to check for 'Safari' because all other browsers (besides Firefox) include that too
listener.call(filesaver, event || filesaver); // https://www.whatismybrowser.com/guides/the-latest-user-agent/macos
} catch (ex) { var isMacOSWebView = _global.navigator && /Macintosh/.test(navigator.userAgent) && /AppleWebKit/.test(navigator.userAgent) && !/Safari/.test(navigator.userAgent)
throw_outside(ex);
} var saveAs = _global.saveAs || (
} // probably in some web worker
} (typeof window !== 'object' || window !== _global)
} ? function saveAs () { /* noop */ }
, auto_bom = function(blob) {
// prepend BOM for UTF-8 XML and text/* types (including HTML) // Use download attribute first if possible (#193 Lumia mobile) unless this is a macOS WebView
// note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF : ('download' in HTMLAnchorElement.prototype && !isMacOSWebView)
if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) { ? function saveAs (blob, name, opts) {
return new Blob([String.fromCharCode(0xFEFF), blob], {type: blob.type}); var URL = _global.URL || _global.webkitURL
} var a = document.createElement('a')
return blob; name = name || blob.name || 'download'
}
, FileSaver = function(blob, name, no_auto_bom) { a.download = name
if (!no_auto_bom) { a.rel = 'noopener' // tabnabbing
blob = auto_bom(blob);
} // TODO: detect chrome extensions & packaged apps
// First try a.download, then web filesystem, then object URLs // a.target = '_blank'
var
filesaver = this if (typeof blob === 'string') {
, type = blob.type // Support regular links
, force = type === force_saveable_type a.href = blob
, object_url if (a.origin !== location.origin) {
, dispatch_all = function() { corsEnabled(a.href)
dispatch(filesaver, "writestart progress write writeend".split(" ")); ? download(blob, name, opts)
} : click(a, a.target = '_blank')
// on any filesys errors revert to saving with object URLs } else {
, fs_error = function() { click(a)
if ((is_chrome_ios || (force && is_safari)) && view.FileReader) { }
// Safari doesn't allow downloading of blob urls } else {
var reader = new FileReader(); // Support blobs
reader.onloadend = function() { a.href = URL.createObjectURL(blob)
var url = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;'); setTimeout(function () { URL.revokeObjectURL(a.href) }, 4E4) // 40s
var popup = view.open(url, '_blank'); setTimeout(function () { click(a) }, 0)
if(!popup) view.location.href = url; }
url=undefined; // release reference before dispatching }
filesaver.readyState = filesaver.DONE;
dispatch_all(); // Use msSaveOrOpenBlob as a second approach
}; : 'msSaveOrOpenBlob' in navigator
reader.readAsDataURL(blob); ? function saveAs (blob, name, opts) {
filesaver.readyState = filesaver.INIT; name = name || blob.name || 'download'
return;
} if (typeof blob === 'string') {
// don't create more object URLs than needed if (corsEnabled(blob)) {
if (!object_url) { download(blob, name, opts)
object_url = get_URL().createObjectURL(blob); } else {
} var a = document.createElement('a')
if (force) { a.href = blob
view.location.href = object_url; a.target = '_blank'
} else { setTimeout(function () { click(a) })
var opened = view.open(object_url, "_blank"); }
if (!opened) { } else {
// Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html navigator.msSaveOrOpenBlob(bom(blob, opts), name)
view.location.href = object_url; }
} }
}
filesaver.readyState = filesaver.DONE; // Fallback to using FileReader and a popup
dispatch_all(); : function saveAs (blob, name, opts, popup) {
revoke(object_url); // Open a popup immediately do go around popup blocker
} // Mostly only available on user interaction and the fileReader is async so...
; popup = popup || open('', '_blank')
filesaver.readyState = filesaver.INIT; if (popup) {
popup.document.title =
if (can_use_save_link) { popup.document.body.innerText = 'downloading...'
object_url = get_URL().createObjectURL(blob); }
setTimeout(function() {
save_link.href = object_url; if (typeof blob === 'string') return download(blob, name, opts)
save_link.download = name;
click(save_link); var force = blob.type === 'application/octet-stream'
dispatch_all(); var isSafari = /constructor/i.test(_global.HTMLElement) || _global.safari
revoke(object_url); var isChromeIOS = /CriOS\/[\d]+/.test(navigator.userAgent)
filesaver.readyState = filesaver.DONE;
}); if ((isChromeIOS || (force && isSafari) || isMacOSWebView) && typeof FileReader !== 'undefined') {
return; // Safari doesn't allow downloading of blob URLs
} var reader = new FileReader()
reader.onloadend = function () {
fs_error(); var url = reader.result
} url = isChromeIOS ? url : url.replace(/^data:[^;]*;/, 'data:attachment/file;')
, FS_proto = FileSaver.prototype if (popup) popup.location.href = url
, saveAs = function(blob, name, no_auto_bom) { else location = url
return new FileSaver(blob, name || blob.name || "download", no_auto_bom); popup = null // reverse-tabnabbing #460
} }
; reader.readAsDataURL(blob)
// IE 10+ (native saveAs) } else {
if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) { var URL = _global.URL || _global.webkitURL
return function(blob, name, no_auto_bom) { var url = URL.createObjectURL(blob)
name = name || blob.name || "download"; if (popup) popup.location = url
else location.href = url
if (!no_auto_bom) { popup = null // reverse-tabnabbing #460
blob = auto_bom(blob); setTimeout(function () { URL.revokeObjectURL(url) }, 4E4) // 40s
} }
return navigator.msSaveOrOpenBlob(blob, name); }
}; )
}
_global.saveAs = saveAs.saveAs = saveAs
FS_proto.abort = function(){};
FS_proto.readyState = FS_proto.INIT = 0; if (typeof module !== 'undefined') {
FS_proto.WRITING = 1; module.exports = saveAs;
FS_proto.DONE = 2;
FS_proto.error =
FS_proto.onwritestart =
FS_proto.onprogress =
FS_proto.onwrite =
FS_proto.onabort =
FS_proto.onerror =
FS_proto.onwriteend =
null;
return saveAs;
}(
typeof self !== "undefined" && self
|| typeof window !== "undefined" && window
|| this.content
));
// `self` is undefined in Firefox for Android content script context
// while `this` is nsIContentFrameMessageManager
// with an attribute `content` that corresponds to the window
if (typeof module !== "undefined" && module.exports) {
module.exports.saveAs = saveAs;
} else if ((typeof define !== "undefined" && define !== null) && (define.amd !== null)) {
define([], function() {
return saveAs;
});
} }

View file

@ -1,7 +1,7 @@
{ {
"manifest_version": 2, "manifest_version": 2,
"name": "__MSG_extName__", "name": "__MSG_extName__",
"version": "1.4.1", "version": "1.4.2",
"default_locale": "en", "default_locale": "en",
"author": "Alex Adam", "author": "Alex Adam",
"homepage_url": "https://github.com/alexadam/save-as-ebook", "homepage_url": "https://github.com/alexadam/save-as-ebook",

View file

@ -188,7 +188,8 @@ function _buildEbook(allPages, fromMenu=false) {
zip.generateAsync({ zip.generateAsync({
type: "blob" type: "blob",
mimeType: "application/epub+zip"
}) })
.then(function(content) { .then(function(content) {
console.log("done !"); console.log("done !");