module HSP.HTML (
renderAsHTML
) where
import Data.List
import HSP.XML
import HSP.XML.PCDATA(unescape)
renderAsHTML :: XML -> String
renderAsHTML xml = renderAsHTML' 0 xml ""
data TagType = Open | Close
renderAsHTML' :: Int -> XML -> ShowS
renderAsHTML' _ (CDATA cd) = showString cd
renderAsHTML' n elm@(Element name@(Nothing,nm) attrs children)
| nm == "area" = renderTagEmpty children
| nm == "base" = renderTagEmpty children
| nm == "br" = renderTagEmpty children
| nm == "col" = renderTagEmpty children
| nm == "hr" = renderTagEmpty children
| nm == "img" = renderTagEmpty children
| nm == "input" = renderTagEmpty children
| nm == "link" = renderTagEmpty children
| nm == "meta" = renderTagEmpty children
| nm == "param" = renderTagEmpty children
| nm == "script" = renderTagCDATA children
| nm == "style" = renderTagCDATA children
where
renderTagEmpty [] = renderTag Open n name attrs
renderTagEmpty _ = renderElement n elm
renderTagCDATA :: Children -> ShowS
renderTagCDATA children =
let open = renderTag Open n name attrs
cs = renderChildrenCDATA 0 children
close = renderTag Close n name []
in
open . cs .close
renderChildrenCDATA :: Int -> Children -> ShowS
renderChildrenCDATA n' cs = foldl (.) id $ map (renderChildCDATA (n'+2)) cs
renderChildCDATA n (CDATA cd) = showString (unescape cd)
renderChildCDATA n e = renderElement n e
renderAsHTML' n e = renderElement n e
renderElement n (Element name attrs children) =
let open = renderTag Open n name attrs
cs = renderChildren n children
close = renderTag Close n name []
in open . cs . close
where renderChildren :: Int -> Children -> ShowS
renderChildren n' cs = foldl (.) id $ map (renderAsHTML' (n'+2)) cs
renderTag :: TagType -> Int -> Name -> Attributes -> ShowS
renderTag typ n name attrs =
let (start,end) = case typ of
Open -> (showChar '<', showChar '>')
Close -> (showString "</", showChar '>')
nam = showName name
as = renderAttrs attrs
in start . nam . as . end
where renderAttrs :: Attributes -> ShowS
renderAttrs [] = nl
renderAttrs attrs' = showChar ' ' . ats . nl
where ats = foldl (.) id $ intersperse (showChar ' ') $ fmap renderAttr attrs'
renderAttr :: Attribute -> ShowS
renderAttr (MkAttr (nam, (Value val))) = showName nam . showChar '=' . renderAttrVal val
renderAttrVal :: String -> ShowS
renderAttrVal s = showChar '\"' . showString s . showChar '\"'
showName (Nothing, s) = showString s
showName (Just d, s) = showString d . showChar ':' . showString s
nl = showChar '\n' . showString (replicate n ' ')