module Web.Page.Widget
(
Widget(..),
MonadWidget,
WidgetWriter,
addBody,
addHead,
addScript,
addScriptLink,
addSection,
addStyle,
addStyleLink,
setTitle,
withTitle,
wHead,
wScript,
wScriptLinks,
wSections,
wStyle,
wStyleLinks,
wTitle
)
where
import qualified Data.Map.Strict as M
import qualified Data.Set as S
import Clay (Css)
import Control.Applicative
import Control.Lens
import Control.Monad.Writer.Class
import Data.Foldable (Foldable)
import Data.Map (Map)
import Data.Monoid
import Data.Set (Set)
import Data.Text (Text)
import Data.Typeable
import Language.Javascript.JMacro (JStat)
import Text.Blaze.Html
type MonadWidget k url = MonadWriter (Widget k url)
data Widget k url =
Widget {
_wHead :: Html,
_wScript :: JStat,
_wScriptLinks :: Set url,
_wSections :: Map k Html,
_wStyle :: Css,
_wStyleLinks :: Set url,
_wTitle :: Last [Text]
}
deriving (Foldable, Typeable)
instance (Ord k, Ord url) => Monoid (Widget k url) where
mempty =
Widget { _wHead = mempty,
_wScript = mempty,
_wScriptLinks = mempty,
_wSections = M.empty,
_wStyle = return (),
_wStyleLinks = mempty,
_wTitle = mempty }
mappend w1 w2 =
Widget { _wHead = _wHead w1 <> _wHead w2,
_wScript = _wScript w1 <> _wScript w2,
_wScriptLinks = _wScriptLinks w1 <> _wScriptLinks w2,
_wSections = M.unionWith (<>) (_wSections w1) (_wSections w2),
_wStyle = _wStyle w1 >> _wStyle w2,
_wStyleLinks = _wStyleLinks w1 <> _wStyleLinks w2,
_wTitle = _wTitle w1 <> _wTitle w2 }
type WidgetWriter k url a = forall m. (MonadWidget k url m) => m a
addBody :: (MonadWriter (Widget () url) m) => Html -> m ()
addBody = addSection ()
addHead :: (MonadWriter (Widget k url) m) => Html -> m ()
addHead = scribe wHead
addScript :: (MonadWriter (Widget k url) m) => JStat -> m ()
addScript = scribe wScript
addScriptLink :: (MonadWriter (Widget k url) m) => url -> m ()
addScriptLink url = scribe wScriptLinks (S.singleton url)
addSection :: (MonadWriter (Widget k url) m) => k -> Html -> m ()
addSection k = scribe wSections . M.singleton k
addStyle :: (MonadWriter (Widget k url) m) => Css -> m ()
addStyle = scribe wStyle
addStyleLink :: (MonadWriter (Widget k url) m) => url -> m ()
addStyleLink url = scribe wStyleLinks (S.singleton url)
setTitle :: (MonadWriter (Widget k url) m) => Text -> m ()
setTitle x = scribe wTitle (Last (Just [x]))
wHead :: Lens' (Widget k url) Html
wHead l w = (\x -> w { _wHead = x }) <$> l (_wHead w)
withTitle :: (MonadWriter (Widget k url) m) => Text -> m a -> m a
withTitle x = censoring wTitle f
where
f (Last Nothing) = Last Nothing
f (Last (Just xs)) = Last (Just (x:xs))
wScript :: Lens' (Widget k url) JStat
wScript l w = (\x -> w { _wScript = x }) <$> l (_wScript w)
wScriptLinks :: Lens' (Widget k url) (Set url)
wScriptLinks l w = (\x -> w { _wScriptLinks = x }) <$> l (_wScriptLinks w)
wSections :: Lens' (Widget k url) (Map k Html)
wSections l w = (\x -> w { _wSections = x }) <$> l (_wSections w)
wStyle :: Lens' (Widget k url) Css
wStyle l w = (\x -> w { _wStyle = x }) <$> l (_wStyle w)
wStyleLinks :: Lens' (Widget k url) (Set url)
wStyleLinks l w = (\x -> w { _wStyleLinks = x }) <$> l (_wStyleLinks w)
wTitle :: Lens' (Widget k url) (Last [Text])
wTitle l w = (\x -> w { _wTitle = x }) <$> l (_wTitle w)