// Strip translator credits and promo lines from an existing EPUB, in place. // Usage: node scripts/clean-epub.js ... import JSZip from 'jszip'; import { load } from 'cheerio'; import fs from 'fs'; import { stripPromo } from './clean-chapter.js'; const files = process.argv.slice(2); if (!files.length) { console.error('Usage: node scripts/clean-epub.js ...'); process.exit(2); } for (const file of files) { const zip = await JSZip.loadAsync(fs.readFileSync(file)); let removed = 0; for (const name of Object.keys(zip.files)) { if (!/\.x?html?$/i.test(name) || /(^|\/)nav\.xhtml$/i.test(name)) continue; const $ = load(await zip.file(name).async('string'), { xml: true }); const n = stripPromo($); if (n) { zip.file(name, $.xml()); removed += n; } } if (removed) { const tmp = `${file}.tmp`; // EPUB requires mimetype stored uncompressed; loaded entries lose that option. zip.file('mimetype', 'application/epub+zip', { compression: 'STORE' }); fs.writeFileSync( tmp, await zip.generateAsync({ type: 'nodebuffer', compression: 'DEFLATE', mimeType: 'application/epub+zip', }), ); fs.renameSync(tmp, file); } process.stdout.write(`${file}: removed ${removed} promo paragraphs\n`); }