styimat 10.2.0 → 10.3.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/dist/build-manifest.json +1 -1
- package/package.json +6 -3
- package/plugin/hex2rgb.js +95 -0
- package/plugin/hsl2rgb.js +154 -0
package/dist/build-manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "styimat",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.3.0",
|
|
4
4
|
"description": "一个高效的CSS变量预处理库,支持Lab/LCH颜色空间自动转换、嵌套选择器和Display P3广色域,让现代CSS开发更简洁强大。",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"css",
|
|
@@ -32,7 +32,9 @@
|
|
|
32
32
|
"./umd": "./dist/styimat.umd.min.js",
|
|
33
33
|
"./esm": "./dist/styimat.min.mjs",
|
|
34
34
|
"./dist/*": "./dist/*",
|
|
35
|
-
"./bin/*": "./bin/*"
|
|
35
|
+
"./bin/*": "./bin/*",
|
|
36
|
+
"./plugin/": "./plugin/",
|
|
37
|
+
"./*": "./dist/*"
|
|
36
38
|
},
|
|
37
39
|
"browser": "dist/styimat.min.js",
|
|
38
40
|
"unpkg": "dist/styimat.min.js",
|
|
@@ -41,7 +43,8 @@
|
|
|
41
43
|
"README.md",
|
|
42
44
|
"bin",
|
|
43
45
|
"src",
|
|
44
|
-
"dist"
|
|
46
|
+
"dist",
|
|
47
|
+
"plugin"
|
|
45
48
|
],
|
|
46
49
|
"bin": {
|
|
47
50
|
"styimat": "bin/cli.min.js"
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
export default class extends styimat.Plugin {
|
|
2
|
+
name = 'hex2rgb';
|
|
3
|
+
|
|
4
|
+
convert(cssText, config = {}) {
|
|
5
|
+
const options = {
|
|
6
|
+
format: config.format || 'rgb', // 'rgb', 'rgba', 'hex'
|
|
7
|
+
preserveAlpha: config.preserveAlpha ?? true,
|
|
8
|
+
...config
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// 匹配3位、4位、6位、8位十六进制颜色
|
|
12
|
+
const hexRegex = /#([0-9a-f]{3,8})\b/gi;
|
|
13
|
+
|
|
14
|
+
return cssText.replace(hexRegex, (match, hex) => {
|
|
15
|
+
const rgb = this.hexToRgb(hex);
|
|
16
|
+
if (!rgb) return match;
|
|
17
|
+
|
|
18
|
+
const alpha = hex.length <= 5 ? 1 : this.hexToAlpha(hex);
|
|
19
|
+
return this.formatRgb(rgb, alpha, options);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* 十六进制转RGB
|
|
25
|
+
* @param {string} hex - 十六进制颜色值
|
|
26
|
+
* @returns {Object|null} RGB颜色对象 {r, g, b} 或 null
|
|
27
|
+
*/
|
|
28
|
+
hexToRgb(hex) {
|
|
29
|
+
// 处理3位/4位十六进制
|
|
30
|
+
if (hex.length === 3 || hex.length === 4) {
|
|
31
|
+
hex = hex.split('').map(char => char + char).join('');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (hex.length === 6 || hex.length === 8) {
|
|
35
|
+
const r = parseInt(hex.substr(0, 2), 16);
|
|
36
|
+
const g = parseInt(hex.substr(2, 2), 16);
|
|
37
|
+
const b = parseInt(hex.substr(4, 2), 16);
|
|
38
|
+
|
|
39
|
+
return { r, g, b };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* 从十六进制提取透明度
|
|
47
|
+
* @param {string} hex - 十六进制颜色值
|
|
48
|
+
* @returns {number} 透明度 (0-1)
|
|
49
|
+
*/
|
|
50
|
+
hexToAlpha(hex) {
|
|
51
|
+
if (hex.length === 4) {
|
|
52
|
+
const alphaHex = hex.charAt(3) + hex.charAt(3);
|
|
53
|
+
return parseInt(alphaHex, 16) / 255;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (hex.length === 8) {
|
|
57
|
+
const alphaHex = hex.substr(6, 2);
|
|
58
|
+
return parseInt(alphaHex, 16) / 255;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return 1;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* 格式化RGB输出
|
|
66
|
+
*/
|
|
67
|
+
formatRgb(rgb, alpha, options) {
|
|
68
|
+
const { r, g, b } = rgb;
|
|
69
|
+
|
|
70
|
+
switch(options.format.toLowerCase()) {
|
|
71
|
+
case 'hex':
|
|
72
|
+
if (alpha < 1 && options.preserveAlpha) {
|
|
73
|
+
const alphaHex = Math.round(alpha * 255).toString(16).padStart(2, '0');
|
|
74
|
+
return `#${this.toHex(r)}${this.toHex(g)}${this.toHex(b)}${alphaHex}`;
|
|
75
|
+
}
|
|
76
|
+
return `#${this.toHex(r)}${this.toHex(g)}${this.toHex(b)}`;
|
|
77
|
+
|
|
78
|
+
case 'rgba':
|
|
79
|
+
if (alpha < 1) {
|
|
80
|
+
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
|
|
81
|
+
}
|
|
82
|
+
return `rgb(${r}, ${g}, ${b})`;
|
|
83
|
+
|
|
84
|
+
case 'rgb':
|
|
85
|
+
default:
|
|
86
|
+
return `rgb(${r}, ${g}, ${b})`;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
toHex(value) {
|
|
91
|
+
return Math.max(0, Math.min(255, value))
|
|
92
|
+
.toString(16)
|
|
93
|
+
.padStart(2, '0');
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
export default class extends styimat.Plugin {
|
|
2
|
+
name = 'hsl2rgb';
|
|
3
|
+
|
|
4
|
+
// 存储已处理元素,用于清理
|
|
5
|
+
processedElements = new WeakMap();
|
|
6
|
+
|
|
7
|
+
install() {
|
|
8
|
+
// 可以在这里添加初始化逻辑,如果需要的话
|
|
9
|
+
console.log('HSL to sRGB 插件已安装');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
destroy() {
|
|
13
|
+
// 清理资源
|
|
14
|
+
this.processedElements = new WeakMap();
|
|
15
|
+
console.log('HSL to sRGB 插件已销毁');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
convert(cssText, config = {}) {
|
|
19
|
+
// 配置选项
|
|
20
|
+
const options = {
|
|
21
|
+
preserveOriginal: config.preserveOriginal || false,
|
|
22
|
+
format: config.format || 'rgb', // 'rgb', 'rgba', 'hex'
|
|
23
|
+
...config
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// 使用正则表达式匹配HSL/HSLA颜色
|
|
27
|
+
const hslRegex = /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)%\s*,\s*(\d+(?:\.\d+)?)%\s*(?:,\s*(\d+(?:\.\d+)?))?\s*\)/gi;
|
|
28
|
+
|
|
29
|
+
// 替换所有HSL颜色为sRGB
|
|
30
|
+
return cssText.replace(hslRegex, (match, h, s, l, a) => {
|
|
31
|
+
const rgb = this.hslToRgb(
|
|
32
|
+
parseFloat(h),
|
|
33
|
+
parseFloat(s),
|
|
34
|
+
parseFloat(l)
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const alpha = a !== undefined ? parseFloat(a) : 1;
|
|
38
|
+
|
|
39
|
+
// 根据配置返回不同格式
|
|
40
|
+
return this.formatRgb(rgb, alpha, options.format);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* HSL转sRGB的辅助函数
|
|
46
|
+
* @param {number} h - 色相 (0-360)
|
|
47
|
+
* @param {number} s - 饱和度 (0-100)
|
|
48
|
+
* @param {number} l - 亮度 (0-100)
|
|
49
|
+
* @returns {Object} RGB颜色对象 {r, g, b}
|
|
50
|
+
*/
|
|
51
|
+
hslToRgb(h, s, l) {
|
|
52
|
+
// 规范化输入值
|
|
53
|
+
h = h % 360;
|
|
54
|
+
if (h < 0) h += 360;
|
|
55
|
+
|
|
56
|
+
s = Math.max(0, Math.min(100, s)) / 100;
|
|
57
|
+
l = Math.max(0, Math.min(100, l)) / 100;
|
|
58
|
+
|
|
59
|
+
// HSL转RGB算法
|
|
60
|
+
const chroma = (1 - Math.abs(2 * l - 1)) * s;
|
|
61
|
+
const huePrime = h / 60;
|
|
62
|
+
const secondComponent = chroma * (1 - Math.abs(huePrime % 2 - 1));
|
|
63
|
+
|
|
64
|
+
let r, g, b;
|
|
65
|
+
|
|
66
|
+
if (huePrime >= 0 && huePrime < 1) {
|
|
67
|
+
[r, g, b] = [chroma, secondComponent, 0];
|
|
68
|
+
} else if (huePrime >= 1 && huePrime < 2) {
|
|
69
|
+
[r, g, b] = [secondComponent, chroma, 0];
|
|
70
|
+
} else if (huePrime >= 2 && huePrime < 3) {
|
|
71
|
+
[r, g, b] = [0, chroma, secondComponent];
|
|
72
|
+
} else if (huePrime >= 3 && huePrime < 4) {
|
|
73
|
+
[r, g, b] = [0, secondComponent, chroma];
|
|
74
|
+
} else if (huePrime >= 4 && huePrime < 5) {
|
|
75
|
+
[r, g, b] = [secondComponent, 0, chroma];
|
|
76
|
+
} else {
|
|
77
|
+
[r, g, b] = [chroma, 0, secondComponent];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// 调整亮度
|
|
81
|
+
const lightnessAdjustment = l - chroma / 2;
|
|
82
|
+
r += lightnessAdjustment;
|
|
83
|
+
g += lightnessAdjustment;
|
|
84
|
+
b += lightnessAdjustment;
|
|
85
|
+
|
|
86
|
+
// 转换为0-255范围并四舍五入
|
|
87
|
+
return {
|
|
88
|
+
r: Math.round(r * 255),
|
|
89
|
+
g: Math.round(g * 255),
|
|
90
|
+
b: Math.round(b * 255)
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* 格式化RGB输出
|
|
96
|
+
* @param {Object} rgb - RGB颜色对象
|
|
97
|
+
* @param {number} alpha - 透明度 (0-1)
|
|
98
|
+
* @param {string} format - 输出格式
|
|
99
|
+
* @returns {string} 格式化后的颜色字符串
|
|
100
|
+
*/
|
|
101
|
+
formatRgb(rgb, alpha, format = 'rgb') {
|
|
102
|
+
const { r, g, b } = rgb;
|
|
103
|
+
|
|
104
|
+
switch(format.toLowerCase()) {
|
|
105
|
+
case 'hex':
|
|
106
|
+
if (alpha < 1) {
|
|
107
|
+
// 带透明度的十六进制
|
|
108
|
+
const alphaHex = Math.round(alpha * 255).toString(16).padStart(2, '0');
|
|
109
|
+
return `#${this.toHex(r)}${this.toHex(g)}${this.toHex(b)}${alphaHex}`;
|
|
110
|
+
}
|
|
111
|
+
return `#${this.toHex(r)}${this.toHex(g)}${this.toHex(b)}`;
|
|
112
|
+
|
|
113
|
+
case 'rgba':
|
|
114
|
+
return alpha < 1
|
|
115
|
+
? `rgba(${r}, ${g}, ${b}, ${alpha})`
|
|
116
|
+
: `rgb(${r}, ${g}, ${b})`;
|
|
117
|
+
|
|
118
|
+
case 'rgb':
|
|
119
|
+
default:
|
|
120
|
+
return `rgb(${r}, ${g}, ${b})`;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* 将数字转换为两位十六进制
|
|
126
|
+
* @param {number} value - 0-255之间的数字
|
|
127
|
+
* @returns {string} 两位十六进制字符串
|
|
128
|
+
*/
|
|
129
|
+
toHex(value) {
|
|
130
|
+
return Math.max(0, Math.min(255, value))
|
|
131
|
+
.toString(16)
|
|
132
|
+
.padStart(2, '0');
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* 处理CSS样式对象(可选扩展功能)
|
|
137
|
+
* @param {Object} style - CSS样式对象
|
|
138
|
+
* @param {Object} config - 配置选项
|
|
139
|
+
* @returns {Object} 处理后的样式对象
|
|
140
|
+
*/
|
|
141
|
+
processStyle(style, config = {}) {
|
|
142
|
+
const processedStyle = {};
|
|
143
|
+
|
|
144
|
+
for (const [property, value] of Object.entries(style)) {
|
|
145
|
+
if (typeof value === 'string' && value.includes('hsl')) {
|
|
146
|
+
processedStyle[property] = this.convert(value, config);
|
|
147
|
+
} else {
|
|
148
|
+
processedStyle[property] = value;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return processedStyle;
|
|
153
|
+
}
|
|
154
|
+
};
|