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 +9/−0
- clay.cabal +3/−3
- src/Clay/Color.hs +4/−4
- src/Clay/Flexbox.hs +1/−1
- src/Clay/Geometry.hs +103/−1
- src/Clay/Grid.hs +729/−12
- src/Clay/Pseudo.hs +19/−3
- src/Clay/Render.hs +5/−0
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 -------------------------------------------------------------------------------