Skip to content

Commit 947d2a2

Browse files
committed
normalizeColor
1 parent d6b45f0 commit 947d2a2

File tree

1 file changed

+200
-0
lines changed

1 file changed

+200
-0
lines changed

spring/src/normalizeColor.ts

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
/*
2+
https://github.com/react-community/normalize-css-color
3+
4+
BSD 3-Clause License
5+
6+
Copyright (c) 2016, React Community
7+
All rights reserved.
8+
9+
Redistribution and use in source and binary forms, with or without
10+
modification, are permitted provided that the following conditions are met:
11+
12+
* Redistributions of source code must retain the above copyright notice, this
13+
list of conditions and the following disclaimer.
14+
15+
* Redistributions in binary form must reproduce the above copyright notice,
16+
this list of conditions and the following disclaimer in the documentation
17+
and/or other materials provided with the distribution.
18+
19+
* Neither the name of the copyright holder nor the names of its
20+
contributors may be used to endorse or promote products derived from
21+
this software without specific prior written permission.
22+
23+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
27+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33+
*/
34+
35+
import * as G from './globals'
36+
37+
// const INTEGER = '[-+]?\\d+';
38+
const NUMBER = '[-+]?\\d*\\.?\\d+'
39+
const PERCENTAGE = NUMBER + '%'
40+
41+
function call(...parts: string[]) {
42+
return '\\(\\s*(' + parts.join(')\\s*,\\s*(') + ')\\s*\\)'
43+
}
44+
45+
export const rgb = new RegExp('rgb' + call(NUMBER, NUMBER, NUMBER))
46+
export const rgba = new RegExp('rgba' + call(NUMBER, NUMBER, NUMBER, NUMBER))
47+
export const hsl = new RegExp('hsl' + call(NUMBER, PERCENTAGE, PERCENTAGE))
48+
export const hsla = new RegExp(
49+
'hsla' + call(NUMBER, PERCENTAGE, PERCENTAGE, NUMBER)
50+
)
51+
export const hex3 = /^#([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/
52+
export const hex4 = /^#([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/
53+
export const hex6 = /^#([0-9a-fA-F]{6})$/
54+
export const hex8 = /^#([0-9a-fA-F]{8})$/
55+
56+
export function normalizeColor(color: number | string) {
57+
let match
58+
59+
if (typeof color === 'number') {
60+
return color >>> 0 === color && color >= 0 && color <= 0xffffffff
61+
? color
62+
: null
63+
}
64+
65+
// Ordered based on occurrences on Facebook codebase
66+
if ((match = hex6.exec(color)))
67+
return parseInt(match[1] + 'ff', 16) >>> 0
68+
69+
if (G.colors && G.colors[color] !== undefined) {
70+
return G.colors[color]
71+
}
72+
73+
if ((match = rgb.exec(color))) {
74+
return (
75+
((parse255(match[1]) << 24) | // r
76+
(parse255(match[2]) << 16) | // g
77+
(parse255(match[3]) << 8) | // b
78+
0x000000ff) >>> // a
79+
0
80+
)
81+
}
82+
83+
if ((match = rgba.exec(color))) {
84+
return (
85+
((parse255(match[1]) << 24) | // r
86+
(parse255(match[2]) << 16) | // g
87+
(parse255(match[3]) << 8) | // b
88+
parse1(match[4])) >>> // a
89+
0
90+
)
91+
}
92+
93+
if ((match = hex3.exec(color))) {
94+
return (
95+
parseInt(
96+
match[1] +
97+
match[1] + // r
98+
match[2] +
99+
match[2] + // g
100+
match[3] +
101+
match[3] + // b
102+
'ff', // a
103+
16
104+
) >>> 0
105+
)
106+
}
107+
108+
// https://drafts.csswg.org/css-color-4/#hex-notation
109+
if ((match = hex8.exec(color))) return parseInt(match[1], 16) >>> 0
110+
111+
if ((match = hex4.exec(color))) {
112+
return (
113+
parseInt(
114+
match[1] +
115+
match[1] + // r
116+
match[2] +
117+
match[2] + // g
118+
match[3] +
119+
match[3] + // b
120+
match[4] +
121+
match[4], // a
122+
16
123+
) >>> 0
124+
)
125+
}
126+
127+
if ((match = hsl.exec(color))) {
128+
return (
129+
(hslToRgb(
130+
parse360(match[1]), // h
131+
parsePercentage(match[2]), // s
132+
parsePercentage(match[3]) // l
133+
) |
134+
0x000000ff) >>> // a
135+
0
136+
)
137+
}
138+
139+
if ((match = hsla.exec(color))) {
140+
return (
141+
(hslToRgb(
142+
parse360(match[1]), // h
143+
parsePercentage(match[2]), // s
144+
parsePercentage(match[3]) // l
145+
) |
146+
parse1(match[4])) >>> // a
147+
0
148+
)
149+
}
150+
return null
151+
}
152+
153+
function hue2rgb(p: number, q: number, t: number) {
154+
if (t < 0) t += 1
155+
if (t > 1) t -= 1
156+
if (t < 1 / 6) return p + (q - p) * 6 * t
157+
if (t < 1 / 2) return q
158+
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6
159+
return p
160+
}
161+
162+
function hslToRgb(h: number, s: number, l: number) {
163+
const q = l < 0.5 ? l * (1 + s) : l + s - l * s
164+
const p = 2 * l - q
165+
const r = hue2rgb(p, q, h + 1 / 3)
166+
const g = hue2rgb(p, q, h)
167+
const b = hue2rgb(p, q, h - 1 / 3)
168+
return (
169+
(Math.round(r * 255) << 24) |
170+
(Math.round(g * 255) << 16) |
171+
(Math.round(b * 255) << 8)
172+
)
173+
}
174+
175+
function parse255(str: string) {
176+
const int = parseInt(str, 10)
177+
if (int < 0) return 0
178+
if (int > 255) return 255
179+
return int
180+
}
181+
182+
function parse360(str: string) {
183+
const int = parseFloat(str)
184+
return (((int % 360) + 360) % 360) / 360
185+
}
186+
187+
function parse1(str: string) {
188+
const num = parseFloat(str)
189+
if (num < 0) return 0
190+
if (num > 1) return 255
191+
return Math.round(num * 255)
192+
}
193+
194+
function parsePercentage(str: string) {
195+
// parseFloat conveniently ignores the final %
196+
const int = parseFloat(str)
197+
if (int < 0) return 0
198+
if (int > 100) return 1
199+
return int / 100
200+
}

0 commit comments

Comments
 (0)