package color
import (
"fmt"
"math"
"regexp"
"strconv"
"strings"
"github.com/lucasb-eyer/go-colorful"
"github.com/mazznoer/csscolorparser"
"oss.terrastruct.com/util-go/go2"
)
var themeColorRegex = regexp .MustCompile (`^(N[1-7]|B[1-6]|AA[245]|AB[45])$` )
func IsThemeColor (colorString string ) bool {
return themeColorRegex .MatchString (colorString )
}
func Darken (colorString string ) (string , error ) {
if IsThemeColor (colorString ) {
switch {
case colorString [0 ] == 'B' :
switch colorString [1 ] {
case '1' , '2' :
return B1 , nil
case '3' :
return B2 , nil
case '4' :
return B3 , nil
case '5' :
return B4 , nil
case '6' :
return B5 , nil
}
case colorString [0 :2 ] == "AA" :
switch colorString [2 ] {
case '2' , '4' :
return AA2 , nil
case '5' :
return AA4 , nil
}
case colorString [0 :2 ] == "AB" :
switch colorString [2 ] {
case '4' :
return AB4 , nil
case '5' :
return AB5 , nil
}
case colorString [0 ] == 'N' :
switch colorString [1 ] {
case '1' , '2' :
return N1 , nil
case '3' :
return N2 , nil
case '4' :
return N3 , nil
case '5' :
return N4 , nil
case '6' :
return N5 , nil
case '7' :
return N6 , nil
}
}
return "" , fmt .Errorf ("invalid color \"%s\"" , colorString )
}
return darkenCSS (colorString )
}
func darkenCSS(colorString string ) (string , error ) {
c , err := csscolorparser .Parse (colorString )
if err != nil {
return "" , err
}
h , s , l := colorful .Color {R : c .R , G : c .G , B : c .B }.Hsl ()
return colorful .Hsl (h , s , l -.1 ).Clamped ().Hex (), nil
}
func LuminanceCategory (colorString string ) (string , error ) {
l , err := Luminance (colorString )
if err != nil {
return "" , err
}
switch {
case l >= .88 :
return "bright" , nil
case l >= .55 :
return "normal" , nil
case l >= .30 :
return "dark" , nil
default :
return "darker" , nil
}
}
func Luminance (colorString string ) (float64 , error ) {
c , err := csscolorparser .Parse (colorString )
if err != nil {
return 0 , err
}
l := float64 (
float64 (0.299 )*float64 (c .R ) +
float64 (0.587 )*float64 (c .G ) +
float64 (0.114 )*float64 (c .B ),
)
return l , nil
}
const (
N1 = "N1"
N2 = "N2"
N3 = "N3"
N4 = "N4"
N5 = "N5"
N6 = "N6"
N7 = "N7"
B1 = "B1"
B2 = "B2"
B3 = "B3"
B4 = "B4"
B5 = "B5"
B6 = "B6"
AA2 = "AA2"
AA4 = "AA4"
AA5 = "AA5"
AB4 = "AB4"
AB5 = "AB5"
Empty = ""
None = "none"
)
type RGB struct {
Red uint8
Green uint8
Blue uint8
}
func (c *RGB ) IsLight () bool {
r := float64 (c .Red )
g := float64 (c .Green )
b := float64 (c .Blue )
hsp := math .Sqrt (0.299 *math .Pow (r , 2 ) + 0.587 *math .Pow (g , 2 ) + 0.114 *math .Pow (b , 2 ))
return hsp > 130
}
func Hex2RGB (hex string ) (RGB , error ) {
var rgb RGB
if len (hex ) > 3 && hex [0 ] == '#' {
hex = hex [1 :]
} else {
return RGB {}, fmt .Errorf ("cannot parse hex color %v" , hex )
}
values , err := strconv .ParseUint (hex , 16 , 32 )
if err != nil {
return RGB {}, err
}
rgb = RGB {
Red : uint8 (values >> 16 ),
Green : uint8 ((values >> 8 ) & 0xFF ),
Blue : uint8 (values & 0xFF ),
}
return rgb , nil
}
var namedRgbMap = map [string ][]uint8 {
"aliceblue" : {240 , 248 , 255 },
"antiquewhite" : {250 , 235 , 215 },
"aqua" : {0 , 255 , 255 },
"aquamarine" : {127 , 255 , 212 },
"azure" : {240 , 255 , 255 },
"beige" : {245 , 245 , 220 },
"bisque" : {255 , 228 , 196 },
"black" : {0 , 0 , 0 },
"blanchedalmond" : {255 , 235 , 205 },
"blue" : {0 , 0 , 255 },
"blueviolet" : {138 , 43 , 226 },
"brown" : {165 , 42 , 42 },
"burlywood" : {222 , 184 , 135 },
"cadetblue" : {95 , 158 , 160 },
"chartreuse" : {127 , 255 , 0 },
"chocolate" : {210 , 105 , 30 },
"coral" : {255 , 127 , 80 },
"cornflowerblue" : {100 , 149 , 237 },
"cornsilk" : {255 , 248 , 220 },
"crimson" : {220 , 20 , 60 },
"cyan" : {0 , 255 , 255 },
"darkblue" : {0 , 0 , 139 },
"darkcyan" : {0 , 139 , 139 },
"darkgoldenrod" : {184 , 134 , 11 },
"darkgray" : {169 , 169 , 169 },
"darkgreen" : {0 , 100 , 0 },
"darkgrey" : {169 , 169 , 169 },
"darkkhaki" : {189 , 183 , 107 },
"darkmagenta" : {139 , 0 , 139 },
"darkolivegreen" : {85 , 107 , 47 },
"darkorange" : {255 , 140 , 0 },
"darkorchid" : {153 , 50 , 204 },
"darkred" : {139 , 0 , 0 },
"darksalmon" : {233 , 150 , 122 },
"darkseagreen" : {143 , 188 , 143 },
"darkslateblue" : {72 , 61 , 139 },
"darkslategray" : {47 , 79 , 79 },
"darkslategrey" : {47 , 79 , 79 },
"darkturquoise" : {0 , 206 , 209 },
"darkviolet" : {148 , 0 , 211 },
"deeppink" : {255 , 20 , 147 },
"deepskyblue" : {0 , 191 , 255 },
"dimgray" : {105 , 105 , 105 },
"dimgrey" : {105 , 105 , 105 },
"dodgerblue" : {30 , 144 , 255 },
"firebrick" : {178 , 34 , 34 },
"floralwhite" : {255 , 250 , 240 },
"forestgreen" : {34 , 139 , 34 },
"fuchsia" : {255 , 0 , 255 },
"gainsboro" : {220 , 220 , 220 },
"ghostwhite" : {248 , 248 , 255 },
"gold" : {255 , 215 , 0 },
"goldenrod" : {218 , 165 , 32 },
"gray" : {128 , 128 , 128 },
"green" : {0 , 128 , 0 },
"greenyellow" : {173 , 255 , 47 },
"grey" : {128 , 128 , 128 },
"honeydew" : {240 , 255 , 240 },
"hotpink" : {255 , 105 , 180 },
"indianred" : {205 , 92 , 92 },
"indigo" : {75 , 0 , 130 },
"ivory" : {255 , 255 , 240 },
"khaki" : {240 , 230 , 140 },
"lavender" : {230 , 230 , 250 },
"lavenderblush" : {255 , 240 , 245 },
"lawngreen" : {124 , 252 , 0 },
"lemonchiffon" : {255 , 250 , 205 },
"lightblue" : {173 , 216 , 230 },
"lightcoral" : {240 , 128 , 128 },
"lightcyan" : {224 , 255 , 255 },
"lightgoldenrodyellow" : {250 , 250 , 210 },
"lightgray" : {211 , 211 , 211 },
"lightgreen" : {144 , 238 , 144 },
"lightgrey" : {211 , 211 , 211 },
"lightpink" : {255 , 182 , 193 },
"lightsalmon" : {255 , 160 , 122 },
"lightseagreen" : {32 , 178 , 170 },
"lightskyblue" : {135 , 206 , 250 },
"lightslategray" : {119 , 136 , 153 },
"lightslategrey" : {119 , 136 , 153 },
"lightsteelblue" : {176 , 196 , 222 },
"lightyellow" : {255 , 255 , 224 },
"lime" : {0 , 255 , 0 },
"limegreen" : {50 , 205 , 50 },
"linen" : {250 , 240 , 230 },
"magenta" : {255 , 0 , 255 },
"maroon" : {128 , 0 , 0 },
"mediumaquamarine" : {102 , 205 , 170 },
"mediumblue" : {0 , 0 , 205 },
"mediumorchid" : {186 , 85 , 211 },
"mediumpurple" : {147 , 112 , 219 },
"mediumseagreen" : {60 , 179 , 113 },
"mediumslateblue" : {123 , 104 , 238 },
"mediumspringgreen" : {0 , 250 , 154 },
"mediumturquoise" : {72 , 209 , 204 },
"mediumvioletred" : {199 , 21 , 133 },
"midnightblue" : {25 , 25 , 112 },
"muintcream" : {245 , 255 , 250 },
"mistyrose" : {255 , 228 , 225 },
"moccasin" : {255 , 228 , 181 },
"navajowhite" : {255 , 222 , 173 },
"navy" : {0 , 0 , 128 },
"oldlace" : {253 , 245 , 230 },
"olive" : {128 , 128 , 0 },
"olivedrab" : {107 , 142 , 35 },
"orange" : {255 , 165 , 0 },
"orangered" : {255 , 69 , 0 },
"orchid" : {218 , 112 , 214 },
"palegoldenrod" : {238 , 232 , 170 },
"palegreen" : {152 , 251 , 152 },
"paleturquoise" : {175 , 238 , 238 },
"palevioletred" : {219 , 112 , 147 },
"papayawhip" : {255 , 239 , 213 },
"peachpuff" : {255 , 218 , 185 },
"peru" : {205 , 133 , 63 },
"pink" : {255 , 192 , 203 },
"plum" : {221 , 160 , 221 },
"powderblue" : {176 , 224 , 230 },
"purple" : {128 , 0 , 128 },
"red" : {255 , 0 , 0 },
"rebeccapurple" : {102 , 51 , 153 },
"rosybrown" : {188 , 143 , 143 },
"royalblue" : {65 , 105 , 225 },
"saddlebrown" : {139 , 69 , 19 },
"salmon" : {250 , 128 , 114 },
"sandybrown" : {244 , 164 , 96 },
"seagreen" : {46 , 139 , 87 },
"seashell" : {255 , 245 , 238 },
"sienna" : {160 , 82 , 45 },
"silver" : {192 , 192 , 192 },
"skyblue" : {135 , 206 , 235 },
"slateblue" : {106 , 90 , 205 },
"slategray" : {112 , 128 , 144 },
"slategrey" : {112 , 128 , 144 },
"snow" : {255 , 250 , 250 },
"springgreen" : {0 , 255 , 127 },
"steelblue" : {70 , 130 , 180 },
"tan" : {210 , 180 , 140 },
"teal" : {0 , 128 , 128 },
"thistle" : {216 , 191 , 216 },
"tomato" : {255 , 99 , 71 },
"turquoise" : {64 , 224 , 208 },
"violet" : {238 , 130 , 238 },
"wheat" : {245 , 222 , 179 },
"white" : {255 , 255 , 255 },
"whitesmoke" : {245 , 245 , 245 },
"yellow" : {255 , 255 , 0 },
"yellowgreen" : {154 , 205 , 50 },
}
func Name2RGB (name string ) RGB {
if rgb , ok := namedRgbMap [strings .ToLower (name )]; ok {
return RGB {
Red : rgb [0 ],
Green : rgb [1 ],
Blue : rgb [2 ],
}
}
return RGB {}
}
var NamedColors = []string {
"currentcolor" ,
"transparent" ,
"aliceblue" ,
"antiquewhite" ,
"aqua" ,
"aquamarine" ,
"azure" ,
"beige" ,
"bisque" ,
"black" ,
"blanchedalmond" ,
"blue" ,
"blueviolet" ,
"brown" ,
"burlywood" ,
"cadetblue" ,
"chartreuse" ,
"chocolate" ,
"coral" ,
"cornflowerblue" ,
"cornsilk" ,
"crimson" ,
"cyan" ,
"darkblue" ,
"darkcyan" ,
"darkgoldenrod" ,
"darkgray" ,
"darkgrey" ,
"darkgreen" ,
"darkkhaki" ,
"darkmagenta" ,
"darkolivegreen" ,
"darkorange" ,
"darkorchid" ,
"darkred" ,
"darksalmon" ,
"darkseagreen" ,
"darkslateblue" ,
"darkslategray" ,
"darkslategrey" ,
"darkturquoise" ,
"darkviolet" ,
"deeppink" ,
"deepskyblue" ,
"dimgray" ,
"dimgrey" ,
"dodgerblue" ,
"firebrick" ,
"floralwhite" ,
"forestgreen" ,
"fuchsia" ,
"gainsboro" ,
"ghostwhite" ,
"gold" ,
"goldenrod" ,
"gray" ,
"grey" ,
"green" ,
"greenyellow" ,
"honeydew" ,
"hotpink" ,
"indianred" ,
"indigo" ,
"ivory" ,
"khaki" ,
"lavender" ,
"lavenderblush" ,
"lawngreen" ,
"lemonchiffon" ,
"lightblue" ,
"lightcoral" ,
"lightcyan" ,
"lightgoldenrodyellow" ,
"lightgray" ,
"lightgrey" ,
"lightgreen" ,
"lightpink" ,
"lightsalmon" ,
"lightseagreen" ,
"lightskyblue" ,
"lightslategray" ,
"lightslategrey" ,
"lightsteelblue" ,
"lightyellow" ,
"lime" ,
"limegreen" ,
"linen" ,
"magenta" ,
"maroon" ,
"mediumaquamarine" ,
"mediumblue" ,
"mediumorchid" ,
"mediumpurple" ,
"mediumseagreen" ,
"mediumslateblue" ,
"mediumspringgreen" ,
"mediumturquoise" ,
"mediumvioletred" ,
"midnightblue" ,
"mintcream" ,
"mistyrose" ,
"moccasin" ,
"navajowhite" ,
"navy" ,
"oldlace" ,
"olive" ,
"olivedrab" ,
"orange" ,
"orangered" ,
"orchid" ,
"palegoldenrod" ,
"palegreen" ,
"paleturquoise" ,
"palevioletred" ,
"papayawhip" ,
"peachpuff" ,
"peru" ,
"pink" ,
"plum" ,
"powderblue" ,
"purple" ,
"rebeccapurple" ,
"red" ,
"rosybrown" ,
"royalblue" ,
"saddlebrown" ,
"salmon" ,
"sandybrown" ,
"seagreen" ,
"seashell" ,
"sienna" ,
"silver" ,
"skyblue" ,
"slateblue" ,
"slategray" ,
"slategrey" ,
"snow" ,
"springgreen" ,
"steelblue" ,
"tan" ,
"teal" ,
"thistle" ,
"tomato" ,
"turquoise" ,
"violet" ,
"wheat" ,
"white" ,
"whitesmoke" ,
"yellow" ,
"yellowgreen" ,
}
var ColorHexRegex = regexp .MustCompile (`^#(([0-9a-fA-F]{2}){3}|([0-9a-fA-F]){3})$` )
func ValidColor (color string ) bool {
if !go2 .Contains (NamedColors , strings .ToLower (color )) && !ColorHexRegex .MatchString (color ) && !IsGradient (color ) {
return false
}
return true
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .