e1e18b00f7
여백 추가된 favicon.svg 기반으로 PNG/ICO 파비콘 재생성. 로고를 캔버스 중앙 영역에 배치해 구글 원형 마스크에도 안 잘리도록 함. - sharp/png-to-ico 기반 생성 스크립트 추가 (npm run favicon) - SVG 파비콘 링크 추가 (최신 브라우저 우선) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
52 lines
1.7 KiB
JavaScript
52 lines
1.7 KiB
JavaScript
// favicon.svg → 검색엔진/브라우저용 PNG·ICO 파비콘 일괄 생성 스크립트
|
|
// 사용법: node scripts/gen-favicon.mjs
|
|
import sharp from 'sharp'
|
|
import pngToIco from 'png-to-ico'
|
|
import { readFile, writeFile } from 'node:fs/promises'
|
|
import { fileURLToPath } from 'node:url'
|
|
import { dirname, resolve } from 'node:path'
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
const publicDir = resolve(__dirname, '../public')
|
|
const svgPath = resolve(publicDir, 'favicon.svg')
|
|
|
|
// 흰 배경으로 평탄화 — 투명 영역이 iOS/검색결과에서 검게 보이는 문제 방지
|
|
const WHITE = { r: 255, g: 255, b: 255, alpha: 1 }
|
|
|
|
// 주어진 한 변 길이로 PNG 버퍼 생성
|
|
async function render(svg, size) {
|
|
return sharp(svg, { density: 384 })
|
|
.resize(size, size, { fit: 'contain', background: WHITE })
|
|
.flatten({ background: WHITE })
|
|
.png()
|
|
.toBuffer()
|
|
}
|
|
|
|
async function main() {
|
|
const svg = await readFile(svgPath)
|
|
|
|
// 개별 PNG 파비콘 생성
|
|
const targets = [
|
|
{ name: 'favicon-16x16.png', size: 16 },
|
|
{ name: 'favicon-32x32.png', size: 32 },
|
|
{ name: 'apple-touch-icon.png', size: 180 },
|
|
]
|
|
for (const { name, size } of targets) {
|
|
const buf = await render(svg, size)
|
|
await writeFile(resolve(publicDir, name), buf)
|
|
console.log(`생성: ${name} (${size}x${size})`)
|
|
}
|
|
|
|
// favicon.ico — 16/32/48 멀티 사이즈 포함
|
|
const icoSizes = [16, 32, 48]
|
|
const icoPngs = await Promise.all(icoSizes.map((s) => render(svg, s)))
|
|
const ico = await pngToIco(icoPngs)
|
|
await writeFile(resolve(publicDir, 'favicon.ico'), ico)
|
|
console.log(`생성: favicon.ico (${icoSizes.join('/')})`)
|
|
}
|
|
|
|
main().catch((err) => {
|
|
console.error(err)
|
|
process.exit(1)
|
|
})
|