91 lines
2.9 KiB
JavaScript
91 lines
2.9 KiB
JavaScript
#!/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()
|
||
}
|