feat(scripts): strip translator credits and promo lines from fetched and existing EPUBs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
// Strip translator credits and promo lines from an existing EPUB, in place.
|
||||
// Usage: node scripts/clean-epub.js <file.epub>...
|
||||
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 <file.epub>...');
|
||||
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`);
|
||||
}
|
||||
Reference in New Issue
Block a user