import { Zip, ZipPassThrough } from "fflate"; import { BaseGenerator } from "./baseGenerator"; import report from "./report"; const enc = new TextEncoder(); /** * Handles epub generation */ export class EpubGenerator extends BaseGenerator { async generate() { this.writer = this.opts.file.getWriter(); this.zip = new Zip(); this.zip.ondata = (error, data, final) => { if(error) { console.error(error); if(this.opts.onerror) this.opts.onerror(error); } if(data) { this.writer.write(data); } if(final) { this.writer.close(); } }; this.hashes = []; for(const chapterI in this.opts.chapters) { const chapter = this.opts.chapters[chapterI]; if(!chapter.links) { let data = await this.getURLs(chapter); chapter.links = data.urls; chapter.hashes = data.hashes; chapter.hash = data.hash; this.hashes.push(...chapter.hashes); } } this.mimetype(); this.container(); this.package(); this.toc(); this.callback(); // signals the template is ready for(const chapterI in this.opts.chapters) { const chapter = this.opts.chapters[chapterI]; if(chapter.number == null || chapter.number == undefined) chapter.number = chapterI; for(const i in chapter.links) { let url = chapter.links[i]; let hash = chapter.hashes[i]; this.callback(chapterI, i, false); const start = performance.now(); const res = await this.fetchImage(url, chapter); const image = new ZipPassThrough("OEBPS/" + hash); this.zip.add(image); const data = new Uint8Array(await res.arrayBuffer()); const end = performance.now() - start; report({ bytes: data.byteLength, cached: res.headers.get("X-Cache") === "HIT", duration: end, success: Math.floor(res.status / 100) === 2, url: url }); image.push(data, true); const textContent = new ZipPassThrough("OEBPS/" + i + ".xhtml"); this.zip.add(textContent); textContent.push(enc.encode(`