styimat 1.6.4 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,12 +1,9 @@
1
1
  # styimat
2
-
3
2
  [![Stars](https://img.shields.io/badge/dynamic/json?label=Stars&query=%24.stargazers_count&url=https%3A%2F%2Fgitee.com%2Fapi%2Fv5%2Frepos%2Fwxy6987%2Fstyimat&color=FFD700&style=yellow)](https://gitee.com/wxy6987/styimat/stargazers)
4
3
  [![Forks](https://img.shields.io/badge/dynamic/json?label=Forks&query=%24.forks_count&url=https%3A%2F%2Fgitee.com%2Fapi%2Fv5%2Frepos%2Fwxy6987%2Fstyimat&color=red)](https://gitee.com/wxy6987/styimat/members)
5
4
  [![version](https://img.shields.io/npm/v/styimat.svg?color=brightgreen)](https://www.npmjs.com/package/styimat)
6
5
  [![license](https://img.shields.io/npm/l/styimat.svg?color=lightgrey)](LICENSE)
7
- [![size](https://img.shields.io/bundlephobia/minzip/styimat?label=size&color=blue)](https://bundlephobia.com/package/styimat)
8
-
9
-
6
+ ![size](https://img.shields.io/bundlephobia/minzip/styimat?label=size&color=blue)
10
7
 
11
8
  一个功能强大的 CSS 变量预处理库,支持嵌套规则、Lab/LCH 颜色空间转换、Display P3 广色域和增强的数学计算功能。
12
9
 
@@ -273,6 +270,38 @@ $font-family: 'Inter', sans-serif;
273
270
  .container {
274
271
  $local-var: 20px;
275
272
  margin: $local-var;
273
+
274
+ &::before {
275
+ content: $$ctx; // 获取元素属性ctx
276
+ }
277
+ }
278
+ ```
279
+
280
+ ### 配置头语法
281
+
282
+ 您可以在CSS文件的开头使用配置头来设置预处理选项,配置行以 `#` 开头:
283
+
284
+ ```css
285
+ #indentSize 4
286
+ #autoProcessStyleTags true
287
+ #preserveOriginal true
288
+ #enableP3 false
289
+ #rootSelector :root
290
+ #enableNesting true
291
+ #enableMath true
292
+ #mathPrecision 8
293
+
294
+ /* 然后写您的CSS代码 */
295
+ $primary-color: lab#32a852;
296
+ $spacing: math(16px * 2 + 4px);
297
+
298
+ body {
299
+ color: $primary-color;
300
+ padding: $spacing;
301
+
302
+ .container {
303
+ margin: math($spacing / 2);
304
+ }
276
305
  }
277
306
  ```
278
307
 
@@ -326,7 +355,7 @@ $font-family: 'Inter', sans-serif;
326
355
 
327
356
  ## 十六进制颜色语法详解
328
357
 
329
- ### Lab 十六进制格式:`lab#L16A16B16`
358
+ ### Lab 十六进制格式:`lab#LLAABB`
330
359
  Lab 颜色使用 `lab#` 前缀,后跟 6 个十六进制字符:
331
360
  - 前 2 位:L(明度),范围 00-FF,映射到 0-100
332
361
  - 中间 2 位:A(红绿轴),范围 00-FF,映射到 -192 到 192
@@ -337,11 +366,11 @@ Lab 颜色使用 `lab#` 前缀,后跟 6 个十六进制字符:
337
366
  - A = 0xFF = 255 → (255-128) × 1.5 ≈ 190.5
338
367
  - B = 0x80 = 128 → (128-128) × 1.5 = 0
339
368
 
340
- ### LCH 十六进制格式:`lch#L16C16H`
369
+ ### LCH 十六进制格式:`lch#LLCCHHH`
341
370
  LCH 颜色使用 `lch#` 前缀,后跟 6 个字符(最后1-3位是十进制色相值):
342
371
  - 前 2 位:L(明度),范围 00-FF,映射到 0-100
343
372
  - 中间 2 位:C(色度),范围 00-FF,映射到 0-150
344
- - 后 1-3 位:H(色相),范围 0-999,映射到 0-360度
373
+ - 后 1-3 位:H(色相),范围 0-100,映射到 0-360度
345
374
 
346
375
  示例:`lch#8CFF090` 表示:
347
376
  - L = 0x8C = 140 → 140/255 × 100 ≈ 55
@@ -362,8 +391,10 @@ LCH 颜色使用 `lch#` 前缀,后跟 6 个字符(最后1-3位是十进制
362
391
  color: lab(20 40 60);
363
392
  }
364
393
  }
394
+ }
365
395
 
366
- @media (min-width: 768px) {
396
+ @media (min-width: 768px) {
397
+ .container {
367
398
  padding: 2rem;
368
399
 
369
400
  .header {
@@ -493,12 +524,12 @@ $border-radius: 0.5rem;
493
524
  ```css
494
525
  /* 使用十六进制语法创建调色板 */
495
526
  $primary: lab#8CFF80;
496
- $secondary: lch#8CFF180;
497
- $accent: lch#6CFF270;
527
+ $secondary: lch#8CFF18;
528
+ $accent: lch#6CFF27;
498
529
 
499
530
  /* 创建变体 */
500
- $primary-light: lab#B4FFA0;
501
- $primary-dark: lab#64FF60;
531
+ $primary-light: lab#B4FF0A;
532
+ $primary-dark: lab#64FF06;
502
533
  $primary-transparent: lab(55 190 0 / 0.8);
503
534
 
504
535
  .theme {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "styimat",
3
- "version": "1.6.4",
3
+ "version": "1.8.0",
4
4
  "description": "一个高效的CSS变量预处理库,支持Lab/LCH颜色空间自动转换、嵌套选择器和Display P3广色域,让现代CSS开发更简洁强大。",
5
5
  "keywords": [
6
6
  "css",
package/styimat.js CHANGED
@@ -9,6 +9,7 @@
9
9
  * 支持 lab# 和 lch# 十六进制语法
10
10
  * 支持 Display P3 广色域显示器
11
11
  * 增强 math() 函数,支持复杂数学计算
12
+ * 支持配置头
12
13
  */
13
14
  (function(root, factory) {
14
15
  if (typeof define === 'function' && define.amd) {
@@ -27,7 +28,7 @@
27
28
  rootSelector: ':root',
28
29
  variablePrefix: '--',
29
30
  preserveOriginal: false,
30
- indentSize: 2,
31
+ indentSize: 4,
31
32
  enableNesting: true,
32
33
  autoProcessStyleTags: true,
33
34
  styleTagAttribute: 'e',
@@ -41,6 +42,70 @@
41
42
  // 全局P3支持检测结果
42
43
  let p3Supported = null;
43
44
 
45
+ /**
46
+ * 解析配置头
47
+ * @param {string} cssText - CSS文本
48
+ * @returns {Object} {config: 配置对象, css: 清理后的CSS}
49
+ */
50
+ function parseConfigHeader(cssText) {
51
+ const config = { ...defaultConfig };
52
+ const lines = cssText.split('\n');
53
+ const cleanLines = [];
54
+
55
+ for (let line of lines) {
56
+ const trimmed = line.trim();
57
+
58
+ // 检查是否是配置行(以 # 开头)
59
+ if (trimmed.startsWith('#')) {
60
+ const configLine = trimmed.substring(1).trim();
61
+ const firstSpace = configLine.indexOf(' ');
62
+
63
+ if (firstSpace !== -1) {
64
+ const key = configLine.substring(0, firstSpace).trim();
65
+ const value = configLine.substring(firstSpace + 1).trim();
66
+
67
+ // 转换配置值
68
+ const configKey = camelCase(key);
69
+
70
+ if (configKey in config) {
71
+ // 根据值的类型进行转换
72
+ if (value === 'true' || value === 'false') {
73
+ config[configKey] = value === 'true';
74
+ } else if (!isNaN(value) && value.trim() !== '') {
75
+ // 数字类型
76
+ config[configKey] = Number(value);
77
+ } else {
78
+ // 字符串类型
79
+ config[configKey] = value;
80
+ }
81
+ } else {
82
+ console.warn(`未知的配置项: ${key}`);
83
+ }
84
+ } else {
85
+ console.warn(`无效的配置行: ${trimmed}`);
86
+ }
87
+ } else {
88
+ cleanLines.push(line);
89
+ }
90
+ }
91
+
92
+ return {
93
+ config,
94
+ css: cleanLines.join('\n')
95
+ };
96
+ }
97
+
98
+ /**
99
+ * 将连字符分隔的字符串转换为驼峰命名
100
+ * @param {string} str - 输入字符串
101
+ * @returns {string} 驼峰命名字符串
102
+ */
103
+ function camelCase(str) {
104
+ return str.replace(/-([a-z])/g, function(match, letter) {
105
+ return letter.toUpperCase();
106
+ });
107
+ }
108
+
44
109
  /**
45
110
  * 检测浏览器是否支持 Display P3
46
111
  * @returns {boolean} 是否支持P3
@@ -958,10 +1023,10 @@
958
1023
 
959
1024
  // 更新缩进级别
960
1025
  if (line.includes('{')) {
961
- currentIndent += 2;
1026
+ currentIndent += config.indentSize;
962
1027
  }
963
1028
  if (line.includes('}')) {
964
- currentIndent = Math.max(0, currentIndent - 2);
1029
+ currentIndent = Math.max(0, currentIndent - config.indentSize);
965
1030
  }
966
1031
  }
967
1032
 
@@ -987,7 +1052,6 @@
987
1052
 
988
1053
  // 计算缩进级别(假设使用空格缩进)
989
1054
  const indent = line.match(/^(\s*)/)[0].length;
990
- const indentLevel = Math.floor(indent / config.indentSize);
991
1055
 
992
1056
  // 处理规则块结束
993
1057
  if (trimmed === '}') {
@@ -1015,8 +1079,7 @@
1015
1079
  const rule = {
1016
1080
  selector: selector,
1017
1081
  properties: [],
1018
- children: [],
1019
- indentLevel: indentLevel
1082
+ children: []
1020
1083
  };
1021
1084
 
1022
1085
  // 推入堆栈
@@ -1064,7 +1127,7 @@
1064
1127
  for (const rule of rules) {
1065
1128
  // 构建完整选择器
1066
1129
  const isAt = rule.selector.startsWith("@");
1067
- let fullSelector = (isParentAt ? ' ' : '') + rule.selector;
1130
+ let fullSelector = (isParentAt ? " ".repeat(config.indentSize) : '') + rule.selector;
1068
1131
 
1069
1132
  if (isAt) {
1070
1133
  fullSelector = rule.selector + " {\n";
@@ -1090,10 +1153,10 @@
1090
1153
  parsed.forEach(obj => {
1091
1154
  const key = Object.keys(obj)[0];
1092
1155
  const value = processCSSValue(obj[key], config);
1093
- result += (isParentAt ? ' ' : '') + ` ${key}: ${value};\n`;
1156
+ result += (isParentAt ? " ".repeat(config.indentSize) : '') + " ".repeat(config.indentSize) +`${key}: ${value};\n`;
1094
1157
  });
1095
1158
  }
1096
- result += isParentAt ? ' }\n' : '}\n\n';
1159
+ result += isParentAt ? " ".repeat(config.indentSize) + '}\n' : '}\n\n';
1097
1160
  }
1098
1161
 
1099
1162
  // 递归处理子规则
@@ -1106,7 +1169,7 @@
1106
1169
  }
1107
1170
  }
1108
1171
 
1109
- return result.trim() + (isParentAt ? "\n\n" : "");
1172
+ return result.trim() + "\n\n";
1110
1173
  }
1111
1174
 
1112
1175
  // 替换变量值中的变量引用
@@ -1123,15 +1186,9 @@
1123
1186
  function replaceVariableUses(cssText, globalVariables, selectorVariables, config) {
1124
1187
  let result = cssText;
1125
1188
 
1126
- // 先替换全局变量
1127
- for (const [varName, varValue] of Object.entries(globalVariables)) {
1128
- const varRegex = new RegExp(`\\$${varName}(?![a-zA-Z0-9_-])`, 'g');
1129
- result = result.replace(varRegex, `var(--${varName})`);
1130
- }
1131
-
1132
- // 然后处理选择器特定的变量
1133
- result = result.replace(/\$([a-zA-Z0-9_-]+)/g, (match, varName) => {
1134
- return `var(--${varName})`;
1189
+ // 处理变量
1190
+ result = result.replace(/(?:\$\$|\$)([a-zA-Z0-9_-]+)/g, (match, varName) => {
1191
+ return match.startsWith('$$') ? `attr(${varName})` : `var(--${varName})`;
1135
1192
  });
1136
1193
 
1137
1194
  // 最后处理所有的LAB、LCH颜色和math()函数
@@ -1178,7 +1235,7 @@
1178
1235
  const vars = selectorVariables.get(currentSelector);
1179
1236
  const indent = line.match(/^(\s*)/)[0];
1180
1237
  for (const [varName, varValue] of Object.entries(vars)) {
1181
- result += indent + ' --' + varName + ': ' + varValue + ';\n';
1238
+ result += ' --' + varName + ': ' + varValue + ';\n';
1182
1239
  }
1183
1240
  }
1184
1241
  currentSelector = null;
@@ -1193,11 +1250,13 @@
1193
1250
 
1194
1251
  // 主转换函数
1195
1252
  function convert(cssText, customConfig = {}) {
1196
- const config = { ...defaultConfig, ...customConfig };
1253
+ // 先解析配置头
1254
+ const { config: headerConfig, css: cleanedCSS } = parseConfigHeader(cssText);
1255
+ const config = { ...defaultConfig, ...customConfig,...headerConfig };
1197
1256
 
1198
1257
  // 1. 提取变量定义(区分全局和选择器局部)
1199
1258
  const { globalVariables, selectorVariables, cssWithoutVars } =
1200
- extractVariablesAndCSS(cssText, config);
1259
+ extractVariablesAndCSS(cleanedCSS, config);
1201
1260
 
1202
1261
  // 2. 解析嵌套规则(如果启用)
1203
1262
  let processedCSS = cssWithoutVars.trim();
package/styimat.min.js CHANGED
@@ -9,6 +9,7 @@
9
9
  * 支持 lab# 和 lch# 十六进制语法
10
10
  * 支持 Display P3 广色域显示器
11
11
  * 增强 math() 函数,支持复杂数学计算
12
+ * 支持配置头
12
13
  */
13
14
  (function(root,factory){if(typeof define==="function"&&define.amd){
14
15
  // AMD 支持 (RequireJS)
@@ -18,10 +19,30 @@ module.exports=factory()}else{
18
19
  // 浏览器全局变量
19
20
  root.styimat=factory()}})(typeof self!=="undefined"?self:this,function(){
20
21
  // 默认配置
21
- let defaultConfig={rootSelector:":root",variablePrefix:"--",preserveOriginal:false,indentSize:2,enableNesting:true,autoProcessStyleTags:true,styleTagAttribute:"e",convertLabToRGB:true,convertLchToRGB:true,enableP3:true,enableMath:true,// 启用math()函数增强
22
+ let defaultConfig={rootSelector:":root",variablePrefix:"--",preserveOriginal:false,indentSize:4,enableNesting:true,autoProcessStyleTags:true,styleTagAttribute:"e",convertLabToRGB:true,convertLchToRGB:true,enableP3:true,enableMath:true,// 启用math()函数增强
22
23
  mathPrecision:6};
23
24
  // 全局P3支持检测结果
24
25
  let p3Supported=null;
26
+ /**
27
+ * 解析配置头
28
+ * @param {string} cssText - CSS文本
29
+ * @returns {Object} {config: 配置对象, css: 清理后的CSS}
30
+ */function parseConfigHeader(cssText){const config={...defaultConfig};const lines=cssText.split("\n");const cleanLines=[];for(let line of lines){const trimmed=line.trim();
31
+ // 检查是否是配置行(以 # 开头)
32
+ if(trimmed.startsWith("#")){const configLine=trimmed.substring(1).trim();const firstSpace=configLine.indexOf(" ");if(firstSpace!==-1){const key=configLine.substring(0,firstSpace).trim();const value=configLine.substring(firstSpace+1).trim();
33
+ // 转换配置值
34
+ const configKey=camelCase(key);if(configKey in config){
35
+ // 根据值的类型进行转换
36
+ if(value==="true"||value==="false"){config[configKey]=value==="true"}else if(!isNaN(value)&&value.trim()!==""){
37
+ // 数字类型
38
+ config[configKey]=Number(value)}else{
39
+ // 字符串类型
40
+ config[configKey]=value}}else{console.warn(`未知的配置项: ${key}`)}}else{console.warn(`无效的配置行: ${trimmed}`)}}else{cleanLines.push(line)}}return{config:config,css:cleanLines.join("\n")}}
41
+ /**
42
+ * 将连字符分隔的字符串转换为驼峰命名
43
+ * @param {string} str - 输入字符串
44
+ * @returns {string} 驼峰命名字符串
45
+ */function camelCase(str){return str.replace(/-([a-z])/g,function(match,letter){return letter.toUpperCase()})}
25
46
  /**
26
47
  * 检测浏览器是否支持 Display P3
27
48
  * @returns {boolean} 是否支持P3
@@ -350,12 +371,12 @@ if(trimmed==="}"){if(inSelectorBlock){
350
371
  // 在选择器结束前插入变量声明
351
372
  if(currentSelector&&selectorVariables.has(currentSelector)){const vars=selectorVariables.get(currentSelector);const indent=" ".repeat(currentIndent);for(const[varName,varValue]of Object.entries(vars)){cssWithoutVars+=`${indent} --${varName}: ${varValue};\n`}}}inSelectorBlock=false;currentSelector=null}cssWithoutVars+=line+"\n";
352
373
  // 更新缩进级别
353
- if(line.includes("{")){currentIndent+=2}if(line.includes("}")){currentIndent=Math.max(0,currentIndent-2)}}return{globalVariables:globalVariables,selectorVariables:selectorVariables,cssWithoutVars:cssWithoutVars.trim()}}
374
+ if(line.includes("{")){currentIndent+=config.indentSize}if(line.includes("}")){currentIndent=Math.max(0,currentIndent-config.indentSize)}}return{globalVariables:globalVariables,selectorVariables:selectorVariables,cssWithoutVars:cssWithoutVars.trim()}}
354
375
  // 修复的嵌套解析函数
355
376
  function parseNestedRules(cssText,config){const lines=cssText.split("\n");const stack=[];// 存储规则信息:{selector, properties, children}
356
377
  const rootRules=[];let currentIndent=0;for(let i=0;i<lines.length;i++){const line=lines[i];const trimmed=line.trim();if(!trimmed)continue;
357
378
  // 计算缩进级别(假设使用空格缩进)
358
- const indent=line.match(/^(\s*)/)[0].length;const indentLevel=Math.floor(indent/config.indentSize);
379
+ const indent=line.match(/^(\s*)/)[0].length;
359
380
  // 处理规则块结束
360
381
  if(trimmed==="}"){if(stack.length>0){const rule=stack.pop();
361
382
  // 如果这个规则有父规则,添加到父规则的children中
@@ -365,7 +386,7 @@ rootRules.push(rule)}}continue}
365
386
  // 处理规则开始
366
387
  if(trimmed.endsWith("{")){const selector=trimmed.slice(0,-1).trim();
367
388
  // 创建新规则
368
- const rule={selector:selector,properties:[],children:[],indentLevel:indentLevel};
389
+ const rule={selector:selector,properties:[],children:[]};
369
390
  // 推入堆栈
370
391
  stack.push(rule);continue}
371
392
  // 处理属性行(不包含 { 或 } 的行)
@@ -379,23 +400,21 @@ return convertRulesToCSS(rootRules,config)}
379
400
  // 将规则树转换为CSS字符串
380
401
  function convertRulesToCSS(rules,config,parentSelector=""){let result="";const isParentAt=parentSelector.startsWith("@");for(const rule of rules){
381
402
  // 构建完整选择器
382
- const isAt=rule.selector.startsWith("@");let fullSelector=(isParentAt?" ":"")+rule.selector;if(isAt){fullSelector=rule.selector+" {\n"}if(parentSelector){
403
+ const isAt=rule.selector.startsWith("@");let fullSelector=(isParentAt?" ".repeat(config.indentSize):"")+rule.selector;if(isAt){fullSelector=rule.selector+" {\n"}if(parentSelector){
383
404
  // 处理 & 选择器
384
405
  if(fullSelector.includes("&")){fullSelector=fullSelector.replace(/&/g,parentSelector)}else if(fullSelector.trim().startsWith(":")){fullSelector=parentSelector+fullSelector}else{fullSelector=parentSelector+(isParentAt?"":" ")+fullSelector}}
385
406
  // 如果有属性,生成规则块
386
407
  if(rule.properties.length>0){result+=(isAt?"":fullSelector)+" {\n";for(const prop of rule.properties){
387
408
  // 再次处理属性值(确保math()函数和颜色被转换)
388
- const parsed=parseSingleLineCSS(prop);parsed.forEach(obj=>{const key=Object.keys(obj)[0];const value=processCSSValue(obj[key],config);result+=(isParentAt?" ":"")+` ${key}: ${value};\n`})}result+=isParentAt?" }\n":"}\n\n"}
409
+ const parsed=parseSingleLineCSS(prop);parsed.forEach(obj=>{const key=Object.keys(obj)[0];const value=processCSSValue(obj[key],config);result+=(isParentAt?" ".repeat(config.indentSize):"")+" ".repeat(config.indentSize)+`${key}: ${value};\n`})}result+=isParentAt?" ".repeat(config.indentSize)+"}\n":"}\n\n"}
389
410
  // 递归处理子规则
390
- if(rule.children&&rule.children.length>0){result+=convertRulesToCSS(rule.children,config,fullSelector)}if(isParentAt){result+="}\n\n"}}return result.trim()+(isParentAt?"\n\n":"")}
411
+ if(rule.children&&rule.children.length>0){result+=convertRulesToCSS(rule.children,config,fullSelector)}if(isParentAt){result+="}\n\n"}}return result.trim()+"\n\n"}
391
412
  // 替换变量值中的变量引用
392
413
  function replaceVariableUsesInValue(value,variables){return value.replace(/\$([a-zA-Z0-9_-]+)/g,(match,varName)=>{if(variables[varName]){return`var(--${varName})`}return match})}
393
414
  // 替换变量使用
394
415
  function replaceVariableUses(cssText,globalVariables,selectorVariables,config){let result=cssText;
395
- // 先替换全局变量
396
- for(const[varName,varValue]of Object.entries(globalVariables)){const varRegex=new RegExp(`\\$${varName}(?![a-zA-Z0-9_-])`,"g");result=result.replace(varRegex,`var(--${varName})`)}
397
- // 然后处理选择器特定的变量
398
- result=result.replace(/\$([a-zA-Z0-9_-]+)/g,(match,varName)=>`var(--${varName})`);
416
+ // 处理变量
417
+ result=result.replace(/(?:\$\$|\$)([a-zA-Z0-9_-]+)/g,(match,varName)=>match.startsWith("$$")?`attr(${varName})`:`var(--${varName})`);
399
418
  // 最后处理所有的LAB、LCH颜色和math()函数
400
419
  result=processCSSValue(result,config);return result}
401
420
  // 生成根规则
@@ -403,13 +422,15 @@ function generateRootRule(variables,config){if(Object.keys(variables).length===0
403
422
  // 处理选择器内部的变量
404
423
  function injectSelectorVariables(cssText,selectorVariables,config){let result="";const lines=cssText.split("\n");let currentSelector=null;for(let line of lines){const trimmed=line.trim();if(trimmed.endsWith("{")){currentSelector=trimmed.slice(0,-1).trim()}if(trimmed==="}"&&currentSelector){
405
424
  // 在选择器结束前插入变量声明
406
- if(selectorVariables.has(currentSelector)){const vars=selectorVariables.get(currentSelector);const indent=line.match(/^(\s*)/)[0];for(const[varName,varValue]of Object.entries(vars)){result+=indent+" --"+varName+": "+varValue+";\n"}}currentSelector=null}
425
+ if(selectorVariables.has(currentSelector)){const vars=selectorVariables.get(currentSelector);const indent=line.match(/^(\s*)/)[0];for(const[varName,varValue]of Object.entries(vars)){result+=" --"+varName+": "+varValue+";\n"}}currentSelector=null}
407
426
  // 使用全局处理函数处理所有math()和颜色
408
427
  result+=processCSSValue(line,config)+"\n"}return result.trim()}
409
428
  // 主转换函数
410
- function convert(cssText,customConfig={}){const config={...defaultConfig,...customConfig};
429
+ function convert(cssText,customConfig={}){
430
+ // 先解析配置头
431
+ const{config:headerConfig,css:cleanedCSS}=parseConfigHeader(cssText);const config={...defaultConfig,...customConfig,...headerConfig};
411
432
  // 1. 提取变量定义(区分全局和选择器局部)
412
- const{globalVariables:globalVariables,selectorVariables:selectorVariables,cssWithoutVars:cssWithoutVars}=extractVariablesAndCSS(cssText,config);
433
+ const{globalVariables:globalVariables,selectorVariables:selectorVariables,cssWithoutVars:cssWithoutVars}=extractVariablesAndCSS(cleanedCSS,config);
413
434
  // 2. 解析嵌套规则(如果启用)
414
435
  let processedCSS=cssWithoutVars.trim();if(config.enableNesting&&cssWithoutVars.includes("{")){try{processedCSS=parseNestedRules(cssWithoutVars,config)}catch(error){console.warn("嵌套解析失败,使用原始CSS:",error)}}
415
436
  // 3. 生成根规则(全局变量)