feat(client): token 地基补字阶/圆角/间距标量层 AppDims(codegen 单源)
gen_tokens.mjs 扩展解析 :root 共享块 → 生成 app_dims.g.dart: 间距 sp1-10 / 圆角 rSm-rPill / 字号 fsDisplay-fsXs,主题无关 const 标量。 为屏幕重建提供「禁硬编码 px」的单一真源;app_tokens.g.dart 保持字节一致。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TSKEiHsvauyxYUW2itzUXX
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
// GENERATED by tool/gen_tokens.mjs — DO NOT EDIT.
|
||||
// 源:lib/core/theme/token_source/tokens.css(:root 共享块,主题无关)。改尺寸请改源后重跑脚本。
|
||||
// 间距/圆角/字号三套主题统一,故为 const 标量,不进 per-theme AppTokens。
|
||||
|
||||
class AppDims {
|
||||
AppDims._();
|
||||
// 间距
|
||||
static const double sp1 = 4;
|
||||
static const double sp2 = 8;
|
||||
static const double sp3 = 12;
|
||||
static const double sp4 = 16;
|
||||
static const double sp5 = 20;
|
||||
static const double sp6 = 24;
|
||||
static const double sp8 = 32;
|
||||
static const double sp10 = 40;
|
||||
// 圆角
|
||||
static const double rSm = 4;
|
||||
static const double rMd = 6;
|
||||
static const double rLg = 10;
|
||||
static const double rXl = 14;
|
||||
static const double rPill = 999;
|
||||
// 字号
|
||||
static const double fsDisplay = 28;
|
||||
static const double fsH1 = 21;
|
||||
static const double fsH2 = 17;
|
||||
static const double fsTitle = 15;
|
||||
static const double fsBody = 13;
|
||||
static const double fsSm = 12;
|
||||
static const double fsXs = 11;
|
||||
}
|
||||
@@ -72,3 +72,50 @@ AppTokens appTokensOf(String key) {
|
||||
`;
|
||||
fs.writeFileSync(path.join(ROOT, 'lib/core/theme/app_tokens.g.dart'), body);
|
||||
console.log('generated app_tokens.g.dart');
|
||||
|
||||
// ── 主题无关标量(间距/圆角/字号):解析 :root{} 共享块 → AppDims ──
|
||||
function rootBlock(){
|
||||
// 匹配 ":root{" 而非 ":root[data-theme=...]"(前者 { 紧跟)
|
||||
const m = css.match(/:root\s*\{([^}]*)\}/);
|
||||
if(!m) throw new Error('missing :root shared block');
|
||||
const out = {};
|
||||
for(const mm of m[1].matchAll(/--([a-z0-9-]+)\s*:\s*([^;]+);/g)) out[mm[1]] = mm[2].trim();
|
||||
return out;
|
||||
}
|
||||
// kebab → camel:sp-1→sp1 · r-sm→rSm · fs-h1→fsH1 · fs-display→fsDisplay
|
||||
function camel(name){
|
||||
const [h, ...rest] = name.split('-');
|
||||
return h + rest.map(s => s.charAt(0).toUpperCase() + s.slice(1)).join('');
|
||||
}
|
||||
function px(raw){
|
||||
const m = raw.trim().match(/^([\d.]+)px$/);
|
||||
if(!m) throw new Error('unsupported dim value: ' + raw);
|
||||
return m[1];
|
||||
}
|
||||
function emitDims(){
|
||||
const r = rootBlock();
|
||||
const groups = [
|
||||
['间距', k => k.startsWith('sp-')],
|
||||
['圆角', k => k.startsWith('r-')],
|
||||
['字号', k => k.startsWith('fs-')],
|
||||
];
|
||||
const lines = [];
|
||||
for(const [label, pick] of groups){
|
||||
const keys = Object.keys(r).filter(pick);
|
||||
if(!keys.length) continue;
|
||||
lines.push(` // ${label}`);
|
||||
for(const k of keys) lines.push(` static const double ${camel(k)} = ${px(r[k])};`);
|
||||
}
|
||||
return lines.join('\n');
|
||||
}
|
||||
const dimsBody = `// GENERATED by tool/gen_tokens.mjs — DO NOT EDIT.
|
||||
// 源:lib/core/theme/token_source/tokens.css(:root 共享块,主题无关)。改尺寸请改源后重跑脚本。
|
||||
// 间距/圆角/字号三套主题统一,故为 const 标量,不进 per-theme AppTokens。
|
||||
|
||||
class AppDims {
|
||||
AppDims._();
|
||||
${emitDims()}
|
||||
}
|
||||
`;
|
||||
fs.writeFileSync(path.join(ROOT, 'lib/core/theme/app_dims.g.dart'), dimsBody);
|
||||
console.log('generated app_dims.g.dart');
|
||||
|
||||
Reference in New Issue
Block a user