Skip to content

Commit 5a3595a

Browse files
committed
Write the rest of API documentation
1 parent 9ea0693 commit 5a3595a

File tree

4 files changed

+184
-37
lines changed

4 files changed

+184
-37
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Zero-dependency, plug-and-play library that enables #hex-color syntax for your own types!
44

5-
![Demo image](images/demo.png)
5+
![Demo image](https://raw.githubusercontent.com/haskell-game/webcolor-labels/refs/heads/master/images/demo.png)
66

77
## Motivation
88

src/WebColor/Labels.hs

Lines changed: 169 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
-- We need this to have correct links inside haddocks
99
{-# OPTIONS_GHC -Wno-unused-imports #-}
1010

11+
-- Required to use `showType` inside haddock coments
12+
{-# OPTIONS_GHC -Wno-unused-top-binds #-}
1113

1214
{- |
1315
= Introduction and intended usage
@@ -163,9 +165,37 @@ import Data.Kind (Constraint)
163165
-- Imports for haddocks
164166
import GHC.OverloadedLabels (IsLabel(..))
165167

168+
#if __GLASGOW_HASKELL__ >= 906
169+
import GHC.TypeError (Unsatisfiable)
170+
171+
showType :: forall a. (Unsatisfiable (ShowType a)) => ()
172+
showType = ()
173+
#endif
174+
175+
-- | Red, green, blue, and optional alpha color channels in range from 0 to 255
166176
type WebColorParsed = (Nat, Nat, Nat, Maybe Nat)
167177

168-
-- |
178+
-- | Parse a string containing a named color from a basic
179+
-- palette or hexadecimal representation with an optional
180+
-- alpha channel.
181+
--
182+
-- * Named colors are always considered RGB-only:
183+
--
184+
-- >>> showType @(`ParseWebColorMaybeAlpha` "red")
185+
-- '(255, 0, 0, 'Nothing)
186+
--
187+
-- >>> showType @(`ParseWebColorMaybeAlpha` "silver")
188+
-- '(192, 192, 192, 'Nothing)
189+
--
190+
-- `ParseWebColorMaybeAlpha` inherits many properties from `ParseHexadecimalColor`:
191+
--
192+
-- * The difference between a `Nothing` alpha channel and @`Just` 255@
193+
-- is purely syntactical, and you have to tackle the difference yourself
194+
-- * This family automatically handles shortened syntax
195+
-- * This family throws a compile-time error when the wrong number
196+
-- of hex characters is supplied
197+
--
198+
-- Please refer to `ParseHexadecimalColor` for the examples.
169199
type ParseWebColorMaybeAlpha :: Symbol -> WebColorParsed
170200
type family ParseWebColorMaybeAlpha s where
171201
ParseWebColorMaybeAlpha "white" = '(255, 255, 255, Nothing)
@@ -186,6 +216,47 @@ type family ParseWebColorMaybeAlpha s where
186216
ParseWebColorMaybeAlpha "purple" = '(128, 0, 128, Nothing)
187217
ParseWebColorMaybeAlpha s = ParseHexadecimalColor s
188218

219+
-- | Parse a string containing hexadecimal representation of a
220+
-- color with an optional alpha channel.
221+
--
222+
-- * This family doesn't handle named colors.
223+
-- * The difference between a `Nothing` alpha channel and @`Just` 255@
224+
-- is purely syntactical, and you have to tackle the difference yourself:
225+
--
226+
-- >>> showType @(`ParseHexadecimalColor` "fafefb")
227+
-- '(250, 254, 251, 'Nothing)
228+
--
229+
-- >>> showType @(`ParseHexadecimalColor` "fafefbff")
230+
-- '(250, 254, 251, 'Just 255)
231+
--
232+
-- * This family automatically handles shortened syntax:
233+
--
234+
-- E.g. #123 is the same as #112233:
235+
--
236+
-- >>> showType @(`ParseHexadecimalColor` "123")
237+
-- '(17, 34, 51, 'Nothing)
238+
--
239+
-- >>> showType @(`ParseHexadecimalColor` "112233")
240+
-- '(17, 34, 51, 'Nothing)
241+
--
242+
-- The same applies to #1234 and #11223344:
243+
--
244+
-- >>> showType @(`ParseHexadecimalColor` "1234")
245+
-- '(17, 34, 51, 'Just 68)
246+
--
247+
-- >>> showType @(`ParseHexadecimalColor` "11223344")
248+
-- '(17, 34, 51, 'Just 68)
249+
--
250+
-- * This family throws a compile-time error when the wrong number
251+
-- of hex characters is supplied:
252+
--
253+
-- >>> showType @(`ParseHexadecimalColor` "1")
254+
-- Unexpected number of hex codes
255+
-- expected 3, 4, 6 or 8
256+
--
257+
-- >>> showType @(`ParseHexadecimalColor` "1122334455")
258+
-- Unexpected number of hex codes
259+
-- expected 3, 4, 6 or 8
189260
type ParseHexadecimalColor :: Symbol -> WebColorParsed
190261
type family ParseHexadecimalColor s where
191262
ParseHexadecimalColor s = ParseColorRec '[] (UnconsSymbol s)
@@ -195,8 +266,36 @@ type family ParseColorRec color str where
195266
ParseColorRec colors Nothing = UpgradeColor colors
196267
ParseColorRec colors (Just '(ch, t)) = ParseColorRec (ParseHexadecimalChar ch : colors) (UnconsSymbol t)
197268

269+
-- | Red, green, and blue color channels in range from 0 to 255
198270
type WebColor = (Nat, Nat, Nat)
199271

272+
-- | Parse a string containing a named color from a basic
273+
-- palette or hexadecimal representation without an alpha channel.
274+
--
275+
-- * For convenience, a 255 alpha channel is interpreted
276+
-- as a solid color without an alpha channel:
277+
--
278+
-- >>> showType @(`ParseWebColor` "123")
279+
-- '(17, 34, 51)
280+
--
281+
-- >>> showType @(`ParseWebColor` "123f")
282+
-- '(17, 34, 51)
283+
--
284+
-- * Other alpha channel values result in a compile-time error:
285+
--
286+
-- >>> showType @(`ParseWebColor` "123d")
287+
-- Unexpected alpha channel! RGB color expected
288+
--
289+
-- This family inherits many properties from `ParseWebColorMaybeAlpha`:
290+
--
291+
-- * Named colors are always considered RGB-only:
292+
--
293+
-- >>> showType @(`ParseWebColor` "red")
294+
-- '(255, 0, 0)
295+
--
296+
-- * This family automatically handles shortened syntax.
297+
-- * This family throws a compile-time error when the wrong number
298+
-- of hex characters is supplied
200299
type ParseWebColor :: Symbol -> WebColor
201300
type family ParseWebColor s where
202301
ParseWebColor s = ParseRGBColorWorker (ParseWebColorMaybeAlpha s)
@@ -207,8 +306,29 @@ type family ParseRGBColorWorker color where
207306
ParseRGBColorWorker '(r, g, b, Just 255) = '(r, g, b)
208307
ParseRGBColorWorker '(_, _, _, Just _) = TypeError (Text "Unexpected alpha channel! RGB color expected")
209308

309+
-- | Red, green, blue, and alpha color channels in range from 0 to 255
210310
type WebColorAlpha = (Nat, Nat, Nat, Nat)
211311

312+
-- | Parse a string containing a named color from a basic
313+
-- palette or a hexadecimal representation with an optional
314+
-- alpha channel.
315+
--
316+
-- * This family converts an absence of an alpha channel into
317+
-- the 255 value.
318+
--
319+
-- >>> showType @(`ParseWebColorAlpha` "123")
320+
-- '(17, 34, 51, 255)
321+
--
322+
-- This family inherits many properties from `ParseWebColorMaybeAlpha`:
323+
--
324+
-- * Named colors are always considered RGB-only and are handled the same way:
325+
--
326+
-- >>> showType @(`ParseWebColorAlpha` "red")
327+
-- '(255, 0, 0, 255)
328+
--
329+
-- * This family automatically handles shortened syntax.
330+
-- * This family throws a compile-time error when the wrong number
331+
-- of hex characters is supplied
212332
type ParseWebColorAlpha :: Symbol -> WebColorAlpha
213333
type family ParseWebColorAlpha s where
214334
ParseWebColorAlpha s = ParseRGBAColorWorker (ParseWebColorMaybeAlpha s)
@@ -220,8 +340,35 @@ type family ParseRGBAColorWorker color where
220340

221341
type a & b = a
222342

343+
-- | Parse a type-level string containing a named color from a basic
344+
-- palette or a hexadecimal representation and convert it into three
345+
-- bytes representing red, green, and blue channels
346+
--
347+
--
348+
-- * For convenience, a 255 alpha channel is interpreted
349+
-- as a solid color without an alpha channel:
350+
--
351+
-- >>> webColor @"123" (,,)
352+
-- (17,34,51)
353+
--
354+
-- >>> webColor @"123f" (,,)
355+
-- (17,34,51)
356+
--
357+
-- * Other alpha channel values result in a compile-time error:
358+
--
359+
-- >>> webColor @"123d" (,,)
360+
-- Unexpected alpha channel! RGB color expected
361+
--
362+
-- * Named colors are always considered RGB-only:
363+
--
364+
-- >>> webColor @"red" (,,)
365+
-- (255,0,0)
223366
type IsWebColor :: Symbol -> Constraint
224367
class IsWebColor s where
368+
-- | Parse a type-level string and give you bytes representing
369+
-- red, green, and blue colors.
370+
--
371+
-- NB: @&@ is just a type alias that should help to keep with order.
225372
webColor ::
226373
(Word8 & "red" -> Word8 & "green" -> Word8 & "blue" -> r) -> r
227374

@@ -237,8 +384,29 @@ instance {-# OVERLAPPABLE #-}
237384
webColor k =
238385
k `color` Proxy @r `color` Proxy @g `color` Proxy @b
239386

387+
-- | Parse a type-level string containing a named color from a basic
388+
-- palette or a hexadecimal representation and convert it into four
389+
-- bytes representing red, green, blue, and alpha channels
390+
--
391+
--
392+
-- * An absent alpha channel get converted into the 255 value:
393+
--
394+
-- >>> webColorAlpha @"123" (,,,)
395+
-- (17,34,51,255)
396+
--
397+
-- >>> webColorAlpha @"123f" (,,,)
398+
-- (17,34,51,255)
399+
--
400+
-- * Named colors are always considered RGB-only:
401+
--
402+
-- >>> webColorAlpha @"red" (,,,)
403+
-- (255,0,0,255)
240404
type IsWebColorAlpha :: Symbol -> Constraint
241405
class IsWebColorAlpha s where
406+
-- | Parse a type-level string and give you bytes representing
407+
-- red, green, blue, and alpha colors.
408+
--
409+
-- NB: @&@ is just a type alias that should help to keep with order.
242410
webColorAlpha ::
243411
(Word8 & "red" -> Word8 & "green" -> Word8 & "blue" -> Word8 & "alpha" -> r) -> r
244412

test/Main.hs

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
{-# OPTIONS_GHC -Wno-orphans #-}
66

7-
module Main (main, gold, transparentPurple, red) where
7+
module Main (main) where
88

99
import WebColor.Labels
1010
import Data.Word (Word8)
@@ -90,30 +90,3 @@ main = defaultMain $ testGroup "Tests"
9090

9191
rgba :: RGBA -> RGBA -> Assertion
9292
rgba = (@?=)
93-
94-
95-
96-
97-
98-
99-
100-
101-
102-
103-
104-
105-
106-
107-
108-
109-
110-
111-
112-
transparentPurple :: RGBA
113-
transparentPurple = #840384c3
114-
115-
gold :: RGBA
116-
gold = #ffd700
117-
118-
red :: RGBA
119-
red = #f00

webcolor-labels.cabal

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ name: webcolor-labels
1313
version: 0.1.0.0
1414

1515
-- A short (one-line) description of the package.
16-
synopsis:
17-
Plug-n-play #hex-syntax for your colors
16+
synopsis: Plug-n-play #hex-syntax for your colors
1817

1918
-- A longer description of the package.
2019
description:
@@ -27,25 +26,32 @@ description:
2726

2827
license: MPL-2.0
2928
license-file: LICENSE
30-
author: Andrei Borzenkov
31-
maintainer: [email protected]
29+
author: Andrei Borzenkov <[email protected]>
30+
maintainer: [email protected]
31+
homepage: https://github.com/haskell-game/webcolor-labels
32+
bug-reports: https://github.com/haskell-game/webcolor-labels/issues
3233

3334
-- A copyright notice.
3435
-- copyright:
3536
category: Graphics
3637
build-type: Simple
38+
extra-doc-files:
39+
CHANGELOG.md
40+
README.md
3741

38-
extra-doc-files: CHANGELOG.md README.md
42+
tested-with: GHC ==9.8.4 || ==9.10.2 || ==9.12.2
3943

40-
tested-with: GHC ==9.12.2 || ==9.10.2 || ==9.8.4
44+
source-repository head
45+
type: git
46+
location: https://github.com/haskell-game/webcolor-labels/
4147

4248
common warnings
4349
ghc-options: -Wall
4450

4551
library
4652
import: warnings
4753
exposed-modules: WebColor.Labels
48-
build-depends: base >=4.16.0.0 && < 5.0.0.0
54+
build-depends: base >=4.16.0.0 && <5.0.0.0
4955
hs-source-dirs: src
5056
default-language: GHC2021
5157

0 commit comments

Comments
 (0)