#!/usr/bin/env node // README 动效资产抓取器(5i T8):把只能靠外部生成的 SVG 数据卡抓成本地静态文件 // 设计取舍: // · 产物入仓(public/github-assets/)→ 构建确定性与离线可构建优先,不在 CI 里跑本脚本 // · 单资产失败保留旧文件;无旧文件则跳过(组件侧按存在性决定是否渲染该块) // · 配色按站点 tokens 近似:透明底 + 文字 #33343a(亮)/#c9ccd4(暗) + 线条 #3454d1 // · manifest.json 记录来源 URL 与抓取时间(可追溯,不含任何凭据) // 用法:node scripts/build-perf/fetch-readme-assets.mjs [--force] import { mkdirSync, writeFileSync, existsSync, readFileSync } from 'node:fs'; import { join } from 'node:path'; const OUT_DIR = 'public/github-assets'; const LOGIN = 'wait4xx'; const TIMEOUT_MS = 10_000; const UA = 'wait4x-blog-assets/1.0 (+https://wait4x.online)'; // 站点 tokens 近似值(与灰阶纪律一致:底透明,线条单一强调色) const ACCENT = '3454d1'; const INK_LIGHT = '33343a'; const INK_DARK = 'c9ccd4'; const MUTED_LIGHT = '8b8f98'; const MUTED_DARK = '9aa0aa'; /** 同一张卡按明暗两套参数各存一份(组件内用 CSS 切换,零运行时请求) */ const ASSETS = [ { name: 'stats', url: (theme) => `https://github-readme-stats.vercel.app/api?username=${LOGIN}` + '&show_icons=true&hide_border=true&include_all_commits=true&count_private=true&rank_icon=github' + `&bg_color=00000000&title_color=${ACCENT}&icon_color=${ACCENT}` + `&text_color=${theme === 'dark' ? INK_DARK : INK_LIGHT}`, label: 'GitHub 统计', }, { name: 'top-langs', url: (theme) => `https://github-readme-stats.vercel.app/api/top-langs/?username=${LOGIN}` + '&layout=compact&hide_border=true&langs_count=6' + `&bg_color=00000000&title_color=${ACCENT}` + `&text_color=${theme === 'dark' ? INK_DARK : INK_LIGHT}`, label: '语言分布', }, { name: 'streak', url: (theme) => `https://streak-stats.demolab.com/?user=${LOGIN}&hide_border=true` + '&background=00000000' + `&ring=${ACCENT}&fire=${ACCENT}&currStreakLabel=${ACCENT}` + `&currStreakNum=${theme === 'dark' ? INK_DARK : INK_LIGHT}` + `&sideNums=${theme === 'dark' ? INK_DARK : INK_LIGHT}` + `&sideLabels=${theme === 'dark' ? MUTED_DARK : MUTED_LIGHT}` + `&dates=${theme === 'dark' ? MUTED_DARK : MUTED_LIGHT}`, label: '连续贡献', }, { // 贡献蛇:GitHub Action 生成,配色由 action 侧决定,无法传参 → 只抓一份 name: 'snake', url: () => `https://raw.githubusercontent.com/${LOGIN}/${LOGIN}/output/github-contribution-grid-snake.svg`, label: '贡献蛇', single: true, }, ]; /** 10s 超时抓取;返回 SVG 文本或 null */ async function grab(url) { try { const res = await fetch(url, { headers: { 'User-Agent': UA, Accept: 'image/svg+xml,image/*;q=0.8,*/*;q=0.5' }, signal: AbortSignal.timeout(TIMEOUT_MS), }); if (!res.ok) { console.warn(`[assets] HTTP ${res.status}: ${url.slice(0, 90)}…`); return null; } const text = await res.text(); if (!text.includes('