{-# LANGUAGE CPP #-} {-# LANGUAGE ExplicitForAll #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TypeFamilies #-} module Yesod.Markdown ( Markdown(..) -- * Wrappers , markdownToHtml , markdownToHtmlTrusted , markdownToHtmlWithExtensions , markdownToHtmlWith , markdownFromFile -- * Conversions , parseMarkdown , writePandoc , writePandocTrusted -- * Option sets , yesodDefaultWriterOptions , yesodDefaultReaderOptions , yesodDefaultExtensions -- * Form helper , markdownField ) where import Control.Monad ((<=<)) import Data.String (IsString) import Data.Text (Text) import Data.Text.Encoding (decodeUtf8With) import Data.Text.Encoding.Error (lenientDecode) import Database.Persist (PersistField, SqlType(SqlString)) import Database.Persist.Sql (PersistFieldSql(..)) import System.Directory (doesFileExist) import Text.Blaze (ToMarkup(toMarkup)) import Text.Blaze.Html (preEscapedToMarkup) import Text.Hamlet (Html, hamlet) import Text.HTML.SanitizeXSS (sanitizeBalance) import Text.Pandoc hiding (handleError) import Yesod.Core (HandlerSite, RenderMessage) import Yesod.Core.Widget (toWidget) import Yesod.Form.Functions (parseHelper) import Yesod.Form.Types import qualified Data.ByteString as B import qualified Data.Text as T #if !MIN_VERSION_base(4,11,0) import Data.Semigroup #endif newtype Markdown = Markdown { unMarkdown :: Text } deriving (Eq, Ord, Show, Read, PersistField, IsString, Monoid, Semigroup) instance PersistFieldSql Markdown where sqlType _ = SqlString instance ToMarkup Markdown where -- | Sanitized by default toMarkup = handleError . markdownToHtml markdownField :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m Markdown markdownField = Field { fieldParse = parseHelper $ Right . Markdown . T.filter (/= '\r') , fieldView = \theId name attrs val _isReq -> toWidget [hamlet|$newline never