color-2-name 1.3.1 → 1.3.3
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/CODE_OF_CONDUCT.md +45 -0
- package/CONTRIBUTING.md +92 -0
- package/biome.json +12 -0
- package/lib/@types/color-utils.d.ts +4 -1
- package/lib/@types/common.d.ts +3 -3
- package/lib/@types/hex-utils.d.ts +1 -1
- package/lib/@types/hsl-utils.d.ts +1 -1
- package/lib/@types/index.d.ts +13 -12
- package/lib/@types/rgb-utils.d.ts +1 -1
- package/lib/@types/types.d.ts +5 -0
- package/lib/browser/color-2-name.js +792 -500
- package/lib/browser/color-2-name.min.js +1 -2
- package/lib/cjs/index.js +1 -0
- package/lib/esm/color-utils.js +1 -0
- package/lib/esm/common.js +1 -0
- package/lib/esm/data/colorSet.js +1 -0
- package/lib/esm/hex-utils.js +1 -0
- package/lib/esm/hsl-utils.js +1 -0
- package/lib/esm/index.js +1 -0
- package/lib/esm/rgb-utils.js +1 -0
- package/package.json +66 -91
- package/readme.md +274 -274
- package/tests/colors_hex.test.ts +73 -64
- package/tests/colors_hsl.test.ts +66 -47
- package/tests/colors_rgb.test.ts +58 -35
- package/tests/core.test.ts +148 -131
- package/tsconfig.json +15 -31
- package/.eslintrc.json +0 -12
- package/babel.config.json +0 -6
- package/jest.config.json +0 -21
- package/lib/browser/color-2-name.js.map +0 -7
- package/lib/browser/color-2-name.min.js.map +0 -7
- package/lib/cjs/_virtual/_tslib.cjs +0 -35
- package/lib/cjs/_virtual/_tslib.cjs.map +0 -1
- package/lib/cjs/color-utils.cjs +0 -38
- package/lib/cjs/color-utils.cjs.map +0 -1
- package/lib/cjs/color-utils.d.ts +0 -18
- package/lib/cjs/common.cjs +0 -200
- package/lib/cjs/common.cjs.map +0 -1
- package/lib/cjs/common.d.ts +0 -93
- package/lib/cjs/data/colorSet.cjs +0 -148
- package/lib/cjs/data/colorSet.cjs.map +0 -1
- package/lib/cjs/data/colorSet.d.ts +0 -2
- package/lib/cjs/hex-utils.cjs +0 -105
- package/lib/cjs/hex-utils.cjs.map +0 -1
- package/lib/cjs/hex-utils.d.ts +0 -47
- package/lib/cjs/hsl-utils.cjs +0 -140
- package/lib/cjs/hsl-utils.cjs.map +0 -1
- package/lib/cjs/hsl-utils.d.ts +0 -47
- package/lib/cjs/index.cjs +0 -165
- package/lib/cjs/index.cjs.map +0 -1
- package/lib/cjs/index.d.ts +0 -87
- package/lib/cjs/rgb-utils.cjs +0 -58
- package/lib/cjs/rgb-utils.cjs.map +0 -1
- package/lib/cjs/rgb-utils.d.ts +0 -26
- package/lib/cjs/types.d.ts +0 -37
- package/lib/esm/_virtual/_tslib.mjs +0 -35
- package/lib/esm/_virtual/_tslib.mjs.map +0 -1
- package/lib/esm/color-utils.d.ts +0 -18
- package/lib/esm/color-utils.mjs +0 -35
- package/lib/esm/color-utils.mjs.map +0 -1
- package/lib/esm/common.d.ts +0 -93
- package/lib/esm/common.mjs +0 -184
- package/lib/esm/common.mjs.map +0 -1
- package/lib/esm/data/colorSet.d.ts +0 -2
- package/lib/esm/data/colorSet.mjs +0 -146
- package/lib/esm/data/colorSet.mjs.map +0 -1
- package/lib/esm/hex-utils.d.ts +0 -47
- package/lib/esm/hex-utils.mjs +0 -98
- package/lib/esm/hex-utils.mjs.map +0 -1
- package/lib/esm/hsl-utils.d.ts +0 -47
- package/lib/esm/hsl-utils.mjs +0 -133
- package/lib/esm/hsl-utils.mjs.map +0 -1
- package/lib/esm/index.d.ts +0 -87
- package/lib/esm/index.mjs +0 -156
- package/lib/esm/index.mjs.map +0 -1
- package/lib/esm/rgb-utils.d.ts +0 -26
- package/lib/esm/rgb-utils.mjs +0 -53
- package/lib/esm/rgb-utils.mjs.map +0 -1
- package/lib/esm/types.d.ts +0 -37
- package/lib/umd/color-2-name.js +0 -820
- package/lib/umd/color-2-name.min.js +0 -1
- package/lib/umd/color-utils.d.ts +0 -18
- package/lib/umd/common.d.ts +0 -93
- package/lib/umd/data/colorSet.d.ts +0 -2
- package/lib/umd/hex-utils.d.ts +0 -47
- package/lib/umd/hsl-utils.d.ts +0 -47
- package/lib/umd/index.d.ts +0 -87
- package/lib/umd/rgb-utils.d.ts +0 -26
- package/lib/umd/types.d.ts +0 -37
|
@@ -1,510 +1,802 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
-
var __export = (target, all) => {
|
|
8
|
-
for (var name in all)
|
|
9
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
-
};
|
|
11
|
-
var __copyProps = (to, from, except, desc) => {
|
|
12
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
-
for (let key of __getOwnPropNames(from))
|
|
14
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
-
}
|
|
17
|
-
return to;
|
|
18
|
-
};
|
|
19
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
1
|
+
var color2name = (function (exports) {
|
|
2
|
+
'use strict';
|
|
20
3
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
[221, 160, 221, "plum"],
|
|
165
|
-
[176, 224, 230, "powderblue"],
|
|
166
|
-
[102, 51, 153, "rebeccapurple"],
|
|
167
|
-
[188, 143, 143, "rosybrown"],
|
|
168
|
-
[65, 105, 225, "royalblue"],
|
|
169
|
-
[139, 69, 19, "saddlebrown"],
|
|
170
|
-
[250, 128, 114, "salmon"],
|
|
171
|
-
[244, 164, 96, "sandybrown"],
|
|
172
|
-
[46, 139, 87, "seagreen"],
|
|
173
|
-
[255, 245, 238, "seashell"],
|
|
174
|
-
[160, 82, 45, "sienna"],
|
|
175
|
-
[135, 206, 235, "skyblue"],
|
|
176
|
-
[106, 90, 205, "slateblue"],
|
|
177
|
-
[112, 128, 144, "slategrey"],
|
|
178
|
-
[255, 250, 250, "snow"],
|
|
179
|
-
[0, 255, 127, "springgreen"],
|
|
180
|
-
[70, 130, 180, "steelblue"],
|
|
181
|
-
[210, 180, 140, "tan"],
|
|
182
|
-
[0, 128, 128, "teal"],
|
|
183
|
-
[216, 191, 216, "thistle"]
|
|
184
|
-
];
|
|
185
|
-
var colorSet_default = colorSet;
|
|
4
|
+
const colorSet = [
|
|
5
|
+
[255, 255, 255, "white"],
|
|
6
|
+
[0, 0, 0, "black"],
|
|
7
|
+
[255, 0, 0, "red"],
|
|
8
|
+
[0, 128, 0, "green"],
|
|
9
|
+
[0, 0, 255, "blue"],
|
|
10
|
+
[255, 165, 0, "orange"],
|
|
11
|
+
[128, 128, 128, "grey"],
|
|
12
|
+
[255, 255, 0, "yellow"],
|
|
13
|
+
[255, 0, 255, "magenta"],
|
|
14
|
+
[154, 205, 50, "yellowgreen"],
|
|
15
|
+
[192, 192, 192, "silver"],
|
|
16
|
+
[0, 255, 0, "lime"],
|
|
17
|
+
[128, 0, 128, "purple"],
|
|
18
|
+
[255, 99, 71, "tomato"],
|
|
19
|
+
[64, 224, 208, "turquoise"],
|
|
20
|
+
[255, 127, 80, "coral"],
|
|
21
|
+
[0, 255, 255, "cyan"],
|
|
22
|
+
[255, 250, 240, "floralwhite"],
|
|
23
|
+
[255, 192, 203, "pink"],
|
|
24
|
+
[34, 139, 34, "forestgreen"],
|
|
25
|
+
[245, 245, 220, "beige"],
|
|
26
|
+
[255, 0, 255, "fuchsia"],
|
|
27
|
+
[220, 220, 220, "gainsboro"],
|
|
28
|
+
[248, 248, 255, "ghostwhite"],
|
|
29
|
+
[255, 215, 0, "gold"],
|
|
30
|
+
[218, 165, 32, "goldenrod"],
|
|
31
|
+
[173, 255, 47, "greenyellow"],
|
|
32
|
+
[238, 130, 238, "violet"],
|
|
33
|
+
[245, 222, 179, "wheat"],
|
|
34
|
+
[245, 245, 245, "whitesmoke"],
|
|
35
|
+
[139, 0, 0, "darkred"],
|
|
36
|
+
[240, 248, 255, "aliceblue"],
|
|
37
|
+
[205, 92, 92, "indianred"],
|
|
38
|
+
[75, 0, 130, "indigo"],
|
|
39
|
+
[250, 235, 215, "antiquewhite"],
|
|
40
|
+
[0, 255, 255, "aqua"],
|
|
41
|
+
[127, 255, 212, "aquamarine"],
|
|
42
|
+
[240, 255, 255, "azure"],
|
|
43
|
+
[255, 228, 196, "bisque"],
|
|
44
|
+
[255, 235, 205, "blanchedalmond"],
|
|
45
|
+
[138, 43, 226, "blueviolet"],
|
|
46
|
+
[165, 42, 42, "brown"],
|
|
47
|
+
[222, 184, 135, "burlywood"],
|
|
48
|
+
[95, 158, 160, "cadetblue"],
|
|
49
|
+
[127, 255, 0, "chartreuse"],
|
|
50
|
+
[210, 105, 30, "chocolate"],
|
|
51
|
+
[100, 149, 237, "cornflowerblue"],
|
|
52
|
+
[255, 248, 220, "cornsilk"],
|
|
53
|
+
[220, 20, 60, "crimson"],
|
|
54
|
+
[0, 0, 139, "darkblue"],
|
|
55
|
+
[0, 139, 139, "darkcyan"],
|
|
56
|
+
[184, 134, 11, "darkgoldenrod"],
|
|
57
|
+
[169, 169, 169, "darkgrey"],
|
|
58
|
+
[0, 100, 0, "darkgreen"],
|
|
59
|
+
[189, 183, 107, "darkkhaki"],
|
|
60
|
+
[139, 0, 139, "darkmagenta"],
|
|
61
|
+
[85, 107, 47, "darkolivegreen"],
|
|
62
|
+
[255, 140, 0, "darkorange"],
|
|
63
|
+
[153, 50, 204, "darkorchid"],
|
|
64
|
+
[233, 150, 122, "darksalmon"],
|
|
65
|
+
[143, 188, 143, "darkseagreen"],
|
|
66
|
+
[72, 61, 139, "darkslateblue"],
|
|
67
|
+
[47, 79, 79, "darkslategrey"],
|
|
68
|
+
[0, 206, 209, "darkturquoise"],
|
|
69
|
+
[148, 0, 211, "darkviolet"],
|
|
70
|
+
[255, 20, 147, "deeppink"],
|
|
71
|
+
[0, 191, 255, "deepskyblue"],
|
|
72
|
+
[105, 105, 105, "dimgrey"],
|
|
73
|
+
[30, 144, 255, "dodgerblue"],
|
|
74
|
+
[178, 34, 34, "firebrick"],
|
|
75
|
+
[240, 255, 240, "honeydew"],
|
|
76
|
+
[255, 105, 180, "hotpink"],
|
|
77
|
+
[255, 255, 240, "ivory"],
|
|
78
|
+
[240, 230, 140, "khaki"],
|
|
79
|
+
[230, 230, 250, "lavender"],
|
|
80
|
+
[255, 240, 245, "lavenderblush"],
|
|
81
|
+
[124, 252, 0, "lawngreen"],
|
|
82
|
+
[255, 250, 205, "lemonchiffon"],
|
|
83
|
+
[173, 216, 230, "lightblue"],
|
|
84
|
+
[240, 128, 128, "lightcoral"],
|
|
85
|
+
[224, 255, 255, "lightcyan"],
|
|
86
|
+
[250, 250, 210, "lightgoldenrodyellow"],
|
|
87
|
+
[144, 238, 144, "lightgreen"],
|
|
88
|
+
[211, 211, 211, "lightgrey"],
|
|
89
|
+
[255, 182, 193, "lightpink"],
|
|
90
|
+
[255, 160, 122, "lightsalmon"],
|
|
91
|
+
[32, 178, 170, "lightseagreen"],
|
|
92
|
+
[135, 206, 250, "lightskyblue"],
|
|
93
|
+
[119, 136, 153, "lightslategrey"],
|
|
94
|
+
[176, 196, 222, "lightsteelblue"],
|
|
95
|
+
[255, 255, 224, "lightyellow"],
|
|
96
|
+
[50, 205, 50, "limegreen"],
|
|
97
|
+
[250, 240, 230, "linen"],
|
|
98
|
+
[128, 0, 0, "maroon"],
|
|
99
|
+
[102, 205, 170, "mediumaquamarine"],
|
|
100
|
+
[0, 0, 205, "mediumblue"],
|
|
101
|
+
[186, 85, 211, "mediumorchid"],
|
|
102
|
+
[147, 112, 219, "mediumpurple"],
|
|
103
|
+
[60, 179, 113, "mediumseagreen"],
|
|
104
|
+
[123, 104, 238, "mediumslateblue"],
|
|
105
|
+
[0, 250, 154, "mediumspringgreen"],
|
|
106
|
+
[72, 209, 204, "mediumturquoise"],
|
|
107
|
+
[199, 21, 133, "mediumvioletred"],
|
|
108
|
+
[25, 25, 112, "midnightblue"],
|
|
109
|
+
[245, 255, 250, "mintcream"],
|
|
110
|
+
[255, 228, 225, "mistyrose"],
|
|
111
|
+
[255, 228, 181, "moccasin"],
|
|
112
|
+
[255, 222, 173, "navajowhite"],
|
|
113
|
+
[0, 0, 128, "navy"],
|
|
114
|
+
[253, 245, 230, "oldlace"],
|
|
115
|
+
[128, 128, 0, "olive"],
|
|
116
|
+
[107, 142, 35, "olivedrab"],
|
|
117
|
+
[255, 69, 0, "orangered"],
|
|
118
|
+
[218, 112, 214, "orchid"],
|
|
119
|
+
[238, 232, 170, "palegoldenrod"],
|
|
120
|
+
[152, 251, 152, "palegreen"],
|
|
121
|
+
[175, 238, 238, "paleturquoise"],
|
|
122
|
+
[219, 112, 147, "palevioletred"],
|
|
123
|
+
[255, 239, 213, "papayawhip"],
|
|
124
|
+
[255, 218, 185, "peachpuff"],
|
|
125
|
+
[205, 133, 63, "peru"],
|
|
126
|
+
[221, 160, 221, "plum"],
|
|
127
|
+
[176, 224, 230, "powderblue"],
|
|
128
|
+
[102, 51, 153, "rebeccapurple"],
|
|
129
|
+
[188, 143, 143, "rosybrown"],
|
|
130
|
+
[65, 105, 225, "royalblue"],
|
|
131
|
+
[139, 69, 19, "saddlebrown"],
|
|
132
|
+
[250, 128, 114, "salmon"],
|
|
133
|
+
[244, 164, 96, "sandybrown"],
|
|
134
|
+
[46, 139, 87, "seagreen"],
|
|
135
|
+
[255, 245, 238, "seashell"],
|
|
136
|
+
[160, 82, 45, "sienna"],
|
|
137
|
+
[135, 206, 235, "skyblue"],
|
|
138
|
+
[106, 90, 205, "slateblue"],
|
|
139
|
+
[112, 128, 144, "slategrey"],
|
|
140
|
+
[255, 250, 250, "snow"],
|
|
141
|
+
[0, 255, 127, "springgreen"],
|
|
142
|
+
[70, 130, 180, "steelblue"],
|
|
143
|
+
[210, 180, 140, "tan"],
|
|
144
|
+
[0, 128, 128, "teal"],
|
|
145
|
+
[216, 191, 216, "thistle"],
|
|
146
|
+
];
|
|
186
147
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
148
|
+
/** The maximum distance possible between colors */
|
|
149
|
+
/** A regex to match hex colors */
|
|
150
|
+
const hexRegex = /^#([\da-f]{3,8})/i;
|
|
151
|
+
/** A regex to match rgb colors */
|
|
152
|
+
const rgbRegex = /^rgba?\(([^)]+)\)/i;
|
|
153
|
+
/** A regex to match hsl colors */
|
|
154
|
+
const hslRegex = /^hsla?\(([^)]+)\)/i;
|
|
155
|
+
/** A regex to match strings that are only valid numbers with and without decimals and the number can be negative and without the 0 in the beginning */
|
|
156
|
+
const isNumeric = /^-?\d*\.?\d+$/i;
|
|
157
|
+
/** Remove comments from string */
|
|
158
|
+
const stripComments = /(\/\*[^*]*\*\/)|(\/\/[^*]*)/g;
|
|
159
|
+
/**
|
|
160
|
+
* This set is used to detect if the color is bright or dark
|
|
161
|
+
*
|
|
162
|
+
* @note the set has been corrected to get pure RGB values (eg. pure red, pure green) in the "bright" area
|
|
163
|
+
*/
|
|
164
|
+
const BLACKANDWHITE = [
|
|
165
|
+
[255, 255, 255, "white"],
|
|
166
|
+
[1, 1, 1, "black"],
|
|
167
|
+
];
|
|
168
|
+
/**
|
|
169
|
+
* This set is used to detect the nearest rgb color
|
|
170
|
+
*/
|
|
171
|
+
const RGBSET = [
|
|
172
|
+
[255, 0, 0, "red"],
|
|
173
|
+
[0, 255, 0, "green"],
|
|
174
|
+
[0, 0, 255, "blue"],
|
|
175
|
+
];
|
|
176
|
+
/**
|
|
177
|
+
* split the content of rgb and hsl colors depending on the parsed value of the css property
|
|
178
|
+
*
|
|
179
|
+
* https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/rgb#syntax
|
|
180
|
+
*
|
|
181
|
+
* @param {string} rawValues - the value inside the rgb(.*) css color definition
|
|
182
|
+
*
|
|
183
|
+
* @return {Array} the array of rgb values found inside the passed string
|
|
184
|
+
*/
|
|
185
|
+
function splitValues(rawValues) {
|
|
186
|
+
return rawValues
|
|
187
|
+
.split(rawValues.includes(",") ? "," : " ")
|
|
188
|
+
.map((s) => s.trim());
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* If the value is an angle in degrees, convert it to the 0-360 range
|
|
192
|
+
*
|
|
193
|
+
* @param {string} angle - the degrees to convert into a number
|
|
194
|
+
*
|
|
195
|
+
* @return {number} the converted value
|
|
196
|
+
*/
|
|
197
|
+
function normalizeDegrees(angle) {
|
|
198
|
+
// Strip label and convert to degrees (if necessary)
|
|
199
|
+
let degAngle = Number.parseFloat(angle) || 0;
|
|
200
|
+
if (angle.indexOf("deg") > -1) {
|
|
201
|
+
degAngle = Number.parseFloat(angle.substring(0, angle.length - 3));
|
|
202
|
+
}
|
|
203
|
+
else if (angle.indexOf("rad") > -1) {
|
|
204
|
+
degAngle = Math.round(Number.parseFloat(angle.substring(0, angle.length - 3)) * (180 / Math.PI));
|
|
205
|
+
}
|
|
206
|
+
else if (angle.indexOf("turn") > -1) {
|
|
207
|
+
degAngle = Math.round(Number.parseFloat(angle.substring(0, angle.length - 4)) * 360);
|
|
208
|
+
}
|
|
209
|
+
while (degAngle < 0) {
|
|
210
|
+
degAngle += 360;
|
|
211
|
+
}
|
|
212
|
+
// Make sure it's a number between 0 and 360
|
|
213
|
+
if (degAngle >= 360)
|
|
214
|
+
degAngle %= 360;
|
|
215
|
+
return degAngle;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Returns a value that is limited between a minimum and maximum value.
|
|
219
|
+
*
|
|
220
|
+
* @param {number} value - The value to be limited.
|
|
221
|
+
* @param {number} min - The minimum allowed value (default is 0).
|
|
222
|
+
* @param {number} max - The maximum allowed value (default is 0).
|
|
223
|
+
* @return {number} The limited value.
|
|
224
|
+
*/
|
|
225
|
+
function limitValue(value, min = 0, max = 0) {
|
|
226
|
+
return Math.min(Math.max(Math.round(value), min), max);
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Calculates the value based on a given string and multiplier.
|
|
230
|
+
*
|
|
231
|
+
* @param {string} valueString - The string representing the value to be calculated.
|
|
232
|
+
* @param {number} multiplier - The multiplier to be applied to the calculated value.
|
|
233
|
+
* @return {number} The calculated value.
|
|
234
|
+
*/
|
|
235
|
+
function calculateValue(valueString, multiplier) {
|
|
236
|
+
// Regular expression to match the calc() function and extract the numerical value
|
|
237
|
+
const regex = /calc\(([^)]+)\)/;
|
|
238
|
+
// Match the calc() function in the CSS string
|
|
239
|
+
const match = valueString.match(regex);
|
|
240
|
+
return convertToInt8(match ? match[1] : valueString, multiplier);
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Removes comments from the input string and extracts the content between the first opening parenthesis
|
|
244
|
+
* and the last closing parenthesis.
|
|
245
|
+
*
|
|
246
|
+
* @param {string} string - The input string.
|
|
247
|
+
* @return {string} The content between the first opening parenthesis and the last closing parenthesis.
|
|
248
|
+
*/
|
|
249
|
+
function cleanDefinition(string) {
|
|
250
|
+
// Remove comments from the string
|
|
251
|
+
const cleanString = string.replace(stripComments, "");
|
|
252
|
+
// Find the positions of the first opening and the last closing parentheses
|
|
253
|
+
const firstParenthesisIndex = cleanString.indexOf("(");
|
|
254
|
+
const lastParenthesisIndex = cleanString.lastIndexOf(")");
|
|
255
|
+
// Extract the content between the parentheses
|
|
256
|
+
return cleanString
|
|
257
|
+
.slice(firstParenthesisIndex + 1, lastParenthesisIndex)
|
|
258
|
+
.trim();
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Normalizes a percentage value by dividing it by 100 and multiplying it by a given multiplier.
|
|
262
|
+
*
|
|
263
|
+
* @param {string} value - The percentage value to be normalized.
|
|
264
|
+
* @param {number} multiplier - The number to multiply the normalized percentage by.
|
|
265
|
+
* @return {number} The normalized percentage value.
|
|
266
|
+
*/
|
|
267
|
+
function normalizePercentage(value, multiplier) {
|
|
268
|
+
return (Number.parseFloat(value) / 100) * multiplier;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Calculates the color value fallbacks for a given value.
|
|
272
|
+
*
|
|
273
|
+
* @param {string} value - The color value to calculate fallbacks for.
|
|
274
|
+
* @param {string} [err] - An optional error message to display.
|
|
275
|
+
* @return {number} - The calculated color value fallbacks.
|
|
276
|
+
*/
|
|
277
|
+
function colorValueFallbacks(value, err) {
|
|
278
|
+
if (value === "infinity") {
|
|
279
|
+
console.warn(err || `Positive infinity value has been set to 255: ${value}`);
|
|
280
|
+
return 255;
|
|
281
|
+
}
|
|
282
|
+
if (value === "currentColor")
|
|
283
|
+
console.warn(err || `The "currentColor" value has been set to 0: ${value}`);
|
|
284
|
+
if (value === "transparent")
|
|
285
|
+
console.warn(err || `The "transparent" value has been set to 0: ${value}`);
|
|
286
|
+
if (value === "NaN")
|
|
287
|
+
console.warn(err || `"NaN" value has been set to 0: ${value}`);
|
|
288
|
+
if (value === "-infinity")
|
|
289
|
+
console.warn(err || `"Negative" infinity value has been set to 0: ${value}`);
|
|
290
|
+
if (value === "none")
|
|
291
|
+
console.warn(err || `The none keyword is invalid in legacy color syntax: ${value}`);
|
|
292
|
+
return 0;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Takes a string with a css value that could be a number or percentage or an angle in degrees and returns the corresponding 8bit value
|
|
296
|
+
*
|
|
297
|
+
* @param value - a valid value for the css color definition (like 255, "100%", "324deg", etc.) *
|
|
298
|
+
* @param multiplier - the number that represent the maximum - default is 255 decimal - 100 hex
|
|
299
|
+
*
|
|
300
|
+
* @example convertToInt8('100%'); // 255
|
|
301
|
+
*
|
|
302
|
+
* @return {string} the corresponding value in 8-bit format
|
|
303
|
+
*/
|
|
304
|
+
function convertToInt8(value, multiplier = 255) {
|
|
305
|
+
const newValue = typeof value === "string" ? value?.trim() : "0";
|
|
306
|
+
if (isNumeric.test(newValue)) {
|
|
307
|
+
// limit the min and the max newValue
|
|
308
|
+
return limitValue(Number.parseFloat(newValue) || 0, 0, multiplier);
|
|
309
|
+
}
|
|
310
|
+
if (newValue.endsWith("%")) {
|
|
311
|
+
// If the newValue is a percentage, divide it by 100 to get a newValue from 0 to 1
|
|
312
|
+
// and then multiply it by 255 to get a newValue from 0 to 255
|
|
313
|
+
return normalizePercentage(newValue, multiplier) || 0;
|
|
314
|
+
}
|
|
315
|
+
if (newValue.endsWith("deg") ||
|
|
316
|
+
newValue.endsWith("rad") ||
|
|
317
|
+
newValue.endsWith("turn")) {
|
|
318
|
+
return normalizeDegrees(newValue);
|
|
319
|
+
}
|
|
320
|
+
if (newValue.startsWith("calc")) {
|
|
321
|
+
// get the newValue from the calc function
|
|
322
|
+
return limitValue(calculateValue(newValue, multiplier), 0, multiplier);
|
|
323
|
+
}
|
|
324
|
+
// If the value is not a percentage or an angle in degrees, it is invalid
|
|
325
|
+
return colorValueFallbacks(newValue, `Invalid value: ${value}`);
|
|
326
|
+
}
|
|
271
327
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
328
|
+
function fallbackRGB(rgb, err = "Invalid RGB color") {
|
|
329
|
+
console.warn(err);
|
|
330
|
+
return [rgb[0] ?? 0, rgb[1] ?? 0, rgb[2]];
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Get the values of the rgb string
|
|
334
|
+
*
|
|
335
|
+
* @param rgbAsString - the rgb color as string split into values
|
|
336
|
+
*
|
|
337
|
+
* @return {Array} the values of the rgb string as Array of strings that represent the rgb color
|
|
338
|
+
*/
|
|
339
|
+
function parseRgb(rgbAsString) {
|
|
340
|
+
const rgbvalue = cleanDefinition(rgbAsString);
|
|
341
|
+
const rgb = splitValues(rgbvalue);
|
|
342
|
+
if (rgb.length !== 3 && rgb.length !== 4) {
|
|
343
|
+
return fallbackRGB(rgb, `Too few values to define rgb: ${rgbAsString} -> ${rgbvalue}`);
|
|
344
|
+
}
|
|
345
|
+
return [rgb[0], rgb[1], rgb[2]];
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* This function takes an array of strings and returns and object with the rgb values converted into INT8 (0-255)
|
|
349
|
+
*
|
|
350
|
+
* @param {Array} rgb - rgb color as Array of strings
|
|
351
|
+
*
|
|
352
|
+
* @return {Object} an object that contains the r, g and b values as INT8
|
|
353
|
+
*/
|
|
354
|
+
function getRgbValues(rgb) {
|
|
355
|
+
// use the channel key as the new array key
|
|
356
|
+
return {
|
|
357
|
+
r: limitValue(Math.round(convertToInt8(rgb[0])), 0, 255) || 0,
|
|
358
|
+
g: limitValue(Math.round(convertToInt8(rgb[1])), 0, 255) || 0,
|
|
359
|
+
b: limitValue(Math.round(convertToInt8(rgb[2])), 0, 255) || 0,
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* returns a string representation of the rgb values
|
|
364
|
+
*
|
|
365
|
+
* @param {Object} rgb the rgb color object
|
|
366
|
+
*
|
|
367
|
+
* @return {string} a string representation of the rgb values
|
|
368
|
+
*/
|
|
369
|
+
function RGB(rgb) {
|
|
370
|
+
return `rgb(${rgb.r},${rgb.g},${rgb.b})`;
|
|
371
|
+
}
|
|
296
372
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
373
|
+
/**
|
|
374
|
+
* It returns an object with the hex values of the 3 digit hex color
|
|
375
|
+
*
|
|
376
|
+
* @param {string} value 3 digit hex
|
|
377
|
+
* @return {string[]} 6 digit hex
|
|
378
|
+
*/
|
|
379
|
+
function shortHexToLongHex(value) {
|
|
380
|
+
// split the string in to an array of digits then return an array that contains that digit doubled for each item
|
|
381
|
+
return Array.from(value).map((v) => (v + v).toUpperCase());
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Checks if a given string represents a hexadecimal number.
|
|
385
|
+
*
|
|
386
|
+
* @param {string} num - The string to be checked.
|
|
387
|
+
* @return {boolean} Returns true if the string is a valid hexadecimal number, false otherwise.
|
|
388
|
+
*/
|
|
389
|
+
function isHex(num) {
|
|
390
|
+
return Boolean(num.match(/^[0-9a-f]+$/i));
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Get the hex value of the color and convert it to an Object of R G And B values (still in hex format)
|
|
394
|
+
*
|
|
395
|
+
* @param value the string that contains the color in hex format
|
|
396
|
+
*
|
|
397
|
+
* @return {string[]} an array of 6 digit hex values in a triplet of R G and B (HEX format)
|
|
398
|
+
*/
|
|
399
|
+
function parseHex(value) {
|
|
400
|
+
// remove # at the beginning of the hex color
|
|
401
|
+
const hexColor = value.substring(1);
|
|
402
|
+
/**
|
|
403
|
+
* then if the number of digits is greater than 2 (so it's something like 123 or abc456)
|
|
404
|
+
* breakdown the string into an object that contains the r g and b values in hex
|
|
405
|
+
*/
|
|
406
|
+
let hexArray = [];
|
|
407
|
+
if (hexColor) {
|
|
408
|
+
if (hexColor.length === 3 || hexColor.length === 4) {
|
|
409
|
+
hexArray = shortHexToLongHex(hexColor);
|
|
410
|
+
}
|
|
411
|
+
else if (hexColor.length === 6 || hexColor.length === 8) {
|
|
412
|
+
// match the hex value in groups of 2
|
|
413
|
+
hexArray = (hexColor.match(/../g) || []).map((value) => value);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
if (hexArray.length) {
|
|
417
|
+
hexArray?.forEach((value, index) => {
|
|
418
|
+
if (isHex(value)) {
|
|
419
|
+
hexArray[index] = value.toUpperCase();
|
|
420
|
+
}
|
|
421
|
+
else {
|
|
422
|
+
console.warn(`Invalid Hex value: ${value}`);
|
|
423
|
+
}
|
|
424
|
+
});
|
|
425
|
+
return hexArray;
|
|
320
426
|
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
427
|
+
console.warn(`Invalid Hex: ${value}`);
|
|
428
|
+
return fallbackRGB(hexArray);
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Converts a Hex color to rgb
|
|
432
|
+
*
|
|
433
|
+
* @param {string} hex a tuple of hex values
|
|
434
|
+
*
|
|
435
|
+
* @return {string} the rgb color values for the given hex color
|
|
436
|
+
*/
|
|
437
|
+
function hexToRgb(hex) {
|
|
438
|
+
// Extract the RGB values from the hex string
|
|
439
|
+
return {
|
|
440
|
+
r: Number.parseInt(hex[0], 16),
|
|
441
|
+
g: Number.parseInt(hex[1], 16),
|
|
442
|
+
b: Number.parseInt(hex[2], 16),
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* Convert a INT8 value to HEX
|
|
447
|
+
*
|
|
448
|
+
* @param {number} int8 - the integer value to convert
|
|
449
|
+
*
|
|
450
|
+
* @return {string} the hex string
|
|
451
|
+
*/
|
|
452
|
+
function toHex(int8) {
|
|
453
|
+
return int8.toString(16).padStart(2, "0");
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Convert rgb values to hex color
|
|
457
|
+
*
|
|
458
|
+
* @param {Object} rgb an object with the rgb values
|
|
459
|
+
*
|
|
460
|
+
* @return {string} the hex string
|
|
461
|
+
*/
|
|
462
|
+
function valuesToHex(rgb) {
|
|
463
|
+
// Extract the RGB values from the hex string
|
|
464
|
+
return `#${toHex(rgb?.r)}${toHex(rgb?.g)}${toHex(rgb?.b)}`;
|
|
465
|
+
}
|
|
340
466
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
467
|
+
function fallbackHSL(hsl, err = "Invalid HSL color") {
|
|
468
|
+
console.warn(err);
|
|
469
|
+
return [hsl[0] ?? 0, hsl[1] ?? 0, hsl[2]];
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Get the values of the hsl string
|
|
473
|
+
*
|
|
474
|
+
* @param {string} hslAsString - the valid hsl color string
|
|
475
|
+
* @return {string[]} the values of the hsl string
|
|
476
|
+
*/
|
|
477
|
+
function parseHsl(hslAsString) {
|
|
478
|
+
const hslvalue = cleanDefinition(hslAsString);
|
|
479
|
+
let hsl = splitValues(hslvalue);
|
|
480
|
+
if (hsl.length !== 3 && hsl.length !== 4) {
|
|
481
|
+
hsl = fallbackHSL(hsl);
|
|
482
|
+
}
|
|
483
|
+
return [hsl[0], hsl[1], hsl[2]];
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* The error message for invalid angle
|
|
487
|
+
* @param value - the invalid angle
|
|
488
|
+
*/
|
|
489
|
+
const angleError = (value) => `Invalid angle: ${value} - The none keyword is invalid in legacy color syntax `;
|
|
490
|
+
/**
|
|
491
|
+
* This function takes an array of strings and returns and object with the hsl values converted into INT8 (0-255)
|
|
492
|
+
*
|
|
493
|
+
* @param {string[]} hsl - the hsl values to parse from string to int8 values
|
|
494
|
+
*
|
|
495
|
+
*/
|
|
496
|
+
function getHslValues(hsl) {
|
|
497
|
+
return {
|
|
498
|
+
h: colorValueFallbacks(hsl[0], angleError(hsl[0])) ||
|
|
499
|
+
Math.round(normalizeDegrees(hsl[0])) ||
|
|
500
|
+
0,
|
|
501
|
+
s: colorValueFallbacks(hsl[1]) || convertToInt8(hsl[1], 100) || 0,
|
|
502
|
+
l: colorValueFallbacks(hsl[2]) || convertToInt8(hsl[2], 100) || 0,
|
|
503
|
+
};
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Takes the hsl values and returns the rgb values
|
|
507
|
+
* @param c chroma
|
|
508
|
+
* @param x X
|
|
509
|
+
* @param h Y
|
|
510
|
+
*/
|
|
511
|
+
function getHue(c, x, h) {
|
|
512
|
+
if (h < 60)
|
|
513
|
+
return [c, x, 0];
|
|
514
|
+
if (h < 120)
|
|
515
|
+
return [x, c, 0];
|
|
516
|
+
if (h < 180)
|
|
517
|
+
return [0, c, x];
|
|
518
|
+
if (h < 240)
|
|
519
|
+
return [0, x, c];
|
|
520
|
+
if (h < 300)
|
|
521
|
+
return [x, 0, c];
|
|
522
|
+
return [c, 0, x];
|
|
523
|
+
}
|
|
524
|
+
/**
|
|
525
|
+
* Given the HSL color it convert the color into RGB
|
|
526
|
+
*
|
|
527
|
+
* @param {string[]} hslColor the HSL value to parse
|
|
528
|
+
* @return {Object} rgb value
|
|
529
|
+
*/
|
|
530
|
+
function hslToRgb(hslColor) {
|
|
531
|
+
const hsl = getHslValues(hslColor);
|
|
532
|
+
const s = hsl.s / 100;
|
|
533
|
+
const l = hsl.l / 100;
|
|
534
|
+
const c = (1 - Math.abs(2 * l - 1)) * s;
|
|
535
|
+
const x = c * (1 - Math.abs(((hsl.h / 60) % 2) - 1));
|
|
536
|
+
const m = l - c / 2;
|
|
537
|
+
let [r, g, b] = getHue(c, x, hsl.h);
|
|
538
|
+
r = Math.round((r + m) * 255);
|
|
539
|
+
g = Math.round((g + m) * 255);
|
|
540
|
+
b = Math.round((b + m) * 255);
|
|
541
|
+
return { r, g, b };
|
|
542
|
+
}
|
|
543
|
+
/**
|
|
544
|
+
* Given the RGB color it convert the color into HSL
|
|
545
|
+
*
|
|
546
|
+
* @param {number} r - red
|
|
547
|
+
* @param {number} g - green
|
|
548
|
+
* @param {number} b - blue
|
|
549
|
+
*
|
|
550
|
+
* @return {Object} hsl value
|
|
551
|
+
*/
|
|
552
|
+
function valuesToHsl({ r, g, b }) {
|
|
553
|
+
// Make r, g, and b fractions of 1
|
|
554
|
+
r /= 255;
|
|
555
|
+
g /= 255;
|
|
556
|
+
b /= 255;
|
|
557
|
+
// Find greatest and smallest channel values
|
|
558
|
+
const cmin = Math.min(r, g, b);
|
|
559
|
+
const cmax = Math.max(r, g, b);
|
|
560
|
+
const delta = cmax - cmin;
|
|
561
|
+
let h = 0;
|
|
562
|
+
let s = 0;
|
|
563
|
+
let l = 0;
|
|
564
|
+
// Calculate hue
|
|
565
|
+
if (delta === 0) {
|
|
566
|
+
// No difference
|
|
567
|
+
h = 0;
|
|
568
|
+
}
|
|
569
|
+
else if (cmax === r) {
|
|
570
|
+
// Red is max
|
|
571
|
+
h = ((g - b) / delta) % 6;
|
|
572
|
+
}
|
|
573
|
+
else if (cmax === g) {
|
|
574
|
+
// Green is max
|
|
575
|
+
h = (b - r) / delta + 2;
|
|
576
|
+
}
|
|
577
|
+
else {
|
|
578
|
+
h = (r - g) / delta + 4;
|
|
579
|
+
} // Blue is max
|
|
580
|
+
h = Math.round(h * 60);
|
|
581
|
+
// Make negative hues positive behind 360°
|
|
582
|
+
if (h < 0) {
|
|
583
|
+
h += 360;
|
|
584
|
+
}
|
|
585
|
+
// Calculate lightness
|
|
586
|
+
l = (cmax + cmin) / 2;
|
|
587
|
+
// Calculate saturation
|
|
588
|
+
s = delta === 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
|
|
589
|
+
// Multiply l and s by 100
|
|
590
|
+
s = +(s * 100).toFixed(1);
|
|
591
|
+
l = +(l * 100).toFixed(1);
|
|
592
|
+
return HSL({ h, s, l });
|
|
593
|
+
}
|
|
594
|
+
/**
|
|
595
|
+
* Converts an HSL color object to a string representation.
|
|
596
|
+
*
|
|
597
|
+
* @param {Object} hsl - Object containing the HSL color values.
|
|
598
|
+
* @param {number} hsl.h - The hue value of the color.
|
|
599
|
+
* @param {number} hsl.s - The saturation value of the color.
|
|
600
|
+
* @param {number} hsl.l - The lightness value of the color.
|
|
601
|
+
* @return {string} The HSL color as a string.
|
|
602
|
+
*/
|
|
603
|
+
function HSL(hsl) {
|
|
604
|
+
return `hsl(${hsl.h},${hsl.s}%,${hsl.l}%)`;
|
|
605
|
+
}
|
|
418
606
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
607
|
+
/**
|
|
608
|
+
* This function was the opposite of the name of the repo and returns the color of the colorSet given the name
|
|
609
|
+
*
|
|
610
|
+
* @param {string} searchedColor -the name of the color to search for
|
|
611
|
+
* @param {Array} set - the colorSet to search in
|
|
612
|
+
*/
|
|
613
|
+
function getColor(searchedColor, set = colorSet) {
|
|
614
|
+
const color = set.find((color) => color[3] === searchedColor);
|
|
615
|
+
if (typeof color !== "undefined") {
|
|
616
|
+
const [r, g, b] = color;
|
|
617
|
+
return {
|
|
618
|
+
hex: valuesToHex({ r, g, b }),
|
|
619
|
+
rgb: RGB({ r, g, b }),
|
|
620
|
+
hsl: valuesToHsl({ r, g, b }),
|
|
621
|
+
};
|
|
622
|
+
}
|
|
623
|
+
throw new Error(`Error: invalid color ${searchedColor} or empty colorSet`);
|
|
624
|
+
}
|
|
625
|
+
/**
|
|
626
|
+
* Get all the colors from the colorSet
|
|
627
|
+
*/
|
|
628
|
+
function getColors() {
|
|
629
|
+
return colorSet.map((colorData) => {
|
|
630
|
+
return {
|
|
631
|
+
name: colorData[3],
|
|
632
|
+
...getColor(colorData[3]),
|
|
633
|
+
};
|
|
634
|
+
});
|
|
635
|
+
}
|
|
442
636
|
|
|
443
|
-
// src/index.ts
|
|
444
|
-
function closest(color, set = colorSet_default, args) {
|
|
445
|
-
let closestGap = Number.MAX_SAFE_INTEGER;
|
|
446
|
-
const closestColor = { name: "error", color: "#F00" };
|
|
447
|
-
if (set.length < 1) {
|
|
448
|
-
return closestColor;
|
|
449
|
-
}
|
|
450
|
-
const rgbColorValues = Object.values(parseColor(color));
|
|
451
|
-
for (const tested of set) {
|
|
452
|
-
const gap = distance(rgbColorValues, tested, true);
|
|
453
|
-
if (gap < closestGap) {
|
|
454
|
-
closestGap = gap;
|
|
455
|
-
closestColor.name = tested[3];
|
|
456
|
-
closestColor.color = `rgb(${String(tested[0])},${String(tested[1])},${String(tested[2])})`;
|
|
457
|
-
}
|
|
458
|
-
if (gap === 0) {
|
|
459
|
-
break;
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
if (args?.info) {
|
|
463
|
-
const colorValue = getColor(closestColor.name, set);
|
|
464
|
-
return {
|
|
465
|
-
...colorValue,
|
|
466
|
-
...closestColor,
|
|
467
|
-
gap: Math.sqrt(closestGap)
|
|
468
|
-
};
|
|
469
|
-
}
|
|
470
|
-
return closestColor;
|
|
471
|
-
}
|
|
472
|
-
function isLight(color) {
|
|
473
|
-
return closest(color, BLACKANDWHITE).name === "white";
|
|
474
|
-
}
|
|
475
|
-
function isDark(color) {
|
|
476
|
-
return closest(color, BLACKANDWHITE).name === "black";
|
|
477
|
-
}
|
|
478
|
-
function closestRGB(color) {
|
|
479
|
-
return closest(color, RGBSET).name;
|
|
480
|
-
}
|
|
481
|
-
function distance(rgb1, rgb2, fast = false) {
|
|
482
|
-
const [rDiff, gDiff, bDiff] = [rgb2[0] - rgb1[0], rgb2[1] - rgb1[1], rgb2[2] - rgb1[2]];
|
|
483
|
-
const dist = rDiff * rDiff + gDiff * gDiff + bDiff * bDiff;
|
|
484
|
-
return fast ? dist : Math.sqrt(dist);
|
|
485
|
-
}
|
|
486
|
-
function rgbToHex(rgbString) {
|
|
487
|
-
if (rgbRegex.test(rgbString)) {
|
|
488
|
-
const rgb = parseRgb(rgbString);
|
|
489
|
-
const RgbValues = getRgbValues(rgb);
|
|
490
|
-
return valuesToHex(RgbValues);
|
|
491
|
-
}
|
|
492
|
-
throw new Error(`Invalid color: ${rgbString}`);
|
|
493
|
-
}
|
|
494
|
-
function parseColor(colorString) {
|
|
495
637
|
const colorParsers = [
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
638
|
+
{ regex: hexRegex, parser: parseHex, converter: hexToRgb },
|
|
639
|
+
{ regex: rgbRegex, parser: parseRgb, converter: getRgbValues },
|
|
640
|
+
{ regex: hslRegex, parser: parseHsl, converter: hslToRgb },
|
|
499
641
|
];
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
}
|
|
510
|
-
|
|
642
|
+
/**
|
|
643
|
+
* Given a color string, it returns the closest corresponding name of the color.
|
|
644
|
+
* Uses the Euclidean distance formula to calculate the distance between colors in the RGB color space.
|
|
645
|
+
*
|
|
646
|
+
* @param {string} color - the color string you want to find the closest color name
|
|
647
|
+
* @param {Object} set - the color set that will be used to find the closest color
|
|
648
|
+
* @param {Object} args - Set a non nullish value to return some additional information (like the distance between the colors, or the hex color value)
|
|
649
|
+
* @param args.info - Set a non nullish value to return some additional information (like the distance between the colors, or the hex color value) about the closest color.
|
|
650
|
+
*
|
|
651
|
+
* @return {Object} the closest color name and rgb value
|
|
652
|
+
*
|
|
653
|
+
* @example // Returns the closest color name and rgb value given a css color string
|
|
654
|
+
* closest('#f00'); // { name: 'red', color: 'rgb(255,0,0)' }
|
|
655
|
+
*
|
|
656
|
+
* closest('#f00', undefined, {info:true}); // { name: 'red', color: 'rgb(255,0,0)', hex: '#ff0000', hsl: 'hsl(0, 100%, 50%)', distance: 0 ) }
|
|
657
|
+
*/
|
|
658
|
+
function closest(color, set = colorSet, args) {
|
|
659
|
+
let closestGap = Number.MAX_SAFE_INTEGER;
|
|
660
|
+
const closestColor = { name: "error", color: "#F00" };
|
|
661
|
+
if (set.length < 1) {
|
|
662
|
+
return closestColor;
|
|
663
|
+
}
|
|
664
|
+
const rgbColorValues = Object.values(parseColor(color));
|
|
665
|
+
const colorSetLength = set.length;
|
|
666
|
+
// Precompute RGB values if needed
|
|
667
|
+
const precomputedRGBValues = set.map((item) => [item[0], item[1], item[2]]);
|
|
668
|
+
// Find the closest color in the color set
|
|
669
|
+
for (let i = 0; i < colorSetLength; i++) {
|
|
670
|
+
const tested = precomputedRGBValues[i];
|
|
671
|
+
const gap = distance(rgbColorValues, tested, true);
|
|
672
|
+
if (gap < closestGap) {
|
|
673
|
+
closestGap = gap;
|
|
674
|
+
closestColor.name = set[i][3];
|
|
675
|
+
closestColor.color = `rgb(${set[i][0]},${set[i][1]},${set[i][2]})`;
|
|
676
|
+
}
|
|
677
|
+
// Break if exact match found
|
|
678
|
+
if (gap === 0) {
|
|
679
|
+
break;
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
if (args?.info) {
|
|
683
|
+
const colorValue = getColor(closestColor.name, set);
|
|
684
|
+
return {
|
|
685
|
+
...colorValue,
|
|
686
|
+
...closestColor,
|
|
687
|
+
gap: Math.sqrt(closestGap),
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
return closestColor;
|
|
691
|
+
}
|
|
692
|
+
/**
|
|
693
|
+
* This function takes a string representing a color (color) and uses regular expressions to check if it matches any of the following formats: hex, hex+alpha, RGB, RGBA, HSL, or HSLA.
|
|
694
|
+
* If the color string matches one of these formats, the function returns an object with the type of color and the value of the color.
|
|
695
|
+
* If the color string does not match any of the formats, the function throws an error.
|
|
696
|
+
*
|
|
697
|
+
* @param {string} colorString - the color string to test and convert to rgb values
|
|
698
|
+
*
|
|
699
|
+
* @return {Object|Error} the object with rgb values of that color
|
|
700
|
+
*/
|
|
701
|
+
function parseColor(colorString) {
|
|
702
|
+
for (const { regex, parser, converter } of colorParsers) {
|
|
703
|
+
if (regex.test(colorString)) {
|
|
704
|
+
const result = parser(colorString);
|
|
705
|
+
return converter(result);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
// If the color string does not match any of the regular expressions, return an error
|
|
709
|
+
throw new Error(`Invalid color: ${colorString}`);
|
|
710
|
+
}
|
|
711
|
+
/**
|
|
712
|
+
* Given a color returns if the color is light (by light is meant more mathematically closer to white)
|
|
713
|
+
*
|
|
714
|
+
* @param {string} color - The color to check
|
|
715
|
+
*
|
|
716
|
+
* @returns {boolean} true when the color is light, false otherwise
|
|
717
|
+
*
|
|
718
|
+
* @example isLight('#ddd'); // true
|
|
719
|
+
*/
|
|
720
|
+
function isLight(color) {
|
|
721
|
+
return closest(color, BLACKANDWHITE).name === "white";
|
|
722
|
+
}
|
|
723
|
+
/**
|
|
724
|
+
* Given a color returns if the color is dark (by dark is meant more mathematically closer to black)
|
|
725
|
+
*
|
|
726
|
+
* @param {string} color - The color to check
|
|
727
|
+
*
|
|
728
|
+
* @returns {boolean} true when the color is dark, false otherwise
|
|
729
|
+
*
|
|
730
|
+
* @example isDark('#333'); // true
|
|
731
|
+
*/
|
|
732
|
+
function isDark(color) {
|
|
733
|
+
return closest(color, BLACKANDWHITE).name === "black";
|
|
734
|
+
}
|
|
735
|
+
/**
|
|
736
|
+
* Given a color returns if the color is closer to "red", "green" or "blue".
|
|
737
|
+
*
|
|
738
|
+
* @param {string} color - The color to check
|
|
739
|
+
*
|
|
740
|
+
* @returns {string} light when the color is close to white, dark otherwise
|
|
741
|
+
*
|
|
742
|
+
* @example closestRGB('#f00'); // 'red'
|
|
743
|
+
*/
|
|
744
|
+
function closestRGB(color) {
|
|
745
|
+
return closest(color, RGBSET).name;
|
|
746
|
+
}
|
|
747
|
+
/**
|
|
748
|
+
* Compute the distance between the two RGB values
|
|
749
|
+
* There are two modes:
|
|
750
|
+
* fast = true -> the distance is calculated without using the Euclidean formula completely, it is reliable but its result is exponential
|
|
751
|
+
* fast = false -> the distance is calculated with the Euclidean formula, its result is linear
|
|
752
|
+
*
|
|
753
|
+
* @param rgb1 - The RGB value of the first color to compare
|
|
754
|
+
* @param rgb2 - The RGB value of the second color to compare
|
|
755
|
+
* @param fast - If you want to calculate the distance without calculating the square root, the result will be exponential otherwise is linear
|
|
756
|
+
*
|
|
757
|
+
* @return {number} the distance between the two RGB values
|
|
758
|
+
*
|
|
759
|
+
* @example distance([10, 20, 30], [120, 120, 120]); // 173.78147196982766
|
|
760
|
+
*/
|
|
761
|
+
function distance(rgb1, rgb2, fast = false) {
|
|
762
|
+
const [rDiff, gDiff, bDiff] = [
|
|
763
|
+
rgb2[0] - rgb1[0],
|
|
764
|
+
rgb2[1] - rgb1[1],
|
|
765
|
+
rgb2[2] - rgb1[2],
|
|
766
|
+
];
|
|
767
|
+
const dist = rDiff * rDiff + gDiff * gDiff + bDiff * bDiff;
|
|
768
|
+
return fast ? dist : Math.sqrt(dist);
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* Given a color string it returns the hex representation
|
|
772
|
+
*
|
|
773
|
+
* @param rgbString - the rgb color string to convert to hex
|
|
774
|
+
*
|
|
775
|
+
* @return {string} the corresponding color hex
|
|
776
|
+
*
|
|
777
|
+
* @example rgbToHex("rgba(100% 0 0 / .5)"); // #FF0000
|
|
778
|
+
*/
|
|
779
|
+
function rgbToHex(rgbString) {
|
|
780
|
+
// if is a rgb string
|
|
781
|
+
if (rgbRegex.test(rgbString)) {
|
|
782
|
+
const rgb = parseRgb(rgbString);
|
|
783
|
+
const RgbValues = getRgbValues(rgb);
|
|
784
|
+
return valuesToHex(RgbValues);
|
|
785
|
+
}
|
|
786
|
+
throw new Error(`Invalid color: ${rgbString}`);
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
exports.closest = closest;
|
|
790
|
+
exports.closestRGB = closestRGB;
|
|
791
|
+
exports.colorParsers = colorParsers;
|
|
792
|
+
exports.distance = distance;
|
|
793
|
+
exports.getColor = getColor;
|
|
794
|
+
exports.getColors = getColors;
|
|
795
|
+
exports.isDark = isDark;
|
|
796
|
+
exports.isLight = isLight;
|
|
797
|
+
exports.parseColor = parseColor;
|
|
798
|
+
exports.rgbToHex = rgbToHex;
|
|
799
|
+
|
|
800
|
+
return exports;
|
|
801
|
+
|
|
802
|
+
})({});
|