const { chromium } = require('playwright'); const fs = require('fs'); const path = require('path'); (async () => { const outDir = path.join(__dirname, '..', 'tmp-screenshots'); fs.mkdirSync(outDir, { recursive: true }); const browser = await chromium.launch({ headless: true }); const page = await browser.newPage({ viewport: { width: 1440, height: 900 } }); await page.goto('https://nomadweb.nomadro.com/book/read#01-first-remote', { waitUntil: 'networkidle', timeout: 60000, }); await page.waitForTimeout(1000); const info = await page.evaluate(() => { const chrome = document.querySelector('.reader-chrome'); const box = (el) => { if (!el) return null; const r = el.getBoundingClientRect(); const s = getComputedStyle(el); return { t: Math.round(r.top), b: Math.round(r.bottom), l: Math.round(r.left), r: Math.round(r.right), position: s.position, top: s.top, overflow: s.overflow, ox: s.overflowX, oy: s.overflowY, cls: (el.className || '').toString().slice(0, 70), tag: el.tagName, }; }; const chain = []; let el = chrome; while (el) { const s = getComputedStyle(el); chain.push({ tag: el.tagName, id: el.id || '', cls: (el.className || '').toString().slice(0, 60), ox: s.overflowX, oy: s.overflowY, o: s.overflow, position: s.position, transform: s.transform, contain: s.contain, filter: s.filter, h: el === document.documentElement ? 'html' : el === document.body ? 'body' : '', }); el = el.parentElement; } const sidebar = document.querySelector('.chapter-sidebar'); const main = document.querySelector('.scroll-reader-main'); const paper = document.querySelector('.reader-paper'); const sb = sidebar?.getBoundingClientRect(); const mn = main?.getBoundingClientRect(); const pp = paper?.getBoundingClientRect(); return { chrome: box(chrome), scrollY: Math.round(window.scrollY), leftGap: sb && mn ? Math.round(mn.left - sb.right) : null, rightGap: mn ? Math.round(window.innerWidth - mn.right) : null, paperLeftGap: sb && pp ? Math.round(pp.left - sb.right) : null, paperRightGap: pp ? Math.round(window.innerWidth - pp.right) : null, chain, }; }); await page.screenshot({ path: path.join(outDir, 'diag-hash.png'), fullPage: false }); // scroll further like user mid-read await page.evaluate(() => window.scrollBy(0, 200)); await page.waitForTimeout(400); const after = await page.evaluate(() => { const chrome = document.querySelector('.reader-chrome'); const r = chrome?.getBoundingClientRect(); return { scrollY: Math.round(window.scrollY), chromeTop: r ? Math.round(r.top) : null, chromeBottom: r ? Math.round(r.bottom) : null, chromeHeight: r ? Math.round(r.height) : null, }; }); await page.screenshot({ path: path.join(outDir, 'diag-scrolled.png'), fullPage: false }); console.log(JSON.stringify({ info, after }, null, 2)); await browser.close(); })().catch((e) => { console.error(e); process.exit(1); });