iter(g183): 字重行高令牌化

This commit is contained in:
HIsheR
2026-10-26 17:36:39 +08:00
parent 089527fd7d
commit fe7972574a
6 changed files with 154 additions and 84 deletions
+62 -1
View File
@@ -46,6 +46,16 @@ export const KIND_META = [
label: '控件高度字面值',
hint: 'height 写死控件档位值(28/34/40px),应改用 --ua-control-h-*',
},
{
key: 'weight-literal',
label: '字重字面值',
hint: 'font-weight 写死数字,应改用 --ua-weight-*',
},
{
key: 'leading-literal',
label: '行高字面值',
hint: 'line-height 写死数值,应改用 --ua-leading-*(px 行高是图形对齐技巧,不入此口径)',
},
];
/*** 作用:需要扫描的 CSS 属性白名单(其余属性本轮不动;用白名单顺带避开伪类选择器误判) ***/
@@ -74,6 +84,8 @@ const SCAN_PROPS = new Set([
'min-height',
'max-height',
'height',
'font-weight',
'line-height',
]);
/*** 作用:内距类属性集合(迁移与统计共用同一判定) ***/
@@ -151,6 +163,26 @@ const CONTROL_H_TOKENS = new Map([
['40px', 'var(--ua-control-h-lg)'],
]);
/*** 作用:字重字面值 → 令牌(normal/medium/semibold/bold 四档覆盖常见取值) ***/
const WEIGHT_TOKENS = new Map([
['400', 'var(--ua-weight-normal)'],
['500', 'var(--ua-weight-medium)'],
['600', 'var(--ua-weight-semibold)'],
['700', 'var(--ua-weight-bold)'],
]);
/*** 作用:行高字面值 → 令牌(unitless 归 none/tight/normal 三档,就近收敛;px 行高是图形对齐不入表) ***/
const LEADING_TOKENS = new Map([
['1', 'var(--ua-leading-none)'],
['1.2', 'var(--ua-leading-none)'],
['1.35', 'var(--ua-leading-tight)'],
['1.4', 'var(--ua-leading-tight)'],
['1.5', 'var(--ua-leading-normal)'],
['1.55', 'var(--ua-leading-normal)'],
['1.6', 'var(--ua-leading-normal)'],
['1.65', 'var(--ua-leading-normal)'],
]);
/*** 作用:压缩空白,便于用稳定字符串比对(不改语义) ***/
export function squash(value) {
return String(value).replace(/\s+/g, ' ').trim();
@@ -176,7 +208,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|min-height|max-height|height|transition-duration|animation-duration|transition|animation|font-size|box-shadow|border-radius|outline)\s*:\s*([^;{}]*);/gi;
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|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();
@@ -288,6 +320,20 @@ function migrateControlH(core) {
return { kind: 'control-h-literal', value: token };
}
/*** 作用:迁移单条字重:整值命中四档即换令牌 ***/
function migrateWeight(core) {
const token = WEIGHT_TOKENS.get(squash(core));
if (!token) return null;
return { kind: 'weight-literal', value: token };
}
/*** 作用:迁移单条行高:unitless 数值命中映射表即换令牌(px 与表外值不动) ***/
function migrateLeading(core) {
const token = LEADING_TOKENS.get(squash(core));
if (!token) return null;
return { kind: 'leading-literal', value: token };
}
/*** 作用:判定单条声明是否需要迁移,返回 { kind, value } 或 null(幂等:已是令牌就返回 null) ***/
export function migrateDeclaration(prop, rawValue) {
const { core, tail } = splitImportant(rawValue);
@@ -306,6 +352,10 @@ export function migrateDeclaration(prop, rawValue) {
result = migrateSpace(core);
} else if (prop === 'height') {
result = migrateControlH(core);
} else if (prop === 'font-weight') {
result = migrateWeight(core);
} else if (prop === 'line-height') {
result = migrateLeading(core);
}
if (!result) return null;
return { kind: result.kind, value: result.value + tail };
@@ -356,6 +406,17 @@ function detect(prop, rawValue, key) {
if (prop !== 'height') return 0; // min/max-height 是约束不是控件档位,不入此口径
return CONTROL_H_TOKENS.has(squash(core)) ? 1 : 0;
}
if (key === 'weight-literal') {
if (prop !== 'font-weight') return 0;
if (/^var\(/.test(value)) return 0;
return /\d+/.test(value) ? 1 : 0; // normal/bold 关键字与数值都算漂移,一律走令牌
}
if (key === 'leading-literal') {
if (prop !== 'line-height') return 0;
if (/^var\(/.test(value)) return 0;
if (/px|em|rem|%|calc/.test(value)) return 0; // px 行高是图形对齐技巧(图标 / 角标),不入此口径
return /^\d+(\.\d+)?$/.test(value) ? 1 : 0; // unitless 数值归三档令牌
}
return 0;
}