12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273 |
- module Text.Ptolemy.Slackdown.Reader
- ( SlackdownOpts(..)
- , defaultOpts
- , inlineOpts
- , readSlackdown
- ) where
- import Control.Applicative (empty)
- import Data.Text (Text)
- import qualified Data.Text as T
- import qualified Data.Vector as V
- import Text.Megaparsec
- import Text.Megaparsec.Text
- import Text.Ptolemy.Core (PtolemyError, Document)
- import qualified Text.Ptolemy.Core as P
- data SlackdownOpts = SlackdownOpts
- { tdBlockElems :: Bool
- } deriving (Eq, Show)
- defaultOpts :: SlackdownOpts
- defaultOpts = SlackdownOpts
- { tdBlockElems = True
- }
- inlineOpts :: SlackdownOpts
- inlineOpts = SlackdownOpts
- { tdBlockElems = False
- }
- readSlackdown :: SlackdownOpts -> Text -> Either PtolemyError Document
- readSlackdown opts tx = case runParser (pSlackdown opts) "[]" tx of
- Right x -> Right x
- Left err -> Left (P.PtolemyError (show err))
- enables :: Bool -> Parser a -> Parser a
- enables True p = p
- enables False _ = empty
- pSlackdown :: SlackdownOpts -> Parser Document
- pSlackdown SlackdownOpts { tdBlockElems = blockElems } =
- P.vec <$> (many pBlock <* eof)
- where pBlock =
- blockElems `enables` (pCodeBlock <|> pQuote) <|>
- pLine
- pLine = (P.Plain . flip V.snoc P.LineBreak . P.vec) <$>
- manyTill pInline (char '\n')
- pQuote = (P.BlockQuote . P.vec) <$> some (char '>' *> pLine)
- pCodeBlock = (P.CodeBlock P.emptyAttr . T.concat) <$>
- (string "```\n" *> manyTill pPlainLine (string "```\n"))
- pPlainLine = T.pack <$> manyTill (noneOf ("\n\r" :: String))
- (char '\n')
- pInline = pWhitespace
- <|> pString
- <|> (P.Code P.emptyAttr . T.pack) <$>
- (char '`' *> many (satisfy (/= '`')) <* char '`')
- <|> P.Strong <$> pSurrounded '*'
- <|> P.Emph <$> pSurrounded '_'
- <|> P.Strikeout <$> pSurrounded '~'
- pWhitespace = (P.Space) <$ some (oneOf (" \t" :: String))
- pString = (P.Str . T.pack) <$> some (noneOf ("*_~` \t\r\n" :: String))
- pSurrounded :: Char -> Parser P.Chunk
- pSurrounded c = try (char c *> rest)
- where rest = P.vec <$> (many (notFollowedBy (char c) *> pInline)
- <* char c)
|