{-# LANGUAGE OverloadedStrings #-}
module Clay.Render
( Config (..)
, pretty
, compact
, render
, htmlInline
, putCss
, renderWith
, renderSelector
, withBanner
)
where
import Control.Applicative
import Control.Monad.Writer
import Data.List (sort)
import Data.Maybe
import Data.Text (Text, pack)
import Data.Text.Lazy.Builder
import Prelude hiding ((**))
import qualified Data.Text as Text
import qualified Data.Text.Lazy as Lazy
import qualified Data.Text.Lazy.IO as Lazy
import Clay.Common (browsers)
import Clay.Property
import Clay.Selector
import Clay.Stylesheet hiding (Child, query, rule)
import qualified Clay.Stylesheet as Rule
data Config = Config
{ Config -> Builder
indentation :: Builder
, Config -> Builder
newline :: Builder
, Config -> Builder
sep :: Builder
, Config -> Builder
lbrace :: Builder
, Config -> Builder
rbrace :: Builder
, Config -> Bool
finalSemicolon :: Bool
, Config -> Bool
warn :: Bool
, Config -> Bool
align :: Bool
, Config -> Bool
banner :: Bool
, :: Bool
}
pretty :: Config
pretty :: Config
pretty = Config :: Builder
-> Builder
-> Builder
-> Builder
-> Builder
-> Bool
-> Bool
-> Bool
-> Bool
-> Bool
-> Config
Config
{ indentation :: Builder
indentation = Builder
" "
, newline :: Builder
newline = Builder
"\n"
, sep :: Builder
sep = Builder
" "
, lbrace :: Builder
lbrace = Builder
"{"
, rbrace :: Builder
rbrace = Builder
"}"
, finalSemicolon :: Bool
finalSemicolon = Bool
True
, warn :: Bool
warn = Bool
True
, align :: Bool
align = Bool
True
, banner :: Bool
banner = Bool
True
, comments :: Bool
comments = Bool
True
}
compact :: Config
compact :: Config
compact = Config :: Builder
-> Builder
-> Builder
-> Builder
-> Builder
-> Bool
-> Bool
-> Bool
-> Bool
-> Bool
-> Config
Config
{ indentation :: Builder
indentation = Builder
""
, newline :: Builder
newline = Builder
""
, sep :: Builder
sep = Builder
""
, lbrace :: Builder
lbrace = Builder
"{"
, rbrace :: Builder
rbrace = Builder
"}"
, finalSemicolon :: Bool
finalSemicolon = Bool
False
, warn :: Bool
warn = Bool
False
, align :: Bool
align = Bool
False
, banner :: Bool
banner = Bool
False
, comments :: Bool
comments = Bool
False
}
htmlInline :: Config
htmlInline :: Config
htmlInline = Config :: Builder
-> Builder
-> Builder
-> Builder
-> Builder
-> Bool
-> Bool
-> Bool
-> Bool
-> Bool
-> Config
Config
{ indentation :: Builder
indentation = Builder
""
, newline :: Builder
newline = Builder
""
, sep :: Builder
sep = Builder
""
, lbrace :: Builder
lbrace = Builder
""
, rbrace :: Builder
rbrace = Builder
""
, finalSemicolon :: Bool
finalSemicolon = Bool
False
, warn :: Bool
warn = Bool
False
, align :: Bool
align = Bool
False
, banner :: Bool
banner = Bool
False
, comments :: Bool
comments = Bool
False
}
putCss :: Css -> IO ()
putCss :: Css -> IO ()
putCss = Text -> IO ()
Lazy.putStr (Text -> IO ()) -> (Css -> Text) -> Css -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Css -> Text
render
render :: Css -> Lazy.Text
render :: Css -> Text
render = Config -> [App] -> Css -> Text
renderWith Config
pretty []
renderWith :: Config -> [App] -> Css -> Lazy.Text
renderWith :: Config -> [App] -> Css -> Text
renderWith Config
cfg [App]
top
= Config -> Text -> Text
renderBanner Config
cfg
(Text -> Text) -> (Css -> Text) -> Css -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> Text
toLazyText
(Builder -> Text) -> (Css -> Builder) -> Css -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Config -> [App] -> [Rule] -> Builder
rules Config
cfg [App]
top
([Rule] -> Builder) -> (Css -> [Rule]) -> Css -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Css -> [Rule]
runS
renderSelector :: Selector -> Lazy.Text
renderSelector :: Selector -> Text
renderSelector = Builder -> Text
toLazyText (Builder -> Text) -> (Selector -> Builder) -> Selector -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Config -> Selector -> Builder
selector Config
compact
renderBanner :: Config -> Lazy.Text -> Lazy.Text
renderBanner :: Config -> Text -> Text
renderBanner Config
cfg
| Config -> Bool
banner Config
cfg = Text -> Text
withBanner
| Bool
otherwise = Text -> Text
forall a. a -> a
id
withBanner :: Lazy.Text -> Lazy.Text
withBanner :: Text -> Text
withBanner = (Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\n/* Generated with Clay, http://fvisser.nl/clay */")
kframe :: Config -> Keyframes -> Builder
kframe :: Config -> Keyframes -> Builder
kframe Config
cfg (Keyframes Text
ident [(Double, [Rule])]
xs) =
((Text, Text) -> Builder) -> [(Text, Text)] -> Builder
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap
( \(Text
browser, Text
_) ->
[Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat [ Builder
"@" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Text -> Builder
fromText Text
browser Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"keyframes "
, Text -> Builder
fromText Text
ident
, Config -> Builder
newline Config
cfg
, Config -> Builder
lbrace Config
cfg
, Config -> Builder
newline Config
cfg
, ((Double, [Rule]) -> Builder) -> [(Double, [Rule])] -> Builder
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (Config -> (Double, [Rule]) -> Builder
frame Config
cfg) [(Double, [Rule])]
xs
, Config -> Builder
rbrace Config
cfg
, Config -> Builder
newline Config
cfg
, Config -> Builder
newline Config
cfg
]
)
(Prefixed -> [(Text, Text)]
unPrefixed Prefixed
browsers)
frame :: Config -> (Double, [Rule]) -> Builder
frame :: Config -> (Double, [Rule]) -> Builder
frame Config
cfg (Double
p, [Rule]
rs) =
[Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat
[ Text -> Builder
fromText (String -> Text
pack (Double -> String
forall a. Show a => a -> String
show Double
p))
, Builder
"% "
, Config -> [App] -> [Rule] -> Builder
rules Config
cfg [] [Rule]
rs
]
query :: Config -> MediaQuery -> [App] -> [Rule] -> Builder
query :: Config -> MediaQuery -> [App] -> [Rule] -> Builder
query Config
cfg MediaQuery
q [App]
sel [Rule]
rs =
[Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat
[ MediaQuery -> Builder
mediaQuery MediaQuery
q
, Config -> Builder
newline Config
cfg
, Config -> Builder
lbrace Config
cfg
, Config -> Builder
newline Config
cfg
, Config -> [App] -> [Rule] -> Builder
rules Config
cfg [App]
sel [Rule]
rs
, Config -> Builder
rbrace Config
cfg
, Config -> Builder
newline Config
cfg
]
mediaQuery :: MediaQuery -> Builder
mediaQuery :: MediaQuery -> Builder
mediaQuery (MediaQuery Maybe NotOrOnly
no MediaType
ty [Feature]
fs) = [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat
[ Builder
"@media "
, case Maybe NotOrOnly
no of
Maybe NotOrOnly
Nothing -> Builder
""
Just NotOrOnly
Not -> Builder
"not "
Just NotOrOnly
Only -> Builder
"only "
, MediaType -> Builder
mediaType MediaType
ty
, [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat ((Builder
" and " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>) (Builder -> Builder) -> (Feature -> Builder) -> Feature -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Feature -> Builder
feature (Feature -> Builder) -> [Feature] -> [Builder]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Feature]
fs)
]
mediaType :: MediaType -> Builder
mediaType :: MediaType -> Builder
mediaType (MediaType (Value Prefixed
v)) = Text -> Builder
fromText (Prefixed -> Text
plain Prefixed
v)
feature :: Feature -> Builder
feature :: Feature -> Builder
feature (Feature Text
k Maybe Value
mv) =
case Maybe Value
mv of
Maybe Value
Nothing -> Text -> Builder
fromText Text
k
Just (Value Prefixed
v) -> [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat
[ Builder
"(" , Text -> Builder
fromText Text
k , Builder
": " , Text -> Builder
fromText (Prefixed -> Text
plain Prefixed
v) , Builder
")" ]
face :: Config -> [Rule] -> Builder
face :: Config -> [Rule] -> Builder
face Config
cfg [Rule]
rs = [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat
[ Builder
"@font-face"
, Config -> [App] -> [Rule] -> Builder
rules Config
cfg [] [Rule]
rs
]
rules :: Config -> [App] -> [Rule] -> Builder
rules :: Config -> [App] -> [Rule] -> Builder
rules Config
cfg [App]
sel [Rule]
rs = [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat
[ Config -> [App] -> [KeyVal] -> Builder
rule Config
cfg [App]
sel ((Rule -> Maybe KeyVal) -> [Rule] -> [KeyVal]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe Rule -> Maybe KeyVal
property [Rule]
rs)
, Config -> Builder
newline Config
cfg
, Config -> Text -> Builder
imp Config
cfg (Text -> Builder) -> [Text] -> Builder
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
`foldMap` (Rule -> Maybe Text) -> [Rule] -> [Text]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe Rule -> Maybe Text
imports [Rule]
rs
, Config -> Keyframes -> Builder
kframe Config
cfg (Keyframes -> Builder) -> [Keyframes] -> Builder
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
`foldMap` (Rule -> Maybe Keyframes) -> [Rule] -> [Keyframes]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe Rule -> Maybe Keyframes
kframes [Rule]
rs
, Config -> [Rule] -> Builder
face Config
cfg ([Rule] -> Builder) -> [[Rule]] -> Builder
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
`foldMap` (Rule -> Maybe [Rule]) -> [Rule] -> [[Rule]]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe Rule -> Maybe [Rule]
faces [Rule]
rs
, (\(App
a, [Rule]
b) -> Config -> [App] -> [Rule] -> Builder
rules Config
cfg (App
a App -> [App] -> [App]
forall a. a -> [a] -> [a]
: [App]
sel) [Rule]
b) ((App, [Rule]) -> Builder) -> [(App, [Rule])] -> Builder
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
`foldMap` (Rule -> Maybe (App, [Rule])) -> [Rule] -> [(App, [Rule])]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe Rule -> Maybe (App, [Rule])
nested [Rule]
rs
, (\(MediaQuery
a, [Rule]
b) -> Config -> MediaQuery -> [App] -> [Rule] -> Builder
query Config
cfg MediaQuery
a [App]
sel [Rule]
b) ((MediaQuery, [Rule]) -> Builder)
-> [(MediaQuery, [Rule])] -> Builder
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
`foldMap` (Rule -> Maybe (MediaQuery, [Rule]))
-> [Rule] -> [(MediaQuery, [Rule])]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe Rule -> Maybe (MediaQuery, [Rule])
queries [Rule]
rs
]
where property :: Rule -> Maybe KeyVal
property (Property [Modifier]
m Key ()
k Value
v) = KeyVal -> Maybe KeyVal
forall a. a -> Maybe a
Just ([Modifier]
m, Key ()
k, Value
v)
property Rule
_ = Maybe KeyVal
forall a. Maybe a
Nothing
nested :: Rule -> Maybe (App, [Rule])
nested (Nested App
a [Rule]
ns ) = (App, [Rule]) -> Maybe (App, [Rule])
forall a. a -> Maybe a
Just (App
a, [Rule]
ns)
nested Rule
_ = Maybe (App, [Rule])
forall a. Maybe a
Nothing
queries :: Rule -> Maybe (MediaQuery, [Rule])
queries (Query MediaQuery
q [Rule]
ns ) = (MediaQuery, [Rule]) -> Maybe (MediaQuery, [Rule])
forall a. a -> Maybe a
Just (MediaQuery
q, [Rule]
ns)
queries Rule
_ = Maybe (MediaQuery, [Rule])
forall a. Maybe a
Nothing
kframes :: Rule -> Maybe Keyframes
kframes (Keyframe Keyframes
fs ) = Keyframes -> Maybe Keyframes
forall a. a -> Maybe a
Just Keyframes
fs;
kframes Rule
_ = Maybe Keyframes
forall a. Maybe a
Nothing
faces :: Rule -> Maybe [Rule]
faces (Face [Rule]
ns ) = [Rule] -> Maybe [Rule]
forall a. a -> Maybe a
Just [Rule]
ns
faces Rule
_ = Maybe [Rule]
forall a. Maybe a
Nothing
imports :: Rule -> Maybe Text
imports (Import Text
i ) = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
i
imports Rule
_ = Maybe Text
forall a. Maybe a
Nothing
imp :: Config -> Text -> Builder
imp :: Config -> Text -> Builder
imp Config
cfg Text
t =
[Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat
[ Builder
"@import url("
, Text -> Builder
fromText Text
t
, Builder
");"
, Config -> Builder
newline Config
cfg ]
type KeyVal = ([Modifier], Key (), Value)
rule :: Config -> [App] -> [KeyVal] -> Builder
rule :: Config -> [App] -> [KeyVal] -> Builder
rule Config
_ [App]
_ [] = Builder
forall a. Monoid a => a
mempty
rule Config
cfg [App]
sel [KeyVal]
props =
let xs :: [Representation]
xs = KeyVal -> [Representation]
collect (KeyVal -> [Representation]) -> [KeyVal] -> [Representation]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< [KeyVal]
props
in [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat
[ Config -> Selector -> Builder
selector Config
cfg ([App] -> Selector
merger [App]
sel)
, Config -> Builder
newline Config
cfg
, Config -> Builder
lbrace Config
cfg
, Config -> Builder
newline Config
cfg
, Config -> [Representation] -> Builder
properties Config
cfg [Representation]
xs
, Config -> Builder
rbrace Config
cfg
, Config -> Builder
newline Config
cfg
]
merger :: [App] -> Selector
merger :: [App] -> Selector
merger [] = Selector
""
merger (App
x:[App]
xs) =
case App
x of
Rule.Child Selector
s -> case [App]
xs of [] -> Selector
s; [App]
_ -> [App] -> Selector
merger [App]
xs Selector -> Selector -> Selector
|> Selector
s
Sub Selector
s -> case [App]
xs of [] -> Selector
s; [App]
_ -> [App] -> Selector
merger [App]
xs Selector -> Selector -> Selector
** Selector
s
Root Selector
s -> Selector
s Selector -> Selector -> Selector
** [App] -> Selector
merger [App]
xs
Pop Int
i -> [App] -> Selector
merger (Int -> [App] -> [App]
forall a. Int -> [a] -> [a]
drop Int
i (App
xApp -> [App] -> [App]
forall a. a -> [a] -> [a]
:[App]
xs))
Self Refinement
f -> case [App]
xs of [] -> Selector
star Selector -> Refinement -> Selector
`with` Refinement
f; [App]
_ -> [App] -> Selector
merger [App]
xs Selector -> Refinement -> Selector
`with` Refinement
f
data Representation
= Warning Text
| KeyValRep [Modifier] Text Text
deriving (Int -> Representation -> ShowS
[Representation] -> ShowS
Representation -> String
(Int -> Representation -> ShowS)
-> (Representation -> String)
-> ([Representation] -> ShowS)
-> Show Representation
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Representation] -> ShowS
$cshowList :: [Representation] -> ShowS
show :: Representation -> String
$cshow :: Representation -> String
showsPrec :: Int -> Representation -> ShowS
$cshowsPrec :: Int -> Representation -> ShowS
Show)
keys :: [Representation] -> [Text]
keys :: [Representation] -> [Text]
keys = (Representation -> Maybe Text) -> [Representation] -> [Text]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe Representation -> Maybe Text
f
where
f :: Representation -> Maybe Text
f (KeyValRep [Modifier]
_ Text
k Text
_) = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
k
f Representation
_ = Maybe Text
forall a. Maybe a
Nothing
collect :: KeyVal -> [Representation]
collect :: KeyVal -> [Representation]
collect ([Modifier]
ms, Key Prefixed
ky, Value Prefixed
vl) = case (Prefixed
ky, Prefixed
vl) of
( Plain Text
k , Plain Text
v ) -> [Text -> Text -> Representation
prop Text
k Text
v]
( Prefixed [(Text, Text)]
ks , Plain Text
v ) -> (((Text, Text) -> Representation)
-> [(Text, Text)] -> [Representation])
-> [(Text, Text)]
-> ((Text, Text) -> Representation)
-> [Representation]
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((Text, Text) -> Representation)
-> [(Text, Text)] -> [Representation]
forall a b. (a -> b) -> [a] -> [b]
map [(Text, Text)]
ks (((Text, Text) -> Representation) -> [Representation])
-> ((Text, Text) -> Representation) -> [Representation]
forall a b. (a -> b) -> a -> b
$ \(Text
p, Text
k) -> Text -> Text -> Representation
prop (Text
p Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
k) Text
v
( Plain Text
k , Prefixed [(Text, Text)]
vs ) -> (((Text, Text) -> Representation)
-> [(Text, Text)] -> [Representation])
-> [(Text, Text)]
-> ((Text, Text) -> Representation)
-> [Representation]
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((Text, Text) -> Representation)
-> [(Text, Text)] -> [Representation]
forall a b. (a -> b) -> [a] -> [b]
map [(Text, Text)]
vs (((Text, Text) -> Representation) -> [Representation])
-> ((Text, Text) -> Representation) -> [Representation]
forall a b. (a -> b) -> a -> b
$ \(Text
p, Text
v) -> Text -> Text -> Representation
prop Text
k (Text
p Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
v)
( Prefixed [(Text, Text)]
ks , Prefixed [(Text, Text)]
vs ) -> (((Text, Text) -> Representation)
-> [(Text, Text)] -> [Representation])
-> [(Text, Text)]
-> ((Text, Text) -> Representation)
-> [Representation]
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((Text, Text) -> Representation)
-> [(Text, Text)] -> [Representation]
forall a b. (a -> b) -> [a] -> [b]
map [(Text, Text)]
ks (((Text, Text) -> Representation) -> [Representation])
-> ((Text, Text) -> Representation) -> [Representation]
forall a b. (a -> b) -> a -> b
$ \(Text
p, Text
k) -> (Text -> Representation
Warning (Text
p Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
k) Representation
-> (Text -> Representation) -> Maybe Text -> Representation
forall b a. b -> (a -> b) -> Maybe a -> b
`maybe` (Text -> Text -> Representation
prop (Text
p Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
k) (Text -> Representation)
-> (Text -> Text) -> Text -> Representation
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text -> Text
forall a. Monoid a => a -> a -> a
mappend Text
p)) (Text -> [(Text, Text)] -> Maybe Text
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup Text
p [(Text, Text)]
vs)
where prop :: Text -> Text -> Representation
prop Text
k Text
v = [Modifier] -> Text -> Text -> Representation
KeyValRep [Modifier]
ms Text
k Text
v
properties :: Config -> [Representation] -> Builder
properties :: Config -> [Representation] -> Builder
properties Config
cfg [Representation]
xs =
let width :: Int
width = Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum (Text -> Int
Text.length (Text -> Int) -> [Text] -> [Int]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Representation] -> [Text]
keys [Representation]
xs)
ind :: Builder
ind = Config -> Builder
indentation Config
cfg
new :: Builder
new = Config -> Builder
newline Config
cfg
finalSemi :: Builder
finalSemi = if Config -> Bool
finalSemicolon Config
cfg then Builder
";" else Builder
""
in (Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
new) (Builder -> Builder) -> Builder -> Builder
forall a b. (a -> b) -> a -> b
$ (Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
finalSemi) (Builder -> Builder) -> Builder -> Builder
forall a b. (a -> b) -> a -> b
$ Builder -> [Builder] -> Builder
forall a. Monoid a => a -> [a] -> a
intercalate (Builder
";" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
new) ([Builder] -> Builder) -> [Builder] -> Builder
forall a b. (a -> b) -> a -> b
$ ((Representation -> Builder) -> [Representation] -> [Builder])
-> [Representation] -> (Representation -> Builder) -> [Builder]
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Representation -> Builder) -> [Representation] -> [Builder]
forall a b. (a -> b) -> [a] -> [b]
map [Representation]
xs ((Representation -> Builder) -> [Builder])
-> (Representation -> Builder) -> [Builder]
forall a b. (a -> b) -> a -> b
$ \Representation
p ->
case Representation
p of
Warning Text
w -> if Config -> Bool
warn Config
cfg
then Builder
ind Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"/* no value for " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Text -> Builder
fromText Text
w Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
" */" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
new
else Builder
forall a. Monoid a => a
mempty
KeyValRep [Modifier]
ms Text
k Text
v ->
let pad :: Builder
pad = if Config -> Bool
align Config
cfg
then Text -> Builder
fromText (Int -> Text -> Text
Text.replicate (Int
width Int -> Int -> Int
forall a. Num a => a -> a -> a
- Text -> Int
Text.length Text
k) Text
" ")
else Builder
""
imptant :: Builder
imptant = Builder -> (Text -> Builder) -> Maybe Text -> Builder
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Builder
"" ((Builder
" " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>) (Builder -> Builder) -> (Text -> Builder) -> Text -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Builder
fromText) (Maybe Text -> Builder)
-> ([Modifier] -> Maybe Text) -> [Modifier] -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Modifier -> Maybe Text) -> [Modifier] -> Maybe Text
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Modifier -> Maybe Text
_Important ([Modifier] -> Builder) -> [Modifier] -> Builder
forall a b. (a -> b) -> a -> b
$ [Modifier]
ms
comm :: Builder
comm = case ((Modifier -> Maybe CommentText) -> [Modifier] -> Maybe CommentText
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Modifier -> Maybe CommentText
_Comment [Modifier]
ms, Config -> Bool
comments Config
cfg) of
(Just CommentText
c, Bool
True) -> Builder
" /* " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Text -> Builder
fromText (CommentText -> Text
unCommentText CommentText
c) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
" */"
(Maybe CommentText, Bool)
_ -> Builder
forall a. Monoid a => a
mempty
in [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat [Builder
ind, Text -> Builder
fromText Text
k, Builder
pad, Builder
":", Config -> Builder
sep Config
cfg, Text -> Builder
fromText Text
v, Builder
imptant, Builder
comm]
selector :: Config -> Selector -> Builder
selector :: Config -> Selector -> Builder
selector Config { lbrace :: Config -> Builder
lbrace = Builder
"", rbrace :: Config -> Builder
rbrace = Builder
"" } = Selector -> Builder
forall p p. IsString p => p -> p
rec
where rec :: p -> p
rec p
_ = p
""
selector Config
cfg = Builder -> [Builder] -> Builder
forall a. Monoid a => a -> [a] -> a
intercalate (Builder
"," Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Config -> Builder
newline Config
cfg) ([Builder] -> Builder)
-> (Selector -> [Builder]) -> Selector -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Selector -> [Builder]
rec
where rec :: Selector -> [Builder]
rec (In (SelectorF (Refinement [Predicate]
ft) Path Selector
p)) = (Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> (Predicate -> Builder) -> [Predicate] -> Builder
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Predicate -> Builder
predicate ([Predicate] -> [Predicate]
forall a. Ord a => [a] -> [a]
sort [Predicate]
ft)) (Builder -> Builder) -> [Builder] -> [Builder]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
case Path Selector
p of
Path Selector
Star -> if [Predicate] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Predicate]
ft then [Builder
"*"] else [Builder
""]
Elem Text
t -> [Text -> Builder
fromText Text
t]
Child Selector
a Selector
b -> Builder -> Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a -> a
ins Builder
" > " (Builder -> Builder -> Builder)
-> [Builder] -> [Builder -> Builder]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Selector -> [Builder]
rec Selector
a [Builder -> Builder] -> [Builder] -> [Builder]
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Selector -> [Builder]
rec Selector
b
Deep Selector
a Selector
b -> Builder -> Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a -> a
ins Builder
" " (Builder -> Builder -> Builder)
-> [Builder] -> [Builder -> Builder]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Selector -> [Builder]
rec Selector
a [Builder -> Builder] -> [Builder] -> [Builder]
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Selector -> [Builder]
rec Selector
b
Adjacent Selector
a Selector
b -> Builder -> Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a -> a
ins Builder
" + " (Builder -> Builder -> Builder)
-> [Builder] -> [Builder -> Builder]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Selector -> [Builder]
rec Selector
a [Builder -> Builder] -> [Builder] -> [Builder]
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Selector -> [Builder]
rec Selector
b
Sibling Selector
a Selector
b -> Builder -> Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a -> a
ins Builder
" ~ " (Builder -> Builder -> Builder)
-> [Builder] -> [Builder -> Builder]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Selector -> [Builder]
rec Selector
a [Builder -> Builder] -> [Builder] -> [Builder]
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Selector -> [Builder]
rec Selector
b
Combined Selector
a Selector
b -> Selector -> [Builder]
rec Selector
a [Builder] -> [Builder] -> [Builder]
forall a. [a] -> [a] -> [a]
++ Selector -> [Builder]
rec Selector
b
where ins :: a -> a -> a -> a
ins a
s a
a a
b = a
a a -> a -> a
forall a. Semigroup a => a -> a -> a
<> a
s a -> a -> a
forall a. Semigroup a => a -> a -> a
<> a
b
predicate :: Predicate -> Builder
predicate :: Predicate -> Builder
predicate Predicate
ft = [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat ([Builder] -> Builder) -> [Builder] -> Builder
forall a b. (a -> b) -> a -> b
$
case Predicate
ft of
Id Text
a -> [ Builder
"#" , Text -> Builder
fromText Text
a ]
Class Text
a -> [ Builder
"." , Text -> Builder
fromText Text
a ]
Attr Text
a -> [ Builder
"[" , Text -> Builder
fromText Text
a, Builder
"]" ]
AttrVal Text
a Text
v -> [ Builder
"[" , Text -> Builder
fromText Text
a, Builder
"='", Text -> Builder
fromText Text
v, Builder
"']" ]
AttrBegins Text
a Text
v -> [ Builder
"[" , Text -> Builder
fromText Text
a, Builder
"^='", Text -> Builder
fromText Text
v, Builder
"']" ]
AttrEnds Text
a Text
v -> [ Builder
"[" , Text -> Builder
fromText Text
a, Builder
"$='", Text -> Builder
fromText Text
v, Builder
"']" ]
AttrContains Text
a Text
v -> [ Builder
"[" , Text -> Builder
fromText Text
a, Builder
"*='", Text -> Builder
fromText Text
v, Builder
"']" ]
AttrSpace Text
a Text
v -> [ Builder
"[" , Text -> Builder
fromText Text
a, Builder
"~='", Text -> Builder
fromText Text
v, Builder
"']" ]
AttrHyph Text
a Text
v -> [ Builder
"[" , Text -> Builder
fromText Text
a, Builder
"|='", Text -> Builder
fromText Text
v, Builder
"']" ]
Pseudo Text
a -> [ Builder
":" , Text -> Builder
fromText Text
a ]
PseudoFunc Text
a [Text]
p -> [ Builder
":" , Text -> Builder
fromText Text
a, Builder
"(", Builder -> [Builder] -> Builder
forall a. Monoid a => a -> [a] -> a
intercalate Builder
"," ((Text -> Builder) -> [Text] -> [Builder]
forall a b. (a -> b) -> [a] -> [b]
map Text -> Builder
fromText [Text]
p), Builder
")" ]
PseudoElem Text
a -> [ Builder
"::", Text -> Builder
fromText Text
a ]