packages feed

clay 0.15.0 → 0.16.0

raw patch · 8 files changed

+873/−24 lines, 8 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Clay: class Not a
+ Clay.Flexbox: instance Clay.Flexbox.Stretch Clay.Flexbox.JustifyContentValue
+ Clay.Geometry: (%) :: Integer -> Integer -> AspectRatio
+ Clay.Geometry: aspectRatio :: AspectRatio -> Css
+ Clay.Geometry: data AspectRatio
+ Clay.Geometry: infixl 7 %
+ Clay.Geometry: instance Clay.Common.Auto Clay.Geometry.AspectRatio
+ Clay.Geometry: instance Clay.Common.Inherit Clay.Geometry.AspectRatio
+ Clay.Geometry: instance Clay.Common.Initial Clay.Geometry.AspectRatio
+ Clay.Geometry: instance Clay.Common.Other Clay.Geometry.AspectRatio
+ Clay.Geometry: instance Clay.Common.Unset Clay.Geometry.AspectRatio
+ Clay.Geometry: instance Clay.Property.Val Clay.Geometry.AspectRatio
+ Clay.Geometry: instance GHC.Num.Num Clay.Geometry.AspectRatio
+ Clay.Geometry: instance GHC.Real.Fractional Clay.Geometry.AspectRatio
+ Clay.Geometry: withFallback :: AspectRatio -> AspectRatio -> AspectRatio
+ Clay.Grid: (//) :: (Slash a r, ToGridLine b) => a -> b -> r
+ Clay.Grid: class ToGridLine a
+ Clay.Grid: class ToGridLines2 a
+ Clay.Grid: class ToGridLines4 a
+ Clay.Grid: class ToSpan a
+ Clay.Grid: customIdentToText :: CustomIdentGrid -> Text
+ Clay.Grid: data CustomIdentGrid
+ Clay.Grid: data FourGridLines
+ Clay.Grid: data GridLine
+ Clay.Grid: data GridLines2
+ Clay.Grid: data GridLines4
+ Clay.Grid: data OneGridLine
+ Clay.Grid: data ThreeGridLines
+ Clay.Grid: data TwoGridLines
+ Clay.Grid: gridArea :: ToGridLines4 a => a -> Css
+ Clay.Grid: gridColumn :: ToGridLines2 a => a -> Css
+ Clay.Grid: gridColumnEnd :: ToGridLine a => a -> Css
+ Clay.Grid: gridColumnStart :: ToGridLine a => a -> Css
+ Clay.Grid: gridRow :: ToGridLines2 a => a -> Css
+ Clay.Grid: gridRowEnd :: ToGridLine a => a -> Css
+ Clay.Grid: gridRowStart :: ToGridLine a => a -> Css
+ Clay.Grid: instance Clay.Common.Auto Clay.Grid.GridLine
+ Clay.Grid: instance Clay.Common.Inherit Clay.Grid.GridLine
+ Clay.Grid: instance Clay.Common.Initial Clay.Grid.GridLine
+ Clay.Grid: instance Clay.Common.Unset Clay.Grid.GridLine
+ Clay.Grid: instance Clay.Grid.Slash (Clay.Grid.CustomIdentGrid, GHC.Num.Integer.Integer) Clay.Grid.TwoGridLines
+ Clay.Grid: instance Clay.Grid.Slash (GHC.Base.String, GHC.Num.Integer.Integer) Clay.Grid.TwoGridLines
+ Clay.Grid: instance Clay.Grid.Slash Clay.Grid.CustomIdentGrid Clay.Grid.TwoGridLines
+ Clay.Grid: instance Clay.Grid.Slash Clay.Grid.GridLine Clay.Grid.TwoGridLines
+ Clay.Grid: instance Clay.Grid.Slash Clay.Grid.ThreeGridLines Clay.Grid.FourGridLines
+ Clay.Grid: instance Clay.Grid.Slash Clay.Grid.TwoGridLines Clay.Grid.ThreeGridLines
+ Clay.Grid: instance Clay.Grid.Slash GHC.Base.String Clay.Grid.TwoGridLines
+ Clay.Grid: instance Clay.Grid.Slash GHC.Num.Integer.Integer Clay.Grid.TwoGridLines
+ Clay.Grid: instance Clay.Grid.ToGridLine (Clay.Grid.CustomIdentGrid, GHC.Num.Integer.Integer)
+ Clay.Grid: instance Clay.Grid.ToGridLine (GHC.Base.String, GHC.Num.Integer.Integer)
+ Clay.Grid: instance Clay.Grid.ToGridLine Clay.Grid.CustomIdentGrid
+ Clay.Grid: instance Clay.Grid.ToGridLine Clay.Grid.GridLine
+ Clay.Grid: instance Clay.Grid.ToGridLine GHC.Base.String
+ Clay.Grid: instance Clay.Grid.ToGridLine GHC.Num.Integer.Integer
+ Clay.Grid: instance Clay.Grid.ToGridLines2 (Clay.Grid.CustomIdentGrid, GHC.Num.Integer.Integer)
+ Clay.Grid: instance Clay.Grid.ToGridLines2 (GHC.Base.String, GHC.Num.Integer.Integer)
+ Clay.Grid: instance Clay.Grid.ToGridLines2 Clay.Grid.CustomIdentGrid
+ Clay.Grid: instance Clay.Grid.ToGridLines2 Clay.Grid.GridLine
+ Clay.Grid: instance Clay.Grid.ToGridLines2 Clay.Grid.GridLines2
+ Clay.Grid: instance Clay.Grid.ToGridLines2 Clay.Grid.OneGridLine
+ Clay.Grid: instance Clay.Grid.ToGridLines2 Clay.Grid.TwoGridLines
+ Clay.Grid: instance Clay.Grid.ToGridLines2 GHC.Base.String
+ Clay.Grid: instance Clay.Grid.ToGridLines2 GHC.Num.Integer.Integer
+ Clay.Grid: instance Clay.Grid.ToGridLines4 (Clay.Grid.CustomIdentGrid, GHC.Num.Integer.Integer)
+ Clay.Grid: instance Clay.Grid.ToGridLines4 (GHC.Base.String, GHC.Num.Integer.Integer)
+ Clay.Grid: instance Clay.Grid.ToGridLines4 Clay.Grid.CustomIdentGrid
+ Clay.Grid: instance Clay.Grid.ToGridLines4 Clay.Grid.FourGridLines
+ Clay.Grid: instance Clay.Grid.ToGridLines4 Clay.Grid.GridLine
+ Clay.Grid: instance Clay.Grid.ToGridLines4 Clay.Grid.GridLines4
+ Clay.Grid: instance Clay.Grid.ToGridLines4 Clay.Grid.OneGridLine
+ Clay.Grid: instance Clay.Grid.ToGridLines4 Clay.Grid.ThreeGridLines
+ Clay.Grid: instance Clay.Grid.ToGridLines4 Clay.Grid.TwoGridLines
+ Clay.Grid: instance Clay.Grid.ToGridLines4 GHC.Base.String
+ Clay.Grid: instance Clay.Grid.ToGridLines4 GHC.Num.Integer.Integer
+ Clay.Grid: instance Clay.Grid.ToSpan (GHC.Base.String, GHC.Num.Integer.Integer)
+ Clay.Grid: instance Clay.Grid.ToSpan GHC.Base.String
+ Clay.Grid: instance Clay.Grid.ToSpan GHC.Num.Integer.Integer
+ Clay.Grid: instance Clay.Property.Val Clay.Grid.FourGridLines
+ Clay.Grid: instance Clay.Property.Val Clay.Grid.GridLine
+ Clay.Grid: instance Clay.Property.Val Clay.Grid.GridLines2
+ Clay.Grid: instance Clay.Property.Val Clay.Grid.GridLines4
+ Clay.Grid: instance Clay.Property.Val Clay.Grid.OneGridLine
+ Clay.Grid: instance Clay.Property.Val Clay.Grid.ThreeGridLines
+ Clay.Grid: instance Clay.Property.Val Clay.Grid.TwoGridLines
+ Clay.Grid: instance GHC.Classes.Eq Clay.Grid.CustomIdentGrid
+ Clay.Grid: instance GHC.Classes.Eq Clay.Grid.GridLine
+ Clay.Grid: instance GHC.Classes.Ord Clay.Grid.CustomIdentGrid
+ Clay.Grid: instance GHC.Read.Read Clay.Grid.CustomIdentGrid
+ Clay.Grid: instance GHC.Show.Show Clay.Grid.CustomIdentGrid
+ Clay.Grid: instance GHC.Show.Show Clay.Grid.GridLine
+ Clay.Grid: partialMkCustomIdentGrid :: Text -> CustomIdentGrid
+ Clay.Grid: span_ :: ToSpan a => a -> GridLine
+ Clay.Pseudo: class Not a
+ Clay.Pseudo: instance Clay.Pseudo.Not Clay.Selector.Refinement
+ Clay.Pseudo: instance Clay.Pseudo.Not Clay.Selector.Selector
+ Clay.Render: renderRefinement :: Refinement -> [Text]
- Clay: class (Val a) => Cursor a
+ Clay: class Val a => Cursor a
- Clay: class (Val a) => VerticalAlign a
+ Clay: class Val a => VerticalAlign a
- Clay: not :: Selector -> Refinement
+ Clay: not :: Not a => a -> Refinement
- Clay.Color: clamp :: Ord a => Num a => a -> a
+ Clay.Color: clamp :: (Ord a, Num a) => a -> a
- Clay.Display: class (Val a) => Cursor a
+ Clay.Display: class Val a => Cursor a
- Clay.Display: class (Val a) => VerticalAlign a
+ Clay.Display: class Val a => VerticalAlign a
- Clay.Pseudo: not :: Selector -> Refinement
+ Clay.Pseudo: not :: Not a => a -> Refinement
- Clay.Selector: In :: f (Fix f) -> Fix f
+ Clay.Selector: In :: f (Fix f) -> Fix (f :: Type -> Type)
- Clay.Selector: [out] :: Fix f -> f (Fix f)
+ Clay.Selector: [out] :: Fix (f :: Type -> Type) -> f (Fix f)
- Clay.Selector: newtype Fix f
+ Clay.Selector: newtype Fix (f :: Type -> Type)

Files

CHANGELOG view
@@ -1,5 +1,14 @@ CHANGELOG +  0.16.0:+    - Add grid size and location support.+    - Derive `Stretch` for justified content+    - Add `AspectRatio`+    - Promote `not` to a type class+    - Render CSS refinements+    - Bugfixes & improved test suite+    Thanks to Leonard Monnier, Yoo Chung, Skyfold, qwbarch, David Fox+   0.15.0:     - Add `all` media type.     - Support `prefers-color-scheme` media feature.
clay.cabal view
@@ -1,5 +1,5 @@ Name:     clay-Version:  0.15.0+Version:  0.16.0 Synopsis: CSS preprocessor as embedded Haskell. Description:   Clay is a CSS preprocessor like LESS and Sass, but implemented as an embedded@@ -77,7 +77,7 @@     Clay.Transition    Build-Depends:-    base  >= 4.11 && < 4.20,+    base  >= 4.11 && < 4.22,     mtl   >= 1,     text  >= 0.11   GHC-Options: -Wall -Wcompat@@ -89,7 +89,7 @@   Build-Tools: hspec-discover   main-is: Spec.hs   Build-Depends:-    base                 >= 4.11  && < 4.20,+    base                 >= 4.11  && < 4.22,     mtl                  >= 1,     text                 >= 0.11,     hspec                >= 2.2.0,
src/Clay/Color.hs view
@@ -178,10 +178,10 @@ instance Val Color where   value clr =     case clr of-      Rgba r g b 1.0 -> Value $mconcat ["#",  p' r, p' g, p' b]-      Rgba r g b a   -> Value $mconcat ["rgba(", p r, ",", p g, ",", p b, ",", ah a, ")"]-      Hsla h s l 1.0 -> Value $mconcat ["hsl(",  p h, ",", f s, ",", f l,            ")"]-      Hsla h s l a   -> Value $mconcat ["hsla(", p h, ",", f s, ",", f l, ",", ah a, ")"]+      Rgba r g b 1.0 -> Value $ mconcat ["#",  p' r, p' g, p' b]+      Rgba r g b a   -> Value $ mconcat ["rgba(", p r, ",", p g, ",", p b, ",", ah a, ")"]+      Hsla h s l 1.0 -> Value $ mconcat ["hsl(",  p h, ",", f s, ",", f l,            ")"]+      Hsla h s l a   -> Value $ mconcat ["hsla(", p h, ",", f s, ",", f l, ",", ah a, ")"]       Other o        -> o     where p  = fromString . show           p' = fromString . printf "%02x"
src/Clay/Flexbox.hs view
@@ -109,7 +109,7 @@  newtype JustifyContentValue = JustifyContentValue Value   deriving (Val, Other, Inherit, Center, FlexEnd-          , FlexStart, SpaceAround, SpaceBetween, SpaceEvenly)+          , FlexStart, SpaceAround, SpaceBetween, SpaceEvenly, Stretch)  justifyContent :: JustifyContentValue -> Css justifyContent = key "justify-content"
src/Clay/Geometry.hs view
@@ -7,6 +7,12 @@ -- * Sizing. , width, height, minWidth, minHeight, maxWidth, maxHeight +-- ** Aspect ratio.+, AspectRatio+, aspectRatio+, (%)+, withFallback+ -- * Padding. , padding , paddingTop, paddingLeft, paddingRight, paddingBottom@@ -17,6 +23,9 @@ ) where +import qualified Data.Ratio as R+import Data.String (fromString)+import Clay.Common import Clay.Property import Clay.Stylesheet import Clay.Size@@ -42,6 +51,100 @@  ------------------------------------------------------------------------------- +-- | Represents an aspect ratio for use with 'aspectRatio'.+--+-- A fixed ratio can be formed from two integers:+--+-- >>> let _ = 4%3 :: AspectRatio+--+-- An aspect ratio can also be converted from a 'Rational':+--+-- >>> let _ = fromRational 0.5 :: AspectRatio+--+data AspectRatio = AspectRatio Rational+                 | AspectRatioValue Value+                 | AspectRatioWithFallback (AspectRatio, AspectRatio)++instance Auto AspectRatio where auto = AspectRatioValue auto+instance Inherit AspectRatio where inherit = AspectRatioValue inherit+instance Initial AspectRatio where initial = AspectRatioValue initial+instance Unset AspectRatio where unset = AspectRatioValue unset+instance Other AspectRatio where other = AspectRatioValue++-- | An 'AspectRatio' can be converted from an 'Integer',+-- but other operations are not supported.+instance Num AspectRatio where+  fromInteger = AspectRatio . toRational+  (+)    = error   "plus not implemented for AspectRatio"+  (*)    = error  "times not implemented for AspectRatio"+  abs    = error    "abs not implemented for AspectRatio"+  signum = error "signum not implemented for AspectRatio"+  negate = error "negate not implemented for AspectRatio"++-- | An 'AspectRatio' can be converted from a 'Rational',+-- but other operations are not supported.+instance Fractional AspectRatio where+  fromRational = AspectRatio+  recip  = error  "recip not implemented for AspectRatio"++instance Val AspectRatio where+  value (AspectRatioValue v) = v+  value (AspectRatio r) = v+    where v = fromString $ numerator <> "/" <> denominator :: Value+          numerator = show (R.numerator r)+          denominator = show (R.denominator r)+  value (AspectRatioWithFallback (a, b)) = value a <> " " <> value b++-- | Defines the width to height ratio of an element.+-- At least one of the width or height must be of automatic size,+-- otherwise the aspect ratio will be ignored.+--+-- It can be given a fixed ratio of the width to the height:+--+-- >>> renderWith compact [] $ aspectRatio (4%3)+-- "{aspect-ratio:4/3}"+--+-- It can also be the intrinsic aspect ratio for the element:+--+-- >>> renderWith compact [] $ aspectRatio auto+-- "{aspect-ratio:auto}"+--+-- It can be told to use the intrinsic aspect ratio for the element,+-- but to use a fixed ratio while it is unknown or if the element does not have one:+--+-- >>> renderWith compact [] $ aspectRatio $ auto `withFallback` (4%3)+-- "{aspect-ratio:auto 4/3}"+--+-- Corresponds to the+-- [@aspect-ratio@](https://developer.mozilla.org/en-US/docs/Web/CSS/aspect-ratio)+-- property in CSS.+aspectRatio :: AspectRatio -> Css+aspectRatio = key "aspect-ratio"++-- | The aspect ratio of the width to the height for use with 'aspectRatio'.+--+-- Note that this is /not/ the same @%@ operator from the "Data.Ratio" module,+-- although they do both semantically represent ratios.  The same symbol is used+-- to signify that the return value is a ratio.+(%) :: Integer -> Integer -> AspectRatio+(%) m n = fromRational $ (R.%) m n++-- The same as the normal % operator.+infixl 7 %++-- | Returns an aspect ratio specifying that the intrinsic aspect+-- ratio should be used, but when it is unknown or there is none,+-- a fixed ratio can be used as a fallback.+withFallback :: AspectRatio -> AspectRatio -> AspectRatio+withFallback x@(AspectRatioValue "auto") y@(AspectRatio _) =+  AspectRatioWithFallback (x, y)+withFallback x@(AspectRatio _) y@(AspectRatioValue "auto") =+  AspectRatioWithFallback (x, y)+withFallback _ _ =+  error "Arguments for aspectRatio . withFallback must be auto and a ratio in either order"++-------------------------------------------------------------------------------+ padding :: Size a -> Size a -> Size a -> Size a -> Css padding a b c d = key "padding" (a ! b ! c ! d) @@ -63,4 +166,3 @@ marginLeft    = key "margin-left" marginRight   = key "margin-right" marginBottom  = key "margin-bottom"-
src/Clay/Grid.hs view
@@ -1,7 +1,70 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE OverloadedStrings #-}--- | Partial implementation of <https://alligator.io/css/css-grid-layout-grid-areas grid area CSS API>.+{-# LANGUAGE ExtendedDefaultRules #-}+{-# OPTIONS_GHC -Wno-type-defaults #-}++-- | Partial implementation of+-- | <https://alligator.io/css/css-grid-layout-grid-areas grid area CSS API>.+module Clay.Grid+(+    -- * Grid+    --+    -- $gridIntro+    gridGap+  , gridTemplateColumns++    -- * Size and location+    --+    -- $sizeAndLocationIntro++    -- ** Data types and type classes+  , GridLine+  , ToGridLine+  , GridLines2+  , ToGridLines2+  , GridLines4+  , ToGridLines4+  , OneGridLine+  , TwoGridLines+  , ThreeGridLines+  , FourGridLines+  , CustomIdentGrid+  , customIdentToText+  , partialMkCustomIdentGrid+  , ToSpan++    -- ** Style properties+    --+    -- $invalidValues+  , gridArea+  , gridColumn+  , gridColumnStart+  , gridColumnEnd+  , gridRow+  , gridRowStart+  , gridRowEnd++    -- ** Keywords+  , (//)+  , span_+)+where++import qualified Clay.Common as Com+import           Clay.Property (Val, Value, noCommas, value)+import           Clay.Size (Size)+import           Clay.Stylesheet (Css, key)+import           Data.Char (isNumber)+import           Data.Text (Text)+import qualified Data.Text as T+import           Prelude++-- $gridIntro+-- @grid-gap@ and @grid-template@ CSS properties. ----- For instance, you want to generate the following CSS:+-- === Example+-- For the below CSS code: -- -- @ -- .grid1 {@@ -24,7 +87,7 @@ -- } -- @ ----- The corresponding clay code:+-- The corresponding clay code is: -- -- @ --  ".grid1" ? do@@ -39,16 +102,7 @@ --    gridGap $ rem 1 --    width maxContent -- @-module Clay.Grid-( gridGap-, gridTemplateColumns-)-where -import Clay.Property-import Clay.Size-import Clay.Stylesheet- -- | Property sets the gaps (gutters) between rows and columns. gridGap :: Size a -> Css gridGap = key "grid-gap"@@ -56,3 +110,666 @@ -- | Property defines the line names and track sizing functions of the grid columns. gridTemplateColumns :: [Size a] -> Css gridTemplateColumns = key "grid-template-columns" . noCommas++-- $sizeAndLocationIntro+--+-- == CSS documentation+-- The below functions are based on+-- [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/CSS)+-- CSS documentation.+--+-- === __Naming note__+-- In this documentation, as the functions are polymorphic we sometimes+-- refer to the CSS types as used in the+-- [mdm web docs_](https://developer.mozilla.org/en-US/docs/Web/CSS)+-- rather than the Haskell types.+-- For example, @grid-line@ is used instead of 'GridLine' as a the argument+-- might be provided as a 'GridLine' but also as an 'Integer', 'String', etc.+--+-- == Pragma+-- #pragma#+-- If you want to avoid specifying the types of the arguments, enable+-- the @ExtendedDefaultRules@ GHC language pragma as well as the+-- @-Wno-type-defaults@ GHC option to avoid compilation warnings.+--+-- @+-- {-# LANGUAGE ExtendedDefaultRules #-}+-- {-# OPTIONS_GHC -Wno-type-defaults #-}+-- @+--+-- === __Examples__+-- With the above enabled, you can write:+--+-- >> gridRowStart 2+--+-- >> gridRowStart "somegridarea"+--+-- If you do not enable those, then you must write:+--+-- >> gridRowStart (2 :: Integer)+--+-- >> gridRowStart ("somegridarea" :: String)+--+-- === __Note__+-- If you decide to enable the above, it is advisable to have your Clay+-- CSS code in its own module, so the behaviour of the rest of your code+-- is not affected.+--+-- == Examples+-- Examples are provided through the documentation for the various functions.+-- Further examples can be found in the source code of the test suite+-- in the GridSpec.hs module.++-- | A @grid-line@ value.+--+-- A @grid-line@ value specifies a size and location in a grid.+--+-- === __Note__+-- To know more about @grid-line@ value, see for example the documentation of+-- the [grid-row-start](https://developer.mozilla.org/en-US/docs/Web/CSS/grid-row-start)+-- CSS property.+data GridLine++  -- | 'Integer' value.+  --+  -- __NOTE:__ 'Integer' value of 0 is invalid.+  = Coordinate Integer++  -- | @custom-ident@ with an optional 'Integer' value.+  --+  -- __NOTE:__ 'Integer' value of 0 is invalid.+  | GridLineCustomIdent CustomIdentGrid (Maybe Integer)++  -- | @span@ CSS keyword with an optional @custom-ident@+  -- | and/or 'Integer' value.+  --+  -- __NOTE:__ negative 'Integer' or 0 are invalid.+  | Span (Maybe CustomIdentGrid) (Maybe Integer)++  -- | Other grid line values: @auto@, @inherit@, @initial@, @unset@.+  | OtherGridLine Value+  deriving (Eq, Show)++class ToGridLine a where+  -- | Convert the provided type to a 'GridLine'.+  toGridLine :: a -> GridLine++instance ToGridLine GridLine where+  toGridLine = id++instance ToGridLine Integer where+  -- | __NOTE:__ 'Integer' value of 0 is invalid.+  toGridLine = Coordinate++-- | @custom-ident@ value.+instance ToGridLine CustomIdentGrid where+  toGridLine x = GridLineCustomIdent x Nothing++-- | @custom-ident@ value.+instance ToGridLine String where+  toGridLine = toGridLine . partialMkCustomIdentGrid . T.pack++-- | Both @custom-ident@ and `Integer` values, provided as a pair.+--+-- __NOTE:__ 'Integer' value of 0 is invalid.+instance ToGridLine (CustomIdentGrid, Integer) where+  toGridLine (x, y) = GridLineCustomIdent x (Just y)++-- | Both @custom-ident@ and `Integer` values, provided as a pair.+--+-- __NOTE:__ 'Integer' value of 0 is invalid.+instance ToGridLine (String, Integer) where+  toGridLine (x, y) = toGridLine (partialMkCustomIdentGrid $ T.pack x, y)++-- | One or two @grid-line@ values.+data GridLines2+    -- | One @grid-line@ value.+  = One2 OneGridLine+    -- | Two @grid-line@ values.+  | Two2 TwoGridLines++class ToGridLines2 a where++  -- | Convert the provided type to 'GridLines2' (one or two @grid-line@ values).+  toGridLines2 :: a -> GridLines2++-- | One @grid-line@ value.+instance ToGridLines2 GridLine where+  toGridLines2 = One2 . OneGridLine++-- | One @grid-line@ value.+instance ToGridLines2 OneGridLine where+  toGridLines2 = One2++-- | Two @grid-line@ values.+instance ToGridLines2 TwoGridLines where+  toGridLines2 = Two2++-- | One or two @grid-line@ values.+instance ToGridLines2 GridLines2 where+  toGridLines2 = id++-- | One 'Integer' value.+--+-- __NOTE:__ 'Integer' value of 0 is invalid.+instance ToGridLines2 Integer where+  toGridLines2 = toGridLines2 . toGridLine++-- | One @custom-ident@ value.+instance ToGridLines2 CustomIdentGrid where+  toGridLines2 = toGridLines2 . toGridLine++-- | One @custom-ident@ value.+instance ToGridLines2 String where+  toGridLines2 = toGridLines2 . toGridLine++-- | One time both a @custom-ident@ and 'Integer' values, provided as a pair.+--+-- __NOTE:__ 'Integer' value of 0 is invalid.+instance ToGridLines2 (CustomIdentGrid, Integer) where+  toGridLines2 = toGridLines2 . toGridLine++-- | One time both a @custom-ident@ and 'Integer' values, provided as a pair.+--+-- __NOTE:__ 'Integer' value of 0 is invalid.+instance ToGridLines2 (String, Integer) where+  toGridLines2 = toGridLines2 . toGridLine++-- | One, two, three or four @grid-line@ values.+data GridLines4++    -- | One @grid-line@ value.+  = One4 OneGridLine++    -- | Two @grid-line@ values.+  | Two4 TwoGridLines++    -- | Three @grid-line@ values.+  | Three4 ThreeGridLines++    -- | Four @grid-line@ values.+  | Four4 FourGridLines++class ToGridLines4 a where+  -- | Convert the provided type to 'GridLines4'+  -- (one, two, three or four @grid-line@ values).+  toGridLines4 :: a -> GridLines4++-- | One @grid-line@ value.+instance ToGridLines4 GridLine where+  toGridLines4 = One4 . OneGridLine++-- | One @grid-line@ value.+instance ToGridLines4 OneGridLine where+  toGridLines4 = One4++-- | Two @grid-line@ values.+instance ToGridLines4 TwoGridLines where+  toGridLines4 = Two4++-- | Three @grid-line@ values.+instance ToGridLines4 ThreeGridLines where+  toGridLines4 = Three4++-- | Four @grid-line@ values.+instance ToGridLines4 FourGridLines where+  toGridLines4 = Four4++-- | One, two, three or four @grid-line@ values.+instance ToGridLines4 GridLines4 where+  toGridLines4 = id++-- | One 'Integer' value.+--+-- __NOTE:__ 'Integer' value of 0 is invalid.+instance ToGridLines4 Integer where+  toGridLines4 = toGridLines4 . toGridLine++-- | One @custom-ident@ value.+instance ToGridLines4 CustomIdentGrid where+  toGridLines4 = toGridLines4 . toGridLine++-- | One @custom-ident@ value.+instance ToGridLines4 String where+  toGridLines4 = toGridLines4 . toGridLine++-- | One time both a @custom-ident@ and 'Integer' values, provided as a pair.+--+-- __NOTE:__ 'Integer' value of 0 is invalid.+instance ToGridLines4 (CustomIdentGrid, Integer) where+  toGridLines4 = toGridLines4 . toGridLine++-- | One time both a @custom-ident@ and 'Integer' values, provided as a pair.+--+-- __NOTE:__ 'Integer' value of 0 is invalid.+instance ToGridLines4 (String, Integer) where+  toGridLines4 = toGridLines4 . toGridLine++-- | One 'GridLine' value.+newtype OneGridLine = OneGridLine GridLine++-- | Two 'GridLine' values.+data TwoGridLines = TwoGridLines GridLine GridLine++-- | Three 'GridLine' values.+data ThreeGridLines = ThreeGridLines GridLine GridLine GridLine++-- | Four 'GridLine' values.+data FourGridLines = FourGridLines GridLine GridLine GridLine GridLine++-- | CSS @custom-ident@.+--+-- The data constructor is not exported. Use the 'partialMkCustomIdentGrid'+-- smart constructor to create a 'CustomIdentGrid'.+--+-- === __Note__+-- In CSS, some values for @custom-ident@ are invalid depending on the CSS+-- property the @custom-ident@ is used with.+-- Consequently, the @custom-ident@ is only for CSS grid.+newtype CustomIdentGrid = CustomIdentGrid Text deriving (Eq, Ord, Read, Show)++-- | Convert a 'CustomIdentGrid' to 'Text'.+--+-- === __Note__+-- The function is defined on its own as the newtype constructor+-- of 'CustomIdentGrid'is not exported.+customIdentToText :: CustomIdentGrid -> Text+customIdentToText (CustomIdentGrid x) = x++-- | Create a 'CustomIdentGrid'.+--+-- __WARNING__: this function is partial. An error will be raised if:+--+-- * "span" is provided as a value (this is a reserved keyword in this context)+-- * a number is provided as first character+-- * __If__ a hyphen (-) is provided as first character:+--+--     ** a number is provided as second character+--     ** a hyphen (-) is provided as second character.+--+-- === __Note__+-- The above is a partial implementation of the CSS custom-ident naming rules.+-- If you stick to the following charset @[a-zA-z0-9-_]@ the checks will be effective+-- and your CSS custom-ident will be a valid one.+-- On the other hand, the following will not be checked:+--+-- * character escaping (for example @\?@) or unicode+-- * characters provided as hexadecimal number (for example @\0x03BB@)+-- * characters outside of the above charset.+--+-- More information regarding this topic can be found on+-- [mdm web docs_](https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident)+partialMkCustomIdentGrid :: Text -> CustomIdentGrid+partialMkCustomIdentGrid "span" = error "Custom-ident for a grid property cannot be named span"+partialMkCustomIdentGrid txt = checkText+  where+    checkText = checkHead (fst unconsTxt)++    checkHead :: Char -> CustomIdentGrid+    checkHead c+      | isNumber c = error "Custom-ident cannot start with a number"+      | c == '-'   = checkSecond second+      | otherwise  = CustomIdentGrid txt++    checkSecond (Just s)+      | s == '-' =+          error "Custom-ident cannot start with two hyphens"+      | isNumber s =+          error "Custom-ident cannot start with a hyphen followed by a number"+      | otherwise = CustomIdentGrid txt+    checkSecond Nothing = CustomIdentGrid txt++    unconsTxt = case T.uncons txt of+      Nothing -> error "Custom-ident cannot be empty"+      Just (f, r) -> (f, r)++    second :: Maybe Char+    second = fst <$> T.uncons (snd unconsTxt)++-- $invalidValues+--+-- #partial#+-- The below functions are partial. They will raise an error if+-- provided with a @grid-line@ value which is:+--+-- * an 'Integer' value of 0+-- * a pair with an 'Integer' component of value 0+-- * a 'span_' function provided with an 'Integer' value of 0 or negative+-- * a 'span_' function provided with a pair value with+-- an 'Integer' component of 0 or negative.+-- * an invalid @custom-ident@ value, see 'partialMkCustomIdentGrid'.++-- | Property shorthand specifies a grid item's size and location+-- within a grid.+--+-- One to four @grid-line@ values can be specified.+-- Grid-line values must be separated by a '(//)' operator.+--+-- __WARNING:__ this function is partial. See above "Clay.Grid#partial".+--+-- ==== __Examples__+--+-- The below examples assume that the @ExtendedDefaultRules@ GHC language+-- pragma is enabled. See above "Clay.Grid#pragma".+--+-- > gridArea (auto :: GridLine)+--+-- > gridArea "somegridarea"+--+-- > gridArea $ ("somegridarea", 4) // ("someothergridarea", 2)+--+-- > gridArea $ 1 // 3 // 4+gridArea :: ToGridLines4 a => a -> Css+gridArea x = key "grid-area" (partialToGridLines4 x)++-- | Property shorthand specifies a grid item's size and location+-- within a grid column.+--+-- __WARNING:__ this function is partial. See above "Clay.Grid#partial".+--+-- ==== __Examples__+--+-- The below examples assume that the @ExtendedDefaultRules@ GHC language+-- pragma is enabled. See above "Clay.Grid#pragma".+--+-- > gridColumn (auto :: GridLine)+--+-- > gridColumn $ span_ 3+--+-- > gridColumn $ span_ ("somegridarea", 5)+--+-- > gridColumn $ span_ 3 // 6+gridColumn :: ToGridLines2 a => a -> Css+gridColumn x = key "grid-column" (partialToGridLines2 x)++-- | Property specifies a grid item's start position within the grid column.+--+-- __WARNING:__ this function is partial. See above "Clay.Grid#partial".+--+-- ==== __Examples__+--+-- The below examples assume that the @ExtendedDefaultRules@ GHC language+-- pragma is enabled. See above "Clay.Grid#pragma".+--+-- > gridColumnStart (inherit :: GridLine)+--+-- > gridColumnStart 2+--+-- > gridColumnStart ("somegridarea", 4)+--+-- > gridColumnStart $ span_ ("somegridarea", 5)+gridColumnStart :: ToGridLine a => a -> Css+gridColumnStart x = key "grid-column-start" (partialToGridLine x)++-- | Property specifies a grid item's end position within the grid column.+--+-- __WARNING:__ this function is partial. See above "Clay.Grid#partial".+--+-- ==== __Examples__+--+-- The below examples assume that the @ExtendedDefaultRules@ GHC language+-- pragma is enabled. See above "Clay.Grid#pragma".+--+-- > gridColumnEnd (initial :: GridLine)+--+-- > gridColumnEnd 2+--+-- > gridColumnEnd "somegridarea"+--+-- > gridColumnEnd $ span_ "somegridarea"+gridColumnEnd :: ToGridLine a => a -> Css+gridColumnEnd x = key "grid-column-end" (partialToGridLine x)++-- | Property shorthand specifies a grid item's size and location+-- within a grid row.+--+-- One or two @grid-line@ values can be specified.+-- @grid-line@ values must be separated by a '(//)' operator.+--+-- __WARNING:__ this function is partial. See above "Clay.Grid#partial".+--+-- ==== __Examples__+--+-- The below examples assume that the @ExtendedDefaultRules@ GHC language+-- pragma is enabled. See above "Clay.Grid#pragma".+--+-- > gridRow (unset :: GridLine)+--+-- > gridRow $ span_ 3+--+-- > gridRow $ span_ 3 // 6+--+-- > gridRow $ span_ ("somegridarea", 5) // span_ 2+gridRow :: ToGridLines2 a => a -> Css+gridRow x = key "grid-row" (partialToGridLines2 x)++-- | Property specifies a grid item's start position within the grid row.+--+-- __WARNING:__ this function is partial. See above "Clay.Grid#partial".+--+-- ==== __Examples__+--+-- The below examples assume that the @ExtendedDefaultRules@ GHC language+-- pragma is enabled. See above "Clay.Grid#pragma".+--+-- > gridRowStart (initial :: GridLine)+--+-- > gridRowStart (-2)+--+-- > gridRowStart $ span_ "somegridarea"+--+-- > gridRowStart "somegridarea"+gridRowStart :: ToGridLine a => a -> Css+gridRowStart x = key "grid-row-start" (partialToGridLine x)++-- | Property specifies a grid item's end position within the grid row.+--+-- __WARNING:__ this function is partial. See above "Clay.Grid#partial".+--+-- ==== __Examples__+--+-- The below examples assume that the @ExtendedDefaultRules@ GHC language+-- pragma is enabled. See above "Clay.Grid#pragma".+--+-- > gridRowEnd (auto :: GridLine)+--+-- > gridRowEnd (-2)+--+-- > gridRowEnd ("somegridarea", 4)+--+-- > gridRowEnd $ span_ 3+gridRowEnd :: ToGridLine a => a -> Css+gridRowEnd x = key "grid-row-end" (partialToGridLine x)++class Slash a r | a -> r where+  -- | `/` CSS operator.+  -- Separates @grid-line@ values.+  (//) :: ToGridLine b => a -> b -> r++instance Slash GridLine TwoGridLines where+  x // y = TwoGridLines x (toGridLine y)++instance Slash Integer TwoGridLines where+  x // y = TwoGridLines (toGridLine x) (toGridLine y)++instance Slash CustomIdentGrid TwoGridLines where+  x // y = TwoGridLines (toGridLine x) (toGridLine y)++instance Slash String TwoGridLines where+  x // y = TwoGridLines (toGridLine x) (toGridLine y)++instance Slash (CustomIdentGrid, Integer) TwoGridLines where+  x // y = TwoGridLines (toGridLine x) (toGridLine y)++instance Slash (String, Integer) TwoGridLines where+  x // y = TwoGridLines (toGridLine x) (toGridLine y)++instance Slash TwoGridLines ThreeGridLines where+  (TwoGridLines xx xy) // y = ThreeGridLines xx xy (toGridLine y)++instance Slash ThreeGridLines FourGridLines where+  (ThreeGridLines xx xy xz) // y = FourGridLines xx xy xz (toGridLine y)++class ToSpan a where++  -- | @span@ CSS keyword, contributes to the grid item's placement.+  span_ :: a -> GridLine++-- | Contributes the nth grid line to the grid item's placement.+--+-- __NOTE:__ negative 'Integer' or 0 values are invalid.+instance ToSpan Integer where+  span_ x = Span Nothing (Just x)++-- | One line from the provided name is counted.+instance ToSpan String where+  span_ x = Span (Just . partialMkCustomIdentGrid $ T.pack x) Nothing++-- | Nth lines from the provided name are counted.+--+-- __NOTE:__ negative 'Integer' or 0 values are invalid.+instance ToSpan (String, Integer) where+  span_ (x, y) = Span (Just . partialMkCustomIdentGrid $ T.pack x) (Just y)++-- | Keyword indicating that the property contributes nothing+-- to the grid item's placement.+instance Com.Auto GridLine where+  auto = OtherGridLine $ value ("auto" :: Text)++-- | Keyword `inherit` applied to a 'GridLine'.+instance Com.Inherit GridLine where+  inherit = OtherGridLine $ value ("inherit" :: Text)++-- | Keyword `initial` applied to a 'GridLine'.+instance Com.Initial GridLine where+  initial = OtherGridLine $ value ("initial" :: Text)++-- | Keyword `unset` applied to a 'GridLine'.+instance Com.Unset GridLine where+  unset = OtherGridLine $ value ("unset" :: Text)++-- | Convertion of 'GridLine' to 'Clay.Property.Value'.+instance Val GridLine where+  value (OtherGridLine val)       = val+  value (Coordinate x)            = value x+  value (GridLineCustomIdent x y) =+    value $ customIdentToText x <> foldMap ((" " <>) . tshow) y+  value (Span x y) =+    value $ "span" <> foldMap ((" " <>)+    . customIdentToText) x <> foldMap ((" " <>) . tshow) y++instance Val OneGridLine where+  value (OneGridLine x) = value x++instance Val TwoGridLines where+  value (TwoGridLines x y) =+    value x <> value (" / " :: Text) <> value y++instance Val ThreeGridLines where+  value (ThreeGridLines x y z) =+       value x+    <> value (" / " :: Text) <> value y+    <> value (" / " :: Text) <> value z++instance Val FourGridLines where+  value (FourGridLines xx xy xz yx) =+       value xx+    <> value (" / " :: Text) <> value xy+    <> value (" / " :: Text) <> value xz+    <> value (" / " :: Text) <> value yx++instance Val GridLines2 where+  value (One2 x) = value x+  value (Two2 x) = value x++instance Val GridLines4 where+  value (One4 x)   = value x+  value (Two4 x)   = value x+  value (Three4 x) = value x+  value (Four4 x)  = value x++-- | Private partial function checking a 'GridLine'.+--+-- An error is raised when:+-- - An 'Integer' value of 0 is provided.+-- - A negative 'Integer' value is provided for a 'Span' constructor.+--+-- Otherwise, the initially provided 'GridLine' value is returned.+partialCheckGridLine :: GridLine -> GridLine+partialCheckGridLine gridLine = case gridLine of+  Coordinate 0                   -> errorValue 0+  GridLineCustomIdent _ (Just 0) -> errorValue 0+  s@(Span _ (Just n))            -> if n < 1+                                    then errorValue n+                                    else s+  _                              -> gridLine+  where+    errorValue n = error ("Value " ++ show n ++ " is invalid")++-- | Private partial function checking 'OneGridLine'.+--+-- An error is raised if an invalid value is found, see 'partialCheckGridLine'.+partialCheckOneGridLine :: OneGridLine -> OneGridLine+partialCheckOneGridLine (OneGridLine gridLine) =+  OneGridLine (partialCheckGridLine gridLine)++-- | Private partial function checking 'TwoGridLines'.+--+-- An error is raised if an invalid value is found, see 'partialCheckGridLine'.+partialCheckTwoGridLines :: TwoGridLines -> TwoGridLines+partialCheckTwoGridLines (TwoGridLines gridLine1 gridLine2) =+  TwoGridLines (partialCheckGridLine gridLine1) (partialCheckGridLine gridLine2)++-- | Private partial function checking 'ThreeGridLines'.+--+-- An error is raised if an invalid value is found, see 'partialCheckGridLine'.+partialCheckThreeGridLines :: ThreeGridLines -> ThreeGridLines+partialCheckThreeGridLines (ThreeGridLines gridLine1 gridLine2 gridLine3) =+  ThreeGridLines+    (partialCheckGridLine gridLine1)+    (partialCheckGridLine gridLine2)+    (partialCheckGridLine gridLine3)++-- | Private partial function checking 'FourGridLines'.+--+-- An error is raised if an invalid value is found, see 'partialCheckGridLine'.+partialCheckFourGridLines :: FourGridLines -> FourGridLines+partialCheckFourGridLines+  (FourGridLines gridLine1 gridLine2 gridLine3 gridLine4) =+    FourGridLines+      (partialCheckGridLine gridLine1)+      (partialCheckGridLine gridLine2)+      (partialCheckGridLine gridLine3)+      (partialCheckGridLine gridLine4)++-- | Private partial function converting its argument to 'GridLine'.+--+-- An error is raised if an invalid value is found, see 'partialCheckGridLine'.+partialToGridLine :: ToGridLine a => a -> GridLine+partialToGridLine = partialCheckGridLine . toGridLine++-- | Private partial function converting its argument to 'GridLines2'.+--+-- An error is raised if an invalid value is found, see 'partialCheckGridLine'.+partialToGridLines2 :: ToGridLines2 a => a -> GridLines2+partialToGridLines2 x = partialGridLine' gridLines+  where+    gridLines = toGridLines2 x+    partialGridLine' (One2 gl) = One2 (partialCheckOneGridLine gl)+    partialGridLine' (Two2 gl) = Two2 (partialCheckTwoGridLines gl)++-- | Private partial function converting its argument to 'GridLines4'.+--+-- An error is raised if an invalid value is found, see 'partialCheckGridLine'.+partialToGridLines4 :: ToGridLines4 a => a -> GridLines4+partialToGridLines4 x = partialGridLine' gridLines+  where+    gridLines = toGridLines4 x+    partialGridLine' (One4 gl)   = One4 (partialCheckOneGridLine gl)+    partialGridLine' (Two4 gl)   = Two4 (partialCheckTwoGridLines gl)+    partialGridLine' (Three4 gl) = Three4 (partialCheckThreeGridLines gl)+    partialGridLine' (Four4 gl)  = Four4 (partialCheckFourGridLines gl)++-- | Private utility function to show 'Text' instead of 'String'.+tshow :: Show a => a -> Text+tshow = T.pack . show
src/Clay/Pseudo.hs view
@@ -1,9 +1,11 @@ {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE FlexibleInstances #-} module Clay.Pseudo where  import Data.Text (Text) -import Clay.Render (renderSelector)+import Clay.Render (renderSelector, renderRefinement) import Clay.Selector  import qualified Data.Text.Lazy as Lazy@@ -64,5 +66,19 @@ nthLastOfType n = func "nth-last-of-type" [n] nthOfType     n = func "nth-of-type"      [n] -not :: Selector -> Refinement-not r = func "not" [Lazy.toStrict (renderSelector r)]+-- | The 'not' pseudo selector can be applied to both a 'Refinement'+--+-- > input # not checked+-- +-- or a 'Selector'+--+-- > not p++class Not a where+  not :: a -> Refinement++instance Not Selector where+  not r = func "not" [Lazy.toStrict (renderSelector r)]++instance Not Refinement where+  not r = func "not" (Lazy.toStrict <$> renderRefinement r)
src/Clay/Render.hs view
@@ -8,6 +8,7 @@ , putCss , renderWith , renderSelector+, renderRefinement , withBanner ) where@@ -119,6 +120,10 @@  renderSelector :: Selector -> Lazy.Text renderSelector = toLazyText . selector compact++-- | Render a CSS `Refinement`.+renderRefinement :: Refinement -> [Lazy.Text]+renderRefinement r = toLazyText . predicate <$> unFilter r  -------------------------------------------------------------------------------