epub-full-text-search
Version:
149 lines (120 loc) • 3.91 kB
JavaScript
import xml2js from 'xml2js';
import path from 'path';
import fs from 'fs';
import Q from 'q';
import winston from './../Logger';
const readdir = Q.denodeify(fs.readdir),
readFile = Q.denodeify(fs.readFile),
stat = Q.denodeify(fs.stat),
parser = new xml2js.Parser(),
parseString = Q.denodeify(parser.parseString);
const MetaDataParser = {};
const container = 'container.xml';
MetaDataParser.getMetaData = function (pathToEPUBs) {
return getContainerFiles(pathToEPUBs)
.then(containerFiles => {
return Q.all(containerFiles.map(file => {
return getBookMetaData(file);
}));
})
.fail(err => {
winston.log('error', err);
});
};
function getContainerFiles(dir, results) {
results = results || [];
return readdir(dir)
.then(files => {
return Q.all(files.map(file => {
file = dir + '/' + file;
return stat(file)
.then(fileStat => {
if (fileStat && fileStat.isDirectory()) {
return getContainerFiles(file, results);
} else if (path.basename(file) === container) {
results.push(file);
}
});
}));
})
.then(() => {
return results;
})
.fail(err => {
winston.log('error', err)
});
}
const getBookMetaData = function (containerFile) {
const root = path.dirname(path.dirname(containerFile));
var manifestPath;
return getManifest(containerFile)
.then(result => {
const opfFile = root + '/' + result;
manifestPath = path.dirname(root + '/' + result);
return readFile(opfFile);
})
.then(opfContent => {
return Q.all([
getBookTitle(opfContent),
getSpineItems(opfContent)
]);
})
.then(results => {
return {
filename: path.basename(root),
manifestPath: manifestPath,
title: results[0],
spineItems: results[1]
};
})
.fail(err => {
winston.log('error', err);
});
};
function getManifest(containerFile) {
return readFile(containerFile)
.then(data => {
return parseString(data);
})
.then(result => {
return result.container.rootfiles[0].rootfile[0].$['full-path'];
})
.fail(err => {
if (err && err.code === 'ENOENT') {
throw new Error('File ' + containerFile + 'doesn\'t exist');
}
});
}
function getBookTitle(data) {
return parseString(data)
.then(result => {
const metadata = result.package.metadata[0];
return metadata['dc:title'][0]._ || metadata['dc:title'][0];
})
.fail(err => {
winston.log('error', err);
});
}
function getSpineItems(data) {
return parseString(data).then(r => {
const manifest = r.package.manifest[0];
const spine = r.package.spine[0];
const result = [];
for (var i = 0; i < spine.itemref.length; i++) {
const spineItem = manifest.item.filter(value => {
if (value.$.id === spine.itemref[i].$.idref)
return value;
});
const spineitem = {};
spineitem.id = spineItem[0].$.id;
spineitem.href = spineItem[0].$.href;
spineitem.baseCfi = "/" + '6' + "/" + (i + 1) * 2 + '[' + spineitem.id + ']!';
result.push(spineitem);
}
return result;
})
.fail(err => {
winston.log('error', err);
})
}
module.exports = MetaDataParser;