mirror of
https://github.com/futurepress/epub.js.git
synced 2025-10-04 15:09:16 +02:00
Added resources, renamed unarchive -> archive, moved replacements to Book
This commit is contained in:
parent
47787678f7
commit
b5cfc74e12
8 changed files with 252 additions and 260 deletions
|
@ -1,15 +1,16 @@
|
||||||
var core = require('./core');
|
var core = require('./core');
|
||||||
var request = require('./request');
|
var request = require('./request');
|
||||||
var mime = require('../libs/mime/mime');
|
var mime = require('../libs/mime/mime');
|
||||||
|
var Path = require('./core').Path;
|
||||||
|
|
||||||
function Unarchive() {
|
function Archive() {
|
||||||
|
|
||||||
this.checkRequirements();
|
this.checkRequirements();
|
||||||
this.urlCache = {};
|
this.urlCache = {};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Unarchive.prototype.checkRequirements = function(callback){
|
Archive.prototype.checkRequirements = function(callback){
|
||||||
try {
|
try {
|
||||||
if (typeof JSZip === 'undefined') {
|
if (typeof JSZip === 'undefined') {
|
||||||
JSZip = require('jszip');
|
JSZip = require('jszip');
|
||||||
|
@ -20,25 +21,26 @@ Unarchive.prototype.checkRequirements = function(callback){
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Unarchive.prototype.open = function(input, isBase64){
|
Archive.prototype.open = function(input, isBase64){
|
||||||
return this.zip.loadAsync(input, {"base64": isBase64});
|
return this.zip.loadAsync(input, {"base64": isBase64});
|
||||||
};
|
};
|
||||||
|
|
||||||
Unarchive.prototype.openUrl = function(zipUrl, isBase64){
|
Archive.prototype.openUrl = function(zipUrl, isBase64){
|
||||||
return request(zipUrl, "binary")
|
return request(zipUrl, "binary")
|
||||||
.then(function(data){
|
.then(function(data){
|
||||||
return this.zip.loadAsync(data, {"base64": isBase64});
|
return this.zip.loadAsync(data, {"base64": isBase64});
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
};
|
};
|
||||||
|
|
||||||
Unarchive.prototype.request = function(url, type){
|
Archive.prototype.request = function(url, type){
|
||||||
var deferred = new core.defer();
|
var deferred = new core.defer();
|
||||||
var response;
|
var response;
|
||||||
var r;
|
var r;
|
||||||
|
var path = new Path(url);
|
||||||
|
|
||||||
// If type isn't set, determine it from the file extension
|
// If type isn't set, determine it from the file extension
|
||||||
if(!type) {
|
if(!type) {
|
||||||
type = core.extension(url);
|
type = path.extension;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(type == 'blob'){
|
if(type == 'blob'){
|
||||||
|
@ -61,7 +63,7 @@ Unarchive.prototype.request = function(url, type){
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
};
|
};
|
||||||
|
|
||||||
Unarchive.prototype.handleResponse = function(response, type){
|
Archive.prototype.handleResponse = function(response, type){
|
||||||
var r;
|
var r;
|
||||||
|
|
||||||
if(type == "json") {
|
if(type == "json") {
|
||||||
|
@ -85,7 +87,7 @@ Unarchive.prototype.handleResponse = function(response, type){
|
||||||
return r;
|
return r;
|
||||||
};
|
};
|
||||||
|
|
||||||
Unarchive.prototype.getBlob = function(url, _mimeType){
|
Archive.prototype.getBlob = function(url, _mimeType){
|
||||||
var decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash
|
var decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash
|
||||||
var entry = this.zip.file(decodededUrl);
|
var entry = this.zip.file(decodededUrl);
|
||||||
var mimeType;
|
var mimeType;
|
||||||
|
@ -98,7 +100,7 @@ Unarchive.prototype.getBlob = function(url, _mimeType){
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Unarchive.prototype.getText = function(url, encoding){
|
Archive.prototype.getText = function(url, encoding){
|
||||||
var decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash
|
var decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash
|
||||||
var entry = this.zip.file(decodededUrl);
|
var entry = this.zip.file(decodededUrl);
|
||||||
|
|
||||||
|
@ -109,7 +111,7 @@ Unarchive.prototype.getText = function(url, encoding){
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Unarchive.prototype.getBase64 = function(url, _mimeType){
|
Archive.prototype.getBase64 = function(url, _mimeType){
|
||||||
var decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash
|
var decodededUrl = window.decodeURIComponent(url.substr(1)); // Remove first slash
|
||||||
var entry = this.zip.file(decodededUrl);
|
var entry = this.zip.file(decodededUrl);
|
||||||
var mimeType;
|
var mimeType;
|
||||||
|
@ -122,7 +124,7 @@ Unarchive.prototype.getBase64 = function(url, _mimeType){
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Unarchive.prototype.createUrl = function(url, options){
|
Archive.prototype.createUrl = function(url, options){
|
||||||
var deferred = new core.defer();
|
var deferred = new core.defer();
|
||||||
var _URL = window.URL || window.webkitURL || window.mozURL;
|
var _URL = window.URL || window.webkitURL || window.mozURL;
|
||||||
var tempUrl;
|
var tempUrl;
|
||||||
|
@ -175,10 +177,10 @@ Unarchive.prototype.createUrl = function(url, options){
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
};
|
};
|
||||||
|
|
||||||
Unarchive.prototype.revokeUrl = function(url){
|
Archive.prototype.revokeUrl = function(url){
|
||||||
var _URL = window.URL || window.webkitURL || window.mozURL;
|
var _URL = window.URL || window.webkitURL || window.mozURL;
|
||||||
var fromCache = this.urlCache[url];
|
var fromCache = this.urlCache[url];
|
||||||
if(fromCache) _URL.revokeObjectURL(fromCache);
|
if(fromCache) _URL.revokeObjectURL(fromCache);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = Unarchive;
|
module.exports = Archive;
|
94
src/book.js
94
src/book.js
|
@ -9,8 +9,9 @@ var Parser = require('./parser');
|
||||||
var Container = require('./container');
|
var Container = require('./container');
|
||||||
var Packaging = require('./packaging');
|
var Packaging = require('./packaging');
|
||||||
var Navigation = require('./navigation');
|
var Navigation = require('./navigation');
|
||||||
|
var Resources = require('./resources');
|
||||||
var Rendition = require('./rendition');
|
var Rendition = require('./rendition');
|
||||||
var Unarchive = require('./unarchive');
|
var Archive = require('./archive');
|
||||||
var request = require('./request');
|
var request = require('./request');
|
||||||
var EpubCFI = require('./epubcfi');
|
var EpubCFI = require('./epubcfi');
|
||||||
|
|
||||||
|
@ -31,7 +32,8 @@ function Book(url, options){
|
||||||
this.settings = core.extend(this.settings || {}, {
|
this.settings = core.extend(this.settings || {}, {
|
||||||
requestMethod: this.requestMethod,
|
requestMethod: this.requestMethod,
|
||||||
requestCredentials: undefined,
|
requestCredentials: undefined,
|
||||||
encoding: undefined // optional to pass 'binary' or base64' for archived Epubs
|
encoding: undefined, // optional to pass 'binary' or base64' for archived Epubs
|
||||||
|
base64: true
|
||||||
});
|
});
|
||||||
|
|
||||||
core.extend(this.settings, options);
|
core.extend(this.settings, options);
|
||||||
|
@ -51,7 +53,8 @@ function Book(url, options){
|
||||||
metadata: new core.defer(),
|
metadata: new core.defer(),
|
||||||
cover: new core.defer(),
|
cover: new core.defer(),
|
||||||
navigation: new core.defer(),
|
navigation: new core.defer(),
|
||||||
pageList: new core.defer()
|
pageList: new core.defer(),
|
||||||
|
resources: new core.defer()
|
||||||
};
|
};
|
||||||
|
|
||||||
this.loaded = {
|
this.loaded = {
|
||||||
|
@ -60,7 +63,8 @@ function Book(url, options){
|
||||||
metadata: this.loading.metadata.promise,
|
metadata: this.loading.metadata.promise,
|
||||||
cover: this.loading.cover.promise,
|
cover: this.loading.cover.promise,
|
||||||
navigation: this.loading.navigation.promise,
|
navigation: this.loading.navigation.promise,
|
||||||
pageList: this.loading.pageList.promise
|
pageList: this.loading.pageList.promise,
|
||||||
|
resources: this.loading.resources.promise
|
||||||
};
|
};
|
||||||
|
|
||||||
// this.ready = RSVP.hash(this.loaded);
|
// this.ready = RSVP.hash(this.loaded);
|
||||||
|
@ -72,7 +76,7 @@ function Book(url, options){
|
||||||
this.loaded.metadata,
|
this.loaded.metadata,
|
||||||
this.loaded.cover,
|
this.loaded.cover,
|
||||||
this.loaded.navigation,
|
this.loaded.navigation,
|
||||||
this.loaded.pageList ]);
|
this.loaded.resources ]);
|
||||||
|
|
||||||
|
|
||||||
// Queue for methods used before opening
|
// Queue for methods used before opening
|
||||||
|
@ -128,22 +132,20 @@ Book.prototype.open = function(input, what){
|
||||||
|
|
||||||
if (type === "binary") {
|
if (type === "binary") {
|
||||||
this.archived = true;
|
this.archived = true;
|
||||||
|
this.url = new Url("/", "");
|
||||||
opening = this.openEpub(input);
|
opening = this.openEpub(input);
|
||||||
} else if (type === "epub") {
|
} else if (type === "epub") {
|
||||||
this.archived = true;
|
this.archived = true;
|
||||||
|
this.url = new Url("/", "");
|
||||||
opening = this.request(input, 'binary')
|
opening = this.request(input, 'binary')
|
||||||
.then(function(epubData) {
|
.then(this.openEpub.bind(this));
|
||||||
return this.openEpub(epubData);
|
|
||||||
}.bind(this));
|
|
||||||
} else if(type == "opf") {
|
} else if(type == "opf") {
|
||||||
this.url = new Url(input);
|
this.url = new Url(input);
|
||||||
opening = this.openPackaging(input);
|
opening = this.openPackaging(input);
|
||||||
} else {
|
} else {
|
||||||
this.url = new Url(input);
|
this.url = new Url(input);
|
||||||
opening = this.openContainer(CONTAINER_PATH)
|
opening = this.openContainer(CONTAINER_PATH)
|
||||||
.then(function(packagePath) {
|
.then(this.openPackaging.bind(this));
|
||||||
return this.openPackaging(packagePath);
|
|
||||||
}.bind(this))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return opening;
|
return opening;
|
||||||
|
@ -152,10 +154,10 @@ Book.prototype.open = function(input, what){
|
||||||
Book.prototype.openEpub = function(data, encoding){
|
Book.prototype.openEpub = function(data, encoding){
|
||||||
return this.unarchive(data, encoding || this.settings.encoding)
|
return this.unarchive(data, encoding || this.settings.encoding)
|
||||||
.then(function() {
|
.then(function() {
|
||||||
return this.openContainer("/" + CONTAINER_PATH);
|
return this.openContainer(CONTAINER_PATH);
|
||||||
}.bind(this))
|
}.bind(this))
|
||||||
.then(function(packagePath) {
|
.then(function(packagePath) {
|
||||||
return this.openPackaging("/" + packagePath);
|
return this.openPackaging(packagePath);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -163,7 +165,7 @@ Book.prototype.openContainer = function(url){
|
||||||
return this.load(url)
|
return this.load(url)
|
||||||
.then(function(xml) {
|
.then(function(xml) {
|
||||||
this.container = new Container(xml);
|
this.container = new Container(xml);
|
||||||
return this.container.packagePath;
|
return this.resolve(this.container.packagePath);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -180,9 +182,9 @@ Book.prototype.openPackaging = function(url){
|
||||||
|
|
||||||
Book.prototype.load = function (path) {
|
Book.prototype.load = function (path) {
|
||||||
var resolved;
|
var resolved;
|
||||||
if(this.unarchived) {
|
if(this.archived) {
|
||||||
resolved = this.resolve(path);
|
resolved = this.resolve(path);
|
||||||
return this.unarchived.request(resolved);
|
return this.archive.request(resolved);
|
||||||
} else {
|
} else {
|
||||||
resolved = this.resolve(path);
|
resolved = this.resolve(path);
|
||||||
return this.request(resolved, null, this.requestCredentials, this.requestHeaders);
|
return this.request(resolved, null, this.requestCredentials, this.requestHeaders);
|
||||||
|
@ -244,6 +246,12 @@ Book.prototype.unpack = function(opf){
|
||||||
|
|
||||||
this.spine.unpack(this.package, this.resolve.bind(this));
|
this.spine.unpack(this.package, this.resolve.bind(this));
|
||||||
|
|
||||||
|
this.resources = new Resources(this.package.manifest, {
|
||||||
|
archive: this.archive,
|
||||||
|
resolver: this.resolve.bind(this),
|
||||||
|
base64: this.settings.base64
|
||||||
|
});
|
||||||
|
|
||||||
this.loadNavigation(this.package).then(function(toc){
|
this.loadNavigation(this.package).then(function(toc){
|
||||||
this.toc = toc;
|
this.toc = toc;
|
||||||
this.loading.navigation.resolve(this.toc);
|
this.loading.navigation.resolve(this.toc);
|
||||||
|
@ -256,11 +264,20 @@ Book.prototype.unpack = function(opf){
|
||||||
this.loading.metadata.resolve(this.package.metadata);
|
this.loading.metadata.resolve(this.package.metadata);
|
||||||
this.loading.spine.resolve(this.spine);
|
this.loading.spine.resolve(this.spine);
|
||||||
this.loading.cover.resolve(this.cover);
|
this.loading.cover.resolve(this.cover);
|
||||||
|
this.loading.resources.resolve(this.resources);
|
||||||
|
|
||||||
|
|
||||||
this.isOpen = true;
|
this.isOpen = true;
|
||||||
|
|
||||||
|
if(this.archived) {
|
||||||
|
this.replacements().then(function() {
|
||||||
|
this.opening.resolve(this);
|
||||||
|
}.bind(this));
|
||||||
|
} else {
|
||||||
// Resolve book opened promise
|
// Resolve book opened promise
|
||||||
this.opening.resolve(this);
|
this.opening.resolve(this);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Book.prototype.loadNavigation = function(opf){
|
Book.prototype.loadNavigation = function(opf){
|
||||||
|
@ -311,34 +328,8 @@ Book.prototype.setRequestHeaders = function(_headers) {
|
||||||
* Unarchive a zipped epub
|
* Unarchive a zipped epub
|
||||||
*/
|
*/
|
||||||
Book.prototype.unarchive = function(bookUrl, encoding){
|
Book.prototype.unarchive = function(bookUrl, encoding){
|
||||||
this.unarchived = new Unarchive();
|
this.archive = new Archive();
|
||||||
return this.unarchived.open(bookUrl, encoding);
|
return this.archive.open(bookUrl, encoding);
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if url has a .epub or .zip extension, or is ArrayBuffer (of zip/epub)
|
|
||||||
*/
|
|
||||||
Book.prototype.isArchivedUrl = function(bookUrl){
|
|
||||||
var extension;
|
|
||||||
|
|
||||||
if (bookUrl instanceof ArrayBuffer) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reuse parsed url or create a new uri object
|
|
||||||
// if(typeof(bookUrl) === "object") {
|
|
||||||
// uri = bookUrl;
|
|
||||||
// } else {
|
|
||||||
// uri = core.uri(bookUrl);
|
|
||||||
// }
|
|
||||||
// uri = URI(bookUrl);
|
|
||||||
extension = core.extension(bookUrl);
|
|
||||||
|
|
||||||
if(extension && (extension == "epub" || extension == "zip")){
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -347,8 +338,8 @@ Book.prototype.isArchivedUrl = function(bookUrl){
|
||||||
Book.prototype.coverUrl = function(){
|
Book.prototype.coverUrl = function(){
|
||||||
var retrieved = this.loaded.cover.
|
var retrieved = this.loaded.cover.
|
||||||
then(function(url) {
|
then(function(url) {
|
||||||
if(this.unarchived) {
|
if(this.archived) {
|
||||||
return this.unarchived.createUrl(this.cover);
|
return this.archive.createUrl(this.cover);
|
||||||
}else{
|
}else{
|
||||||
return this.cover;
|
return this.cover;
|
||||||
}
|
}
|
||||||
|
@ -359,6 +350,17 @@ Book.prototype.coverUrl = function(){
|
||||||
return retrieved;
|
return retrieved;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Book.prototype.replacements = function(){
|
||||||
|
this.spine.hooks.serialize.register(function(output, section) {
|
||||||
|
section.output = this.resources.substitute(output, section.url);
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
return this.resources.replacements().
|
||||||
|
then(function() {
|
||||||
|
return this.resources.replaceCss();
|
||||||
|
}.bind(this));
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a DOM Range for a given CFI Range
|
* Find a DOM Range for a given CFI Range
|
||||||
*/
|
*/
|
||||||
|
|
49
src/core.js
49
src/core.js
|
@ -12,6 +12,7 @@ var requestAnimationFrame = (typeof window != 'undefined') ? (window.requestAnim
|
||||||
*/
|
*/
|
||||||
function Url(urlString, baseString) {
|
function Url(urlString, baseString) {
|
||||||
var absolute = (urlString.indexOf('://') > -1);
|
var absolute = (urlString.indexOf('://') > -1);
|
||||||
|
var pathname;
|
||||||
|
|
||||||
this.href = urlString;
|
this.href = urlString;
|
||||||
this.protocol = "";
|
this.protocol = "";
|
||||||
|
@ -20,7 +21,7 @@ function Url(urlString, baseString) {
|
||||||
this.search = "";
|
this.search = "";
|
||||||
this.base = baseString || undefined;
|
this.base = baseString || undefined;
|
||||||
|
|
||||||
if (!absolute && !baseString) {
|
if (!absolute && typeof(baseString) !== "string") {
|
||||||
this.base = window && window.location.href;
|
this.base = window && window.location.href;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,12 +33,15 @@ function Url(urlString, baseString) {
|
||||||
this.origin = this.Url.origin;
|
this.origin = this.Url.origin;
|
||||||
this.fragment = this.Url.fragment;
|
this.fragment = this.Url.fragment;
|
||||||
this.search = this.Url.search;
|
this.search = this.Url.search;
|
||||||
|
|
||||||
|
pathname = this.Url.pathname;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// console.error(e);
|
// console.error(e);
|
||||||
this.Url = undefined;
|
this.Url = undefined;
|
||||||
|
pathname = urlString;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.Path = new Path(this.Url.pathname);
|
this.Path = new Path(pathname);
|
||||||
this.directory = this.Path.directory;
|
this.directory = this.Path.directory;
|
||||||
this.filename = this.Path.filename;
|
this.filename = this.Path.filename;
|
||||||
this.extension = this.Path.extension;
|
this.extension = this.Path.extension;
|
||||||
|
@ -96,6 +100,10 @@ Path.prototype.parse = function (what) {
|
||||||
return path.parse(what);
|
return path.parse(what);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Path.prototype.isAbsolute = function (what) {
|
||||||
|
return path.isAbsolute(what || this.path);
|
||||||
|
};
|
||||||
|
|
||||||
Path.prototype.isDirectory = function (what) {
|
Path.prototype.isDirectory = function (what) {
|
||||||
return (what.charAt(what.length-1) === '/');
|
return (what.charAt(what.length-1) === '/');
|
||||||
};
|
};
|
||||||
|
@ -122,41 +130,6 @@ function assertPath(path) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function extension(_url) {
|
|
||||||
var url;
|
|
||||||
var pathname;
|
|
||||||
var ext;
|
|
||||||
|
|
||||||
try {
|
|
||||||
url = new Url(url);
|
|
||||||
pathname = url.pathname;
|
|
||||||
} catch (e) {
|
|
||||||
pathname = _url;
|
|
||||||
}
|
|
||||||
|
|
||||||
ext = path.extname(pathname);
|
|
||||||
if (ext) {
|
|
||||||
return ext.slice(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
function directory(_url) {
|
|
||||||
var url;
|
|
||||||
var pathname;
|
|
||||||
var ext;
|
|
||||||
|
|
||||||
try {
|
|
||||||
url = new Url(url);
|
|
||||||
pathname = url.pathname;
|
|
||||||
} catch (e) {
|
|
||||||
pathname = _url;
|
|
||||||
}
|
|
||||||
|
|
||||||
return path.dirname(pathname);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isElement(obj) {
|
function isElement(obj) {
|
||||||
return !!(obj && obj.nodeType == 1);
|
return !!(obj && obj.nodeType == 1);
|
||||||
};
|
};
|
||||||
|
@ -630,8 +603,6 @@ function defer() {
|
||||||
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
'extension' : extension,
|
|
||||||
'directory' : directory,
|
|
||||||
'isElement': isElement,
|
'isElement': isElement,
|
||||||
'uuid': uuid,
|
'uuid': uuid,
|
||||||
'values': values,
|
'values': values,
|
||||||
|
|
155
src/rendition.js
155
src/rendition.js
|
@ -58,11 +58,6 @@ function Rendition(book, options) {
|
||||||
// this.starting = new core.defer();
|
// this.starting = new core.defer();
|
||||||
// this.started = this.starting.promise;
|
// this.started = this.starting.promise;
|
||||||
this.q.enqueue(this.start);
|
this.q.enqueue(this.start);
|
||||||
|
|
||||||
if(this.book.archived) {
|
|
||||||
this.q.enqueue(this.replacements.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Rendition.prototype.setManager = function(manager) {
|
Rendition.prototype.setManager = function(manager) {
|
||||||
|
@ -400,156 +395,6 @@ Rendition.prototype.triggerSelectedEvent = function(cfirange){
|
||||||
this.emit("selected", cfirange);
|
this.emit("selected", cfirange);
|
||||||
};
|
};
|
||||||
|
|
||||||
Rendition.prototype.replacements = function(){
|
|
||||||
// Wait for loading
|
|
||||||
// return this.q.enqueue(function () {
|
|
||||||
// Get thes books manifest
|
|
||||||
var manifest = this.book.package.manifest;
|
|
||||||
var manifestArray = Object.keys(manifest).
|
|
||||||
map(function (key){
|
|
||||||
return manifest[key];
|
|
||||||
});
|
|
||||||
|
|
||||||
// Exclude HTML
|
|
||||||
var items = manifestArray.
|
|
||||||
filter(function (item){
|
|
||||||
if (item.type != "application/xhtml+xml" &&
|
|
||||||
item.type != "text/html") {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Only CSS
|
|
||||||
var css = items.
|
|
||||||
filter(function (item){
|
|
||||||
if (item.type === "text/css") {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Css Urls
|
|
||||||
var cssUrls = css.map(function(item) {
|
|
||||||
return item.href;
|
|
||||||
});
|
|
||||||
|
|
||||||
// All Assets Urls
|
|
||||||
var urls = items.
|
|
||||||
map(function(item) {
|
|
||||||
return item.href;
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
// Create blob urls for all the assets
|
|
||||||
var processing = urls.
|
|
||||||
map(function(url) {
|
|
||||||
// var absolute = new URL(url, this.book.baseUrl).toString();
|
|
||||||
var absolute = this.book.resolve(url);
|
|
||||||
// Full url from archive base
|
|
||||||
return this.book.unarchived.createUrl(absolute, {"base64": this.settings.useBase64});
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
var replacementUrls;
|
|
||||||
|
|
||||||
// After all the urls are created
|
|
||||||
return Promise.all(processing)
|
|
||||||
.then(function(_replacementUrls) {
|
|
||||||
var replaced = [];
|
|
||||||
|
|
||||||
replacementUrls = _replacementUrls;
|
|
||||||
|
|
||||||
// Replace Asset Urls in the text of all css files
|
|
||||||
cssUrls.forEach(function(href) {
|
|
||||||
replaced.push(this.replaceCss(href, urls, replacementUrls));
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
return Promise.all(replaced);
|
|
||||||
|
|
||||||
}.bind(this))
|
|
||||||
.then(function () {
|
|
||||||
// Replace Asset Urls in chapters
|
|
||||||
// by registering a hook after the sections contents has been serialized
|
|
||||||
this.book.spine.hooks.serialize.register(function(output, section) {
|
|
||||||
|
|
||||||
this.replaceAssets(section, urls, replacementUrls);
|
|
||||||
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
}.bind(this))
|
|
||||||
.catch(function(reason){
|
|
||||||
console.error(reason);
|
|
||||||
});
|
|
||||||
// }.bind(this));
|
|
||||||
};
|
|
||||||
|
|
||||||
Rendition.prototype.replaceCss = function(href, urls, replacementUrls){
|
|
||||||
var newUrl;
|
|
||||||
var indexInUrls;
|
|
||||||
|
|
||||||
// Find the absolute url of the css file
|
|
||||||
// var fileUri = URI(href);
|
|
||||||
// var absolute = fileUri.absoluteTo(this.book.baseUrl).toString();
|
|
||||||
|
|
||||||
if (path.isAbsolute(href)) {
|
|
||||||
return new Promise(function(resolve, reject){
|
|
||||||
resolve(urls, replacementUrls);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var fileUri;
|
|
||||||
var absolute = this.book.resolve(href);
|
|
||||||
|
|
||||||
// Get the text of the css file from the archive
|
|
||||||
var textResponse = this.book.unarchived.getText(absolute);
|
|
||||||
// Get asset links relative to css file
|
|
||||||
var relUrls = urls.
|
|
||||||
map(function(assetHref) {
|
|
||||||
var resolved = this.book.resolve(assetHref);
|
|
||||||
var relative = new Path(absolute).relative(resolved);
|
|
||||||
|
|
||||||
return relative;
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
return textResponse.then(function (text) {
|
|
||||||
// Replacements in the css text
|
|
||||||
text = replace.substitute(text, relUrls, replacementUrls);
|
|
||||||
|
|
||||||
// Get the new url
|
|
||||||
if (this.settings.useBase64) {
|
|
||||||
newUrl = core.createBase64Url(text, 'text/css');
|
|
||||||
} else {
|
|
||||||
newUrl = core.createBlobUrl(text, 'text/css');
|
|
||||||
}
|
|
||||||
|
|
||||||
// switch the url in the replacementUrls
|
|
||||||
indexInUrls = urls.indexOf(href);
|
|
||||||
if (indexInUrls > -1) {
|
|
||||||
replacementUrls[indexInUrls] = newUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Promise(function(resolve, reject){
|
|
||||||
resolve(urls, replacementUrls);
|
|
||||||
});
|
|
||||||
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
Rendition.prototype.replaceAssets = function(section, urls, replacementUrls){
|
|
||||||
// var fileUri = URI(section.url);
|
|
||||||
var fileUri;
|
|
||||||
var absolute = section.url;
|
|
||||||
|
|
||||||
// Get Urls relative to current sections
|
|
||||||
var relUrls = urls.
|
|
||||||
map(function(href) {
|
|
||||||
var resolved = this.book.resolve(href);
|
|
||||||
var relative = new Path(absolute).relative(resolved);
|
|
||||||
|
|
||||||
return relative;
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
section.output = replace.substitute(section.output, relUrls, replacementUrls);
|
|
||||||
};
|
|
||||||
|
|
||||||
Rendition.prototype.range = function(_cfi, ignoreClass){
|
Rendition.prototype.range = function(_cfi, ignoreClass){
|
||||||
var cfi = new EpubCFI(_cfi);
|
var cfi = new EpubCFI(_cfi);
|
||||||
var found = this.visible().filter(function (view) {
|
var found = this.visible().filter(function (view) {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
var core = require('./core');
|
var core = require('./core');
|
||||||
|
var Path = require('./core').Path;
|
||||||
|
|
||||||
function request(url, type, withCredentials, headers) {
|
function request(url, type, withCredentials, headers) {
|
||||||
var supportsURL = (typeof window != "undefined") ? window.URL : false; // TODO: fallback for url if window isn't defined
|
var supportsURL = (typeof window != "undefined") ? window.URL : false; // TODO: fallback for url if window isn't defined
|
||||||
|
@ -40,9 +41,7 @@ function request(url, type, withCredentials, headers) {
|
||||||
|
|
||||||
// If type isn't set, determine it from the file extension
|
// If type isn't set, determine it from the file extension
|
||||||
if(!type) {
|
if(!type) {
|
||||||
// uri = new URI(url);
|
type = new Path(url).extension;
|
||||||
// type = uri.suffix();
|
|
||||||
type = core.extension(url);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(type == 'blob'){
|
if(type == 'blob'){
|
||||||
|
|
172
src/resources.js
Normal file
172
src/resources.js
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
var replace = require('./replacements');
|
||||||
|
var core = require('./core');
|
||||||
|
var Path = require('./core').Path;
|
||||||
|
var path = require('path');
|
||||||
|
|
||||||
|
function Resources(manifest, options) {
|
||||||
|
this.settings = {
|
||||||
|
base64: (options && options.base64) || true,
|
||||||
|
archive: (options && options.archive),
|
||||||
|
resolver: (options && options.resolver)
|
||||||
|
};
|
||||||
|
this.manifest = manifest;
|
||||||
|
this.resources = Object.keys(manifest).
|
||||||
|
map(function (key){
|
||||||
|
return manifest[key];
|
||||||
|
});
|
||||||
|
|
||||||
|
this.replacementUrls = undefined;
|
||||||
|
|
||||||
|
this.split();
|
||||||
|
this.urls();
|
||||||
|
}
|
||||||
|
|
||||||
|
Resources.prototype.split = function(){
|
||||||
|
|
||||||
|
// HTML
|
||||||
|
this.html = this.resources.
|
||||||
|
filter(function (item){
|
||||||
|
if (item.type === "application/xhtml+xml" ||
|
||||||
|
item.type === "text/html") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Exclude HTML
|
||||||
|
this.assets = this.resources.
|
||||||
|
filter(function (item){
|
||||||
|
if (item.type !== "application/xhtml+xml" &&
|
||||||
|
item.type !== "text/html") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Only CSS
|
||||||
|
this.css = this.resources.
|
||||||
|
filter(function (item){
|
||||||
|
if (item.type === "text/css") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Resources.prototype.urls = function(){
|
||||||
|
|
||||||
|
// All Assets Urls
|
||||||
|
this.urls = this.assets.
|
||||||
|
map(function(item) {
|
||||||
|
return item.href;
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
// Css Urls
|
||||||
|
this.cssUrls = this.css.map(function(item) {
|
||||||
|
return item.href;
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create blob urls for all the assets
|
||||||
|
* @param {Archive} archive
|
||||||
|
* @param {resolver} resolver Url resolver
|
||||||
|
* @return {Promise} returns replacement urls
|
||||||
|
*/
|
||||||
|
Resources.prototype.replacements = function(archive, resolver){
|
||||||
|
archive = archive || this.settings.archive;
|
||||||
|
resolver = resolver || this.settings.resolver;
|
||||||
|
var replacements = this.urls.
|
||||||
|
map(function(url) {
|
||||||
|
var absolute = resolver(url);
|
||||||
|
|
||||||
|
return archive.createUrl(absolute, {"base64": this.settings.base64});
|
||||||
|
}.bind(this))
|
||||||
|
|
||||||
|
return Promise.all(replacements)
|
||||||
|
.then(function(replacementUrls) {
|
||||||
|
this.replacementUrls = replacementUrls;
|
||||||
|
return replacementUrls;
|
||||||
|
}.bind(this));
|
||||||
|
};
|
||||||
|
|
||||||
|
Resources.prototype.replaceCss = function(archive, resolver){
|
||||||
|
var replaced = [];
|
||||||
|
archive = archive || this.settings.archive;
|
||||||
|
resolver = resolver || this.settings.resolver;
|
||||||
|
this.cssUrls.forEach(function(href) {
|
||||||
|
var replacment = this.createCssFile(href, archive, resolver)
|
||||||
|
.then(function (replacementUrl) {
|
||||||
|
// switch the url in the replacementUrls
|
||||||
|
var indexInUrls = this.urls.indexOf(href);
|
||||||
|
if (indexInUrls > -1) {
|
||||||
|
this.replacementUrls[indexInUrls] = replacementUrl;
|
||||||
|
}
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
replaced.push(replacment);
|
||||||
|
}.bind(this));
|
||||||
|
return Promise.all(replaced);
|
||||||
|
};
|
||||||
|
|
||||||
|
Resources.prototype.createCssFile = function(href, archive, resolver){
|
||||||
|
var newUrl;
|
||||||
|
var indexInUrls;
|
||||||
|
archive = archive || this.settings.archive;
|
||||||
|
resolver = resolver || this.settings.resolver;
|
||||||
|
|
||||||
|
if (path.isAbsolute(href)) {
|
||||||
|
return new Promise(function(resolve, reject){
|
||||||
|
resolve(urls, replacementUrls);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var absolute = resolver(href);
|
||||||
|
|
||||||
|
// Get the text of the css file from the archive
|
||||||
|
var textResponse = archive.getText(absolute);
|
||||||
|
// Get asset links relative to css file
|
||||||
|
var relUrls = this.urls.map(function(assetHref) {
|
||||||
|
var resolved = resolver(assetHref);
|
||||||
|
var relative = new Path(absolute).relative(resolved);
|
||||||
|
|
||||||
|
return relative;
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
return textResponse.then(function (text) {
|
||||||
|
// Replacements in the css text
|
||||||
|
text = replace.substitute(text, relUrls, this.replacementUrls);
|
||||||
|
|
||||||
|
// Get the new url
|
||||||
|
if (this.settings.base64) {
|
||||||
|
newUrl = core.createBase64Url(text, 'text/css');
|
||||||
|
} else {
|
||||||
|
newUrl = core.createBlobUrl(text, 'text/css');
|
||||||
|
}
|
||||||
|
|
||||||
|
return newUrl;
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Resources.prototype.relativeTo = function(absolute, resolver){
|
||||||
|
resolver = resolver || this.settings.resolver;
|
||||||
|
|
||||||
|
// Get Urls relative to current sections
|
||||||
|
return this.urls.
|
||||||
|
map(function(href) {
|
||||||
|
var resolved = resolver(href);
|
||||||
|
var relative = new Path(absolute).relative(resolved);
|
||||||
|
return relative;
|
||||||
|
}.bind(this));
|
||||||
|
};
|
||||||
|
|
||||||
|
Resources.prototype.substitute = function(content, url) {
|
||||||
|
var relUrls;
|
||||||
|
if (url) {
|
||||||
|
relUrls = this.relativeTo(url);
|
||||||
|
} else {
|
||||||
|
relUrls = this.urls;
|
||||||
|
}
|
||||||
|
return replace.substitute(content, relUrls, this.replacementUrls);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = Resources;
|
|
@ -1,6 +1,7 @@
|
||||||
var core = require('./core');
|
var core = require('./core');
|
||||||
var EpubCFI = require('./epubcfi');
|
var EpubCFI = require('./epubcfi');
|
||||||
var Hook = require('./hook');
|
var Hook = require('./hook');
|
||||||
|
var Url = require('./core').Url;
|
||||||
|
|
||||||
function Section(item, hooks){
|
function Section(item, hooks){
|
||||||
this.idref = item.idref;
|
this.idref = item.idref;
|
||||||
|
@ -36,7 +37,7 @@ Section.prototype.load = function(_request){
|
||||||
request(this.url)
|
request(this.url)
|
||||||
.then(function(xml){
|
.then(function(xml){
|
||||||
var base;
|
var base;
|
||||||
var directory = core.directory(this.url);
|
var directory = new Url(this.url).directory;
|
||||||
|
|
||||||
this.document = xml;
|
this.document = xml;
|
||||||
this.contents = xml.documentElement;
|
this.contents = xml.documentElement;
|
||||||
|
|
|
@ -45,7 +45,7 @@ describe('ePub', function() {
|
||||||
|
|
||||||
return book.opened.then(function(){
|
return book.opened.then(function(){
|
||||||
assert.equal( book.isOpen, true, "book is opened" );
|
assert.equal( book.isOpen, true, "book is opened" );
|
||||||
assert( book.unarchived, "book is unarchived" );
|
assert( book.archive, "book is unarchived" );
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue