// The web reader's own block list for EPUBs, from the real app code (static/js/app/40-epub.js // parseEpub + the reader's block selector) in headless Chromium. Reference for compare_blocks.py. // // node web_blocks.cjs book.epub [more.epub ...] // // Needs playwright-core (e.g. NODE_PATH=/node_modules) and a Chromium // (PLAYWRIGHT_BROWSERS_PATH as for the e2e tests). const fs = require('fs'); const path = require('path'); const { chromium } = require('playwright-core'); (async () => { const [web, out, ...books] = process.argv.slice(2); const browser = await chromium.launch(); const page = await browser.newPage(); await page.goto('about:blank'); await page.addScriptTag({ path: path.join(web, 'static/js/jszip.min.js') }); await page.addScriptTag({ path: path.join(web, 'static/js/app/40-epub.js') }); const result = {}; for (const file of books) { const b64 = fs.readFileSync(file).toString('base64'); result[file] = await page.evaluate(async (b64) => { const bin = Uint8Array.from(atob(b64), (c) => c.charCodeAt(0)); const book = await parseEpub(bin.buffer); const el = document.createElement('div'); el.innerHTML = book.chapters.join(''); document.body.appendChild(el); const SEL = 'p, h1, h2, h3, h4, h5, h6, li, blockquote, dt, dd, figcaption, div:not(:has(*))'; // EPUB_BLOCK_SELECTOR, 44-books.js const blocks = Array.from(el.querySelectorAll(SEL)); const chapters = Array.from(el.querySelectorAll('[data-epub-src]')); const res = blocks.map((b) => ({ tag: b.tagName.toLowerCase(), text: b.textContent.replace(/\s+/g, ' ').trim(), len: b.textContent.length, ch: chapters.findIndex((c) => c.contains(b)), })); el.remove(); return { title: book.title, chapters: chapters.length, blocks: res }; }, b64); console.error(path.basename(file), result[file].blocks.length, 'blocks'); } fs.writeFileSync(out, JSON.stringify(result)); await browser.close(); })().catch((e) => { console.error(e); process.exit(1); });