{-# LANGUAGE GADTs #-}
module Markup where
import Data.List (intersperse)
import Data.Monoid ((<>))
import Data.Text (Text)
import qualified Data.Text as T
import Lucid
import Text.Megaparsec
import Text.Megaparsec.Char
data Chunk
= Bold Text
| Italic Text
| Code Text
| Strike Text
| Chunk Text
deriving (Eq, Show)
-- | Understands a very limited form of markup, and does not understand
-- nested markup yet.
markup :: Text -> Html ()
markup = div_
. sequence_
. intersperse (br_ [])
. map (build . format)
. T.lines
format :: Text -> [Chunk]
format t = case runParser parseF "[]" t of
Left _ -> [Chunk t]
Right cs -> cs
parseF :: (Stream s, Token s ~ Char) => Parsec () s [Chunk]
parseF = many go
where go = Bold <$> delim '*'
<|> Italic <$> delim '_'
<|> Code <$> delim '`'
<|> Strike <$> delim '~'
<|> (Chunk . T.pack) <$> pChunk
delim c = (T.pack . (<> " ")) <$>
(char c *> manyTill asciiChar (try (char c >> space)))
pChunk = some (noneOf ("*_`~" :: String))
build :: [Chunk] -> Html ()
build = mapM_ go
where go (Chunk t) = toHtml t
go (Bold t) = strong_ $ toHtml t
go (Italic t) = em_ $ toHtml t
go (Strike t) = span_ [ class_ "strike" ] $ toHtml t
go (Code t) = pre_ $ toHtml t