module Text.Ptolemy.HTML.Writer (writeHtml, writeHtmlStrict) where import Data.Monoid ((<>)) import qualified Data.Text as TS import Data.Text.Lazy (Text, toStrict) import Data.Text.Lazy.Builder (Builder) import qualified Data.Text.Lazy.Builder as B import Data.Vector (Vector) import qualified Data.Vector as V import Text.Ptolemy.Core -- | Render a Ptolemy @Document@ as HTML represented as lazy @Text@. writeHtml :: Document -> Text writeHtml = B.toLazyText . build -- | Render a Ptolemy @Document@ as HTML represented as strict @Text@. writeHtmlStrict :: Document -> TS.Text writeHtmlStrict = toStrict . writeHtml -- These will be our helper functions for building tags tag :: Text -> Builder -> Builder tag t bs = "<" <> build t <> ">" <> bs <> "" <> build t <> ">" tagAttrs :: Text -> [(TS.Text, TS.Text)] -> Builder -> Builder tagAttrs t [] bs = tag t bs tagAttrs t as bs = "<" <> build t <> attrs as <> ">" <> bs <> "" <> build t <> ">" where attrs [] = mempty attrs ((k,v):xs) = " " <> build k <> "=\"" <> build v <> "\"" <> attrs xs -- Right now, this just makes the code below a lot smaller: we -- abstract out the notion of 'building' a thing, so we can -- more or less indiscriminately apply @build@ to vectors or -- maps or what-have-you. class Build t where build :: t -> Builder -- And to that end, we define a handful of utility -- implementations of things: instance Build t => Build (Vector t) where build = foldMap build instance Build Text where build = B.fromLazyText instance Build TS.Text where build = B.fromText instance Build Block where build (Plain cs) = build cs build (Para cs) = tag "p" $ build cs build (CodeBlock _ ts) = tag "pre" $ tag "code" $ build ts build (RawBlock _ _) = undefined build (BlockQuote bs) = tag "blockquote" $ build bs build (OrderedList la ds) = tagAttrs "ol" (orderedListAttrs la) $ foldMap (tag "li" . build) ds build (BulletList ds) = tag "ul" $ foldMap (tag "li" . build) ds build (DefinitionList ds) = tag "dl" $ foldMap build ds build (Header n _ is) = case n of 1 -> tag "h1" $ build is 2 -> tag "h2" $ build is 3 -> tag "h3" $ build is 4 -> tag "h4" $ build is _ -> undefined -- XXX build HorizontalRule = "