- ui-audit.mjs:路由发现扩展至 33 路由(standalone 构建产物 + erp-upgrade 系列); GA/gtm 请求 mock(gtag/js 空 JS + collect 204);第三方统计噪音与同源 ERR_ABORTED(重调度成功/prefetch)降级 INFO;LCP/CLS 断言按系统负载门控 (load >= 5 跳过并注明,防测量环境假阳性);LCP 超阈值热缓存 reload 复测 取优(lcpCold 留存冷值);clip 探针 sr-only 白名单;onReqFail 防御性修复 - ui-audit-report.mjs(新增):多主题探针聚合 HTML 报告,含截图画廊与 INFO 分级 - hardcoded-color-audit.mjs:bg-black/50 半透明遮罩误报修正(负向前瞻)+ 白名单 - 新增 brand-usage-scan.mjs / brand-ink-migrate.mjs(品牌令牌迁移辅助)
57 lines
2.3 KiB
JavaScript
57 lines
2.3 KiB
JavaScript
/**
|
||
* text-brand → text-brand-ink 批量迁移(暗黑模式品牌文字色修复)
|
||
*
|
||
* 背景:`text-brand` 与 `bg-brand` 原本共用 `--color-brand-rgb`,无法只在深色下提亮文字
|
||
* (提亮会连按钮底色一起改,红底白字 5.58:1 → 3.75:1)。故拆分出文字专用通道
|
||
* `--color-brand-ink-rgb`,本脚本把「文字用法」迁到新 utility `text-brand-ink`。
|
||
*
|
||
* 匹配规则:
|
||
* - 只匹配独立的 `text-brand`(后不接 `-` 或字母数字),保留 `text-brand-light` 等子 token
|
||
* - 保留变体前缀(hover: / focus: / group-hover: / sm: 等)与透明度修饰符(/80)
|
||
*
|
||
* 用法:
|
||
* node scripts/audit/brand-ink-migrate.mjs # 预演,只打印不落盘
|
||
* node scripts/audit/brand-ink-migrate.mjs --apply # 实际写入
|
||
*/
|
||
|
||
import fs from 'node:fs';
|
||
import path from 'node:path';
|
||
import { fileURLToPath } from 'node:url';
|
||
|
||
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');
|
||
const APPLY = process.argv.includes('--apply');
|
||
const EXTS = new Set(['.tsx', '.ts', '.css', '.jsx', '.js', '.mdx']);
|
||
const SKIP = new Set(['node_modules', '.next', '.git', '_archive', 'dist', 'coverage']);
|
||
|
||
function walk(dir, out = []) {
|
||
for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
|
||
const p = path.join(dir, e.name);
|
||
if (e.isDirectory()) { if (!SKIP.has(e.name)) walk(p, out); }
|
||
else if (EXTS.has(path.extname(e.name))) out.push(p);
|
||
}
|
||
return out;
|
||
}
|
||
|
||
// 后不接 `-` 或字母数字 → 排除 text-brand-light / text-brand-ink(幂等)
|
||
const re = /text-brand(?![-\w])/g;
|
||
|
||
let fileCount = 0, hitCount = 0;
|
||
const perFile = [];
|
||
|
||
for (const f of walk(path.join(ROOT, 'src'))) {
|
||
const before = fs.readFileSync(f, 'utf8');
|
||
const after = before.replace(re, 'text-brand-ink');
|
||
if (after === before) continue;
|
||
const n = (before.match(re) || []).length;
|
||
hitCount += n;
|
||
fileCount++;
|
||
perFile.push({ f: path.relative(ROOT, f), n });
|
||
if (APPLY) fs.writeFileSync(f, after);
|
||
}
|
||
|
||
perFile.sort((a, b) => b.n - a.n);
|
||
console.log(`${APPLY ? '已写入' : '预演(未落盘)'}:${hitCount} 处 / ${fileCount} 文件`);
|
||
for (const { f, n } of perFile.slice(0, 20)) console.log(String(n).padStart(4), f);
|
||
if (perFile.length > 20) console.log(` ... 另有 ${perFile.length - 20} 个文件`);
|
||
if (!APPLY) console.log('\n确认无误后加 --apply 执行。');
|