Files
surinz/.design/surinz/make-subset.mjs
T
ttipo 049bc5e2cf feat: 서린즈 홈 디자인 캔버스 구성
홈 확정안과 디자인 시스템을 아트보드로 정리한다. 후보 셋(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
2026-09-05 16:42:54 +09:00

47 lines
2.1 KiB
JavaScript

// 아트보드가 실제로 쓰는 글자만 남긴 Pretendard 서브셋을 만든다.
// 아트보드마다 폰트가 통째로 들어가므로(각 아트보드는 독립 문서), 글자 수를 줄이는 것이 곧 캔버스 용량이다.
import { readFileSync, writeFileSync, readdirSync, mkdirSync } from 'node:fs';
import { join } from 'node:path';
import subsetFont from 'subset-font';
import { decompress } from 'wawoff2';
const DIR = process.argv[2]; // .design/surinz
const TPL = join(DIR, 'templates');
const SRC = join(DIR, 'fonts');
const OUT = join(DIR, 'fonts', 'mini');
// 1) 아트보드 텍스트에서 쓰이는 글자를 모은다 (style 블록과 태그는 제외)
const used = new Set();
for (const name of readdirSync(TPL).filter((n) => n.endsWith('.dc.html'))) {
const src = readFileSync(join(TPL, name), 'utf8')
.replace(/<style[\s\S]*?<\/style>/g, '')
.replace(/<[^>]+>/g, ' ');
for (const c of src) used.add(c);
}
// 2) 안전 여유 — 아스키 인쇄 가능 문자와 자주 쓰는 기호는 항상 포함
for (let i = 0x20; i <= 0x7e; i += 1) used.add(String.fromCharCode(i));
for (const c of '·…—–‘’“”「」『』〈〉《》±×÷≤≥→←↑↓★☆※℃%㎏㎜㎝가나다라마바사아자차카타파하') used.add(c);
const text = [...used].filter((c) => c.charCodeAt(0) > 0x1f).join('');
console.log(`서브셋 글자 수 ${text.length}`);
mkdirSync(OUT, { recursive: true });
writeFileSync(join(OUT, 'charset.txt'), text, 'utf8');
const WEIGHTS = ['Regular', 'SemiBold', 'Bold'];
let before = 0;
let after = 0;
for (const w of WEIGHTS) {
const woff2 = readFileSync(join(SRC, `Pretendard-${w}.subset.woff2`));
before += woff2.length;
const ttf = Buffer.from(await decompress(woff2));
const out = await subsetFont(ttf, text, { targetFormat: 'woff2' });
after += out.length;
writeFileSync(join(OUT, `Pretendard-${w}.mini.woff2`), out);
console.log(`${w.padEnd(9)} ${(woff2.length / 1024).toFixed(0).padStart(4)} KB → ${(out.length / 1024).toFixed(0).padStart(3)} KB`);
}
console.log(`합계 ${(before / 1024).toFixed(0)} KB → ${(after / 1024).toFixed(0)} KB (아트보드 1개당)`);