-- | A renderer that produces a native Haskell 'String', mostly meant for -- debugging purposes. -- {-# LANGUAGE OverloadedStrings #-} module Text.Blaze.Renderer.String ( fromChoiceString , renderMarkup , renderHtml ) where import Data.List (isInfixOf) import qualified Data.ByteString.Char8 as SBC import qualified Data.Text as T import qualified Data.ByteString as S import Text.Blaze.Internal -- | Escape predefined XML entities in a string -- escapeMarkupEntities :: String -- ^ String to escape -> String -- ^ String to append -> String -- ^ Resulting string escapeMarkupEntities [] k = k escapeMarkupEntities (c:cs) k = case c of '<' -> '&' : 'l' : 't' : ';' : escapeMarkupEntities cs k '>' -> '&' : 'g' : 't' : ';' : escapeMarkupEntities cs k '&' -> '&' : 'a' : 'm' : 'p' : ';' : escapeMarkupEntities cs k '"' -> '&' : 'q' : 'u' : 'o' : 't' : ';' : escapeMarkupEntities cs k '\'' -> '&' : '#' : '3' : '9' : ';' : escapeMarkupEntities cs k x -> x : escapeMarkupEntities cs k -- | Render a 'ChoiceString'. -- fromChoiceString :: ChoiceString -- ^ String to render -> String -- ^ String to append -> String -- ^ Resulting string fromChoiceString (Static s) = getString s fromChoiceString (String s) = escapeMarkupEntities s fromChoiceString (Text s) = escapeMarkupEntities $ T.unpack s fromChoiceString (ByteString s) = (SBC.unpack s ++) fromChoiceString (PreEscaped x) = case x of String s -> (s ++) Text s -> (\k -> T.foldr (:) k s) s -> fromChoiceString s fromChoiceString (External x) = case x of -- Check that the sequence " if " if " T.foldr (:) k s) ByteString s -> if " fromChoiceString s fromChoiceString (AppendChoiceString x y) = fromChoiceString x . fromChoiceString y fromChoiceString EmptyChoiceString = id {-# INLINE fromChoiceString #-} -- | Render some 'Markup' to an appending 'String'. -- renderString :: Markup -- ^ Markup to render -> String -- ^ String to append -> String -- ^ Resulting String renderString = go id where go :: (String -> String) -> MarkupM b -> String -> String go attrs (Parent _ open close content) = getString open . attrs . ('>' :) . go id content . getString close go attrs (CustomParent tag content) = ('<' :) . fromChoiceString tag . attrs . ('>' :) . go id content . ("' :) go attrs (Leaf _ begin end) = getString begin . attrs . getString end go attrs (CustomLeaf tag close) = ('<' :) . fromChoiceString tag . attrs . (if close then (" />" ++) else ('>' :)) go attrs (AddAttribute _ key value h) = flip go h $ getString key . fromChoiceString value . ('"' :) . attrs go attrs (AddCustomAttribute key value h) = flip go h $ (' ' :) . fromChoiceString key . ("=\"" ++) . fromChoiceString value . ('"' :) . attrs go _ (Content content) = fromChoiceString content go attrs (Append h1 h2) = go attrs h1 . go attrs h2 go _ Empty = id {-# NOINLINE go #-} {-# INLINE renderString #-} -- | Render markup to a lazy 'String'. -- renderMarkup :: Markup -> String renderMarkup html = renderString html "" {-# INLINE renderMarkup #-} renderHtml :: Markup -> String renderHtml = renderMarkup {-# INLINE renderHtml #-} {-# DEPRECATED renderHtml "Use renderHtml from Text.Blaze.Html.Renderer.String instead" #-}