Skip to content

Commit a5a4a2a

Browse files
committed
Add fromHexString, toHexString, closes #1
1 parent b760d98 commit a5a4a2a

File tree

8 files changed

+132
-5
lines changed

8 files changed

+132
-5
lines changed

bower.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
"dependencies": {
1313
"purescript-integers": "^0.2.1",
1414
"purescript-orders": "^0.1.1",
15-
"purescript-arrays": "^0.4.4"
15+
"purescript-arrays": "^0.4.4",
16+
"purescript-strings": "^0.7.1"
1617
},
1718
"devDependencies": {
1819
"purescript-test-unit": "^4.1.0",

docs/Color.md

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,19 @@ Create a `Color` from RGB values between 0.0 and 1.0.
5757
hsla :: Number -> Number -> Number -> Number -> Color
5858
```
5959

60-
Create a `Color` from hue, saturation, lightness and alpha values.
60+
Create a `Color` from hue, saturation, lightness and alpha values. The
61+
hue is given in degrees, as a `Number` between 0.0 and 360.0. Saturation,
62+
lightness and alpha are numbers between 0.0 and 1.0.
6163

6264
#### `hsl`
6365

6466
``` purescript
6567
hsl :: Number -> Number -> Number -> Color
6668
```
6769

68-
Create a `Color` from hue, saturation and lightness values.
70+
Create a `Color` from hue, saturation and lightness values. The hue is
71+
given in degrees, as a `Number` between 0.0 and 360.0. Both saturation and
72+
lightness are numbers between 0.0 and 1.0.
6973

7074
#### `black`
7175

@@ -117,6 +121,27 @@ toRGBA' :: Color -> { r :: Number, g :: Number, b :: Number, a :: Number }
117121
Convert a `Color` to its red, green, blue and alpha values. All values
118122
are numbers in the range from 0.0 to 1.0.
119123

124+
#### `fromHexString`
125+
126+
``` purescript
127+
fromHexString :: String -> Maybe Color
128+
```
129+
130+
Parse a HEX code of the form `#ddd` or `#dddddd`, where `d` is a single
131+
hexadecimal digit ([0-9a-f], case insensitive). Returns `Nothing` if the
132+
string is in a wrong format.
133+
134+
#### `toHexString`
135+
136+
``` purescript
137+
toHexString :: Color -> String
138+
```
139+
140+
Return a hexadecimal representation of the color in the form `#rrggbb`,
141+
where `rr`, `gg` and `bb` refer to hexadecimal digits corresponding to
142+
the RGB channel values between `00` and `ff`. The alpha channel is not
143+
represented.
144+
120145
#### `cssStringHSLA`
121146

122147
``` purescript

docs/Color/Gradient.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
## Module Color.Gradient
2+
3+
#### `hslGradient`
4+
5+
``` purescript
6+
hslGradient :: Int -> Color -> Color -> Array Color
7+
```
8+
9+
A range of colors that linearly interpolates between the two boundaries.
10+
11+

html/purescript-colors.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

src/Color.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// module Color
2+
// jshint node: true
3+
4+
"use strict";
5+
6+
// Parse a string which guaranteed to be of the form `[0-9a-f]{1,2}`.
7+
exports.parseHex = function(str) {
8+
return parseInt(str, 16);
9+
};
10+
11+
// Convert a number between 0 and 255 to a hex value between 00 and ff.
12+
exports.toHex = function(n) {
13+
var str = n.toString(16);
14+
if (str.length == 1) {
15+
return "0" + str;
16+
}
17+
return str;
18+
};

src/Color.purs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

2729
import Prelude
30+
import Control.Bind (join)
31+
import Data.Array ((!!))
2832
import Data.Int (toNumber, round)
29-
import Math (abs, (%))
33+
import Data.Maybe (Maybe(..))
3034
import 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.
3340
data 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(...)`.
161204
cssStringHSLA :: Color -> String
162205
cssStringHSLA (HSLA h s l a) =

test/Interactive.purs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ main = do
7979
doc "hsl" (id :: TColor -> _)
8080
doc "rgb" $
8181
(\(Int255 r) (Int255 g) (Int255 b) -> TColor (rgb r g b))
82+
doc "toHexString" (\(TColor c) -> toHexString c)
8283
doc "cssStringHSLA" (\(TColor c) -> cssStringHSLA c)
8384
doc "black" (TColor black)
8485
doc "white" (TColor white)

test/Main.purs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import Prelude
55
import Data.Array ((..))
66
import Data.Foldable (sequence_)
77
import Data.Int (toNumber)
8+
import Data.Maybe (Maybe(..))
89

910
import Test.Unit (test, runTest)
1011
import Test.Unit.Assert (assert, assertFalse, equal)
@@ -55,6 +56,33 @@ main = runTest do
5556
degree <- 0 .. 360
5657
return $ roundtrip (toNumber degree) 0.5 0.8
5758

59+
test "fromHexString" do
60+
equal (Just black) (fromHexString "#000")
61+
equal (Just black) (fromHexString "#000000")
62+
equal (Just white) (fromHexString "#fff")
63+
equal (Just white) (fromHexString "#fffFFF")
64+
equal (Just white) (fromHexString "#ffffff")
65+
equal (Just (rgb 87 166 206)) (fromHexString "#57A6CE")
66+
equal Nothing (fromHexString "000")
67+
equal Nothing (fromHexString "000000")
68+
equal Nothing (fromHexString "#0")
69+
equal Nothing (fromHexString "#00")
70+
equal Nothing (fromHexString "#0000")
71+
equal Nothing (fromHexString "#00000")
72+
equal Nothing (fromHexString "#0000000")
73+
74+
test "toHexString" do
75+
let hexRoundtrip h s l = equal (Just $ hsl h s l) (fromHexString (toHexString (hsl h s l)))
76+
hexRoundtrip 0.0 0.0 1.0
77+
hexRoundtrip 0.0 0.0 0.5
78+
hexRoundtrip 0.0 0.0 0.0
79+
hexRoundtrip 0.0 1.0 0.5
80+
hexRoundtrip 60.0 1.0 0.375
81+
hexRoundtrip 120.0 1.0 0.25
82+
hexRoundtrip 240.0 1.0 0.75
83+
hexRoundtrip 49.5 0.893 0.497
84+
hexRoundtrip 162.4 0.779 0.447
85+
5886
test "cssStringHSLA" do
5987
equal "hsla(120, 33%, 55%, 0.3)" (cssStringHSLA (hsla 120.1 0.33 0.55 0.3))
6088
equal "hsl(120, 33%, 55%)" (cssStringHSLA (hsla 120.1 0.332 0.549 1.0))

0 commit comments

Comments
 (0)