const { chromium } = require('playwright'); const input = process.argv[2]; const presenterNames = ['Zhihao Zhao', 'Zipeng Wang', 'Jiuqi Feng', 'Siyuan Zhang']; function baseWithoutHash(url) { const hashIndex = url.indexOf('#'); return hashIndex >= 0 ? url.slice(0, hashIndex) : url; } async function applyRequestedEdits(page) { await page.evaluate((names) => { const visible = Array.from(document.querySelectorAll('section')).find((section) => { const style = getComputedStyle(section); return style.visibility !== 'hidden' && style.opacity !== '0'; }); if (!visible) return; if ((visible.getAttribute('data-label') || '').startsWith('01')) { for (const el of Array.from(visible.querySelectorAll('div'))) { const text = (el.innerText || '').replace(/\s+/g, ' ').trim(); if (text === 'PRESENTED [ Presentation Date ] 4-person team walkthrough ยท ~10 min') { el.style.display = 'none'; } } } if ((visible.getAttribute('data-label') || '').startsWith('15')) { const placeholders = Array.from(visible.querySelectorAll('div')) .filter((el) => (el.innerText || '').trim() === '[ name ]'); placeholders.forEach((el, index) => { if (names[index]) { el.textContent = names[index]; } }); } }, presenterNames); } (async () => { if (!input) { throw new Error('Usage: node html_to_ppt_check_placeholders.js '); } const launchOptions = { headless: true }; if (process.env.BROWSER_EXE) { launchOptions.executablePath = process.env.BROWSER_EXE; } const browser = await chromium.launch(launchOptions); const baseUrl = baseWithoutHash(input); const findings = []; const nameChecks = []; for (let i = 1; i <= 15; i += 1) { const page = await browser.newPage({ viewport: { width: 1920, height: 1080 } }); await page.goto(`${baseUrl}#${i}`, { waitUntil: 'load', timeout: 30000 }); await page.waitForSelector('section', { state: 'attached', timeout: 10000 }); await page.waitForTimeout(500); await applyRequestedEdits(page); const result = await page.evaluate((names) => { const visible = Array.from(document.querySelectorAll('section')).find((section) => { const style = getComputedStyle(section); return style.visibility !== 'hidden' && style.opacity !== '0'; }); const label = visible?.getAttribute('data-label') || ''; const text = visible?.innerText || ''; const placeholderMatches = text.match(/\[[^\]]+\]|Presentation Date|Slide Number|placeholder|PRESENTED\s+\[/gi) || []; return { label, placeholderMatches, presenterNamesPresent: names.map((name) => text.includes(name)), }; }, presenterNames); if (result.placeholderMatches.length) { findings.push({ slide: i, label: result.label, matches: result.placeholderMatches }); } if (i === 15) { nameChecks.push(...result.presenterNamesPresent); } await page.close(); } await browser.close(); console.log(JSON.stringify({ findings, slide15NamesPresent: nameChecks }, null, 2)); })().catch((err) => { console.error(err); process.exit(1); });