From 4fd9b8f2b5a98bfcde57970b48fed2488a80f356 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Fri, 17 Sep 2021 21:53:37 +0300 Subject: add in master snapshot of epubjs --- lib/epub.js/src/archive.js | 255 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 255 insertions(+) create mode 100644 lib/epub.js/src/archive.js (limited to 'lib/epub.js/src/archive.js') diff --git a/lib/epub.js/src/archive.js b/lib/epub.js/src/archive.js new file mode 100644 index 0000000..ea22a81 --- /dev/null +++ b/lib/epub.js/src/archive.js @@ -0,0 +1,255 @@ +import {defer, isXml, parse} from "./utils/core"; +import request from "./utils/request"; +import mime from "./utils/mime"; +import Path from "./utils/path"; +import JSZip from "jszip/dist/jszip"; + +/** + * Handles Unzipping a requesting files from an Epub Archive + * @class + */ +class Archive { + + constructor() { + this.zip = undefined; + this.urlCache = {}; + + this.checkRequirements(); + + } + + /** + * Checks to see if JSZip exists in global namspace, + * Requires JSZip if it isn't there + * @private + */ + checkRequirements(){ + try { + this.zip = new JSZip(); + } catch (e) { + throw new Error("JSZip lib not loaded"); + } + } + + /** + * Open an archive + * @param {binary} input + * @param {boolean} [isBase64] tells JSZip if the input data is base64 encoded + * @return {Promise} zipfile + */ + open(input, isBase64){ + return this.zip.loadAsync(input, {"base64": isBase64}); + } + + /** + * Load and Open an archive + * @param {string} zipUrl + * @param {boolean} [isBase64] tells JSZip if the input data is base64 encoded + * @return {Promise} zipfile + */ + openUrl(zipUrl, isBase64){ + return request(zipUrl, "binary") + .then(function(data){ + return this.zip.loadAsync(data, {"base64": isBase64}); + }.bind(this)); + } + + /** + * Request a url from the archive + * @param {string} url a url to request from the archive + * @param {string} [type] specify the type of the returned result + * @return {Promise} + */ + request(url, type){ + var deferred = new defer(); + var response; + var path = new Path(url); + + // If type isn't set, determine it from the file extension + if(!type) { + type = path.extension; + } + + if(type == "blob"){ + response = this.getBlob(url); + } else { + response = this.getText(url); + } + + if (response) { + response.then(function (r) { + let result = this.handleResponse(r, type); + deferred.resolve(result); + }.bind(this)); + } else { + deferred.reject({ + message : "File not found in the epub: " + url, + stack : new Error().stack + }); + } + return deferred.promise; + } + + /** + * Handle the response from request + * @private + * @param {any} response + * @param {string} [type] + * @return {any} the parsed result + */ + handleResponse(response, type){ + var r; + + if(type == "json") { + r = JSON.parse(response); + } + else + if(isXml(type)) { + r = parse(response, "text/xml"); + } + else + if(type == "xhtml") { + r = parse(response, "application/xhtml+xml"); + } + else + if(type == "html" || type == "htm") { + r = parse(response, "text/html"); + } else { + r = response; + } + + return r; + } + + /** + * Get a Blob from Archive by Url + * @param {string} url + * @param {string} [mimeType] + * @return {Blob} + */ + getBlob(url, mimeType){ + var decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash + var entry = this.zip.file(decodededUrl); + + if(entry) { + mimeType = mimeType || mime.lookup(entry.name); + return entry.async("uint8array").then(function(uint8array) { + return new Blob([uint8array], {type : mimeType}); + }); + } + } + + /** + * Get Text from Archive by Url + * @param {string} url + * @param {string} [encoding] + * @return {string} + */ + getText(url, encoding){ + var decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash + var entry = this.zip.file(decodededUrl); + + if(entry) { + return entry.async("string").then(function(text) { + return text; + }); + } + } + + /** + * Get a base64 encoded result from Archive by Url + * @param {string} url + * @param {string} [mimeType] + * @return {string} base64 encoded + */ + getBase64(url, mimeType){ + var decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash + var entry = this.zip.file(decodededUrl); + + if(entry) { + mimeType = mimeType || mime.lookup(entry.name); + return entry.async("base64").then(function(data) { + return "data:" + mimeType + ";base64," + data; + }); + } + } + + /** + * Create a Url from an unarchived item + * @param {string} url + * @param {object} [options.base64] use base64 encoding or blob url + * @return {Promise} url promise with Url string + */ + createUrl(url, options){ + var deferred = new defer(); + var _URL = window.URL || window.webkitURL || window.mozURL; + var tempUrl; + var response; + var useBase64 = options && options.base64; + + if(url in this.urlCache) { + deferred.resolve(this.urlCache[url]); + return deferred.promise; + } + + if (useBase64) { + response = this.getBase64(url); + + if (response) { + response.then(function(tempUrl) { + + this.urlCache[url] = tempUrl; + deferred.resolve(tempUrl); + + }.bind(this)); + + } + + } else { + + response = this.getBlob(url); + + if (response) { + response.then(function(blob) { + + tempUrl = _URL.createObjectURL(blob); + this.urlCache[url] = tempUrl; + deferred.resolve(tempUrl); + + }.bind(this)); + + } + } + + + if (!response) { + deferred.reject({ + message : "File not found in the epub: " + url, + stack : new Error().stack + }); + } + + return deferred.promise; + } + + /** + * Revoke Temp Url for a achive item + * @param {string} url url of the item in the archive + */ + revokeUrl(url){ + var _URL = window.URL || window.webkitURL || window.mozURL; + var fromCache = this.urlCache[url]; + if(fromCache) _URL.revokeObjectURL(fromCache); + } + + destroy() { + var _URL = window.URL || window.webkitURL || window.mozURL; + for (let fromCache in this.urlCache) { + _URL.revokeObjectURL(fromCache); + } + this.zip = undefined; + this.urlCache = {}; + } +} + +export default Archive; -- cgit v1.2.3