Updated for JSHint
This commit is contained in:
parent
ea226be4c4
commit
44df08632e
3
README.md
Normal file
3
README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#epub
|
||||||
|
|
||||||
|
**epub** is a node.js module to parse EPUB electronic book files.
|
115
epub.js
115
epub.js
@ -3,11 +3,7 @@ var ZipFile = require("zipfile").ZipFile,
|
|||||||
utillib = require("util"),
|
utillib = require("util"),
|
||||||
EventEmitter = require('events').EventEmitter;
|
EventEmitter = require('events').EventEmitter;
|
||||||
|
|
||||||
|
//TODO: Cache parsed data
|
||||||
//TODO: Cache parsed data to DB
|
|
||||||
|
|
||||||
// export
|
|
||||||
module.exports = EPub;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* new EPub(fname[, imageroot][, linkroot])
|
* new EPub(fname[, imageroot][, linkroot])
|
||||||
@ -41,8 +37,12 @@ function EPub(fname, imageroot, linkroot){
|
|||||||
this.imageroot = (imageroot || "/images/").trim();
|
this.imageroot = (imageroot || "/images/").trim();
|
||||||
this.linkroot = (linkroot || "/links/").trim();
|
this.linkroot = (linkroot || "/links/").trim();
|
||||||
|
|
||||||
if(this.imageroot.substr(-1)!="/")this.imageroot+="/";
|
if (this.imageroot.substr(-1) != "/") {
|
||||||
if(this.linkroot.substr(-1)!="/")this.linkroot+="/";
|
this.imageroot += "/";
|
||||||
|
}
|
||||||
|
if (this.linkroot.substr(-1) != "/") {
|
||||||
|
this.linkroot += "/";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
utillib.inherits(EPub, EventEmitter);
|
utillib.inherits(EPub, EventEmitter);
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ EPub.prototype.parse = function(){
|
|||||||
this.toc = [];
|
this.toc = [];
|
||||||
|
|
||||||
this.open();
|
this.open();
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EPub#open() -> undefined
|
* EPub#open() -> undefined
|
||||||
@ -72,7 +72,7 @@ EPub.prototype.parse = function(){
|
|||||||
* and runs mime type check
|
* and runs mime type check
|
||||||
**/
|
**/
|
||||||
EPub.prototype.open = function () {
|
EPub.prototype.open = function () {
|
||||||
try{
|
try {
|
||||||
this.zip = new ZipFile(this.filename);
|
this.zip = new ZipFile(this.filename);
|
||||||
} catch (E) {
|
} catch (E) {
|
||||||
this.emit("error", new Error("Invalid/missing file"));
|
this.emit("error", new Error("Invalid/missing file"));
|
||||||
@ -85,7 +85,7 @@ EPub.prototype.open = function(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.checkMimeType();
|
this.checkMimeType();
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EPub#checkMimeType() -> undefined
|
* EPub#checkMimeType() -> undefined
|
||||||
@ -94,7 +94,9 @@ EPub.prototype.open = function(){
|
|||||||
* are "application/epub+zip". On success runs root file check.
|
* are "application/epub+zip". On success runs root file check.
|
||||||
**/
|
**/
|
||||||
EPub.prototype.checkMimeType = function () {
|
EPub.prototype.checkMimeType = function () {
|
||||||
for(var i=0, len = this.zip.names.length; i<len; i++){
|
var i, len;
|
||||||
|
|
||||||
|
for (i = 0, len = this.zip.names.length; i < len; i++) {
|
||||||
if (this.zip.names[i].toLowerCase() == "mimetype") {
|
if (this.zip.names[i].toLowerCase() == "mimetype") {
|
||||||
this.mimeFile = this.zip.names[i];
|
this.mimeFile = this.zip.names[i];
|
||||||
break;
|
break;
|
||||||
@ -118,7 +120,7 @@ EPub.prototype.checkMimeType = function(){
|
|||||||
|
|
||||||
this.getRootFiles();
|
this.getRootFiles();
|
||||||
}).bind(this));
|
}).bind(this));
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EPub#getRootFiles() -> undefined
|
* EPub#getRootFiles() -> undefined
|
||||||
@ -128,7 +130,8 @@ EPub.prototype.checkMimeType = function(){
|
|||||||
* On success calls the rootfile parser
|
* On success calls the rootfile parser
|
||||||
**/
|
**/
|
||||||
EPub.prototype.getRootFiles = function () {
|
EPub.prototype.getRootFiles = function () {
|
||||||
for(var i=0, len = this.zip.names.length; i<len; i++){
|
var i, len;
|
||||||
|
for (i = 0, len = this.zip.names.length; i < len; i++) {
|
||||||
if (this.zip.names[i].toLowerCase() == "meta-inf/container.xml") {
|
if (this.zip.names[i].toLowerCase() == "meta-inf/container.xml") {
|
||||||
this.containerFile = this.zip.names[i];
|
this.containerFile = this.zip.names[i];
|
||||||
break;
|
break;
|
||||||
@ -155,11 +158,11 @@ EPub.prototype.getRootFiles = function(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
var rootfile = result.rootfiles.rootfile,
|
var rootfile = result.rootfiles.rootfile,
|
||||||
filename = false;
|
filename = false, i, len;
|
||||||
|
|
||||||
if (Array.isArray(rootfile)) {
|
if (Array.isArray(rootfile)) {
|
||||||
|
|
||||||
for(var i=0, len = rootfile.length; i<len; i++){
|
for (i = 0, len = rootfile.length; i < len; i++) {
|
||||||
if (rootfile[i]["@"]["media-type"] &&
|
if (rootfile[i]["@"]["media-type"] &&
|
||||||
rootfile[i]["@"]["media-type"] == "application/oebps-package+xml" &&
|
rootfile[i]["@"]["media-type"] == "application/oebps-package+xml" &&
|
||||||
rootfile[i]["@"]["full-path"]) {
|
rootfile[i]["@"]["full-path"]) {
|
||||||
@ -182,7 +185,7 @@ EPub.prototype.getRootFiles = function(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for(var i=0, len = this.zip.names.length; i<len; i++){
|
for (i = 0, len = this.zip.names.length; i < len; i++) {
|
||||||
if (this.zip.names[i].toLowerCase() == filename) {
|
if (this.zip.names[i].toLowerCase() == filename) {
|
||||||
this.rootFile = this.zip.names[i];
|
this.rootFile = this.zip.names[i];
|
||||||
break;
|
break;
|
||||||
@ -207,7 +210,7 @@ EPub.prototype.getRootFiles = function(){
|
|||||||
|
|
||||||
|
|
||||||
}).bind(this));
|
}).bind(this));
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EPub#handleRootFile() -> undefined
|
* EPub#handleRootFile() -> undefined
|
||||||
@ -234,7 +237,7 @@ EPub.prototype.handleRootFile = function(){
|
|||||||
xmlparser.parseString(xml);
|
xmlparser.parseString(xml);
|
||||||
|
|
||||||
}).bind(this));
|
}).bind(this));
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EPub#parseRootFile() -> undefined
|
* EPub#parseRootFile() -> undefined
|
||||||
@ -244,10 +247,10 @@ EPub.prototype.handleRootFile = function(){
|
|||||||
**/
|
**/
|
||||||
EPub.prototype.parseRootFile = function (rootfile) {
|
EPub.prototype.parseRootFile = function (rootfile) {
|
||||||
|
|
||||||
var keys, keyparts, key;
|
var i, len, keys, keyparts, key;
|
||||||
|
|
||||||
keys = Object.keys(rootfile);
|
keys = Object.keys(rootfile);
|
||||||
for(var i=0, len = keys.length; i<len; i++){
|
for (i = 0, len = keys.length; i < len; i++) {
|
||||||
keyparts = keys[i].split(":");
|
keyparts = keys[i].split(":");
|
||||||
key = (keyparts.pop() || "").toLowerCase().trim();
|
key = (keyparts.pop() || "").toLowerCase().trim();
|
||||||
switch (key) {
|
switch (key) {
|
||||||
@ -268,9 +271,10 @@ EPub.prototype.parseRootFile = function(rootfile){
|
|||||||
|
|
||||||
if (this.spine.toc) {
|
if (this.spine.toc) {
|
||||||
this.parseTOC();
|
this.parseTOC();
|
||||||
}else
|
} else {
|
||||||
this.emit("end");
|
this.emit("end");
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EPub#parseMetadata() -> undefined
|
* EPub#parseMetadata() -> undefined
|
||||||
@ -278,10 +282,10 @@ EPub.prototype.parseRootFile = function(rootfile){
|
|||||||
* Parses "metadata" block (book metadata, title, author etc.)
|
* Parses "metadata" block (book metadata, title, author etc.)
|
||||||
**/
|
**/
|
||||||
EPub.prototype.parseMetadata = function (metadata) {
|
EPub.prototype.parseMetadata = function (metadata) {
|
||||||
var keys, keyparts, key;
|
var i, j, len, keys, keyparts, key;
|
||||||
|
|
||||||
keys = Object.keys(metadata);
|
keys = Object.keys(metadata);
|
||||||
for(var i=0, len = keys.length; i<len; i++){
|
for (i = 0, len = keys.length; i < len; i++) {
|
||||||
keyparts = keys[i].split(":");
|
keyparts = keys[i].split(":");
|
||||||
key = (keyparts.pop() || "").toLowerCase().trim();
|
key = (keyparts.pop() || "").toLowerCase().trim();
|
||||||
switch (key) {
|
switch (key) {
|
||||||
@ -339,14 +343,14 @@ EPub.prototype.parseMetadata = function(metadata){
|
|||||||
case "identifier":
|
case "identifier":
|
||||||
if (metadata[keys[i]]["@"] && metadata[keys[i]]["@"]["opf:scheme"] == "ISBN") {
|
if (metadata[keys[i]]["@"] && metadata[keys[i]]["@"]["opf:scheme"] == "ISBN") {
|
||||||
this.metadata.ISBN = String(metadata[keys[i]]["#"] || "").trim();
|
this.metadata.ISBN = String(metadata[keys[i]]["#"] || "").trim();
|
||||||
}else if(metadata[keys[i]]["@"] && metadata[keys[i]]["@"]["id"] && metadata[keys[i]]["@"]["id"].match(/uuid/i)){
|
} else if (metadata[keys[i]]["@"] && metadata[keys[i]]["@"].id && metadata[keys[i]]["@"].id.match(/uuid/i)) {
|
||||||
this.metadata.UUID = String(metadata[keys[i]]["#"] || "").replace('urn:uuid:', '').toUpperCase().trim();
|
this.metadata.UUID = String(metadata[keys[i]]["#"] || "").replace('urn:uuid:', '').toUpperCase().trim();
|
||||||
} else if (Array.isArray(metadata[keys[i]])) {
|
} else if (Array.isArray(metadata[keys[i]])) {
|
||||||
for(var j=0; j<metadata[keys[i]].length; j++){
|
for (j = 0; j < metadata[keys[i]].length; j++) {
|
||||||
if (metadata[keys[i]][j]["@"]) {
|
if (metadata[keys[i]][j]["@"]) {
|
||||||
if (metadata[keys[i]][j]["@"]["opf:scheme"] == "ISBN") {
|
if (metadata[keys[i]][j]["@"]["opf:scheme"] == "ISBN") {
|
||||||
this.metadata.ISBN = String(metadata[keys[i]][j]["#"] || "").trim();
|
this.metadata.ISBN = String(metadata[keys[i]][j]["#"] || "").trim();
|
||||||
}else if(metadata[keys[i]][j]["@"]["id"] && metadata[keys[i]][j]["@"]["id"].match(/uuid/i)){
|
} else if (metadata[keys[i]][j]["@"].id && metadata[keys[i]][j]["@"].id.match(/uuid/i)) {
|
||||||
this.metadata.UUID = String(metadata[keys[i]][j]["#"] || "").replace('urn:uuid:', '').toUpperCase().trim();
|
this.metadata.UUID = String(metadata[keys[i]][j]["#"] || "").replace('urn:uuid:', '').toUpperCase().trim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -355,7 +359,7 @@ EPub.prototype.parseMetadata = function(metadata){
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EPub#parseManifest() -> undefined
|
* EPub#parseManifest() -> undefined
|
||||||
@ -363,12 +367,12 @@ EPub.prototype.parseMetadata = function(metadata){
|
|||||||
* Parses "manifest" block (all items included, html files, images, styles)
|
* Parses "manifest" block (all items included, html files, images, styles)
|
||||||
**/
|
**/
|
||||||
EPub.prototype.parseManifest = function (manifest) {
|
EPub.prototype.parseManifest = function (manifest) {
|
||||||
var path = this.rootFile.split("/"), element, path_str;
|
var i, len, path = this.rootFile.split("/"), element, path_str;
|
||||||
path.pop();
|
path.pop();
|
||||||
path_str = path.join("/");
|
path_str = path.join("/");
|
||||||
|
|
||||||
if (manifest.item) {
|
if (manifest.item) {
|
||||||
for(var i=0, len = manifest.item.length; i<len; i++){
|
for (i = 0, len = manifest.item.length; i < len; i++) {
|
||||||
if (manifest.item[i]['@']) {
|
if (manifest.item[i]['@']) {
|
||||||
element = manifest.item[i]['@'];
|
element = manifest.item[i]['@'];
|
||||||
|
|
||||||
@ -381,7 +385,7 @@ EPub.prototype.parseManifest = function(manifest){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EPub#parseSpine() -> undefined
|
* EPub#parseSpine() -> undefined
|
||||||
@ -389,7 +393,7 @@ EPub.prototype.parseManifest = function(manifest){
|
|||||||
* Parses "spine" block (all html elements that are shown to the reader)
|
* Parses "spine" block (all html elements that are shown to the reader)
|
||||||
**/
|
**/
|
||||||
EPub.prototype.parseSpine = function (spine) {
|
EPub.prototype.parseSpine = function (spine) {
|
||||||
var path = this.rootFile.split("/"), element, path_s
|
var i, len, path = this.rootFile.split("/"), element;
|
||||||
path.pop();
|
path.pop();
|
||||||
|
|
||||||
if (spine['@'] && spine['@'].toc) {
|
if (spine['@'] && spine['@'].toc) {
|
||||||
@ -397,7 +401,7 @@ EPub.prototype.parseSpine = function(spine){
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (spine.itemref) {
|
if (spine.itemref) {
|
||||||
for(var i=0, len = spine.itemref.length; i<len; i++){
|
for (i = 0, len = spine.itemref.length; i < len; i++) {
|
||||||
if (spine.itemref[i]['@']) {
|
if (spine.itemref[i]['@']) {
|
||||||
if (element = this.manifest[spine.itemref[i]['@'].idref]) {
|
if (element = this.manifest[spine.itemref[i]['@'].idref]) {
|
||||||
this.spine.contents.push(element);
|
this.spine.contents.push(element);
|
||||||
@ -405,7 +409,7 @@ EPub.prototype.parseSpine = function(spine){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EPub#parseTOC() -> undefined
|
* EPub#parseTOC() -> undefined
|
||||||
@ -413,11 +417,11 @@ EPub.prototype.parseSpine = function(spine){
|
|||||||
* Parses ncx file for table of contents (title, html file)
|
* Parses ncx file for table of contents (title, html file)
|
||||||
**/
|
**/
|
||||||
EPub.prototype.parseTOC = function () {
|
EPub.prototype.parseTOC = function () {
|
||||||
var path = this.spine.toc.href.split("/"), id_list = {}, keys;
|
var i, len, path = this.spine.toc.href.split("/"), id_list = {}, keys;
|
||||||
path.pop();
|
path.pop();
|
||||||
|
|
||||||
keys = Object.keys(this.manifest);
|
keys = Object.keys(this.manifest);
|
||||||
for(var i=0, len = keys.length; i<len; i++){
|
for (i = 0, len = keys.length; i < len; i++) {
|
||||||
id_list[this.manifest[keys[i]].href] = keys[i];
|
id_list[this.manifest[keys[i]].href] = keys[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -445,7 +449,7 @@ EPub.prototype.parseTOC = function(){
|
|||||||
xmlparser.parseString(xml);
|
xmlparser.parseString(xml);
|
||||||
|
|
||||||
}).bind(this));
|
}).bind(this));
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EPub#walkNavMap(branch, path, id_list,[, level]) -> Array
|
* EPub#walkNavMap(branch, path, id_list,[, level]) -> Array
|
||||||
@ -461,29 +465,31 @@ EPub.prototype.walkNavMap = function(branch, path, id_list, level){
|
|||||||
level = level || 0;
|
level = level || 0;
|
||||||
|
|
||||||
// don't go too far
|
// don't go too far
|
||||||
if(level>7)return [];
|
if (level > 7) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
var output = [], element, id, title, order, href;
|
var i, len, output = [], element, title, order, href;
|
||||||
|
|
||||||
if (!Array.isArray(branch)) {
|
if (!Array.isArray(branch)) {
|
||||||
branch = [branch];
|
branch = [branch];
|
||||||
}
|
}
|
||||||
|
|
||||||
for(var i=0, len = branch.length; i<len; i++){
|
for (i = 0, len = branch.length; i < len; i++) {
|
||||||
if(branch[i]["navLabel"]){
|
if (branch[i].navLabel) {
|
||||||
|
|
||||||
title = (branch[i]["navLabel"] && branch[i]["navLabel"].text || branch[i]["navLabel"] || "").trim();
|
title = (branch[i].navLabel && branch[i].navLabel.text || branch[i].navLabel || "").trim();
|
||||||
order = Number(branch[i]["@"] && branch[i]["@"].playOrder || 0);
|
order = Number(branch[i]["@"] && branch[i]["@"].playOrder || 0);
|
||||||
href = (branch[i]["content"] && branch[i]["content"]["@"] && branch[i]["content"]["@"].src || "").trim();
|
href = (branch[i].content && branch[i].content["@"] && branch[i].content["@"].src || "").trim();
|
||||||
|
|
||||||
element = {
|
element = {
|
||||||
level: level,
|
level: level,
|
||||||
order: order,
|
order: order,
|
||||||
title: title
|
title: title
|
||||||
}
|
};
|
||||||
|
|
||||||
if (href) {
|
if (href) {
|
||||||
href = path.concat([href]).join("/")
|
href = path.concat([href]).join("/");
|
||||||
element.href = href;
|
element.href = href;
|
||||||
|
|
||||||
if (id_list[element.href]) {
|
if (id_list[element.href]) {
|
||||||
@ -501,12 +507,12 @@ EPub.prototype.walkNavMap = function(branch, path, id_list, level){
|
|||||||
output.push(element);
|
output.push(element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(branch[i]["navPoint"]){
|
if (branch[i].navPoint) {
|
||||||
output = output.concat(this.walkNavMap(branch[i]["navPoint"], path, id_list, level + 1));
|
output = output.concat(this.walkNavMap(branch[i].navPoint, path, id_list, level + 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EPub#getChapter(id, callback) -> undefined
|
* EPub#getChapter(id, callback) -> undefined
|
||||||
@ -517,7 +523,7 @@ EPub.prototype.walkNavMap = function(branch, path, id_list, level){
|
|||||||
* <head> etc. elements. Return only chapters with mime type application/xhtml+xml
|
* <head> etc. elements. Return only chapters with mime type application/xhtml+xml
|
||||||
**/
|
**/
|
||||||
EPub.prototype.getChapter = function (id, callback) {
|
EPub.prototype.getChapter = function (id, callback) {
|
||||||
var path = this.rootFile.split("/"), keys = Object.keys(this.manifest);
|
var i, len, path = this.rootFile.split("/"), keys = Object.keys(this.manifest);
|
||||||
path.pop();
|
path.pop();
|
||||||
|
|
||||||
if (this.manifest[id]) {
|
if (this.manifest[id]) {
|
||||||
@ -562,7 +568,7 @@ EPub.prototype.getChapter = function(id, callback){
|
|||||||
var img = path.concat([b]).join("/").trim(),
|
var img = path.concat([b]).join("/").trim(),
|
||||||
element;
|
element;
|
||||||
|
|
||||||
for(var i=0, len=keys.length; i<len; i++){
|
for (i = 0, len = keys.length; i < len; i++) {
|
||||||
if (this.manifest[keys[i]].href == img) {
|
if (this.manifest[keys[i]].href == img) {
|
||||||
element = this.manifest[keys[i]];
|
element = this.manifest[keys[i]];
|
||||||
break;
|
break;
|
||||||
@ -584,7 +590,7 @@ EPub.prototype.getChapter = function(id, callback){
|
|||||||
link = path.concat([(linkparts.shift() || "")]).join("/").trim(),
|
link = path.concat([(linkparts.shift() || "")]).join("/").trim(),
|
||||||
element;
|
element;
|
||||||
|
|
||||||
for(var i=0, len=keys.length; i<len; i++){
|
for (i = 0, len = keys.length; i < len; i++) {
|
||||||
if (this.manifest[keys[i]].href.split("#")[0] == link) {
|
if (this.manifest[keys[i]].href.split("#")[0] == link) {
|
||||||
element = this.manifest[keys[i]];
|
element = this.manifest[keys[i]];
|
||||||
break;
|
break;
|
||||||
@ -613,7 +619,7 @@ EPub.prototype.getChapter = function(id, callback){
|
|||||||
} else {
|
} else {
|
||||||
callback(new Error("File not found"));
|
callback(new Error("File not found"));
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -623,7 +629,7 @@ EPub.prototype.getChapter = function(id, callback){
|
|||||||
*
|
*
|
||||||
* Finds an image an id. Returns the image as Buffer. Callback gets
|
* Finds an image an id. Returns the image as Buffer. Callback gets
|
||||||
* an error object, image buffer and image content-type.
|
* an error object, image buffer and image content-type.
|
||||||
* Return only images with mime type image/*
|
* Return only images with mime type image
|
||||||
**/
|
**/
|
||||||
EPub.prototype.getImage = function (id, callback) {
|
EPub.prototype.getImage = function (id, callback) {
|
||||||
if (this.manifest[id]) {
|
if (this.manifest[id]) {
|
||||||
@ -643,4 +649,7 @@ EPub.prototype.getImage = function(id, callback){
|
|||||||
} else {
|
} else {
|
||||||
callback(new Error("File not found"));
|
callback(new Error("File not found"));
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
// Expose to the world
|
||||||
|
module.exports = EPub;
|
Reference in New Issue
Block a user