iter(g343): 校验红环改为聚焦时亮

This commit is contained in:
HIsheR
2026-10-27 02:25:59 +08:00
parent d0ef012290
commit d5e16027f8
3 changed files with 37 additions and 2 deletions
+27
View File
@@ -1700,6 +1700,32 @@ function checkFormReset(pkgs) {
return issues;
}
/*** 校验错误环:红环常驻会把长表单染成一片警报,也会与相邻字段的环叠加——环只该在聚焦时亮 ***/
function checkInvalidRing(pkgs) {
const issues = [];
for (const pkg of pkgs) {
if (pkg.type !== 'skin-dom') continue;
const cssPath = path.join(ROOT, pkg.dir, 'ui.css');
if (!fs.existsSync(cssPath)) continue;
const lines = fs.readFileSync(cssPath, 'utf8').split(/\r?\n/);
let hasFocusRing = false; // 聚焦态危险环是否已单独写过
lines.forEach((line, i) => {
if (!line.trim().endsWith('{')) return; // 卫语句:只从选择器收尾行起算(一选择器一行是仓库既有排版)
let top = i; // 选择器首行:往上吃掉所有逗号收尾的续行
while (top > 0 && lines[top - 1].trim().endsWith(',')) top--;
const selector = lines.slice(top, i + 1).join(' ');
if (!selector.includes('.ua-invalid')) return; // 卫语句:与本规则无关的块
let body = ''; // 规则体:拼到第一行收尾的 }
for (let k = i + 1; k < lines.length && !lines[k].trim().startsWith('}'); k++) body += lines[k];
if (!/focus-ring-danger/.test(body)) return; // 卫语句:本块不涉及危险环
if (/focus/.test(selector)) hasFocusRing = true;
else issues.push(`${pkg.name}/ui.css:${i + 1} 的「${selector.trim().slice(0, 60)}」常驻危险光环:校验失败但未聚焦的字段也挂着 3px 红环,长表单看着像整页报错`);
});
if (!hasFocusRing) issues.push(`${pkg.name}/ui.css 缺 .ua-invalid:focus-visible 的危险环:改完常驻环后聚焦态反而没有错误强调`);
}
return issues;
}
/*** 校验同义词表:目标 id 必须真实存在(改名后残留会让回退指到空气),同一个词不得归两组(歧义会让结果随表序漂移) ***/
function checkSynonyms(ids) {
const issues = [];
@@ -1784,6 +1810,7 @@ function cmdVerify() {
issues.push(...checkToastLive(pkgs)); // toast 必须有 live 区域与 alert 抢占
issues.push(...checkFormErrorLink(pkgs)); // 表单错误文案必须被控件关联
issues.push(...checkFormReset(pkgs)); // 重置按钮必须真复位
issues.push(...checkInvalidRing(pkgs)); // 错误环只该在聚焦时亮
issues.push(...checkSynonyms(new Set(pkgs.flatMap((p) => (p.docs?.components ?? []).map((c) => c.id))))); // 同义词表指向的组件必须真实存在
checkDarkTokens(issues);
checkTokenParity(issues);