{-# LANGUAGE FlexibleInstances #-}
{-|
Module exposing a generic class to convert to/from UTF8 'ByteString's, and the
corresponding generic markdown functions.
-}
module Text.Sundown.Html
    ( renderHtml
    , smartypants
      -- * Generic ByteString conversion
    , ToBS(..)
    , FromBS(..)
      -- * Markdown extensions
    , Extensions (..)
    , allExtensions
    , noExtensions
      -- * Html render modes
    , HtmlRenderMode(..)
    , noHtmlModes
    , allHtmlModes
    ) where

import Data.ByteString (ByteString)
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Encoding as T

import Text.Sundown.Foreign
import Text.Sundown.Html.ByteString (noHtmlModes, allHtmlModes)
import qualified Text.Sundown.Html.ByteString as BS
import Text.Sundown.Html.Foreign

-- | Converts something to an UTF8 'ByteString'.
class ToBS   a where toBS   :: a -> ByteString
-- | Converts an UTF8 'ByteString' to something.
class FromBS a where fromBS :: ByteString -> a

instance ToBS   ByteString where toBS :: ByteString -> ByteString
toBS   = ByteString -> ByteString
forall a. a -> a
id
instance FromBS ByteString where fromBS :: ByteString -> ByteString
fromBS = ByteString -> ByteString
forall a. a -> a
id

instance ToBS   [Char]     where toBS :: [Char] -> ByteString
toBS   = Text -> ByteString
T.encodeUtf8 (Text -> ByteString) -> ([Char] -> Text) -> [Char] -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> Text
T.pack
instance FromBS [Char]     where fromBS :: ByteString -> [Char]
fromBS = Text -> [Char]
T.unpack (Text -> [Char]) -> (ByteString -> Text) -> ByteString -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Text
T.decodeUtf8

instance ToBS   Text       where toBS :: Text -> ByteString
toBS   = Text -> ByteString
T.encodeUtf8
instance FromBS Text       where fromBS :: ByteString -> Text
fromBS = ByteString -> Text
T.decodeUtf8

-- | Parses markdown, returns the Html.
renderHtml :: (ToBS a, FromBS b)
           => Extensions
           -> HtmlRenderMode
           -> Bool              -- ^ If true, smartypant the output
           -> Maybe Int
           -- ^ The maximum nesting of the HTML. If Nothing, a default value
           -- (16) will be used.
           -> a
           -> b
renderHtml :: Extensions -> HtmlRenderMode -> Bool -> Maybe Int -> a -> b
renderHtml Extensions
exts HtmlRenderMode
mode Bool
sp Maybe Int
maxNestingM a
input =
    ByteString -> b
forall a. FromBS a => ByteString -> a
fromBS (ByteString -> b) -> ByteString -> b
forall a b. (a -> b) -> a -> b
$ Extensions
-> HtmlRenderMode -> Bool -> Maybe Int -> ByteString -> ByteString
BS.renderHtml Extensions
exts HtmlRenderMode
mode Bool
sp Maybe Int
maxNestingM (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ a -> ByteString
forall a. ToBS a => a -> ByteString
toBS a
input

smartypants :: (ToBS a, FromBS b) => a -> b
smartypants :: a -> b
smartypants = ByteString -> b
forall a. FromBS a => ByteString -> a
fromBS (ByteString -> b) -> (a -> ByteString) -> a -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
BS.smartypants (ByteString -> ByteString) -> (a -> ByteString) -> a -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> ByteString
forall a. ToBS a => a -> ByteString
toBS