iter(g185): 分割线统一改走细分边框令牌
This commit is contained in:
@@ -62,7 +62,7 @@ function writeBaseline(root, result) {
|
||||
const file = path.join(root, BASELINE_REL);
|
||||
const total = KIND_META.reduce((sum, meta) => sum + (result.counts[meta.key] ?? 0), 0);
|
||||
const data = {
|
||||
$schema: '视觉漂移基线:五类硬编码视觉字面量的允许上限,任一类超出即 ua audit:visual 退出码 1;迁移后用 --baseline 重写',
|
||||
$schema: '视觉漂移基线:各类硬编码视觉字面量的允许上限,任一类超出即 ua audit:visual 退出码 1;迁移后用 --baseline 重写',
|
||||
file: UI_CSS_REL,
|
||||
commit: shortCommit(root),
|
||||
generatedAt: new Date().toISOString(),
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
/*** 皮肤包样式表相对仓库根的路径(迁移与审计共同的目标文件) ***/
|
||||
export const UI_CSS_REL = 'packages/skin/ui/ui.css';
|
||||
|
||||
/*** 作用:五类硬编码的键名、中文名与判定口径,审计输出与报告都按这个顺序 ***/
|
||||
/*** 作用:各类硬编码的键名、中文名与判定口径,审计输出与报告都按这个顺序 ***/
|
||||
export const KIND_META = [
|
||||
{
|
||||
key: 'font-size-literal',
|
||||
@@ -61,6 +61,11 @@ export const KIND_META = [
|
||||
label: '层级字面值',
|
||||
hint: 'z-index 写死数字,应改用 --ua-z-* 五档(组件内 1/2 微排序豁免)',
|
||||
},
|
||||
{
|
||||
key: 'border-literal',
|
||||
label: '边框色字面值',
|
||||
hint: 'border/border-color 写死色值(rgba()/#hex),组件轮廓用 --ua-color-border、分割线用 --ua-border-subtle',
|
||||
},
|
||||
];
|
||||
|
||||
/*** 作用:需要扫描的 CSS 属性白名单(其余属性本轮不动;用白名单顺带避开伪类选择器误判) ***/
|
||||
@@ -92,6 +97,30 @@ const SCAN_PROPS = new Set([
|
||||
'font-weight',
|
||||
'line-height',
|
||||
'z-index',
|
||||
'border',
|
||||
'border-top',
|
||||
'border-right',
|
||||
'border-bottom',
|
||||
'border-left',
|
||||
'border-color',
|
||||
'border-top-color',
|
||||
'border-right-color',
|
||||
'border-bottom-color',
|
||||
'border-left-color',
|
||||
]);
|
||||
|
||||
/*** 作用:边框类属性集合(轮廓与分割线共用一套色值口径,禁用字面色) ***/
|
||||
const BORDER_PROPS = new Set([
|
||||
'border',
|
||||
'border-top',
|
||||
'border-right',
|
||||
'border-bottom',
|
||||
'border-left',
|
||||
'border-color',
|
||||
'border-top-color',
|
||||
'border-right-color',
|
||||
'border-bottom-color',
|
||||
'border-left-color',
|
||||
]);
|
||||
|
||||
/*** 作用:内距类属性集合(迁移与统计共用同一判定) ***/
|
||||
@@ -217,7 +246,7 @@ export function blankComments(src) {
|
||||
|
||||
/*** 作用:逐条产出「属性 + 值」及其在原文中的偏移;只认白名单属性且必须以分号收尾(避开伪类选择器) ***/
|
||||
export function eachDeclaration(code) {
|
||||
const re = /(padding-top|padding-right|padding-bottom|padding-left|padding|margin-top|margin-right|margin-bottom|margin-left|margin|row-gap|column-gap|gap|font-weight|line-height|z-index|min-height|max-height|height|transition-duration|animation-duration|transition|animation|font-size|box-shadow|border-radius|outline)\s*:\s*([^;{}]*);/gi;
|
||||
const re = /(border-top-color|border-right-color|border-bottom-color|border-left-color|border-color|border-top|border-right|border-bottom|border-left|border|padding-top|padding-right|padding-bottom|padding-left|padding|margin-top|margin-right|margin-bottom|margin-left|margin|row-gap|column-gap|gap|font-weight|line-height|z-index|min-height|max-height|height|transition-duration|animation-duration|transition|animation|font-size|box-shadow|border-radius|outline)\s*:\s*([^;{}]*);/gi;
|
||||
const list = [];
|
||||
for (const m of code.matchAll(re)) {
|
||||
const prop = m[1].toLowerCase();
|
||||
@@ -350,6 +379,15 @@ function migrateZ(core) {
|
||||
return { kind: 'z-literal', value: token };
|
||||
}
|
||||
|
||||
/*** 作用:迁移单条边框:纯黑 rgba 边(历史上手写的「深一层黑边」)归到基础边框色;其余留在门禁里由人按轮廓/分割线语义定位 ***/
|
||||
function migrateBorder(prop, core) {
|
||||
if (!BORDER_PROPS.has(prop)) return null;
|
||||
const value = squash(core);
|
||||
const next = value.replace(/rgba\(\s*0\s*,\s*0\s*,\s*0\s*,\s*[\d.]+\s*\)/g, 'var(--ua-color-border)'); // 空格宽容,避免只认一种写法
|
||||
if (next === value) return null;
|
||||
return { kind: 'border-literal', value: next };
|
||||
}
|
||||
|
||||
/*** 作用:判定单条声明是否需要迁移,返回 { kind, value } 或 null(幂等:已是令牌就返回 null) ***/
|
||||
export function migrateDeclaration(prop, rawValue) {
|
||||
const { core, tail } = splitImportant(rawValue);
|
||||
@@ -374,6 +412,8 @@ export function migrateDeclaration(prop, rawValue) {
|
||||
result = migrateLeading(core);
|
||||
} else if (prop === 'z-index') {
|
||||
result = migrateZ(core);
|
||||
} else {
|
||||
result = migrateBorder(prop, core); // 边框类:只收敛纯黑 rgba 边
|
||||
}
|
||||
if (!result) return null;
|
||||
return { kind: result.kind, value: result.value + tail };
|
||||
@@ -441,10 +481,16 @@ function detect(prop, rawValue, key) {
|
||||
if (value === '1' || value === '2') return 0; // 组件内微排序(表头压行、水印叠层、头像悬停),不是全局层级
|
||||
return /^\d+$/.test(value) ? 1 : 0;
|
||||
}
|
||||
if (key === 'border-literal') {
|
||||
if (!BORDER_PROPS.has(prop)) return 0;
|
||||
if (value === 'none' || value === '0' || value === 'inherit') return 0; // 无边框与继承不算色值漂移
|
||||
const stripped = value.replace(/var\(--ua-[\w-]+\)/g, ' '); // 已是令牌的色先剔除
|
||||
return /(#[0-9a-f]{3,8}\b|rgba?\(|hsla?\()/i.test(stripped) ? 1 : 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*** 作用:扫描整段 CSS,返回五类硬编码的计数与命中行号(审计命令的唯一统计口径) ***/
|
||||
/*** 作用:扫描整段 CSS,返回各类硬编码的计数与命中行号(审计命令的唯一统计口径) ***/
|
||||
export function scanSource(src) {
|
||||
const code = blankComments(src);
|
||||
const lineAt = (offset) => {
|
||||
@@ -487,7 +533,7 @@ export function migrateSource(src) {
|
||||
return { text: out, counts };
|
||||
}
|
||||
|
||||
/*** 作用:把五类计数拍平成「类别: 数量」数组,供审计报告与基线文件共用同一顺序 ***/
|
||||
/*** 作用:把各类计数拍平成「类别: 数量」数组,供审计报告与基线文件共用同一顺序 ***/
|
||||
export function countRows(counts) {
|
||||
return KIND_META.map((meta) => ({ ...meta, count: counts[meta.key] ?? 0 }));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user