styimat 10.3.0 → 11.0.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
@@ -332,8 +332,6 @@ body {
332
332
  }
333
333
 
334
334
  .container {
335
- @grid(3, 20px);
336
- // 也可以
337
335
  @grid: 3 20px;
338
336
  }
339
337
  ```
@@ -460,18 +458,6 @@ styimat.config({
460
458
  preserveOriginal: false
461
459
  });
462
460
 
463
- // 数学工具
464
- styimat.math.evaluate('100px/2'); // "calc(100px / 2)"
465
- styimat.math.evaluate('(16px*1.5)+4px'); // "calc((16px * 1.5) + 4px)"
466
-
467
- // 颜色工具
468
- const rgb = styimat.colorUtils.labToRGB(54.7, 77.9, 80.1);
469
- const p3 = styimat.colorUtils.labToP3(54.7, 77.9, 80.1);
470
- const lab = styimat.colorUtils.lchToLab(54.7, 78.9, 38.5);
471
-
472
- // 解析颜色
473
- const colorInfo = styimat.colorUtils.parseColor('lab(54.7 77.9 80.1 / 0.8)');
474
-
475
461
  // 导入工具
476
462
  styimat.imports.clearCache(); // 清除导入缓存
477
463
  styimat.imports.setBaseUrl('/css/'); // 设置导入基础URL
@@ -1,53 +1,53 @@
1
1
  {
2
- "generatedAt": "2026-01-08T02:20:22.011Z",
2
+ "generatedAt": "2026-01-10T03:44:31.269Z",
3
3
  "files": [
4
4
  {
5
5
  "name": "dist/styimat.js",
6
- "size": "55.73 KB"
6
+ "size": "47.83 KB"
7
7
  },
8
8
  {
9
9
  "name": "dist/styimat.min.js",
10
- "size": "17.43 KB"
10
+ "size": "14.81 KB"
11
11
  },
12
12
  {
13
13
  "name": "dist/styimat.mjs",
14
- "size": "55.89 KB"
14
+ "size": "47.96 KB"
15
15
  },
16
16
  {
17
17
  "name": "dist/styimat.min.mjs",
18
- "size": "17.55 KB"
18
+ "size": "14.91 KB"
19
19
  },
20
20
  {
21
21
  "name": "dist/styimat.cjs",
22
- "size": "55.75 KB"
22
+ "size": "47.86 KB"
23
23
  },
24
24
  {
25
25
  "name": "dist/styimat.min.cjs",
26
- "size": "17.45 KB"
26
+ "size": "14.83 KB"
27
27
  },
28
28
  {
29
29
  "name": "dist/styimat.umd.js",
30
- "size": "56.07 KB"
30
+ "size": "48.17 KB"
31
31
  },
32
32
  {
33
33
  "name": "dist/styimat.umd.min.js",
34
- "size": "17.66 KB"
34
+ "size": "15.05 KB"
35
35
  },
36
36
  {
37
37
  "name": "dist/styimat.amd.js",
38
- "size": "55.75 KB"
38
+ "size": "47.85 KB"
39
39
  },
40
40
  {
41
41
  "name": "dist/styimat.amd.min.js",
42
- "size": "17.45 KB"
42
+ "size": "14.83 KB"
43
43
  },
44
44
  {
45
45
  "name": "dist/styimat.browser.js",
46
- "size": "55.88 KB"
46
+ "size": "47.99 KB"
47
47
  },
48
48
  {
49
49
  "name": "dist/styimat.browser.min.js",
50
- "size": "17.54 KB"
50
+ "size": "14.92 KB"
51
51
  },
52
52
  {
53
53
  "name": "bin/cli.min.js",
@@ -2,19 +2,6 @@
2
2
  * MIT License
3
3
  * Copyright (c) 2025 王小玗
4
4
  */
5
- /**
6
- * CSS 变量预处理库 - 增强版
7
- * 支持 CSS 变量预处理、嵌套选择器和嵌套变量
8
- * 支持 Lab 和 LCH 颜色空间转换为 RGB(CSS标准格式)
9
- * 支持 lab# 和 lch# 十六进制语法
10
- * 支持 Display P3 广色域显示器
11
- * 增强 math() 函数,支持复杂数学计算
12
- * 支持配置头
13
- * 支持 @import 语法
14
- * 支持 @alias 语法
15
- * 支持 @macro 宏定义系统
16
- */
17
-
18
5
 
19
6
  const styimat = (function() {
20
7
  // 默认配置
@@ -95,7 +82,7 @@ const styimat = (function() {
95
82
  * 解析配置头
96
83
  */
97
84
  function parseConfigHeader(cssText) {
98
- const config = { ...defaultConfig };
85
+ const config = Object.create(null);
99
86
  const lines = splitLines(cssText);
100
87
  const cleanLines = [];
101
88
 
@@ -283,6 +270,7 @@ const styimat = (function() {
283
270
 
284
271
  result = result.replace(REGEX.VARIABLE, (match, paramName) => {
285
272
  const paramValue = args.get(paramName);
273
+
286
274
  if (paramValue) return args.get(paramName);
287
275
  return match;
288
276
  });
@@ -374,7 +362,7 @@ const styimat = (function() {
374
362
  declarations.push(currentDeclaration.trim());
375
363
  }
376
364
 
377
- const result = {};
365
+ const result = Object.create(null);
378
366
 
379
367
  for (let declaration of declarations) {
380
368
  declaration = declaration.replace(REGEX.COMMENT, '');
@@ -403,6 +391,7 @@ const styimat = (function() {
403
391
  if (property.startsWith("@") && macros.get(property.slice(1))) {
404
392
  const macro = macros.get(property.slice(1));
405
393
  const args = parseMacroArguments(value, macro.params, ' ');
394
+
406
395
  property = applyMacro(macro.body, args, config);
407
396
  value = "";
408
397
  }
@@ -851,7 +840,7 @@ const styimat = (function() {
851
840
  function parseNestedRules(cssText, config, aliases, macros) {
852
841
  const rootRules = [];
853
842
  const stack = [];
854
- const globalVariables = {}; // 存储全局变量
843
+ const globalVariables = Object.create(null); // 存储全局变量
855
844
 
856
845
  let currentRule = null;
857
846
  let currentLine = '';
@@ -896,7 +885,7 @@ function parseNestedRules(cssText, config, aliases, macros) {
896
885
  // 新规则开始
897
886
  currentRule = {
898
887
  selector: currentLine.trim(),
899
- properties: {},
888
+ properties: Object.create(null),
900
889
  children: []
901
890
  };
902
891
  stack.push(currentRule);
@@ -916,7 +905,7 @@ function parseNestedRules(cssText, config, aliases, macros) {
916
905
  // 开始嵌套规则
917
906
  const nestedRule = {
918
907
  selector: currentLine.trim(),
919
- properties: {},
908
+ properties: Object.create(null),
920
909
  children: []
921
910
  };
922
911
  stack.push(nestedRule);
@@ -1034,7 +1023,7 @@ function parseNestedRules(cssText, config, aliases, macros) {
1034
1023
  if (Object.keys(globalVariables).length > 0) {
1035
1024
  const rootVarsRule = {
1036
1025
  selector: config.rootSelector,
1037
- properties: {},
1026
+ properties: Object.create(null),
1038
1027
  children: []
1039
1028
  };
1040
1029
  // 将变量转换为CSS属性
@@ -1054,6 +1043,8 @@ function parseNestedRules(cssText, config, aliases, macros) {
1054
1043
  */
1055
1044
  function convertRulesToCSS(rules, config, parentSelector = '', aliases, macros, isRootAt = false) {
1056
1045
  let result = '';
1046
+ const indentSize = " ".repeat(config.indentSize);
1047
+ const rootIndentSize = (isRootAt ? indentSize : '');
1057
1048
 
1058
1049
  for (const rule of rules) {
1059
1050
  const isAt = rule.selector.startsWith("@");
@@ -1077,14 +1068,12 @@ function parseNestedRules(cssText, config, aliases, macros) {
1077
1068
  fullSelector = fullSelector;
1078
1069
 
1079
1070
  if (Object.keys(rule.properties).length > 0) {
1080
- result += (isRootAt ? " ".repeat(config.indentSize) : '') + fullSelector + ' {\n';
1071
+ result += rootIndentSize + fullSelector + ' {\n';
1081
1072
  for (let key in rule.properties) {
1082
- if (rule.properties.hasOwnProperty(key)) {
1083
- const value = processCSSValue(rule.properties[key], config);
1084
- result += (isRootAt ? " ".repeat(config.indentSize) : '') + " ".repeat(config.indentSize) + (!value.length ? `${key}\n` : `${key}: ${value};\n`);
1085
- }
1073
+ const value = processCSSValue(rule.properties[key], config);
1074
+ result += rootIndentSize + indentSize + (!value.length ? `${key}\n` : `${key}: ${value};\n`);
1086
1075
  }
1087
- result += isRootAt ? " ".repeat(config.indentSize) + '}\n' : '}\n\n';
1076
+ result += isRootAt ? indentSize + '}\n' : '}\n\n';
1088
1077
  }
1089
1078
 
1090
1079
  if (rule.children && rule.children.length > 0) {
@@ -1219,63 +1208,52 @@ function parseNestedRules(cssText, config, aliases, macros) {
1219
1208
 
1220
1209
  return content;
1221
1210
  }
1222
-
1211
+
1223
1212
  /**
1224
1213
  * 主转换函数
1225
1214
  */
1226
- /**
1227
- * 主转换函数
1228
- */
1229
- async function convert(cssText, customConfig = {}) {
1230
- let { config: headerConfig, css: cleanedCSS } = parseConfigHeader(cssText);
1231
- const finalConfig = { ...defaultConfig, ...customConfig, ...headerConfig };
1232
- cleanedCSS = await processImports(cleanedCSS, finalConfig);
1233
-
1234
- let aliases = new Map();
1235
-
1236
- let cssWithMacros = cleanedCSS;
1237
- let macros = new Map();
1238
- if (finalConfig.enableMacros) {
1239
- const { macros: parsedMacros, css: cssWithoutMacros } = parseMacroStatements(cssWithMacros, finalConfig);
1240
- macros = parsedMacros;
1241
- cssWithMacros = cssWithoutMacros;
1242
-
1243
- for (const [name, macro] of macros) {
1244
- macroRegistry.set(name, macro);
1245
- }
1246
- }
1247
-
1248
- let processedCSS = cssWithMacros.trim();
1249
- if (finalConfig.enableNesting && cssWithMacros.includes('{')) {
1250
- try {
1251
- // parseNestedRules 现在会在内部处理 @alias 语句
1252
- processedCSS = parseNestedRules(cssWithMacros, finalConfig, aliases, macros);
1253
- } catch (error) {
1254
- console.warn('嵌套解析失败,使用原始CSS:', error);
1215
+ async function convert(cssText, customConfig = {}) {
1216
+ let { config: headerConfig, css: cleanedCSS } = parseConfigHeader(cssText);
1217
+ const finalConfig = { ...defaultConfig, ...customConfig, ...headerConfig };
1218
+ cleanedCSS = await processImports(cleanedCSS, finalConfig);
1219
+
1220
+ let aliases = new Map();
1221
+
1222
+ let cssWithMacros = cleanedCSS;
1223
+ let macros = new Map();
1224
+ if (finalConfig.enableMacros) {
1225
+ const { macros: parsedMacros, css: cssWithoutMacros } = parseMacroStatements(cssWithMacros, finalConfig);
1226
+ macros = parsedMacros;
1227
+ cssWithMacros = cssWithoutMacros;
1228
+
1229
+ for (const [name, macro] of macros) {
1230
+ macroRegistry.set(name, macro);
1231
+ }
1255
1232
  }
1256
- } else {
1257
- // 对于非嵌套CSS,仍然需要单独处理 @alias
1258
- if (finalConfig.enableAlias) {
1259
- const { aliases: parsedAliases, css: cssWithoutAliases } = parseAliasStatements(cssWithMacros);
1260
- aliases = parsedAliases;
1261
- cssWithMacros = cssWithoutAliases;
1233
+
1234
+ let processedCSS = cssWithMacros.trim();
1235
+ if (finalConfig.enableNesting && cssWithMacros.includes('{')) {
1236
+ try {
1237
+ processedCSS = parseNestedRules(cssWithMacros, finalConfig, aliases, macros);
1238
+ } catch (error) {
1239
+ console.warn('嵌套解析失败,使用原始CSS:', error);
1240
+ }
1262
1241
  }
1263
- }
1264
-
1265
- let finalCSS = processedCSS;
1266
-
1267
- finalCSS = replaceVariableUses(finalCSS, finalConfig);
1268
-
1269
- for (const [name, plugin] of pluginMap) {
1270
- try {
1271
- finalCSS = plugin.convert(finalCSS, finalConfig);
1272
- } catch (error) {
1273
- console.error('插件处理失败:', error);
1242
+
1243
+ let finalCSS = processedCSS;
1244
+
1245
+ finalCSS = replaceVariableUses(finalCSS, finalConfig);
1246
+
1247
+ for (const [name, plugin] of pluginMap) {
1248
+ try {
1249
+ finalCSS = plugin.convert(finalCSS, finalConfig);
1250
+ } catch (error) {
1251
+ console.error('插件处理失败:', error);
1252
+ }
1274
1253
  }
1254
+
1255
+ return finalCSS;
1275
1256
  }
1276
-
1277
- return finalCSS;
1278
- }
1279
1257
 
1280
1258
  /**
1281
1259
  * 自动处理带有特定属性的 style 标签
@@ -1315,7 +1293,7 @@ async function convert(cssText, customConfig = {}) {
1315
1293
  return styleTags.length;
1316
1294
  }
1317
1295
 
1318
- function config(config = {}) {
1296
+ function config(config) {
1319
1297
  defaultConfig = { ...defaultConfig, ...config };
1320
1298
  }
1321
1299
 
@@ -1393,179 +1371,6 @@ async function convert(cssText, customConfig = {}) {
1393
1371
  clear: function() {
1394
1372
  pluginMap.clear();
1395
1373
  }
1396
- },
1397
-
1398
- aliases: {
1399
- add: function(alias, property) {
1400
- aliasMap.set(alias, property);
1401
- },
1402
- remove: function(alias) {
1403
- aliasMap.delete(alias);
1404
- },
1405
- getAll: function() {
1406
- return Array.from(aliasMap.entries());
1407
- },
1408
- clear: function() {
1409
- aliasMap.clear();
1410
- }
1411
- },
1412
-
1413
- macros: {
1414
- define: function(name, body, params = []) {
1415
- if (typeof body === 'function') {
1416
- const funcString = body.toString();
1417
- const bodyMatch = funcString.match(/{([\s\S]*)}/);
1418
- if (bodyMatch) {
1419
- macroRegistry.set(name, {
1420
- params: params.map(p => typeof p === 'string' ? { name: p } : p),
1421
- body: bodyMatch[1].trim()
1422
- });
1423
- }
1424
- } else {
1425
- macroRegistry.set(name, {
1426
- params: params.map(p => typeof p === 'string' ? { name: p } : p),
1427
- body: body
1428
- });
1429
- }
1430
- },
1431
-
1432
- call: function(name, ...args) {
1433
- const macro = macroRegistry.get(name);
1434
- if (!macro) {
1435
- throw new Error(`未定义的宏: ${name}`);
1436
- }
1437
-
1438
- const argsMap = new Map();
1439
- for (let i = 0, length = macro.params.length; i < length; i++) {
1440
- const param = macro.params[i];
1441
- const value = i < args.length ? args[i] : param.defaultValue;
1442
- if (value === undefined && param.defaultValue === null) {
1443
- throw new Error(`缺少必需参数: ${param.name}`);
1444
- }
1445
- argsMap.set(param.name, value !== undefined ? value : '');
1446
- }
1447
-
1448
- return applyMacro(macro.body, argsMap, defaultConfig);
1449
- },
1450
-
1451
- getAll: function() {
1452
- return Array.from(macroRegistry.entries());
1453
- },
1454
-
1455
- remove: function(name) {
1456
- macroRegistry.delete(name);
1457
- },
1458
-
1459
- clear: function() {
1460
- macroRegistry.clear();
1461
- },
1462
-
1463
- parse: function(cssText) {
1464
- const { macros } = parseMacroStatements(cssText, defaultConfig);
1465
- for (const [name, macro] of macros) {
1466
- macroRegistry.set(name, macro);
1467
- }
1468
- }
1469
- },
1470
-
1471
- math: {
1472
- evaluate: function(expression) {
1473
- return evaluateMathExpression(expression, defaultConfig);
1474
- }
1475
- },
1476
-
1477
- colorUtils: {
1478
- labToRGB: preciseLabToRGB,
1479
- lchToLab: lchToLab,
1480
- lchToRGB: function(L, C, H) {
1481
- const lab = lchToLab(L, C, H);
1482
- return preciseLabToRGB(lab.L, lab.a, lab.b);
1483
- },
1484
- labToP3: labToP3,
1485
- lchToP3: function(L, C, H) {
1486
- const lab = lchToLab(L, C, H);
1487
- return labToP3(lab.L, lab.a, lab.b);
1488
- },
1489
- parseHexLab: function(hexString) {
1490
- const match = hexString.match(/lab#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/i);
1491
- if (!match) return null;
1492
-
1493
- const L_hex = match[1];
1494
- const A_hex = match[2];
1495
- const B_hex = match[3];
1496
-
1497
- const L = parseInt(L_hex, 16) / 255 * 100;
1498
- const A = (parseInt(A_hex, 16) - 128) * 1.5;
1499
- const B = (parseInt(B_hex, 16) - 128) * 1.5;
1500
-
1501
- return preciseLabToRGB(L, A, B);
1502
- },
1503
- parseHexLch: function(hexString) {
1504
- const match = hexString.match(/lch#([0-9a-f]{2})([0-9a-f]{2})(\d{1,3})/i);
1505
- if (!match) return null;
1506
-
1507
- const L_hex = match[1];
1508
- const C_hex = match[2];
1509
- const H_dec = match[3];
1510
-
1511
- const L = parseInt(L_hex, 16) / 255 * 100;
1512
- const C = parseInt(C_hex, 16) / 255 * 150;
1513
- const H = parseInt(H_dec) / 100 * 360;
1514
-
1515
- const lab = lchToLab(L, C, H);
1516
- return preciseLabToRGB(lab.L, lab.a, lab.b);
1517
- },
1518
- generateColor: function(L, a, b, alpha = null, useP3 = true) {
1519
- return generateColorString(L, a, b, { enableP3: useP3 }, alpha);
1520
- },
1521
- parseColor: function(colorString) {
1522
- try {
1523
- const labMatch = colorString.match(/lab\(\s*([\d.]+)(%?)\s+([\d.-]+)\s+([\d.-]+)(?:\s*\/\s*([\d.%]+))?\s*\)/i);
1524
- if (labMatch) {
1525
- let L = parseFloat(labMatch[1]);
1526
- const A = parseFloat(labMatch[3]);
1527
- const B = parseFloat(labMatch[4]);
1528
- const alpha = labMatch[5] ?
1529
- (labMatch[5].includes('%') ? parseFloat(labMatch[5]) / 100 : parseFloat(labMatch[5])) :
1530
- null;
1531
-
1532
- const colorStr = generateColorString(L, A, B, defaultConfig, alpha);
1533
-
1534
- return {
1535
- L, A, B, alpha,
1536
- rgb: preciseLabToRGB(L, A, B),
1537
- p3: labToP3(L, A, B),
1538
- colorString: colorStr
1539
- };
1540
- }
1541
-
1542
- const lchMatch = colorString.match(/lch\(\s*([\d.]+)(%?)\s+([\d.]+)\s+([\d.]+)(deg)?(?:\s*\/\s*([\d.%]+))?\s*\)/i);
1543
- if (lchMatch) {
1544
- let L = parseFloat(lchMatch[1]);
1545
- const C = parseFloat(lchMatch[3]);
1546
- let H = parseFloat(lchMatch[4]);
1547
- const alpha = lchMatch[6] ?
1548
- (lchMatch[6].includes('%') ? parseFloat(lchMatch[6]) / 100 : parseFloat(lchMatch[6])) :
1549
- null;
1550
-
1551
- const lab = lchToLab(L, C, H);
1552
- const colorStr = generateColorString(lab.L, lab.a, lab.b, defaultConfig, alpha);
1553
-
1554
- return {
1555
- L, C, H, alpha,
1556
- lab: lab,
1557
- rgb: preciseLabToRGB(lab.L, lab.a, lab.b),
1558
- p3: labToP3(lab.L, lab.a, lab.b),
1559
- colorString: colorStr
1560
- };
1561
- }
1562
-
1563
- return null;
1564
- } catch (error) {
1565
- console.warn('无法解析颜色:', colorString, error);
1566
- return null;
1567
- }
1568
- }
1569
1374
  }
1570
1375
  };
1571
1376
 
@@ -1620,12 +1425,7 @@ async function convert(cssText, customConfig = {}) {
1620
1425
  const firstArg = args[0];
1621
1426
 
1622
1427
  if (typeof firstArg === 'string') {
1623
- const result = await convert(firstArg, args[1]);
1624
-
1625
- if (result && typeof result.then === 'function') {
1626
- return result;
1627
- }
1628
- return result;
1428
+ return await convert(firstArg, args[1]);
1629
1429
  }
1630
1430
 
1631
1431
  if (typeof firstArg === 'object' && firstArg !== null) {
@@ -1657,13 +1457,8 @@ async function convert(cssText, customConfig = {}) {
1657
1457
 
1658
1458
  cssText += result + strings[i + 1];
1659
1459
  }
1660
-
1661
- const result = await convert(cssText, defaultConfig);
1662
1460
 
1663
- if (result && typeof result.then === 'function') {
1664
- return result;
1665
- }
1666
- return result;
1461
+ return await convert(cssText);
1667
1462
  }
1668
1463
 
1669
1464
  Object.assign(styimat, api);