{-# LANGUAGE CPP, OverloadedStrings #-}
{-# LANGUAGE BangPatterns, RankNTypes #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving #-}
{-# LANGUAGE UndecidableInstances #-}
module Lucid.Base
(
renderText
,renderBS
,renderTextT
,renderBST
,renderToFile
,execHtmlT
,evalHtmlT
,runHtmlT
,relaxHtmlT
,makeElement
,makeElementNoEnd
,makeAttributes
,makeAttributesRaw
,Attributes
,Html
,HtmlT
,Term(..)
,TermRaw(..)
,ToHtml(..))
where
import Blaze.ByteString.Builder (Builder)
import qualified Blaze.ByteString.Builder as Blaze
import qualified Blaze.ByteString.Builder.Html.Utf8 as Blaze
import Control.Applicative
import Control.Monad
import Control.Monad.Fix (MonadFix(..))
import Control.Monad.IO.Class (MonadIO(..))
import Control.Monad.Reader (MonadReader(..))
import Control.Monad.State.Class (MonadState(..))
import Control.Monad.Trans (MonadTrans(..))
import Control.Monad.Trans.State.Strict (StateT(..), modify')
import qualified Data.ByteString as S
import Data.ByteString.Lazy (ByteString)
import qualified Data.ByteString.Lazy as L
import Data.Foldable (toList)
import Data.Functor.Identity
import qualified Data.Map.Strict as M
import Data.Maybe
import Data.Sequence (Seq)
import qualified Data.Set as Set
import Data.String
import Data.Text (Text)
import qualified Data.Text.Encoding as T
import qualified Data.Text.Lazy as LT
import qualified Data.Text.Lazy.Encoding as LT
import Data.Tuple (swap)
import Prelude
data Attribute = Attribute !Text !Builder
newtype Attributes = Attributes { Attributes -> Seq Attribute
unAttributes :: Seq Attribute }
deriving (Semigroup Attributes
Attributes
Semigroup Attributes
-> Attributes
-> (Attributes -> Attributes -> Attributes)
-> ([Attributes] -> Attributes)
-> Monoid Attributes
[Attributes] -> Attributes
Attributes -> Attributes -> Attributes
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
mconcat :: [Attributes] -> Attributes
$cmconcat :: [Attributes] -> Attributes
mappend :: Attributes -> Attributes -> Attributes
$cmappend :: Attributes -> Attributes -> Attributes
mempty :: Attributes
$cmempty :: Attributes
$cp1Monoid :: Semigroup Attributes
Monoid, b -> Attributes -> Attributes
NonEmpty Attributes -> Attributes
Attributes -> Attributes -> Attributes
(Attributes -> Attributes -> Attributes)
-> (NonEmpty Attributes -> Attributes)
-> (forall b. Integral b => b -> Attributes -> Attributes)
-> Semigroup Attributes
forall b. Integral b => b -> Attributes -> Attributes
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
stimes :: b -> Attributes -> Attributes
$cstimes :: forall b. Integral b => b -> Attributes -> Attributes
sconcat :: NonEmpty Attributes -> Attributes
$csconcat :: NonEmpty Attributes -> Attributes
<> :: Attributes -> Attributes -> Attributes
$c<> :: Attributes -> Attributes -> Attributes
Semigroup)
type Html = HtmlT Identity
newtype HtmlT m a = HtmlT { HtmlT m a -> StateT Builder m a
unHtmlT :: StateT Builder m a }
deriving (Applicative (HtmlT m)
a -> HtmlT m a
Applicative (HtmlT m)
-> (forall a b. HtmlT m a -> (a -> HtmlT m b) -> HtmlT m b)
-> (forall a b. HtmlT m a -> HtmlT m b -> HtmlT m b)
-> (forall a. a -> HtmlT m a)
-> Monad (HtmlT m)
HtmlT m a -> (a -> HtmlT m b) -> HtmlT m b
HtmlT m a -> HtmlT m b -> HtmlT m b
forall a. a -> HtmlT m a
forall a b. HtmlT m a -> HtmlT m b -> HtmlT m b
forall a b. HtmlT m a -> (a -> HtmlT m b) -> HtmlT m b
forall (m :: * -> *). Monad m => Applicative (HtmlT m)
forall (m :: * -> *) a. Monad m => a -> HtmlT m a
forall (m :: * -> *) a b.
Monad m =>
HtmlT m a -> HtmlT m b -> HtmlT m b
forall (m :: * -> *) a b.
Monad m =>
HtmlT m a -> (a -> HtmlT m b) -> HtmlT m 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 -> HtmlT m a
$creturn :: forall (m :: * -> *) a. Monad m => a -> HtmlT m a
>> :: HtmlT m a -> HtmlT m b -> HtmlT m b
$c>> :: forall (m :: * -> *) a b.
Monad m =>
HtmlT m a -> HtmlT m b -> HtmlT m b
>>= :: HtmlT m a -> (a -> HtmlT m b) -> HtmlT m b
$c>>= :: forall (m :: * -> *) a b.
Monad m =>
HtmlT m a -> (a -> HtmlT m b) -> HtmlT m b
$cp1Monad :: forall (m :: * -> *). Monad m => Applicative (HtmlT m)
Monad, a -> HtmlT m b -> HtmlT m a
(a -> b) -> HtmlT m a -> HtmlT m b
(forall a b. (a -> b) -> HtmlT m a -> HtmlT m b)
-> (forall a b. a -> HtmlT m b -> HtmlT m a) -> Functor (HtmlT m)
forall a b. a -> HtmlT m b -> HtmlT m a
forall a b. (a -> b) -> HtmlT m a -> HtmlT m b
forall (m :: * -> *) a b. Functor m => a -> HtmlT m b -> HtmlT m a
forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> HtmlT m a -> HtmlT m b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> HtmlT m b -> HtmlT m a
$c<$ :: forall (m :: * -> *) a b. Functor m => a -> HtmlT m b -> HtmlT m a
fmap :: (a -> b) -> HtmlT m a -> HtmlT m b
$cfmap :: forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> HtmlT m a -> HtmlT m b
Functor, Functor (HtmlT m)
a -> HtmlT m a
Functor (HtmlT m)
-> (forall a. a -> HtmlT m a)
-> (forall a b. HtmlT m (a -> b) -> HtmlT m a -> HtmlT m b)
-> (forall a b c.
(a -> b -> c) -> HtmlT m a -> HtmlT m b -> HtmlT m c)
-> (forall a b. HtmlT m a -> HtmlT m b -> HtmlT m b)
-> (forall a b. HtmlT m a -> HtmlT m b -> HtmlT m a)
-> Applicative (HtmlT m)
HtmlT m a -> HtmlT m b -> HtmlT m b
HtmlT m a -> HtmlT m b -> HtmlT m a
HtmlT m (a -> b) -> HtmlT m a -> HtmlT m b
(a -> b -> c) -> HtmlT m a -> HtmlT m b -> HtmlT m c
forall a. a -> HtmlT m a
forall a b. HtmlT m a -> HtmlT m b -> HtmlT m a
forall a b. HtmlT m a -> HtmlT m b -> HtmlT m b
forall a b. HtmlT m (a -> b) -> HtmlT m a -> HtmlT m b
forall a b c. (a -> b -> c) -> HtmlT m a -> HtmlT m b -> HtmlT m c
forall (m :: * -> *). Monad m => Functor (HtmlT m)
forall (m :: * -> *) a. Monad m => a -> HtmlT m a
forall (m :: * -> *) a b.
Monad m =>
HtmlT m a -> HtmlT m b -> HtmlT m a
forall (m :: * -> *) a b.
Monad m =>
HtmlT m a -> HtmlT m b -> HtmlT m b
forall (m :: * -> *) a b.
Monad m =>
HtmlT m (a -> b) -> HtmlT m a -> HtmlT m b
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> c) -> HtmlT m a -> HtmlT m b -> HtmlT m 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
<* :: HtmlT m a -> HtmlT m b -> HtmlT m a
$c<* :: forall (m :: * -> *) a b.
Monad m =>
HtmlT m a -> HtmlT m b -> HtmlT m a
*> :: HtmlT m a -> HtmlT m b -> HtmlT m b
$c*> :: forall (m :: * -> *) a b.
Monad m =>
HtmlT m a -> HtmlT m b -> HtmlT m b
liftA2 :: (a -> b -> c) -> HtmlT m a -> HtmlT m b -> HtmlT m c
$cliftA2 :: forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> c) -> HtmlT m a -> HtmlT m b -> HtmlT m c
<*> :: HtmlT m (a -> b) -> HtmlT m a -> HtmlT m b
$c<*> :: forall (m :: * -> *) a b.
Monad m =>
HtmlT m (a -> b) -> HtmlT m a -> HtmlT m b
pure :: a -> HtmlT m a
$cpure :: forall (m :: * -> *) a. Monad m => a -> HtmlT m a
$cp1Applicative :: forall (m :: * -> *). Monad m => Functor (HtmlT m)
Applicative, m a -> HtmlT m a
(forall (m :: * -> *) a. Monad m => m a -> HtmlT m a)
-> MonadTrans HtmlT
forall (m :: * -> *) a. Monad m => m a -> HtmlT m a
forall (t :: (* -> *) -> * -> *).
(forall (m :: * -> *) a. Monad m => m a -> t m a) -> MonadTrans t
lift :: m a -> HtmlT m a
$clift :: forall (m :: * -> *) a. Monad m => m a -> HtmlT m a
MonadTrans, Monad (HtmlT m)
Monad (HtmlT m)
-> (forall a. (a -> HtmlT m a) -> HtmlT m a) -> MonadFix (HtmlT m)
(a -> HtmlT m a) -> HtmlT m a
forall a. (a -> HtmlT m a) -> HtmlT m a
forall (m :: * -> *).
Monad m -> (forall a. (a -> m a) -> m a) -> MonadFix m
forall (m :: * -> *). MonadFix m => Monad (HtmlT m)
forall (m :: * -> *) a. MonadFix m => (a -> HtmlT m a) -> HtmlT m a
mfix :: (a -> HtmlT m a) -> HtmlT m a
$cmfix :: forall (m :: * -> *) a. MonadFix m => (a -> HtmlT m a) -> HtmlT m a
$cp1MonadFix :: forall (m :: * -> *). MonadFix m => Monad (HtmlT m)
MonadFix)
instance MonadReader r m => MonadReader r (HtmlT m) where
ask :: HtmlT m r
ask = m r -> HtmlT m r
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m r
forall r (m :: * -> *). MonadReader r m => m r
ask
local :: (r -> r) -> HtmlT m a -> HtmlT m a
local r -> r
f (HtmlT StateT Builder m a
a) = StateT Builder m a -> HtmlT m a
forall (m :: * -> *) a. StateT Builder m a -> HtmlT m a
HtmlT ((r -> r) -> StateT Builder m a -> StateT Builder m a
forall r (m :: * -> *) a. MonadReader r m => (r -> r) -> m a -> m a
local r -> r
f StateT Builder m a
a)
instance MonadState s m => MonadState s (HtmlT m) where
get :: HtmlT m s
get = m s -> HtmlT m s
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m s
forall s (m :: * -> *). MonadState s m => m s
get
put :: s -> HtmlT m ()
put = m () -> HtmlT m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> HtmlT m ()) -> (s -> m ()) -> s -> HtmlT m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. s -> m ()
forall s (m :: * -> *). MonadState s m => s -> m ()
put
state :: (s -> (a, s)) -> HtmlT m a
state = m a -> HtmlT m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m a -> HtmlT m a)
-> ((s -> (a, s)) -> m a) -> (s -> (a, s)) -> HtmlT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (s -> (a, s)) -> m a
forall s (m :: * -> *) a. MonadState s m => (s -> (a, s)) -> m a
state
runHtmlT :: Monad m => HtmlT m a -> m (Builder, a)
runHtmlT :: HtmlT m a -> m (Builder, a)
runHtmlT = ((a, Builder) -> (Builder, a)) -> m (a, Builder) -> m (Builder, a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a, Builder) -> (Builder, a)
forall a b. (a, b) -> (b, a)
swap (m (a, Builder) -> m (Builder, a))
-> (HtmlT m a -> m (a, Builder)) -> HtmlT m a -> m (Builder, a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (StateT Builder m a -> Builder -> m (a, Builder))
-> Builder -> StateT Builder m a -> m (a, Builder)
forall a b c. (a -> b -> c) -> b -> a -> c
flip StateT Builder m a -> Builder -> m (a, Builder)
forall s (m :: * -> *) a. StateT s m a -> s -> m (a, s)
runStateT Builder
forall a. Monoid a => a
mempty (StateT Builder m a -> m (a, Builder))
-> (HtmlT m a -> StateT Builder m a) -> HtmlT m a -> m (a, Builder)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HtmlT m a -> StateT Builder m a
forall (m :: * -> *) a. HtmlT m a -> StateT Builder m a
unHtmlT
instance (a ~ (),Monad m) => Semigroup (HtmlT m a) where
<> :: HtmlT m a -> HtmlT m a -> HtmlT m a
(<>) = (a -> a -> a) -> HtmlT m a -> HtmlT m a -> HtmlT m a
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 a -> a -> a
forall a. Semigroup a => a -> a -> a
(<>)
instance (a ~ (),Monad m) => Monoid (HtmlT m a) where
mempty :: HtmlT m a
mempty = a -> HtmlT m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
forall a. Monoid a => a
mempty
mappend :: HtmlT m a -> HtmlT m a -> HtmlT m a
mappend = (a -> a -> a) -> HtmlT m a -> HtmlT m a -> HtmlT m a
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 a -> a -> a
forall a. Monoid a => a -> a -> a
mappend
instance MonadIO m => MonadIO (HtmlT m) where
liftIO :: IO a -> HtmlT m a
liftIO = m a -> HtmlT m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m a -> HtmlT m a) -> (IO a -> m a) -> IO a -> HtmlT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO
instance (Monad m,a ~ ()) => IsString (HtmlT m a) where
fromString :: String -> HtmlT m a
fromString = String -> HtmlT m a
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
toHtml
instance (m ~ Identity) => Show (HtmlT m a) where
show :: HtmlT m a -> String
show = Text -> String
LT.unpack (Text -> String) -> (Html a -> Text) -> Html a -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Html a -> Text
forall a. Html a -> Text
renderText
class ToHtml a where
toHtml :: Monad m => a -> HtmlT m ()
toHtmlRaw :: Monad m => a -> HtmlT m ()
instance (a ~ (), m ~ Identity) => ToHtml (HtmlT m a) where
toHtml :: HtmlT m a -> HtmlT m ()
toHtml = HtmlT m a -> HtmlT m ()
forall (m :: * -> *) a. Monad m => HtmlT Identity a -> HtmlT m a
relaxHtmlT
toHtmlRaw :: HtmlT m a -> HtmlT m ()
toHtmlRaw = HtmlT m a -> HtmlT m ()
forall (m :: * -> *) a. Monad m => HtmlT Identity a -> HtmlT m a
relaxHtmlT
instance ToHtml String where
toHtml :: String -> HtmlT m ()
toHtml = Builder -> HtmlT m ()
forall (m :: * -> *). Monad m => Builder -> HtmlT m ()
write (Builder -> HtmlT m ())
-> (String -> Builder) -> String -> HtmlT m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Builder
Blaze.fromHtmlEscapedString
toHtmlRaw :: String -> HtmlT m ()
toHtmlRaw = Builder -> HtmlT m ()
forall (m :: * -> *). Monad m => Builder -> HtmlT m ()
write (Builder -> HtmlT m ())
-> (String -> Builder) -> String -> HtmlT m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Builder
Blaze.fromString
instance ToHtml Text where
toHtml :: Text -> HtmlT m ()
toHtml = Builder -> HtmlT m ()
forall (m :: * -> *). Monad m => Builder -> HtmlT m ()
write (Builder -> HtmlT m ()) -> (Text -> Builder) -> Text -> HtmlT m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Builder
Blaze.fromHtmlEscapedText
toHtmlRaw :: Text -> HtmlT m ()
toHtmlRaw = Builder -> HtmlT m ()
forall (m :: * -> *). Monad m => Builder -> HtmlT m ()
write (Builder -> HtmlT m ()) -> (Text -> Builder) -> Text -> HtmlT m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Builder
Blaze.fromText
instance ToHtml LT.Text where
toHtml :: Text -> HtmlT m ()
toHtml = Builder -> HtmlT m ()
forall (m :: * -> *). Monad m => Builder -> HtmlT m ()
write (Builder -> HtmlT m ()) -> (Text -> Builder) -> Text -> HtmlT m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Builder
Blaze.fromHtmlEscapedLazyText
toHtmlRaw :: Text -> HtmlT m ()
toHtmlRaw = Builder -> HtmlT m ()
forall (m :: * -> *). Monad m => Builder -> HtmlT m ()
write (Builder -> HtmlT m ()) -> (Text -> Builder) -> Text -> HtmlT m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Builder
Blaze.fromLazyText
instance ToHtml S.ByteString where
toHtml :: ByteString -> HtmlT m ()
toHtml = Builder -> HtmlT m ()
forall (m :: * -> *). Monad m => Builder -> HtmlT m ()
write (Builder -> HtmlT m ())
-> (ByteString -> Builder) -> ByteString -> HtmlT m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Builder
Blaze.fromHtmlEscapedText (Text -> Builder) -> (ByteString -> Text) -> ByteString -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Text
T.decodeUtf8
toHtmlRaw :: ByteString -> HtmlT m ()
toHtmlRaw = Builder -> HtmlT m ()
forall (m :: * -> *). Monad m => Builder -> HtmlT m ()
write (Builder -> HtmlT m ())
-> (ByteString -> Builder) -> ByteString -> HtmlT m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Builder
Blaze.fromByteString
instance ToHtml L.ByteString where
toHtml :: ByteString -> HtmlT m ()
toHtml = Builder -> HtmlT m ()
forall (m :: * -> *). Monad m => Builder -> HtmlT m ()
write (Builder -> HtmlT m ())
-> (ByteString -> Builder) -> ByteString -> HtmlT m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Builder
Blaze.fromHtmlEscapedLazyText (Text -> Builder) -> (ByteString -> Text) -> ByteString -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Text
LT.decodeUtf8
toHtmlRaw :: ByteString -> HtmlT m ()
toHtmlRaw = Builder -> HtmlT m ()
forall (m :: * -> *). Monad m => Builder -> HtmlT m ()
write (Builder -> HtmlT m ())
-> (ByteString -> Builder) -> ByteString -> HtmlT m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Builder
Blaze.fromLazyByteString
class Term arg result | result -> arg where
term :: Text
-> arg
-> result
instance (Monad m,f ~ HtmlT m a) => Term [Attributes] (f -> HtmlT m a) where
term :: Text -> [Attributes] -> f -> HtmlT m a
term Text
name = Text -> [Attributes] -> HtmlT m a -> HtmlT m a
forall (m :: * -> *) a.
Monad m =>
Text -> [Attributes] -> HtmlT m a -> HtmlT m a
makeElement Text
name
instance (Monad m) => Term (HtmlT m a) (HtmlT m a) where
term :: Text -> HtmlT m a -> HtmlT m a
term Text
name = Text -> [Attributes] -> HtmlT m a -> HtmlT m a
forall (m :: * -> *) a.
Monad m =>
Text -> [Attributes] -> HtmlT m a -> HtmlT m a
makeElement Text
name [Attributes]
forall a. Monoid a => a
mempty
{-# INLINE term #-}
instance Term Text Attributes where
term :: Text -> Text -> Attributes
term Text
key Text
value = Text -> Text -> Attributes
makeAttributes Text
key Text
value
class TermRaw arg result | result -> arg where
termRaw :: Text
-> arg
-> result
instance (Monad m,ToHtml f, a ~ ()) => TermRaw [Attributes] (f -> HtmlT m a) where
termRaw :: Text -> [Attributes] -> f -> HtmlT m a
termRaw Text
name [Attributes]
attrs = Text -> [Attributes] -> HtmlT m () -> HtmlT m ()
forall (m :: * -> *) a.
Monad m =>
Text -> [Attributes] -> HtmlT m a -> HtmlT m a
makeElement Text
name [Attributes]
attrs (HtmlT m () -> HtmlT m ()) -> (f -> HtmlT m ()) -> f -> HtmlT m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. f -> HtmlT m ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
toHtmlRaw
instance (Monad m,a ~ ()) => TermRaw Text (HtmlT m a) where
termRaw :: Text -> Text -> HtmlT m a
termRaw Text
name = Text -> [Attributes] -> HtmlT m () -> HtmlT m ()
forall (m :: * -> *) a.
Monad m =>
Text -> [Attributes] -> HtmlT m a -> HtmlT m a
makeElement Text
name [Attributes]
forall a. Monoid a => a
mempty (HtmlT m () -> HtmlT m ())
-> (Text -> HtmlT m ()) -> Text -> HtmlT m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> HtmlT m ()
forall a (m :: * -> *). (ToHtml a, Monad m) => a -> HtmlT m ()
toHtmlRaw
instance TermRaw Text Attributes where
termRaw :: Text -> Text -> Attributes
termRaw Text
key Text
value = Text -> Text -> Attributes
makeAttributesRaw Text
key Text
value
renderToFile :: FilePath -> Html a -> IO ()
renderToFile :: String -> Html a -> IO ()
renderToFile String
fp = String -> ByteString -> IO ()
L.writeFile String
fp (ByteString -> IO ()) -> (Html a -> ByteString) -> Html a -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> ByteString
Blaze.toLazyByteString (Builder -> ByteString)
-> (Html a -> Builder) -> Html a -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Identity Builder -> Builder
forall a. Identity a -> a
runIdentity (Identity Builder -> Builder)
-> (Html a -> Identity Builder) -> Html a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Html a -> Identity Builder
forall (m :: * -> *) a. Monad m => HtmlT m a -> m Builder
execHtmlT
renderBS :: Html a -> ByteString
renderBS :: Html a -> ByteString
renderBS = Builder -> ByteString
Blaze.toLazyByteString (Builder -> ByteString)
-> (Html a -> Builder) -> Html a -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Identity Builder -> Builder
forall a. Identity a -> a
runIdentity (Identity Builder -> Builder)
-> (Html a -> Identity Builder) -> Html a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Html a -> Identity Builder
forall (m :: * -> *) a. Monad m => HtmlT m a -> m Builder
execHtmlT
renderText :: Html a -> LT.Text
renderText :: Html a -> Text
renderText = ByteString -> Text
LT.decodeUtf8 (ByteString -> Text) -> (Html a -> ByteString) -> Html a -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> ByteString
Blaze.toLazyByteString (Builder -> ByteString)
-> (Html a -> Builder) -> Html a -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Identity Builder -> Builder
forall a. Identity a -> a
runIdentity (Identity Builder -> Builder)
-> (Html a -> Identity Builder) -> Html a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Html a -> Identity Builder
forall (m :: * -> *) a. Monad m => HtmlT m a -> m Builder
execHtmlT
renderBST :: Monad m => HtmlT m a -> m ByteString
renderBST :: HtmlT m a -> m ByteString
renderBST = (Builder -> ByteString) -> m Builder -> m ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Builder -> ByteString
Blaze.toLazyByteString (m Builder -> m ByteString)
-> (HtmlT m a -> m Builder) -> HtmlT m a -> m ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HtmlT m a -> m Builder
forall (m :: * -> *) a. Monad m => HtmlT m a -> m Builder
execHtmlT
renderTextT :: Monad m => HtmlT m a -> m LT.Text
renderTextT :: HtmlT m a -> m Text
renderTextT = (Builder -> Text) -> m Builder -> m Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (ByteString -> Text
LT.decodeUtf8 (ByteString -> Text) -> (Builder -> ByteString) -> Builder -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> ByteString
Blaze.toLazyByteString) (m Builder -> m Text)
-> (HtmlT m a -> m Builder) -> HtmlT m a -> m Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HtmlT m a -> m Builder
forall (m :: * -> *) a. Monad m => HtmlT m a -> m Builder
execHtmlT
execHtmlT :: Monad m
=> HtmlT m a
-> m Builder
execHtmlT :: HtmlT m a -> m Builder
execHtmlT HtmlT m a
m =
do (Builder
builder,a
_) <- HtmlT m a -> m (Builder, a)
forall (m :: * -> *) a. Monad m => HtmlT m a -> m (Builder, a)
runHtmlT HtmlT m a
m
Builder -> m Builder
forall (m :: * -> *) a. Monad m => a -> m a
return Builder
builder
{-# inline execHtmlT #-}
relaxHtmlT :: Monad m
=> HtmlT Identity a
-> HtmlT m a
relaxHtmlT :: HtmlT Identity a -> HtmlT m a
relaxHtmlT = HtmlT Identity a -> HtmlT m a
forall a. HasCallStack => a
undefined
evalHtmlT :: Monad m
=> HtmlT m a
-> m a
evalHtmlT :: HtmlT m a -> m a
evalHtmlT HtmlT m a
m =
do (Builder
_,a
a) <- HtmlT m a -> m (Builder, a)
forall (m :: * -> *) a. Monad m => HtmlT m a -> m (Builder, a)
runHtmlT HtmlT m a
m
a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return a
a
makeAttributes :: Text
-> Text
-> Attributes
makeAttributes :: Text -> Text -> Attributes
makeAttributes Text
x Text
y = Seq Attribute -> Attributes
Attributes (Attribute -> Seq Attribute
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Builder -> Attribute
Attribute Text
x (Text -> Builder
Blaze.fromHtmlEscapedText Text
y)))
makeAttributesRaw ::
Text
-> Text
-> Attributes
makeAttributesRaw :: Text -> Text -> Attributes
makeAttributesRaw Text
x Text
y = Seq Attribute -> Attributes
Attributes (Attribute -> Seq Attribute
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Builder -> Attribute
Attribute Text
x (Text -> Builder
Blaze.fromText Text
y)))
makeElement :: Monad m
=> Text
-> [Attributes]
-> HtmlT m a
-> HtmlT m a
{-# INLINE[1] makeElement #-}
makeElement :: Text -> [Attributes] -> HtmlT m a -> HtmlT m a
makeElement Text
name [Attributes]
attr HtmlT m a
children = do
Builder -> HtmlT m ()
forall (m :: * -> *). Monad m => Builder -> HtmlT m ()
write
(String -> Builder
s String
"<" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Text -> Builder
Blaze.fromText Text
name Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> (Text -> Builder -> Builder) -> Seq Attribute -> Builder
foldlMapWithKey Text -> Builder -> Builder
buildAttr ([Attributes] -> Seq Attribute
attributeList [Attributes]
attr) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> String -> Builder
s String
">")
a
v <- HtmlT m a
children
Builder -> HtmlT m ()
forall (m :: * -> *). Monad m => Builder -> HtmlT m ()
write (String -> Builder
s String
"</" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Text -> Builder
Blaze.fromText Text
name Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> String -> Builder
s String
">")
a -> HtmlT m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
v
makeElementNoEnd :: Monad m
=> Text
-> [Attributes]
-> HtmlT m ()
makeElementNoEnd :: Text -> [Attributes] -> HtmlT m ()
makeElementNoEnd Text
name [Attributes]
attr =
Builder -> HtmlT m ()
forall (m :: * -> *). Monad m => Builder -> HtmlT m ()
write
(String -> Builder
s String
"<" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Text -> Builder
Blaze.fromText Text
name Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> (Text -> Builder -> Builder) -> Seq Attribute -> Builder
foldlMapWithKey Text -> Builder -> Builder
buildAttr ([Attributes] -> Seq Attribute
attributeList [Attributes]
attr) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> String -> Builder
s String
">")
buildAttr :: Text -> Builder -> Builder
buildAttr :: Text -> Builder -> Builder
buildAttr Text
key Builder
val = String -> Builder
s String
" " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Text -> Builder
Blaze.fromText Text
key Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> String -> Builder
s String
"=\"" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
val Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> String -> Builder
s String
"\""
foldlMapWithKey :: (Text -> Builder -> Builder) -> Seq Attribute -> Builder
foldlMapWithKey :: (Text -> Builder -> Builder) -> Seq Attribute -> Builder
foldlMapWithKey Text -> Builder -> Builder
f Seq Attribute
attributes =
case [Text] -> Maybe [Text]
forall a. Ord a => [a] -> Maybe [a]
nubOrdMaybe (((Text, Builder) -> Text) -> [(Text, Builder)] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (Text, Builder) -> Text
forall a b. (a, b) -> a
fst [(Text, Builder)]
pairs) of
Just [Text]
keyList ->
(Text -> Builder) -> [Text] -> Builder
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (\Text
k -> Builder -> Maybe Builder -> Builder
forall a. a -> Maybe a -> a
fromMaybe Builder
forall a. Monoid a => a
mempty ((Builder -> Builder) -> Maybe Builder -> Maybe Builder
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Text -> Builder -> Builder
f Text
k) (Text -> Map Text Builder -> Maybe Builder
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup Text
k Map Text Builder
values))) [Text]
keyList
where values :: Map Text Builder
values = (Text -> Builder -> Builder -> Builder)
-> [(Text, Builder)] -> Map Text Builder
forall k a. Ord k => (k -> a -> a -> a) -> [(k, a)] -> Map k a
M.fromListWithKey Text -> Builder -> Builder -> Builder
combineAttributes [(Text, Builder)]
pairs
Maybe [Text]
Nothing -> (Attribute -> Builder) -> Seq Attribute -> Builder
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (\(Attribute Text
k Builder
v) -> Text -> Builder -> Builder
f Text
k Builder
v) Seq Attribute
attributes
where
pairs :: [(Text, Builder)]
pairs = (Attribute -> (Text, Builder)) -> [Attribute] -> [(Text, Builder)]
forall a b. (a -> b) -> [a] -> [b]
map (\(Attribute Text
k Builder
v) -> (Text
k,Builder
v)) (Seq Attribute -> [Attribute]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList Seq Attribute
attributes)
combineAttributes :: Text -> Builder -> Builder -> Builder
combineAttributes :: Text -> Builder -> Builder -> Builder
combineAttributes Text
"class" Builder
v2 Builder
v1 = Builder
v1 Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
" " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
v2
combineAttributes Text
"style" Builder
v2 Builder
v1 = Builder
v1 Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
";" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
v2
combineAttributes Text
_ Builder
v2 Builder
v1 = Builder
v1 Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
v2
nubOrdMaybe :: Ord a => [a] -> Maybe [a]
nubOrdMaybe :: [a] -> Maybe [a]
nubOrdMaybe = Bool -> Set a -> [a] -> [a] -> Maybe [a]
forall a. Ord a => Bool -> Set a -> [a] -> [a] -> Maybe [a]
go Bool
False Set a
forall a. Set a
Set.empty []
where
go :: Bool -> Set a -> [a] -> [a] -> Maybe [a]
go (!Bool
removed) Set a
set [a]
acc (a
x:[a]
xs)
| a
x a -> Set a -> Bool
forall a. Ord a => a -> Set a -> Bool
`Set.member` Set a
set = Bool -> Set a -> [a] -> [a] -> Maybe [a]
go Bool
True Set a
set [a]
acc [a]
xs
| Bool
otherwise = Bool -> Set a -> [a] -> [a] -> Maybe [a]
go Bool
removed (a -> Set a -> Set a
forall a. Ord a => a -> Set a -> Set a
Set.insert a
x Set a
set) (a
x a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
acc) [a]
xs
go Bool
removed Set a
_set [a]
acc [] =
if Bool
removed
then [a] -> Maybe [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([a] -> [a]
forall a. [a] -> [a]
reverse [a]
acc)
else Maybe [a]
forall a. Maybe a
Nothing
s :: String -> Builder
s :: String -> Builder
s = String -> Builder
Blaze.fromString
{-# INLINE s #-}
write :: Monad m => Builder -> HtmlT m ()
write :: Builder -> HtmlT m ()
write Builder
b = StateT Builder m () -> HtmlT m ()
forall (m :: * -> *) a. StateT Builder m a -> HtmlT m a
HtmlT ((Builder -> Builder) -> StateT Builder m ()
forall (m :: * -> *) s. Monad m => (s -> s) -> StateT s m ()
modify' (Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
b))
{-# inline write #-}
attributeList :: [Attributes] -> Seq Attribute
attributeList :: [Attributes] -> Seq Attribute
attributeList = (Attributes -> Seq Attribute) -> [Attributes] -> Seq Attribute
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Attributes -> Seq Attribute
unAttributes