import { mkdir, readFile, writeFile } from 'node:fs/promises'; import { resolve } from 'node:path'; import { pathToFileURL } from 'node:url'; import { chromium } from '@playwright/test'; const refRoot = resolve(process.env.REF_SAM_ROOT ?? '/home/letrhee/sam_rebuild/ref/sam'); const artifactDir = process.env.REF_PERSONAL_WAR_LOG_ARTIFACT_DIR; const formatterUrl = pathToFileURL(resolve(refRoot, 'hwe/ts/utilGame/formatLog.ts')).href; const { formatLog } = await import(formatterUrl); const css = await readFile(resolve(refRoot, 'dist_js/hwe_dynamic/vue/v_main.css'), 'utf8'); const records = [ '●10월:천귀병으로 ⓝ염행의 보병을 수비합니다. <1>12:54', '●10월:천귀병으로 ⓝ염행의 보병을 공격합니다. <1>12:55', ]; const browser = await chromium.launch({ headless: true }); try { const context = await browser.newContext({ colorScheme: 'dark', deviceScaleFactor: 1, locale: 'ko-KR', timezoneId: 'UTC', }); const page = await context.newPage(); const lines = records.map((record) => `
${formatLog(record)}
`).join(''); await page.setContent( `` + `
` + `
개인 기록
${lines}
`, { waitUntil: 'networkidle' } ); await page.evaluate(() => document.fonts.ready); for (const viewport of [ { name: 'desktop', width: 1200, height: 900 }, { name: 'mobile', width: 500, height: 900 }, ]) { await page.setViewportSize(viewport); const measurement = await page.locator('.fixture-line').evaluateAll((elements) => elements.map((element) => { const spans = [...element.querySelectorAll('span')]; const time = spans.find((span) => /^\d{2}:\d{2}$/u.test(span.textContent ?? '')); const name = spans.find((span) => span.textContent === 'ⓝ염행'); const action = spans.find((span) => span.textContent === '수비' || span.textContent === '공격'); if ( !(time instanceof HTMLElement) || !(name instanceof HTMLElement) || !(action instanceof HTMLElement) ) { throw new Error('Ref 개인 공격·수비 기록의 비교 span을 찾지 못했습니다.'); } const rect = element.getBoundingClientRect(); return { text: element.textContent, row: { width: rect.width, height: rect.height, fontSize: getComputedStyle(element).fontSize, lineHeight: getComputedStyle(element).lineHeight, }, timeFontSize: getComputedStyle(time).fontSize, nameFontSize: getComputedStyle(name).fontSize, actionFontSize: getComputedStyle(action).fontSize, }; }) ); const output = { viewport, measurement }; console.log(JSON.stringify(output)); if (artifactDir) { await mkdir(artifactDir, { recursive: true }); await Promise.all([ page.screenshot({ path: resolve(artifactDir, `ref-personal-war-log-font-${viewport.name}.png`) }), writeFile( resolve(artifactDir, `ref-personal-war-log-font-${viewport.name}.json`), `${JSON.stringify(output, null, 2)}\n` ), ]); } } } finally { await browser.close(); }