packages feed

clay 0.12.2 → 0.12.3

raw patch · 11 files changed

+338/−59 lines, 11 filesdep ~basePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: base

API changes (from Hackage documentation)

- Clay.Property: intersperse :: Monoid a => a -> [a] -> a
- Clay.Selector: filterFromText :: Text -> Refinement
- Clay.Selector: text :: Text -> Selector
+ Clay: commenting :: CommentText -> Css -> Css
+ Clay: important :: Css -> Css
+ Clay: infixl 3 `commenting`
+ Clay.Box: boxShadow' :: Size a -> Size a -> Size a -> Color -> Css
+ Clay.Box: bsColor :: Color -> BoxShadow -> BoxShadow
+ Clay.Box: bsInset :: BoxShadow -> BoxShadow
+ Clay.Box: infixr 9 `bsColor`
+ Clay.Box: instance Clay.Common.Inherit Clay.Box.BoxShadow
+ Clay.Box: instance Clay.Common.Initial Clay.Box.BoxShadow
+ Clay.Box: instance Clay.Common.None Clay.Box.BoxShadow
+ Clay.Box: instance Clay.Common.Other Clay.Box.BoxShadow
+ Clay.Box: instance Clay.Common.Unset Clay.Box.BoxShadow
+ Clay.Box: instance Clay.Property.Val Clay.Box.BoxShadow
+ Clay.Box: shadow :: Size a -> Size a -> BoxShadow
+ Clay.Box: shadowWithBlur :: Size a -> Size a -> Size a -> BoxShadow
+ Clay.Box: shadowWithSpread :: Size a -> Size a -> Size a -> Size a -> BoxShadow
+ Clay.Comments: addComment :: CommentText -> Rule -> Rule
+ Clay.Comments: commenting :: CommentText -> Css -> Css
+ Clay.Comments: infixl 3 `commenting`
+ Clay.FontFace: WOFF2 :: FontFaceFormat
+ Clay.Property: instance Clay.Property.Val a => Clay.Property.Val (Data.List.NonEmpty.NonEmpty a)
+ Clay.Property: intercalate :: Monoid a => a -> [a] -> a
+ Clay.Render: [comments] :: Config -> Bool
+ Clay.Render: instance GHC.Show.Show Clay.Render.Representation
+ Clay.Render: withBanner :: Text -> Text
+ Clay.Selector: instance GHC.Base.Monoid Clay.Selector.Refinement
+ Clay.Selector: refinementFromText :: Text -> Refinement
+ Clay.Selector: selectorFromText :: Text -> Selector
+ Clay.Stylesheet: Comment :: CommentText -> Modifier
+ Clay.Stylesheet: CommentText :: Text -> CommentText
+ Clay.Stylesheet: Important :: Modifier
+ Clay.Stylesheet: [unCommentText] :: CommentText -> Text
+ Clay.Stylesheet: _Comment :: Modifier -> Maybe CommentText
+ Clay.Stylesheet: _Important :: Modifier -> Maybe Text
+ Clay.Stylesheet: addImportant :: Rule -> Rule
+ Clay.Stylesheet: data Modifier
+ Clay.Stylesheet: important :: Css -> Css
+ Clay.Stylesheet: instance Data.Semigroup.Semigroup Clay.Stylesheet.CommentText
+ Clay.Stylesheet: instance Data.String.IsString Clay.Stylesheet.CommentText
+ Clay.Stylesheet: instance GHC.Base.Monoid Clay.Stylesheet.CommentText
+ Clay.Stylesheet: instance GHC.Show.Show Clay.Stylesheet.CommentText
+ Clay.Stylesheet: instance GHC.Show.Show Clay.Stylesheet.Modifier
+ Clay.Stylesheet: newtype CommentText
+ Clay.Text: instance Clay.Common.Initial Clay.Text.TextIndent
+ Clay.Text: instance Clay.Common.Unset Clay.Text.TextIndent
- Clay.Background: class Val a => Background a where background = key "background"
+ Clay.Background: class Val a => Background a
- Clay.Background: class Val a => Loc a where location = Location . value
+ Clay.Background: class Val a => Loc a
- Clay.Box: boxShadow :: Size a -> Size a -> Size a -> Color -> Css
+ Clay.Box: boxShadow :: NonEmpty BoxShadow -> Css
- Clay.Display: class (Val a) => Cursor a where cursor = key "cursor"
+ Clay.Display: class (Val a) => Cursor a
- Clay.Display: class (Val a) => VerticalAlign a where verticalAlign = key "vertical-align"
+ Clay.Display: class (Val a) => VerticalAlign a
- Clay.Font: class Val a => Font a where font = key "font"
+ Clay.Font: class Val a => Font a
- Clay.Mask: class Val a => Mask a where mask = pkey "mask"
+ Clay.Mask: class Val a => Mask a
- Clay.Pseudo: not :: Text -> Refinement
+ Clay.Pseudo: not :: Selector -> Refinement
- Clay.Render: Config :: Builder -> Builder -> Builder -> Builder -> Builder -> Bool -> Bool -> Bool -> Bool -> Config
+ Clay.Render: Config :: Builder -> Builder -> Builder -> Builder -> Builder -> Bool -> Bool -> Bool -> Bool -> Bool -> Config
- Clay.Stylesheet: Property :: (Key ()) -> Value -> Rule
+ Clay.Stylesheet: Property :: [Modifier] -> (Key ()) -> Value -> Rule
- Clay.Text: eachLine :: TextIndent
+ Clay.Text: eachLine :: TextIndent -> TextIndent
- Clay.Text: hanging :: TextIndent
+ Clay.Text: hanging :: TextIndent -> TextIndent

Files

clay.cabal view
@@ -1,5 +1,5 @@ Name:     clay-Version:  0.12.2+Version:  0.12.3 Synopsis: CSS preprocessor as embedded Haskell. Description:   Clay is a CSS preprocessor like LESS and Sass, but implemented as an embedded@@ -43,6 +43,7 @@     Clay.Border     Clay.Box     Clay.Color+    Clay.Comments     Clay.Common     Clay.Dynamic     Clay.Display
src/Clay.hs view
@@ -22,6 +22,10 @@  , (-:) +-- ** Comments+-- $comments+, commenting+ -- * The selector language.  , Selector@@ -69,8 +73,12 @@  , fontFace --- * Import other CSS files+-- * !important +, important++-- * Import other CSS files+ , importUrl  -- * Pseudo elements and classes.@@ -138,6 +146,7 @@ import Clay.Box import Clay.Color import Clay.Time+import Clay.Comments (commenting) import Clay.Common import Clay.Display    hiding (table) import Clay.Dynamic@@ -160,3 +169,19 @@ -- Because a large part of the names export by "Clay.Media" clash with names -- export by other modules we don't re-export it here and recommend you to -- import the module qualified.++-- $comments+--+-- It is occasionally useful to output comments in the generated css.+-- 'commenting' appends comments (surrounded by '@ /* @' and '@ */@') to the+-- values of the supplied 'Css' as+--+-- > key: value /* comment */;+--+-- Placing the comments before the semicolon ensures they are obviously+-- grouped with the preceding value when rendered compactly.+--+-- Note that /every/ generated line in the generated content will feature the+-- comment. +--+-- An empty comment generates '@/*  */@'.
src/Clay/Box.hs view
@@ -3,7 +3,17 @@ ( BoxType , paddingBox, borderBox, contentBox , boxSizing+-- * @box-shadow@+-- $box-shadow , boxShadow+, shadow+, shadowWithBlur+, shadowWithSpread+, bsInset+, bsColor+-- ** Deprecated+-- $box-shadow-deprecated+, boxShadow' , boxShadowWithSpread , boxShadows , insetBoxShadow@@ -11,6 +21,7 @@ where  import Data.Monoid+import Data.List.NonEmpty (NonEmpty)  import Clay.Color import Clay.Common@@ -37,17 +48,127 @@  ------------------------------------------------------------------------------- -boxShadow :: Size a -> Size a -> Size a -> Color -> Css-boxShadow x y w c = prefixed (browsers <> "box-shadow") (x ! y ! w ! c)+-- $box-shadow+--+-- === Formal argument syntax+--+-- > none | <shadow>#+-- > where +-- > <shadow> = inset? && <length>{2,4} && <color>?+-- > +-- > where +-- > <color> = <rgb()> | <rgba()> | <hsl()> | <hsla()> | <hex-color> | <named-color> | currentcolor | <deprecated-system-color>+-- > +-- > where +-- > <rgb()> = rgb( [ [ <percentage>{3} | <number>{3} ] [ / <alpha-value> ]? ] | [ [ <percentage>#{3} | <number>#{3} ] , <alpha-value>? ] )+-- > <rgba()> = rgba( [ [ <percentage>{3} | <number>{3} ] [ / <alpha-value> ]? ] | [ [ <percentage>#{3} | <number>#{3} ] , <alpha-value>? ] )+-- > <hsl()> = hsl( [ <hue> <percentage> <percentage> [ / <alpha-value> ]? ] | [ <hue>, <percentage>, <percentage>, <alpha-value>? ] )+-- > <hsla()> = hsla( [ <hue> <percentage> <percentage> [ / <alpha-value> ]? ] | [ <hue>, <percentage>, <percentage>, <alpha-value>? ] )+-- > +-- > where +-- > <alpha-value> = <number> | <percentage>+-- > <hue> = <number> | <angle> +newtype BoxShadow = BoxShadow Value+  deriving (Val, Inherit, Initial, Unset, None, Other)++-- | This function will usually take a singleton list, but requiring a (non-empty)+-- list prevents accidentally applying the modifiers ('bsInset', 'bsColor')+-- incorrectly.+--+-- 'pure' (from "Control.Applicative") creates a singleton list.+--+-- > boxShadow . pure $ none+-- > boxShadow . pure $ shadow (px 1) (px 1)+--+-- Use with @{-# LANGUAGE OverloadedLists #-}@ for the simplest list syntax.+--+-- > boxShadow [none]+-- > boxShadow [shadow (px 1) (px 1)]+--+-- This is recommended for supplying multiple 'BoxShadow' values.+--+-- > boxShadow [shadowWithBlur (em 2) (em 1), bsInset . bsColor red $ shadow (px 1) (px 2)]+boxShadow :: NonEmpty BoxShadow -> Css+boxShadow = prefixed (browsers <> "box-shadow") . value++shadow+  :: Size a -- ^ Horizontal offset+  -> Size a -- ^ Vertical offset+  -> BoxShadow+shadow x y = BoxShadow . value $ (x ! y)++shadowWithBlur+  :: Size a -- ^ Horizontal offset+  -> Size a -- ^ Vertical offset+  -> Size a -- ^ Blur radius+  -> BoxShadow+shadowWithBlur x y w = BoxShadow . value $ (x ! y ! w)++-- | While this function is the correct type to work with the 'sym', 'sym2'+-- or 'sym3' functions, such applications are unlikely to be meaningful.+shadowWithSpread+  :: Size a -- ^ Horizontal offset+  -> Size a -- ^ Vertical offset+  -> Size a -- ^ Blur radius+  -> Size a -- ^ Spread radius+  -> BoxShadow+shadowWithSpread x y blurRadius spreadRadius =+    BoxShadow . value $ (x ! y ! blurRadius ! spreadRadius)++-- | Adapt the provided @box-shadow@ with the @inset@ prefix.+-- +-- > boxShadow . pure . bsInset+bsInset :: BoxShadow -> BoxShadow+bsInset (BoxShadow v) = BoxShadow . value $ ("inset" :: Value, v)++-- | Supply a color to the provided @box-shadow@.+bsColor :: Color -> BoxShadow -> BoxShadow+bsColor c (BoxShadow v) = BoxShadow . value $ (v, c)+infixr 9 `bsColor`++-------------------------------------------------------------------------------++-- $box-shadow-deprecated+--+-- The old implementation was both restrictive and slightly off-spec. It+-- shall be discontinued in a future release. The 'boxShadow' name has already+-- been taken, so the functionality that used to provide is now provided by+-- 'boxShadow\''.++-- | This is the drop-in replacement for the old 'boxShadow' function (< 0.13).+-- It is possible to continue for now+boxShadow' :: Size a -> Size a -> Size a -> Color -> Css+boxShadow' x y w c = prefixed (browsers <> "box-shadow") (x ! y ! w ! c)+{-# DEPRECATED boxShadow' "This function is only present for compatibility purposes and will be removed." #-}++-- | Replace calls to this function as follows (using -XOverloadedLists)+--+-- > boxShadowWithSpread x y rb rs c+--+-- > boxShadow [c `bsColor` shadowWithSpread x y rb rs] boxShadowWithSpread :: Size a -> Size a -> Size a -> Size a -> Color -> Css boxShadowWithSpread x y blurRadius spreadRadius color =     prefixed (browsers <> "box-shadow") (x ! y ! blurRadius ! spreadRadius ! color)+{-# DEPRECATED boxShadowWithSpread "This function has been replaced with shadowWithSpread and bsColor and will be removed." #-} +-- | Replace calls to this function as follows (using -XOverloadedLists)+--+-- > boxShadows [(x1, y1, rb1, c1), (x2, y2, rb2, c2)]+--+-- > boxShadow+-- >   [ c1 `bsColor` shadowWithBlur x1 y1 rb1+-- >   , c2 `bsColor` shadowWithBlur x2 y2 rb2+-- >   ] boxShadows :: [(Size a, Size a, Size a, Color)] -> Css boxShadows = prefixed (browsers <> "box-shadow") . map (\(a, b, c, d) -> a ! b ! c ! d)---------------------------------------------------------------------------------+{-# DEPRECATED boxShadows "This function is replaced with boxShadow and will be removed." #-} +-- | Replace calls to this function as follows (using -XOverloadedLists)+--+-- > insetBoxShadow s x y rb c+--+-- > boxShadow [bsInset $ c `bsColor` shadowWithBlur x y rb] insetBoxShadow :: Stroke -> Size a -> Size a -> Size a -> Color -> Css insetBoxShadow x y w c z = prefixed (browsers <> "box-shadow") (x ! y ! w ! c ! z)+{-# DEPRECATED insetBoxShadow "This function has been replaced with shadowWithSpread, bsInset and bsColor and will be removed." #-}
+ src/Clay/Comments.hs view
@@ -0,0 +1,30 @@+{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE OverloadedStrings #-}+module Clay.Comments where++import Data.Monoid ((<>))+import Data.Maybe (isNothing)+import Data.List (partition)++import Clay.Stylesheet++-- | Annotate the supplied 'Css' with the supplied comment.+-- Comments work with 'OverloadedStrings'. This will annotate every non-nested+-- value.+commenting :: CommentText -> Css -> Css+commenting c css = foldMap (rule . addComment c) $ runS css+infixl 3 `commenting`++-- The last case indicates there may be something wrong in the typing, as+-- it shouldn't be possible to comment a wrong rule. In practice, this implementation+-- means only the directly applied property rule is affected, i.e. no nested+-- rules. That could be changed by adding recursive cases.+addComment :: CommentText -> Rule -> Rule+addComment c (Property (PartitionComments xs (Just cs)) k v) = let c1 = Comment $ cs <> "; " <> c in+  Property (c1 : xs) k v+addComment c (Property ms k v  ) = Property (Comment c : ms) k v+addComment _ r                   = r++pattern PartitionComments :: [Modifier] -> Maybe CommentText -> [Modifier]+pattern PartitionComments xs cs <- (fmap (foldMap _Comment) . partition (isNothing . _Comment) -> (xs, cs))
src/Clay/FontFace.hs view
@@ -16,13 +16,20 @@  ------------------------------------------------------------------------------- -data FontFaceFormat = WOFF | TrueType | OpenType | EmbeddedOpenType | SVG+data FontFaceFormat+  = WOFF+  | WOFF2+  | TrueType+  | OpenType+  | EmbeddedOpenType+  | SVG   deriving Show  -- | name of format according to CSS specification formatName :: FontFaceFormat -> Text formatName format = case format of   WOFF             -> "woff"+  WOFF2            -> "woff2"   TrueType         -> "truetype"   OpenType         -> "opentype"   EmbeddedOpenType -> "embedded-opentype"
src/Clay/Property.hs view
@@ -5,6 +5,7 @@ import Control.Monad.Writer import Data.Fixed (Fixed, HasResolution (resolution), showFixed) import Data.List (partition, sort)+import Data.List.NonEmpty (NonEmpty, toList) import Data.Maybe import Data.String import Data.Text (Text, replace)@@ -92,16 +93,19 @@   value (Right a) = value a  instance Val a => Val [a] where-  value xs = intersperse "," (map value xs)+  value xs = intercalate "," (map value xs) -intersperse :: Monoid a => a -> [a] -> a-intersperse _ []     = mempty-intersperse s (x:xs) = foldl (\a b -> a <> s <> b) x xs+instance Val a => Val (NonEmpty a) where+  value = value . toList +intercalate :: Monoid a => a -> [a] -> a+intercalate _ []     = mempty+intercalate s (x:xs) = foldl (\a b -> a <> s <> b) x xs+ -------------------------------------------------------------------------------  noCommas :: Val a => [a] -> Value-noCommas xs = intersperse " " (map value xs)+noCommas xs = intercalate " " (map value xs)  infixr ! 
src/Clay/Pseudo.hs view
@@ -3,8 +3,11 @@  import Data.Text (Text) +import Clay.Render (renderSelector) import Clay.Selector +import qualified Data.Text.Lazy as Lazy+ -- List of specific pseudo classes, from: -- https://developer.mozilla.org/en-US/docs/CSS/Pseudo-classes @@ -53,11 +56,13 @@ target        = ":target" valid         = ":valid" -lang, nthChild, nthLastChild, nthLastOfType, nthOfType, not :: Text -> Refinement+lang, nthChild, nthLastChild, nthLastOfType, nthOfType :: Text -> Refinement  lang          n = func "lang"             [n] nthChild      n = func "nth-child"        [n] nthLastChild  n = func "nth-last-child"   [n] nthLastOfType n = func "nth-last-of-type" [n] nthOfType     n = func "nth-of-type"      [n]-not           n = func "not"              [n]++not :: Selector -> Refinement+not r = func "not" [Lazy.toStrict (renderSelector r)]
src/Clay/Render.hs view
@@ -8,12 +8,12 @@ , putCss , renderWith , renderSelector+, withBanner ) where  import           Control.Applicative import           Control.Monad.Writer-import           Data.Either import           Data.Foldable          (foldMap) import           Data.List              (sort) import           Data.Maybe@@ -43,6 +43,7 @@   , warn           :: Bool   , align          :: Bool   , banner         :: Bool+  , comments       :: Bool   }  -- | Configuration to print to a pretty human readable CSS output.@@ -58,6 +59,7 @@   , warn           = True   , align          = True   , banner         = True+  , comments       = True   }  -- | Configuration to print to a compacted unreadable CSS output.@@ -73,6 +75,7 @@   , warn           = False   , align          = False   , banner         = False+  , comments       = False   }  -- | Configuration to print to a compacted unreadable CSS output for embedding inline with HTML.@@ -88,6 +91,7 @@   , warn           = False   , align          = False   , banner         = False+  , comments       = False   }  -- | Render to CSS using the default configuration (`pretty`) and directly@@ -121,10 +125,12 @@  renderBanner :: Config -> Lazy.Text -> Lazy.Text renderBanner cfg-  | banner cfg = (<> b)+  | banner cfg = withBanner   | otherwise  = id-  where b = "\n/* Generated with Clay, http://fvisser.nl/clay */" +withBanner :: Lazy.Text -> Lazy.Text+withBanner = (<> "\n/* Generated with Clay, http://fvisser.nl/clay */")+ kframe :: Config -> Keyframes -> Builder kframe cfg (Keyframes ident xs) =   foldMap@@ -199,18 +205,18 @@   , (\(a, b) -> rules  cfg (a : sel) b) `foldMap` mapMaybe nested  rs   , (\(a, b) -> query  cfg  a   sel  b) `foldMap` mapMaybe queries rs   ]-  where property (Property k v) = Just (k, v)-        property _              = Nothing-        nested   (Nested a ns ) = Just (a, ns)-        nested   _              = Nothing-        queries  (Query q ns  ) = Just (q, ns)-        queries  _              = Nothing-        kframes  (Keyframe fs ) = Just fs;-        kframes  _              = Nothing-        faces    (Face ns     ) = Just ns-        faces    _              = Nothing-        imports  (Import i    ) = Just i-        imports  _              = Nothing+  where property (Property m k v) = Just (m, k, v)+        property _                = Nothing+        nested   (Nested a ns   ) = Just (a, ns)+        nested   _                = Nothing+        queries  (Query q ns    ) = Just (q, ns)+        queries  _                = Nothing+        kframes  (Keyframe fs   ) = Just fs;+        kframes  _                = Nothing+        faces    (Face ns       ) = Just ns+        faces    _                = Nothing+        imports  (Import i      ) = Just i+        imports  _                = Nothing  imp :: Config -> Text -> Builder imp cfg t =@@ -220,8 +226,10 @@     , ");"     , newline cfg ] +-- | A key-value pair with associated comment.+type KeyVal = ([Modifier], Key (), Value) -rule :: Config -> [App] -> [(Key (), Value)] -> Builder+rule :: Config -> [App] -> [KeyVal] -> Builder rule _   _   []    = mempty rule cfg sel props =   let xs = collect =<< props@@ -245,36 +253,50 @@     Pop        i -> merger (drop i (x:xs))     Self       f -> case xs of [] -> star `with` f; _ -> merger xs `with` f -collect :: (Key (), Value) -> [Either Text (Text, Text)]-collect (Key ky, Value vl) =-  case (ky, vl) of+data Representation+  = Warning Text+  | KeyValRep [Modifier] Text Text+  deriving (Show)++keys :: [Representation] -> [Text]+keys = mapMaybe f+  where+    f (KeyValRep _ k _) = Just k+    f _                 = Nothing++collect :: KeyVal -> [Representation]+collect (ms, Key ky, Value vl) = case (ky, vl) of     ( Plain    k  , Plain    v  ) -> [prop k v]     ( Prefixed ks , Plain    v  ) -> flip map ks $ \(p, k) -> prop (p <> k) v     ( Plain    k  , Prefixed vs ) -> flip map vs $ \(p, v) -> prop k (p <> v)-    ( Prefixed ks , Prefixed vs ) -> flip map ks $ \(p, k) -> (Left (p <> k) `maybe` (prop (p <> k) . mappend p)) (lookup p vs)-  where prop k v = Right (k, v)+    ( Prefixed ks , Prefixed vs ) -> flip map ks $ \(p, k) -> (Warning (p <> k) `maybe` (prop (p <> k) . mappend p)) (lookup p vs)+  where prop k v = KeyValRep ms k v -properties :: Config -> [Either Text (Text, Text)] -> Builder+properties :: Config -> [Representation] -> Builder properties cfg xs =-  let width     = 1 + maximum (Text.length . fst <$> rights xs)+  let width     = 1 + maximum (Text.length <$> keys xs)       ind       = indentation cfg       new       = newline cfg       finalSemi = if finalSemicolon cfg then ";" else ""-   in (<> new) $ (<> finalSemi) $ intersperse (";" <> new) $ flip map xs $ \p ->+   in (<> new) $ (<> finalSemi) $ intercalate (";" <> new) $ flip map xs $ \p ->         case p of-          Left w -> if warn cfg+          Warning w -> if warn cfg                     then ind <> "/* no value for " <> fromText w <> " */" <> new                     else mempty-          Right (k, v) ->+          KeyValRep ms k v ->             let pad = if align cfg                       then fromText (Text.replicate (width - Text.length k) " ")                       else ""-             in mconcat [ind, fromText k, pad, ":", sep cfg, fromText v]+                imptant = maybe "" ((" " <>) . fromText) . foldMap _Important $ ms+                comm = case (foldMap _Comment ms, comments cfg) of+                  (Just c, True) -> " /* " <> fromText (unCommentText c) <> " */"+                  _              -> mempty+             in mconcat [ind, fromText k, pad, ":", sep cfg, fromText v, imptant, comm]  selector :: Config -> Selector -> Builder selector Config { lbrace = "", rbrace = "" } = rec   where rec _ = ""-selector cfg = intersperse ("," <> newline cfg) . rec+selector cfg = intercalate ("," <> newline cfg) . rec   where rec (In (SelectorF (Refinement ft) p)) = (<> foldMap predicate (sort ft)) <$>           case p of             Star           -> if null ft then ["*"] else [""]@@ -298,6 +320,6 @@     AttrSpace    a v -> [ "[" , fromText a, "~='", fromText v, "']"                    ]     AttrHyph     a v -> [ "[" , fromText a, "|='", fromText v, "']"                    ]     Pseudo       a   -> [ ":" , fromText a                                             ]-    PseudoFunc   a p -> [ ":" , fromText a, "(", intersperse "," (map fromText p), ")" ]+    PseudoFunc   a p -> [ ":" , fromText a, "(", intercalate "," (map fromText p), ")" ]     PseudoElem   a   -> [ "::", fromText a                                             ] 
src/Clay/Selector.hs view
@@ -157,13 +157,13 @@   deriving (Eq, Ord, Show)  newtype Refinement = Refinement { unFilter :: [Predicate] }-  deriving Show+  deriving (Show, Monoid)  instance IsString Refinement where-  fromString = filterFromText . fromString+  fromString = refinementFromText . fromString -filterFromText :: Text -> Refinement-filterFromText t = Refinement $+refinementFromText :: Text -> Refinement+refinementFromText t = Refinement $   case Text.uncons t of     Just ('#', s) -> [Id     s]     Just ('.', s) -> [Class  s]@@ -195,14 +195,14 @@ type Selector = Fix SelectorF  instance IsString (Fix SelectorF) where-  fromString = text . fromString+  fromString = selectorFromText . fromString -text :: Text -> Selector-text t = In $+selectorFromText :: Text -> Selector+selectorFromText t =   case Text.uncons t of-    Just ('#', s) -> SelectorF (Refinement [Id s]) Star-    Just ('.', s) -> SelectorF (Refinement [Class s]) Star-    _             -> SelectorF (Refinement []) (Elem t)+    Just (c, _) | elem c ("#.:@" :: [Char])+      -> with star (refinementFromText t)+    _ -> In $ SelectorF (Refinement []) (Elem t)  #if MIN_VERSION_base(4,9,0) instance Semigroup (Fix SelectorF) where
src/Clay/Stylesheet.hs view
@@ -1,10 +1,15 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ViewPatterns #-} module Clay.Stylesheet where  import Control.Applicative import Control.Arrow (second) import Control.Monad.Writer hiding (All)+import Data.Maybe (isJust)+import Data.Semigroup (Semigroup)+import Data.String (IsString) import Data.Text (Text)  import Clay.Selector hiding (Child)@@ -25,6 +30,22 @@ data Feature = Feature Text (Maybe Value)   deriving Show +newtype CommentText = CommentText { unCommentText :: Text }+  deriving (Show, IsString, Semigroup, Monoid)++data Modifier+  = Important+  | Comment CommentText+  deriving (Show)++_Important :: Modifier -> Maybe Text+_Important Important   = Just "!important"+_Important (Comment _) = Nothing++_Comment :: Modifier -> Maybe CommentText+_Comment (Comment c) = Just c+_Comment Important   = Nothing+ -------------------------------------------------------------------------------  data App@@ -39,7 +60,7 @@   deriving Show  data Rule-  = Property (Key ()) Value+  = Property [Modifier] (Key ()) Value   | Nested   App [Rule]   | Query    MediaQuery [Rule]   | Face     [Rule]@@ -71,7 +92,7 @@ -- words: can be converted to a `Value`.  key :: Val a => Key a -> a -> Css-key k v = rule $ Property (cast k) (value v)+key k v = rule $ Property [] (cast k) (value v)  -- | Add a new style property to the stylesheet with the specified `Key` and -- value, like `key` but use a `Prefixed` key.@@ -161,3 +182,21 @@ importUrl :: Text -> Css importUrl l = rule $ Import l +-------------------------------------------------------------------------------++-- | Indicate the supplied css should override css declarations that would+-- otherwise take precedence.+--+-- Use sparingly.+important :: Css -> Css+important = foldMap (rule . addImportant) . runS++-- The last case indicates there may be something wrong in the typing, as+-- it shouldn't be possible to make a non-property important. In practice,+-- this implementation means only the directly applied property rule is+-- affected, i.e. no nested rules. That could be changed by adding recursive cases.+addImportant :: Rule -> Rule+addImportant (Property ms@(filter (isJust . _Important) -> (_:_)) k v) =+  Property ms k v+addImportant (Property ms k v  ) = Property (Important : ms) k v+addImportant r                   = r
src/Clay/Text.hs view
@@ -17,6 +17,7 @@ , textShadow  -- * Text-indent.+-- $text-indent  , TextIndent , textIndent@@ -134,13 +135,37 @@  ------------------------------------------------------------------------------- +-- $text-indent+--+-- Supply a length — optionally annotated with @each-line@ or @hanging@ or+-- both, or a global value. It is possible to apply the same annotation+-- multiple times, but it has no defined effect.+--+-- Note browser support is currently (March 2018) non-existent, but the+-- Prince typesetting system supports the syntax.+--+-- === Formal argument syntax+--+-- > <length-percentage> && hanging? && each-line?+-- > where+-- > <length-percentage> = <length> | <percentage>+ newtype TextIndent = TextIndent Value-  deriving (Val, Inherit, Other)+  deriving (Val, Inherit, Initial, Unset, Other) -eachLine, hanging :: TextIndent+-- | An internal function that ensures each-line and hanging are processed+-- correctly.+tagTextIndent :: Value -> TextIndent -> TextIndent+tagTextIndent v (TextIndent v0) = TextIndent . value $ (v0, v) -eachLine = TextIndent "each-line"-hanging  = TextIndent "hanging"+-- | Annotate the supplied 'TextIndent' with @each-line@ or @hanging@ or+-- both.+--+-- > eachLine . hanging . indent $ px 3 :: TextIndent+eachLine, hanging :: TextIndent -> TextIndent++eachLine = tagTextIndent "each-line"+hanging  = tagTextIndent "hanging"  indent :: Size a -> TextIndent indent = TextIndent . value