module Data.CSS.Render
(
renderCSS,
renderCSST,
fromCSS
)
where
import qualified Data.Map as M
import qualified Data.Set as S
import Blaze.ByteString.Builder
import Blaze.ByteString.Builder.Char.Utf8
import Control.Monad.Writer
import Data.CSS.Types
import Data.CSS.Utils
import Data.Foldable (fold, foldMap)
import Data.List
fromCSS :: CSS -> Builder
fromCSS (CSS imports medias) =
foldMap (uncurry fromImport) (M.toAscList imports) <>
foldMap (uncurry media) (M.toAscList medias)
where
bs = fromByteString
fromImport uri mts
| S.member "all" mts = bs "@import url(" <> cssString uri <> bs ");"
| otherwise =
bs "@import url(" <> cssString uri <> fromChar ')' <>
(fold . intersperse (fromChar ',') . map (bs . _mediaTypeStr) . S.toAscList) mts <>
fromChar ';'
media mts props
| null props = mempty
| S.null mts = mempty
| S.member "all" mts = properties0 props
| otherwise =
bs "@media " <>
(commasBS . map _mediaTypeStr . S.toList) mts <>
fromChar '{' <>
properties0 props <>
fromChar '}'
properties0 [] = mempty
properties0 (Property sels (PropName name) (PropValue val) imp : props) =
(commasBS . map _selectorStr) sels <> fromChar '{' <>
bs name <> fromChar ':' <> bs val <>
(if imp then fromByteString " !important" else mempty) <>
properties sels props
properties _ [] = fromChar '}'
properties sels' props0@(Property sels (PropName name) (PropValue val) imp : props)
| sels' == sels =
fromChar ';' <>
bs name <> fromChar ':' <> bs val <>
(if imp then fromByteString " !important" else mempty) <>
properties sels props
| otherwise = fromChar '}' <> properties0 props0
renderCSS :: Writer CSS a -> Builder
renderCSS = fromCSS . execWriter
renderCSST :: (Monad m) => WriterT CSS m a -> m Builder
renderCSST = liftM fromCSS . execWriterT