#!/usr/bin/env node // Bilder für die Community-Posts in r/Ninelands (1080 × 1350, hochkant für den Feed am Handy). // Aufruf: npm run capture:community → dist/marketing/community/how-to-play.png, realms.png import {copyFileSync, mkdirSync, readFileSync, statSync} from 'node:fs' import {createServer} from 'node:http' import {dirname, extname, join, resolve} from 'node:path' import {fileURLToPath} from 'node:url' import {build} from 'esbuild' import {chromium} from 'playwright' const root = resolve(dirname(fileURLToPath(import.meta.url)), '../..') const site = join(root, 'dist/community') const out = join(root, 'dist/marketing/community') mkdirSync(site, {recursive: true}) mkdirSync(out, {recursive: true}) await build({ entryPoints: [join(root, 'scripts/capture/community.ts')], bundle: true, format: 'esm', outdir: site, logLevel: 'warning', define: { 'import.meta.env.MODE': '"reddit"', 'import.meta.env.BASE_URL': '"/"', __API_ORIGIN__: '""', }, loader: {'.woff2': 'file', '.woff': 'file'}, assetNames: 'fonts/[name]-[hash]', }) copyFileSync( join(root, 'scripts/capture/community.html'), join(site, 'index.html'), ) const types = { '.html': 'text/html', '.js': 'text/javascript', '.css': 'text/css', '.png': 'image/png', '.woff2': 'font/woff2', '.woff': 'font/woff', } const server = createServer((req, res) => { const path = decodeURIComponent((req.url ?? '/').split('?')[0]) for (const dir of [site, join(root, 'public')]) { const file = join(dir, path === '/' ? 'index.html' : path) try { if (file.startsWith(dir) && statSync(file).isFile()) { res.writeHead(200, { 'Content-Type': types[extname(file)] ?? 'application/octet-stream', }) res.end(readFileSync(file)) return } } catch {} } res.writeHead(404) res.end() }) await new Promise(r => server.listen(0, '127.0.0.1', r)) const base = `http://127.0.0.1:${server.address().port}/` const browser = await chromium.launch() try { for (const page of ['howto', 'realms']) { const p = await browser.newPage({ viewport: {width: 540, height: 675}, deviceScaleFactor: 2, }) p.on('pageerror', e => console.error(`Seitenfehler: ${e.message}`)) await p.goto(`${base}?page=${page}`) await p.evaluate(() => document.fonts.ready) await p.waitForLoadState('networkidle') // Passt alles aufs Bild? const over = await p.evaluate(() => { const s = document.getElementById('sheet') return s ? s.scrollHeight - s.clientHeight : 0 }) if (over > 0) console.error(`${page}: ${over} px zu hoch`) const name = page === 'howto' ? 'how-to-play.png' : 'realms.png' await p.screenshot({path: join(out, name)}) console.log( `${name} ${Math.round(statSync(join(out, name)).size / 1024)} KB`, ) await p.close() } } finally { await browser.close() server.close() }