module Text.XHtmlCombinators.Internal where
import Control.Applicative
import Control.Monad
import Control.Monad.Trans.Class
import Control.Monad.Trans.Writer
import Data.Functor.Identity
import Data.Monoid
import Data.Sequence
import qualified Data.Sequence as Seq
import Data.Text (Text)
import qualified Data.Text as T
newtype XHtmlMT x t a = XHtmlMT
{ unXHtmlMT :: WriterT (Seq x) t a }
instance Functor t => Functor (XHtmlMT x t) where
fmap f (XHtmlMT w) = XHtmlMT $ fmap f w
instance (Functor t, Monad t) => Applicative (XHtmlMT x t) where
pure = return
(<*>) = ap
instance Monad t => Monad (XHtmlMT x t) where
return = XHtmlMT . return
(XHtmlMT w) >>= f = XHtmlMT $ w >>= unXHtmlMT . f
instance MonadTrans (XHtmlMT x) where
lift = XHtmlMT . lift
tellS :: Monad t => x -> XHtmlMT x t ()
tellS = XHtmlMT . tell . singleton
execXHtmlMT :: Monad t => XHtmlMT x t () -> t (Seq x)
execXHtmlMT = execWriterT . unXHtmlMT
type XHtmlT t x = XHtmlMT x t ()
type XHtml x = XHtmlT Identity x
empty :: Monad t => XHtmlT t x
empty = return ()
type Attrs = [Attr]
data Attr = Attr Text Text deriving (Show)
data Node = Node Text Attrs Attrs (Seq Node)
| TextNode Text
deriving (Show)
class CData c where
cdata :: Text -> c
text :: (Functor t, Monad t, CData c) => Text -> XHtmlT t c
text = tellS . cdata
class Content e where
toContent :: e -> Node
newtype Root = Root { rootToNode :: Node }
instance Content Root where toContent = rootToNode
textNode :: Text -> Attrs -> Attrs -> Text -> Node
textNode name rattrs attrs content =
Node name rattrs attrs (singleton (TextNode content))
emptyNode :: Text -> Attrs -> Attrs -> Node
emptyNode name rattrs attrs = Node name rattrs attrs Seq.empty
node :: (Functor t, Monad t, Content e) => Text -> Attrs -> Attrs -> XHtmlT t e -> t Node
node name rattrs attrs content = do
nodes <- fmap toContent <$> execXHtmlMT content
return $ Node name rattrs attrs nodes
tellTextNode :: Monad t => (Node -> e) -> Text -> Attrs -> Attrs -> Text -> XHtmlT t e
tellTextNode c name rattrs attrs = tellS . c . textNode name rattrs attrs
tellEmptyNode :: Monad t => (Node -> e) -> Text -> Attrs -> Attrs -> XHtmlT t e
tellEmptyNode c name rattrs = tellS . c . emptyNode name rattrs
tellNode :: (Functor t, Monad t, Content a)
=> (Node -> b) -> Text -> Attrs -> Attrs -> XHtmlT t a -> XHtmlT t b
tellNode c name rattrs attrs content = do
n <- lift $ node name rattrs attrs content
tellS (c n)
first :: Seq a -> a
first seq | x :< _ <- viewl seq = x