049bc5e2cf
홈 확정안과 디자인 시스템을 아트보드로 정리한다. 후보 셋(HomeA/B/C)은 확정안 Main 으로 합치고 지운다. 디자인 시스템 페이지 - Logo: 워드마크를 글꼴 대신 획으로 그려 내보내기에서도 모양이 유지된다 - Brand: 탄피 오렌지 확정. 면 #FF6A00(흰 글자) / 글자 #C24A00 로 값이 갈린다 - Foundations: 홈에서 굳어진 글자 아홉 단계·색·컴포넌트·치수 - Blocks: 실패 · 비어 있음 블록 규격과 섹션별 문구 홈 페이지 - Main: 검색 히어로를 최상단으로, 그 아래 균등 3열 밀도 그리드 - Loading / States: 스켈레톤과 섹션별로 섞인 네 가지 상태 - Search: 헤더 돋보기 + 검색 시트 - Tablet(768) / Mobile(390): 기준점 두 개로 2열 · 1열 전환 랭크전 랭킹에 티어 이미지 자리를 추가한다. 티어와 RP 는 한 몸으로 읽혀야 해서 한 칸(72px)에 묶고 그 안에서만 4px 로 붙였다. 계급·티어·클랜 표장을 막대/육각/방패로 갈라 한 줄에 놓여도 구분된다. Pretendard 는 아트보드가 실제로 쓰는 글자만 서브셋(fonts/mini)해 아트보드마다 복사되는 용량을 줄인다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DNo7LSAWohdk6vpEhmtqLY
55 lines
2.2 KiB
JavaScript
55 lines
2.2 KiB
JavaScript
// templates/*.dc.html 의 /*PRETENDARD*/ 토큰을 Pretendard woff2 data URI 로 치환해
|
|
// 작업 디렉터리 루트에 최종 .dc.html 아트보드를 생성한다.
|
|
//
|
|
// 아트보드는 각각 독립 문서로 렌더되므로 폰트가 아트보드 수만큼 복사된다.
|
|
// 그래서 fonts/mini 의 서브셋(아트보드가 실제로 쓰는 글자만)을 쓴다.
|
|
// 새 글자가 들어오면 아래 검사에서 경고가 뜨고, make-subset.mjs 로 다시 만들면 된다.
|
|
import { readFileSync, writeFileSync, readdirSync } from 'node:fs';
|
|
import { join } from 'node:path';
|
|
|
|
const WEIGHTS = [
|
|
['Regular', 400],
|
|
['SemiBold', 600],
|
|
['Bold', 700],
|
|
];
|
|
|
|
const faces = WEIGHTS.map(([file, weight]) => {
|
|
const b64 = readFileSync(join('fonts', 'mini', `Pretendard-${file}.mini.woff2`)).toString('base64');
|
|
return `@font-face{font-family:'Pretendard';font-style:normal;font-weight:${weight};font-display:swap;src:url(data:font/woff2;base64,${b64}) format('woff2');}`;
|
|
}).join('\n');
|
|
|
|
const charset = new Set(readFileSync(join('fonts', 'mini', 'charset.txt'), 'utf8'));
|
|
|
|
let count = 0;
|
|
let total = 0;
|
|
const missing = new Set();
|
|
|
|
for (const name of readdirSync('templates')) {
|
|
if (!name.endsWith('.dc.html')) continue;
|
|
const src = readFileSync(join('templates', name), 'utf8');
|
|
if (!src.includes('/*PRETENDARD*/')) {
|
|
console.error(`warn: ${name} 에 /*PRETENDARD*/ 토큰이 없습니다`);
|
|
}
|
|
|
|
// 서브셋에 없는 글자 찾기 — 태그·스타일을 뺀 실제 텍스트만 본다
|
|
const text = src.replace(/<style[\s\S]*?<\/style>/g, '').replace(/<[^>]+>/g, ' ');
|
|
for (const ch of text) {
|
|
if (ch.charCodeAt(0) > 0x1f && !charset.has(ch)) missing.add(ch);
|
|
}
|
|
|
|
const out = src.replace('/*PRETENDARD*/', faces);
|
|
writeFileSync(name, out, 'utf8');
|
|
count += 1;
|
|
total += out.length;
|
|
console.log(`${name} — ${(out.length / 1024).toFixed(0)} KB`);
|
|
}
|
|
|
|
console.log(`${count} artboards built · 합계 ${(total / 1024 / 1024).toFixed(1)} MB`);
|
|
|
|
if (missing.size > 0) {
|
|
console.error(
|
|
`\nwarn: 서브셋에 없는 글자 ${missing.size}개 — ${[...missing].join('')}\n` +
|
|
' 이 글자들은 대체 글꼴로 그려집니다. node make-subset.mjs . 로 서브셋을 다시 만드세요.',
|
|
);
|
|
}
|