{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
module Shpadoinkle.Backend.Static ( renderStatic ) where
import Control.Compactable
import Data.Monoid ((<>))
import Data.Text
import Shpadoinkle hiding (name, props, text)
renderStatic :: Html m a -> Text
renderStatic = \case
Node tag props _ | isSelfClosing tag
-> renderSelfClosing tag props
Node tag props cs -> renderWrapping tag props cs
Potato _ -> mempty
TextNode t -> t
isSelfClosing :: Text -> Bool
isSelfClosing = flip elem
[ "area", "base", "br", "embed", "hr", "iframe"
, "img", "input", "link", "meta", "param", "source", "track" ]
renderWrapping :: Text -> [(Text, Prop m a)] -> [Html m a] -> Text
renderWrapping tag props cs = renderOpening tag props <> ">"
<> mconcat (renderStatic <$> cs) <> "</" <> tag <> ">"
renderSelfClosing :: Text -> [(Text, Prop m a)] -> Text
renderSelfClosing tag props = renderOpening tag props <> " />"
renderOpening :: Text -> [(Text, Prop m a)] -> Text
renderOpening tag props = let ps = renderProps props in
"<" <> tag <> (if Data.Text.null ps then mempty else " " <> ps)
renderProps :: [(Text, Prop m a)] -> Text
renderProps = Data.Text.unwords . fmapMaybe (uncurry renderProp)
renderProp :: Text -> Prop m a -> Maybe Text
renderProp name = \case
PListener _ -> Nothing
PText t -> Just $ name <> "=\"" <> t <> "\""
PFlag True -> Just name
PFlag False -> Nothing