UNPKG

packdir-cli

Version:
151 lines 7.43 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.EPub = exports.chapterDefaults = exports.optionsDefaults = void 0; const tslib_1 = require("tslib"); const ejs_1 = require("ejs"); const jszip_1 = tslib_1.__importDefault(require("jszip")); const mime_1 = require("mime"); const ow_1 = tslib_1.__importDefault(require("ow")); const util_1 = require("./util"); Object.defineProperty(exports, "chapterDefaults", { enumerable: true, get: function () { return util_1.chapterDefaults; } }); Object.defineProperty(exports, "optionsDefaults", { enumerable: true, get: function () { return util_1.optionsDefaults; } }); class EPub { constructor(options, content) { this.images = []; this.options = (0, util_1.validateAndNormalizeOptions)(options); switch (this.options.verbose) { case true: this.log = console.log.bind(console); this.warn = console.warn.bind(console); break; case false: this.log = this.warn = () => { }; break; default: this.log = this.options.verbose.bind(null, 'log'); this.warn = this.options.verbose.bind(null, 'warn'); break; } this.uuid = (0, util_1.uuid)(); this.content = util_1.validateAndNormalizeChapters.call(this, content); this.zip = new jszip_1.default(); this.zip.file('mimetype', 'application/epub+zip', { compression: 'STORE' }); if (this.options.cover) { const mediaType = (0, mime_1.getType)(this.options.cover); const extension = (0, mime_1.getExtension)(mediaType || ''); if (mediaType && extension) this.cover = { mediaType, extension }; } } async render() { this.log('Generating Template Files...'); await this.generateTemplateFiles(); this.log('Downloading fonts...'); //await this.downloadAllFonts(); this.log('Downloading images...'); await this.downloadAllImages(); this.log('Making cover...'); await this.makeCover(); this.log('Finishing up...'); return this; } async genEpub() { await this.render(); const content = this.zip.generateAsync({ type: util_1.type, mimeType: 'application/epub+zip', compression: 'DEFLATE', compressionOptions: { level: 9, }, }); this.log('Done'); return content; } generateAsync(options) { return this.zip.generateAsync(options); } async generateTemplateFiles() { const oebps = this.zip.folder('OEBPS'); oebps.file('style.css', this.options.css); this.content.forEach(chapter => { const rendered = (0, ejs_1.render)(this.options.chapterXHTML, { lang: this.options.lang, prependChapterTitles: this.options.prependChapterTitles, ...chapter, }); oebps.file(chapter.filename, rendered); }); const metainf = this.zip.folder('META-INF'); metainf.file('container.xml', '<?xml version="1.0" encoding="UTF-8" ?><container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container"><rootfiles><rootfile full-path="OEBPS/content.opf" media-type="application/oebps-package+xml"/></rootfiles></container>'); if (this.options.version === 2) { // write meta-inf/com.apple.ibooks.display-options.xml [from pedrosanta:xhtml#6] metainf.file('com.apple.ibooks.display-options.xml', '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><display_options><platform name="*"><option name="specified-fonts">true</option></platform></display_options>'); } const opt = { ...this.options, id: this.uuid, images: this.images, cover: this.cover, content: this.content, }; oebps.file('content.opf', (0, ejs_1.render)(this.options.contentOPF, opt)); oebps.file('toc.ncx', (0, ejs_1.render)(this.options.tocNCX, opt)); oebps.file('toc.xhtml', (0, ejs_1.render)(this.options.tocXHTML, opt)); } async downloadAllFonts() { if (!this.options.fonts.length) return this.log('No fonts to download'); const oebps = this.zip.folder('OEBPS'); const fonts = oebps.folder('fonts'); for (let i = 0; i < this.options.fonts.length; i += this.options.batchSize) { const fontContents = await Promise.all(this.options.fonts.slice(i, i + this.options.batchSize).map(font => { const d = (0, util_1.retryFetch)(font.url, this.options.fetchTimeout, this.options.retryTimes, this.log) .then(res => (this.log(`Downloaded font ${font.url}`), { ...font, data: res })); return this.options.ignoreFailedDownloads ? d.catch(reason => (this.warn(`Warning (font ${font.url}): Download failed`, reason), { ...font, data: '' })) : d; })); fontContents.forEach(font => fonts.file(font.filename, font.data)); } } async downloadAllImages() { if (!this.images.length) return this.log('No images to download'); const oebps = this.zip.folder('OEBPS'); const images = oebps.folder('images'); for (let i = 0; i < this.images.length; i += this.options.batchSize) { const imageContents = await Promise.all(this.images.slice(i, i + this.options.batchSize).map(image => { const d = (0, util_1.retryFetch)(image.url, this.options.fetchTimeout, this.options.retryTimes, this.log) .then(res => (this.log(`Downloaded image ${image.url}`), { ...image, data: res })); return this.options.ignoreFailedDownloads ? d.catch(reason => (this.warn(`Warning (image ${image.url}): Download failed`, reason), { ...image, data: '' })) : d; })); imageContents.forEach(image => images.file(`${image.id}.${image.extension}`, image.data)); } } async makeCover() { if (!this.cover) return this.log('No cover to download'); const oebps = this.zip.folder('OEBPS'); const coverContent = await (0, util_1.retryFetch)(this.options.cover, this.options.fetchTimeout, this.options.retryTimes, this.log) .catch(reason => (this.warn(`Warning (cover ${this.options.cover}): Download failed`, reason), '')); oebps.file(`cover.${this.cover.extension}`, coverContent); } } exports.EPub = EPub; const epub = (optionsOrTitle, content, ...args) => { (0, ow_1.default)(optionsOrTitle, ow_1.default.any(util_1.optionsPredicate, ow_1.default.string)); const options = ow_1.default.isValid(optionsOrTitle, ow_1.default.string) ? { title: optionsOrTitle } : optionsOrTitle; (0, ow_1.default)(args, ow_1.default.array.ofType(ow_1.default.any(ow_1.default.boolean, ow_1.default.number))); args.forEach(arg => { if (ow_1.default.isValid(arg, ow_1.default.boolean)) options.verbose = arg; else options.version = arg; }); return new EPub(options, content).genEpub(); }; exports.default = epub; //# sourceMappingURL=index.js.map