commonmark-extensions-0.1.0.0: src/Commonmark/Extensions/Math.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
module Commonmark.Extensions.Math
( HasMath(..)
, mathSpec )
where
import Commonmark.Types
import Commonmark.Tokens
import Commonmark.Syntax
import Commonmark.Inlines
import Commonmark.SourceMap
import Commonmark.TokParsers
import Commonmark.Html
import Text.Parsec
import Data.Text (Text)
#if !MIN_VERSION_base(4,11,0)
import Data.Semigroup (Semigroup(..))
#endif
mathSpec :: (Monad m, IsBlock il bl, IsInline il, HasMath il)
=> SyntaxSpec m il bl
mathSpec = mempty
{ syntaxInlineParsers = [withAttributes parseMath]
}
class HasMath a where
inlineMath :: Text -> a
displayMath :: Text -> a
instance HasMath (Html a) where
inlineMath t = addAttribute ("class", "math inline") $
htmlInline "span" $ Just $ htmlRaw "\\(" <> htmlText t <> htmlRaw "\\)"
displayMath t = addAttribute ("class", "math display") $
htmlInline "span" $ Just $ htmlRaw "\\[" <> htmlText t <> htmlRaw "\\]"
instance (HasMath i, Monoid i) => HasMath (WithSourceMap i) where
inlineMath t = (inlineMath t) <$ addName "inlineMath"
displayMath t = (displayMath t) <$ addName "displayMath"
parseMath :: (Monad m, HasMath a) => InlineParser m a
parseMath = pDisplayMath <|> pInlineMath
pInlineMath :: (Monad m, HasMath a) => InlineParser m a
pInlineMath = try $ do
symbol '$'
notFollowedBy whitespace
(_, toks) <- withRaw $ many1 $
choice [ () <$ symbol '\\' >> anyTok
, whitespace >> lookAhead (noneOfToks [Symbol '$'])
, noneOfToks [Symbol '$']
]
symbol '$'
return $! inlineMath (untokenize toks)
pDisplayMath :: (Monad m, HasMath a) => InlineParser m a
pDisplayMath = try $ do
count 2 $ symbol '$'
(_, toks) <- withRaw $ many1 $
choice [ () <$ symbol '\\' >> anyTok
, noneOfToks [Symbol '$']
]
count 2 $ symbol '$'
return $! displayMath (untokenize toks)