iter(g180): 内距字面值令牌化
This commit is contained in:
@@ -36,6 +36,11 @@ export const KIND_META = [
|
||||
label: '焦点环变体',
|
||||
hint: '自绘 0 0 0 Npx 色环,应改用 --ua-focus-ring / --ua-focus-ring-inset',
|
||||
},
|
||||
{
|
||||
key: 'space-literal',
|
||||
label: '内距字面值',
|
||||
hint: 'padding/gap/margin 写死 px,应改用 --ua-space-*',
|
||||
},
|
||||
];
|
||||
|
||||
/*** 作用:需要扫描的 CSS 属性白名单(其余属性本轮不动;用白名单顺带避开伪类选择器误判) ***/
|
||||
@@ -48,6 +53,48 @@ const SCAN_PROPS = new Set([
|
||||
'box-shadow',
|
||||
'border-radius',
|
||||
'outline',
|
||||
'padding',
|
||||
'padding-top',
|
||||
'padding-right',
|
||||
'padding-bottom',
|
||||
'padding-left',
|
||||
'margin',
|
||||
'margin-top',
|
||||
'margin-right',
|
||||
'margin-bottom',
|
||||
'margin-left',
|
||||
'gap',
|
||||
'row-gap',
|
||||
'column-gap',
|
||||
]);
|
||||
|
||||
/*** 作用:内距类属性集合(迁移与统计共用同一判定) ***/
|
||||
const SPACE_PROPS = new Set([
|
||||
'padding',
|
||||
'padding-top',
|
||||
'padding-right',
|
||||
'padding-bottom',
|
||||
'padding-left',
|
||||
'margin',
|
||||
'margin-top',
|
||||
'margin-right',
|
||||
'margin-bottom',
|
||||
'margin-left',
|
||||
'gap',
|
||||
'row-gap',
|
||||
'column-gap',
|
||||
]);
|
||||
|
||||
/*** 作用:内距 px 字面值 → 令牌(半步档位 05/15/25/35 与既有 1..4 组成完整梯子;1px 是边框语义不入表) ***/
|
||||
const SPACE_TOKENS = new Map([
|
||||
['2px', 'var(--ua-space-05)'],
|
||||
['4px', 'var(--ua-space-1)'],
|
||||
['6px', 'var(--ua-space-15)'],
|
||||
['8px', 'var(--ua-space-2)'],
|
||||
['10px', 'var(--ua-space-25)'],
|
||||
['12px', 'var(--ua-space-3)'],
|
||||
['14px', 'var(--ua-space-35)'],
|
||||
['16px', 'var(--ua-space-4)'],
|
||||
]);
|
||||
|
||||
/*** 作用:字号字面值 → 令牌(10/11 归并到 xs,避免 11px 单独成档) ***/
|
||||
@@ -114,7 +161,7 @@ export function blankComments(src) {
|
||||
|
||||
/*** 作用:逐条产出「属性 + 值」及其在原文中的偏移;只认白名单属性且必须以分号收尾(避开伪类选择器) ***/
|
||||
export function eachDeclaration(code) {
|
||||
const re = /(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|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();
|
||||
@@ -205,6 +252,20 @@ function migrateShadow(core) {
|
||||
return { kind: 'shadow-literal', value: `var(--ua-shadow-${hit})` };
|
||||
}
|
||||
|
||||
/*** 作用:迁移单条内距声明:逐个 px 记号查 SPACE_TOKENS 替换(负值与 calc 内不算,返回 null 表示无需改动) ***/
|
||||
function migrateSpace(core) {
|
||||
let hits = 0;
|
||||
const next = String(core).replace(/(^|[\s(,])(-?\d+(?:\.\d+)?)px\b/gi, (full, lead, num) => {
|
||||
if (String(num).startsWith('-')) return full; // 负外距是偏移语义,不入令牌
|
||||
const mapped = SPACE_TOKENS.get(`${num}px`);
|
||||
if (!mapped) return full; // 表外取值(3px / 5px / 22px 等)留给后续条目评估
|
||||
hits++;
|
||||
return `${lead}${mapped}`;
|
||||
});
|
||||
if (!hits) return null;
|
||||
return { kind: 'space-literal', value: next };
|
||||
}
|
||||
|
||||
/*** 作用:判定单条声明是否需要迁移,返回 { kind, value } 或 null(幂等:已是令牌就返回 null) ***/
|
||||
export function migrateDeclaration(prop, rawValue) {
|
||||
const { core, tail } = splitImportant(rawValue);
|
||||
@@ -219,6 +280,8 @@ export function migrateDeclaration(prop, rawValue) {
|
||||
result = migrateMotion(prop, core);
|
||||
} else if (prop === 'box-shadow') {
|
||||
result = migrateShadow(core);
|
||||
} else if (SPACE_PROPS.has(prop)) {
|
||||
result = migrateSpace(core);
|
||||
}
|
||||
if (!result) return null;
|
||||
return { kind: result.kind, value: result.value + tail };
|
||||
@@ -259,6 +322,12 @@ function detect(prop, rawValue, key) {
|
||||
if (!/^(inset )?0 0 0 [2-8]px \S/.test(value)) return 0;
|
||||
return /var\(--ua-color-(accent|warning|danger)/.test(value) ? 1 : 0;
|
||||
}
|
||||
if (key === 'space-literal') {
|
||||
if (!SPACE_PROPS.has(prop)) return 0;
|
||||
// 口径:数非负、非 1px 的 px 记号(1px 是边框/分隔线语义,负外距是偏移语义,都不算漂移)
|
||||
const tokens = String(value).match(/(^|[\s(,])(\d+(?:\.\d+)?)px\b/gi) ?? [];
|
||||
return tokens.filter((t) => !/(^|[\s(,])1px$/i.test(t)).length;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user