module Text.HTML.Moe2.Renderer
(
render
, render_bytestring
)
where
import Text.HTML.Moe2.Element
import Text.HTML.Moe2.Attribute
import Text.HTML.Moe2.Utils
import Text.HTML.Moe2.Type hiding (name, value)
import qualified Text.HTML.Moe2.Type as T
import Prelude hiding ((/), (), head, (>), (.), concat, concatMap, (+))
import qualified Prelude as P
import Air.Env ((>), (.), times, belongs_to, reject, (+))
import Control.Monad.Writer (execWriter)
import qualified Data.ByteString.Char8 as B
import qualified Data.ByteString.Lazy.Char8 as L
import Data.DList (toList)
import Data.List (intersperse)
render :: MoeUnit -> String
render = render_bytestring > L.unpack
render_bytestring :: MoeUnit -> L.ByteString
render_bytestring = execWriter > toList > map render_element > intercalate new_line > to_bs > return > L.fromChunks
_indent_space :: Int
_indent_space = 2
new_line :: Internal
new_line = pack "\n"
space :: Internal
space = pack " "
_indent :: Int -> Internal
_indent n = (n * _indent_space).times space.concat
render_element' :: Int -> Element -> Internal
render_element' _ (Raw x) = x
render_element' _ (Pre x) = x
render_element' n (Prim x) = _indent n + x
render_element' n (Data x) = _indent n + x
render_element' n (Attributes xs e) =
let xs' = e.attributes.reject (key > belongs_to (xs.map key)) ++ xs
in
render_element' n e {attributes = xs'}
render_element' n x
| x.self_close =
[ _indent n
, "<".pack
, x.T.name
, x.attributes.map render_attribute. join_attribute
, " />".pack
]
.concat
| otherwise =
[ self_indent
, "<".pack
, x.T.name
, x.attributes.map render_attribute. join_attribute
, ">".pack
, inner_elements
, "</".pack
, x.T.name
, ">".pack
]
.concat
where
self_indent = if x.indent then _indent n else "".pack
join_attribute xs = xs.map (pack " " `append`) .concat
inner_elements =
if x.elements.null
then "".pack
else
[ new_line
, x.elements.map (render_element' (n P.+ 1)) .intersperse new_line .concat
, new_line
, self_indent
]
.concat
render_element :: Element -> Internal
render_element = render_element' 0
render_attribute :: Attribute -> Internal
render_attribute x =
[x.key, pack "=", pack "\"", x.T.value, pack "\""].concat