@@ -14,6 +14,8 @@ module Color
1414 , toHSLA
1515 , toRGBA
1616 , toRGBA'
17+ , fromHexString
18+ , toHexString
1719 , cssStringHSLA
1820 , complementary
1921 , lighten
@@ -25,9 +27,14 @@ module Color
2527 ) where
2628
2729import Prelude
30+ import Control.Bind (join )
31+ import Data.Array ((!!))
2832import Data.Int (toNumber , round )
29- import Math ( abs , (% ))
33+ import Data.Maybe ( Maybe (.. ))
3034import Data.Ord (min , max , clamp )
35+ import Data.String (length )
36+ import Data.String.Regex (regex , parseFlags , match )
37+ import Math (abs , (%))
3138
3239-- | The representation of a color.
3340data Color = HSLA Number Number Number Number
@@ -157,6 +164,42 @@ toRGBA' (HSLA h s l a) = { r: rgb'.r + m, g: rgb'.g + m, b: rgb'.b + m, a }
157164 | 4.0 <= h' && h' < 5.0 = { r: x , g: 0.0 , b: chr }
158165 | otherwise = { r: chr, g: 0.0 , b: x }
159166
167+ foreign import parseHex :: String -> Int
168+
169+ -- | Parse a hexadecimal RGB code of the form `#rgb` or `#rrggbb`, where the
170+ -- | hexadecimal digits are of the format [0-9a-f] (case insensitive). Returns
171+ -- | `Nothing` if the string is in a wrong format.
172+ fromHexString :: String -> Maybe Color
173+ fromHexString str = do
174+ groups <- match pattern str
175+ r <- parseHex <$> join (groups !! 1 )
176+ g <- parseHex <$> join (groups !! 2 )
177+ b <- parseHex <$> join (groups !! 3 )
178+ if isShort
179+ then
180+ pure $ rgb (16 * r + r) (16 * g + g) (16 * b + b)
181+ else
182+ pure (rgb r g b)
183+ where
184+ isShort = length str == 4
185+ digit = " [0-9a-f]"
186+ single = " (" <> digit <> " )"
187+ pair = " (" <> digit <> digit <> " )"
188+ variant = if isShort
189+ then single <> single <> single
190+ else pair <> pair <> pair
191+ pattern = regex (" ^#(?:" <> variant <> " )$" ) (parseFlags " i" )
192+
193+ foreign import toHex :: Int -> String
194+
195+ -- | Return a hexadecimal representation of the color in the form `#rrggbb`,
196+ -- | where `rr`, `gg` and `bb` refer to hexadecimal digits corresponding to
197+ -- | the RGB channel values between `00` and `ff`. The alpha channel is not
198+ -- | represented.
199+ toHexString :: Color -> String
200+ toHexString color = " #" <> toHex c.r <> toHex c.g <> toHex c.b
201+ where c = toRGBA color
202+
160203-- | The CSS representation of the color in the form `hsl(..)` or `hsla(...)`.
161204cssStringHSLA :: Color -> String
162205cssStringHSLA (HSLA h s l a) =
0 commit comments