{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ViewPatterns #-}
module Clay.Stylesheet where

import Control.Applicative
import Control.Arrow (second)
import Control.Monad.Writer (Writer, execWriter, tell)
import Data.Foldable (foldMap)
import Data.Maybe (isJust)
import Data.Monoid (Monoid(..))
import Data.Semigroup (Semigroup(..))
import Data.String (IsString)
import Data.Text (Text)

import Clay.Selector hiding (Child)
import Clay.Property
import Clay.Common

-------------------------------------------------------------------------------

newtype MediaType = MediaType Value
  deriving (MediaType -> Value
(MediaType -> Value) -> Val MediaType
forall a. (a -> Value) -> Val a
value :: MediaType -> Value
$cvalue :: MediaType -> Value
Val, Value -> MediaType
(Value -> MediaType) -> Other MediaType
forall a. (Value -> a) -> Other a
other :: Value -> MediaType
$cother :: Value -> MediaType
Other, Int -> MediaType -> ShowS
[MediaType] -> ShowS
MediaType -> String
(Int -> MediaType -> ShowS)
-> (MediaType -> String)
-> ([MediaType] -> ShowS)
-> Show MediaType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MediaType] -> ShowS
$cshowList :: [MediaType] -> ShowS
show :: MediaType -> String
$cshow :: MediaType -> String
showsPrec :: Int -> MediaType -> ShowS
$cshowsPrec :: Int -> MediaType -> ShowS
Show, MediaType
MediaType -> All MediaType
forall a. a -> All a
all :: MediaType
$call :: MediaType
All)

data NotOrOnly = Not | Only
  deriving Int -> NotOrOnly -> ShowS
[NotOrOnly] -> ShowS
NotOrOnly -> String
(Int -> NotOrOnly -> ShowS)
-> (NotOrOnly -> String)
-> ([NotOrOnly] -> ShowS)
-> Show NotOrOnly
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [NotOrOnly] -> ShowS
$cshowList :: [NotOrOnly] -> ShowS
show :: NotOrOnly -> String
$cshow :: NotOrOnly -> String
showsPrec :: Int -> NotOrOnly -> ShowS
$cshowsPrec :: Int -> NotOrOnly -> ShowS
Show

data MediaQuery = MediaQuery (Maybe NotOrOnly) MediaType [Feature]
  deriving Int -> MediaQuery -> ShowS
[MediaQuery] -> ShowS
MediaQuery -> String
(Int -> MediaQuery -> ShowS)
-> (MediaQuery -> String)
-> ([MediaQuery] -> ShowS)
-> Show MediaQuery
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MediaQuery] -> ShowS
$cshowList :: [MediaQuery] -> ShowS
show :: MediaQuery -> String
$cshow :: MediaQuery -> String
showsPrec :: Int -> MediaQuery -> ShowS
$cshowsPrec :: Int -> MediaQuery -> ShowS
Show

data Feature = Feature Text (Maybe Value)
  deriving Int -> Feature -> ShowS
[Feature] -> ShowS
Feature -> String
(Int -> Feature -> ShowS)
-> (Feature -> String) -> ([Feature] -> ShowS) -> Show Feature
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Feature] -> ShowS
$cshowList :: [Feature] -> ShowS
show :: Feature -> String
$cshow :: Feature -> String
showsPrec :: Int -> Feature -> ShowS
$cshowsPrec :: Int -> Feature -> ShowS
Show

newtype CommentText = CommentText { CommentText -> Text
unCommentText :: Text }
  deriving (Int -> CommentText -> ShowS
[CommentText] -> ShowS
CommentText -> String
(Int -> CommentText -> ShowS)
-> (CommentText -> String)
-> ([CommentText] -> ShowS)
-> Show CommentText
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CommentText] -> ShowS
$cshowList :: [CommentText] -> ShowS
show :: CommentText -> String
$cshow :: CommentText -> String
showsPrec :: Int -> CommentText -> ShowS
$cshowsPrec :: Int -> CommentText -> ShowS
Show, String -> CommentText
(String -> CommentText) -> IsString CommentText
forall a. (String -> a) -> IsString a
fromString :: String -> CommentText
$cfromString :: String -> CommentText
IsString, b -> CommentText -> CommentText
NonEmpty CommentText -> CommentText
CommentText -> CommentText -> CommentText
(CommentText -> CommentText -> CommentText)
-> (NonEmpty CommentText -> CommentText)
-> (forall b. Integral b => b -> CommentText -> CommentText)
-> Semigroup CommentText
forall b. Integral b => b -> CommentText -> CommentText
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
stimes :: b -> CommentText -> CommentText
$cstimes :: forall b. Integral b => b -> CommentText -> CommentText
sconcat :: NonEmpty CommentText -> CommentText
$csconcat :: NonEmpty CommentText -> CommentText
<> :: CommentText -> CommentText -> CommentText
$c<> :: CommentText -> CommentText -> CommentText
Semigroup, Semigroup CommentText
CommentText
Semigroup CommentText
-> CommentText
-> (CommentText -> CommentText -> CommentText)
-> ([CommentText] -> CommentText)
-> Monoid CommentText
[CommentText] -> CommentText
CommentText -> CommentText -> CommentText
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
mconcat :: [CommentText] -> CommentText
$cmconcat :: [CommentText] -> CommentText
mappend :: CommentText -> CommentText -> CommentText
$cmappend :: CommentText -> CommentText -> CommentText
mempty :: CommentText
$cmempty :: CommentText
$cp1Monoid :: Semigroup CommentText
Monoid)

data Modifier
  = Important
  | Comment CommentText
  deriving (Int -> Modifier -> ShowS
[Modifier] -> ShowS
Modifier -> String
(Int -> Modifier -> ShowS)
-> (Modifier -> String) -> ([Modifier] -> ShowS) -> Show Modifier
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Modifier] -> ShowS
$cshowList :: [Modifier] -> ShowS
show :: Modifier -> String
$cshow :: Modifier -> String
showsPrec :: Int -> Modifier -> ShowS
$cshowsPrec :: Int -> Modifier -> ShowS
Show)

_Important :: Modifier -> Maybe Text
_Important :: Modifier -> Maybe Text
_Important Modifier
Important   = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"!important"
_Important (Comment CommentText
_) = Maybe Text
forall a. Maybe a
Nothing

_Comment :: Modifier -> Maybe CommentText
_Comment :: Modifier -> Maybe CommentText
_Comment (Comment CommentText
c) = CommentText -> Maybe CommentText
forall a. a -> Maybe a
Just CommentText
c
_Comment Modifier
Important   = Maybe CommentText
forall a. Maybe a
Nothing

-------------------------------------------------------------------------------

data App
  = Self   Refinement
  | Root   Selector
  | Pop    Int
  | Child  Selector
  | Sub    Selector
  deriving Int -> App -> ShowS
[App] -> ShowS
App -> String
(Int -> App -> ShowS)
-> (App -> String) -> ([App] -> ShowS) -> Show App
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [App] -> ShowS
$cshowList :: [App] -> ShowS
show :: App -> String
$cshow :: App -> String
showsPrec :: Int -> App -> ShowS
$cshowsPrec :: Int -> App -> ShowS
Show

data Keyframes = Keyframes Text [(Double, [Rule])]
  deriving Int -> Keyframes -> ShowS
[Keyframes] -> ShowS
Keyframes -> String
(Int -> Keyframes -> ShowS)
-> (Keyframes -> String)
-> ([Keyframes] -> ShowS)
-> Show Keyframes
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Keyframes] -> ShowS
$cshowList :: [Keyframes] -> ShowS
show :: Keyframes -> String
$cshow :: Keyframes -> String
showsPrec :: Int -> Keyframes -> ShowS
$cshowsPrec :: Int -> Keyframes -> ShowS
Show

data Rule
  = Property [Modifier] (Key ()) Value
  | Nested   App [Rule]
  | Query    MediaQuery [Rule]
  | Face     [Rule]
  | Keyframe Keyframes
  | Import   Text
  deriving Int -> Rule -> ShowS
[Rule] -> ShowS
Rule -> String
(Int -> Rule -> ShowS)
-> (Rule -> String) -> ([Rule] -> ShowS) -> Show Rule
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Rule] -> ShowS
$cshowList :: [Rule] -> ShowS
show :: Rule -> String
$cshow :: Rule -> String
showsPrec :: Int -> Rule -> ShowS
$cshowsPrec :: Int -> Rule -> ShowS
Show

newtype StyleM a = S (Writer [Rule] a)
  deriving (a -> StyleM b -> StyleM a
(a -> b) -> StyleM a -> StyleM b
(forall a b. (a -> b) -> StyleM a -> StyleM b)
-> (forall a b. a -> StyleM b -> StyleM a) -> Functor StyleM
forall a b. a -> StyleM b -> StyleM a
forall a b. (a -> b) -> StyleM a -> StyleM b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> StyleM b -> StyleM a
$c<$ :: forall a b. a -> StyleM b -> StyleM a
fmap :: (a -> b) -> StyleM a -> StyleM b
$cfmap :: forall a b. (a -> b) -> StyleM a -> StyleM b
Functor, Functor StyleM
a -> StyleM a
Functor StyleM
-> (forall a. a -> StyleM a)
-> (forall a b. StyleM (a -> b) -> StyleM a -> StyleM b)
-> (forall a b c.
    (a -> b -> c) -> StyleM a -> StyleM b -> StyleM c)
-> (forall a b. StyleM a -> StyleM b -> StyleM b)
-> (forall a b. StyleM a -> StyleM b -> StyleM a)
-> Applicative StyleM
StyleM a -> StyleM b -> StyleM b
StyleM a -> StyleM b -> StyleM a
StyleM (a -> b) -> StyleM a -> StyleM b
(a -> b -> c) -> StyleM a -> StyleM b -> StyleM c
forall a. a -> StyleM a
forall a b. StyleM a -> StyleM b -> StyleM a
forall a b. StyleM a -> StyleM b -> StyleM b
forall a b. StyleM (a -> b) -> StyleM a -> StyleM b
forall a b c. (a -> b -> c) -> StyleM a -> StyleM b -> StyleM c
forall (f :: * -> *).
Functor f
-> (forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
<* :: StyleM a -> StyleM b -> StyleM a
$c<* :: forall a b. StyleM a -> StyleM b -> StyleM a
*> :: StyleM a -> StyleM b -> StyleM b
$c*> :: forall a b. StyleM a -> StyleM b -> StyleM b
liftA2 :: (a -> b -> c) -> StyleM a -> StyleM b -> StyleM c
$cliftA2 :: forall a b c. (a -> b -> c) -> StyleM a -> StyleM b -> StyleM c
<*> :: StyleM (a -> b) -> StyleM a -> StyleM b
$c<*> :: forall a b. StyleM (a -> b) -> StyleM a -> StyleM b
pure :: a -> StyleM a
$cpure :: forall a. a -> StyleM a
$cp1Applicative :: Functor StyleM
Applicative, Applicative StyleM
a -> StyleM a
Applicative StyleM
-> (forall a b. StyleM a -> (a -> StyleM b) -> StyleM b)
-> (forall a b. StyleM a -> StyleM b -> StyleM b)
-> (forall a. a -> StyleM a)
-> Monad StyleM
StyleM a -> (a -> StyleM b) -> StyleM b
StyleM a -> StyleM b -> StyleM b
forall a. a -> StyleM a
forall a b. StyleM a -> StyleM b -> StyleM b
forall a b. StyleM a -> (a -> StyleM b) -> StyleM b
forall (m :: * -> *).
Applicative m
-> (forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
return :: a -> StyleM a
$creturn :: forall a. a -> StyleM a
>> :: StyleM a -> StyleM b -> StyleM b
$c>> :: forall a b. StyleM a -> StyleM b -> StyleM b
>>= :: StyleM a -> (a -> StyleM b) -> StyleM b
$c>>= :: forall a b. StyleM a -> (a -> StyleM b) -> StyleM b
$cp1Monad :: Applicative StyleM
Monad)

runS :: Css -> [Rule]
runS :: Css -> [Rule]
runS (S Writer [Rule] ()
a) = Writer [Rule] () -> [Rule]
forall w a. Writer w a -> w
execWriter Writer [Rule] ()
a

rule :: Rule -> Css
rule :: Rule -> Css
rule Rule
a = Writer [Rule] () -> Css
forall a. Writer [Rule] a -> StyleM a
S ([Rule] -> Writer [Rule] ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell [Rule
a])

-- | The `Css` context is used to collect style rules which are mappings from
-- selectors to style properties. The `Css` type is a computation in the
-- `StyleM` monad that just collects and doesn't return anything.

type Css = StyleM ()

instance Semigroup Css where
  <> :: Css -> Css -> Css
(<>) = (() -> () -> ()) -> Css -> Css -> Css
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 () -> () -> ()
forall a. Semigroup a => a -> a -> a
(<>)

instance Monoid Css where
  mempty :: Css
mempty = () -> Css
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
  mappend :: Css -> Css -> Css
mappend = Css -> Css -> Css
forall a. Semigroup a => a -> a -> a
(<>)

-- | Add a new style property to the stylesheet with the specified `Key` and
-- value. The value can be any type that is in the `Val' typeclass, with other
-- words: can be converted to a `Value`.

key :: Val a => Key a -> a -> Css
key :: Key a -> a -> Css
key Key a
k a
v = Rule -> Css
rule (Rule -> Css) -> Rule -> Css
forall a b. (a -> b) -> a -> b
$ [Modifier] -> Key () -> Value -> Rule
Property [] (Key a -> Key ()
forall a. Key a -> Key ()
cast Key a
k) (a -> Value
forall a. Val a => a -> Value
value a
v)

-- | Add a new style property to the stylesheet with the specified `Key` and
-- value, like `key` but use a `Prefixed` key.

prefixed :: Val a => Prefixed -> a -> Css
prefixed :: Prefixed -> a -> Css
prefixed Prefixed
xs = Key a -> a -> Css
forall a. Val a => Key a -> a -> Css
key (Prefixed -> Key a
forall a. Prefixed -> Key a
Key Prefixed
xs)

infix 4 -:

-- | The colon operator can be used to add style rules to the current context
-- for which there is no embedded version available. Both the key and the value
-- are plain text values and rendered as is to the output CSS.

(-:) :: Key Text -> Text -> Css
-: :: Key Text -> Text -> Css
(-:) = Key Text -> Text -> Css
forall a. Val a => Key a -> a -> Css
key

-------------------------------------------------------------------------------

infixr 5 <?
infixr 5 ?
infixr 5 &

-- | Assign a stylesheet to a selector. When the selector is nested inside an
-- outer scope it will be composed with `deep`.

(?) :: Selector -> Css -> Css
? :: Selector -> Css -> Css
(?) Selector
sel Css
rs = Rule -> Css
rule (Rule -> Css) -> Rule -> Css
forall a b. (a -> b) -> a -> b
$ App -> [Rule] -> Rule
Nested (Selector -> App
Sub Selector
sel) (Css -> [Rule]
runS Css
rs)

-- | Assign a stylesheet to a selector. When the selector is nested inside an
-- outer scope it will be composed with `|>`.

(<?) :: Selector -> Css -> Css
<? :: Selector -> Css -> Css
(<?) Selector
sel Css
rs = Rule -> Css
rule (Rule -> Css) -> Rule -> Css
forall a b. (a -> b) -> a -> b
$ App -> [Rule] -> Rule
Nested (Selector -> App
Child Selector
sel) (Css -> [Rule]
runS Css
rs)

-- | Assign a stylesheet to a filter selector. When the selector is nested
-- inside an outer scope it will be composed with the `with` selector.

(&) :: Refinement -> Css -> Css
& :: Refinement -> Css -> Css
(&) Refinement
p Css
rs = Rule -> Css
rule (Rule -> Css) -> Rule -> Css
forall a b. (a -> b) -> a -> b
$ App -> [Rule] -> Rule
Nested (Refinement -> App
Self Refinement
p) (Css -> [Rule]
runS Css
rs)

-- | Root is used to add style rules to the top scope.

root :: Selector -> Css -> Css
root :: Selector -> Css -> Css
root Selector
sel Css
rs = Rule -> Css
rule (Rule -> Css) -> Rule -> Css
forall a b. (a -> b) -> a -> b
$ App -> [Rule] -> Rule
Nested (Selector -> App
Root Selector
sel) (Css -> [Rule]
runS Css
rs)

-- | Pop is used to add style rules to selectors defined in an outer scope. The
-- counter specifies how far up the scope stack we want to add the rules.

pop :: Int -> Css -> Css
pop :: Int -> Css -> Css
pop Int
i Css
rs = Rule -> Css
rule (Rule -> Css) -> Rule -> Css
forall a b. (a -> b) -> a -> b
$ App -> [Rule] -> Rule
Nested (Int -> App
Pop Int
i) (Css -> [Rule]
runS Css
rs)

-------------------------------------------------------------------------------

-- | Apply a set of style rules when the media type and feature queries apply.

query :: MediaType -> [Feature] -> Css -> Css
query :: MediaType -> [Feature] -> Css -> Css
query MediaType
ty [Feature]
fs Css
rs = Rule -> Css
rule (Rule -> Css) -> Rule -> Css
forall a b. (a -> b) -> a -> b
$ MediaQuery -> [Rule] -> Rule
Query (Maybe NotOrOnly -> MediaType -> [Feature] -> MediaQuery
MediaQuery Maybe NotOrOnly
forall a. Maybe a
Nothing MediaType
ty [Feature]
fs) (Css -> [Rule]
runS Css
rs)

-- | Apply a set of style rules when the media type and feature queries do not apply.

queryNot :: MediaType -> [Feature] -> Css -> Css
queryNot :: MediaType -> [Feature] -> Css -> Css
queryNot MediaType
ty [Feature]
fs Css
rs = Rule -> Css
rule (Rule -> Css) -> Rule -> Css
forall a b. (a -> b) -> a -> b
$ MediaQuery -> [Rule] -> Rule
Query (Maybe NotOrOnly -> MediaType -> [Feature] -> MediaQuery
MediaQuery (NotOrOnly -> Maybe NotOrOnly
forall a. a -> Maybe a
Just NotOrOnly
Not) MediaType
ty [Feature]
fs) (Css -> [Rule]
runS Css
rs)

-- | Apply a set of style rules only when the media type and feature queries apply.

queryOnly :: MediaType -> [Feature] -> Css -> Css
queryOnly :: MediaType -> [Feature] -> Css -> Css
queryOnly MediaType
ty [Feature]
fs Css
rs = Rule -> Css
rule (Rule -> Css) -> Rule -> Css
forall a b. (a -> b) -> a -> b
$ MediaQuery -> [Rule] -> Rule
Query (Maybe NotOrOnly -> MediaType -> [Feature] -> MediaQuery
MediaQuery (NotOrOnly -> Maybe NotOrOnly
forall a. a -> Maybe a
Just NotOrOnly
Only) MediaType
ty [Feature]
fs) (Css -> [Rule]
runS Css
rs)

-------------------------------------------------------------------------------

keyframes :: Text -> [(Double, Css)] -> Css
keyframes :: Text -> [(Double, Css)] -> Css
keyframes Text
n [(Double, Css)]
xs = Rule -> Css
rule (Rule -> Css) -> Rule -> Css
forall a b. (a -> b) -> a -> b
$ Keyframes -> Rule
Keyframe (Text -> [(Double, [Rule])] -> Keyframes
Keyframes Text
n (((Double, Css) -> (Double, [Rule]))
-> [(Double, Css)] -> [(Double, [Rule])]
forall a b. (a -> b) -> [a] -> [b]
map ((Css -> [Rule]) -> (Double, Css) -> (Double, [Rule])
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (d, b) (d, c)
second Css -> [Rule]
runS) [(Double, Css)]
xs))

keyframesFromTo :: Text -> Css -> Css -> Css
keyframesFromTo :: Text -> Css -> Css -> Css
keyframesFromTo Text
n Css
a Css
b = Text -> [(Double, Css)] -> Css
keyframes Text
n [(Double
0, Css
a), (Double
100, Css
b)]

-------------------------------------------------------------------------------

-- | Define a new font-face.

fontFace :: Css -> Css
fontFace :: Css -> Css
fontFace Css
rs = Rule -> Css
rule (Rule -> Css) -> Rule -> Css
forall a b. (a -> b) -> a -> b
$ [Rule] -> Rule
Face (Css -> [Rule]
runS Css
rs)


-- | Import a CSS file from a URL

importUrl :: Text -> Css
importUrl :: Text -> Css
importUrl Text
l = Rule -> Css
rule (Rule -> Css) -> Rule -> Css
forall a b. (a -> b) -> a -> b
$ Text -> Rule
Import Text
l

-------------------------------------------------------------------------------

-- | Indicate the supplied css should override css declarations that would
-- otherwise take precedence.
--
-- Use sparingly.
important :: Css -> Css
important :: Css -> Css
important = (Rule -> Css) -> [Rule] -> Css
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (Rule -> Css
rule (Rule -> Css) -> (Rule -> Rule) -> Rule -> Css
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rule -> Rule
addImportant) ([Rule] -> Css) -> (Css -> [Rule]) -> Css -> Css
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Css -> [Rule]
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 :: Rule -> Rule
addImportant (Property ms :: [Modifier]
ms@((Modifier -> Bool) -> [Modifier] -> [Modifier]
forall a. (a -> Bool) -> [a] -> [a]
filter (Maybe Text -> Bool
forall a. Maybe a -> Bool
isJust (Maybe Text -> Bool)
-> (Modifier -> Maybe Text) -> Modifier -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Modifier -> Maybe Text
_Important) -> (Modifier
_:[Modifier]
_)) Key ()
k Value
v) =
  [Modifier] -> Key () -> Value -> Rule
Property [Modifier]
ms Key ()
k Value
v
addImportant (Property [Modifier]
ms Key ()
k Value
v  ) = [Modifier] -> Key () -> Value -> Rule
Property (Modifier
Important Modifier -> [Modifier] -> [Modifier]
forall a. a -> [a] -> [a]
: [Modifier]
ms) Key ()
k Value
v
addImportant Rule
r                   = Rule
r