    {-# LANGUAGE OverloadedStrings #-}
    module Text.Pandoc.Writers.Math
      ( texMathToInlines
      , convertMath
      , defaultMathJaxURL
      , defaultKaTeXURL
      )
    where

    import qualified Data.Text as T
    import Text.Pandoc.Class.PandocMonad
    import Text.Pandoc.Definition
    import Text.Pandoc.Logging
    import Text.TeXMath (DisplayType (..), Exp, readTeX, writePandoc)
    import Text.Pandoc.Options (defaultMathJaxURL, defaultKaTeXURL)

    -- | Converts a raw TeX math formula to a list of 'Pandoc' inlines.
    -- Defaults to raw formula between @$@ or @$$@ characters if entire formula
    -- can't be converted.
    texMathToInlines :: PandocMonad m
                     => MathType
                     -> T.Text         -- ^ String to parse (assumes @'\n'@ line endings)
                     -> m [Inline]
    texMathToInlines :: forall (m :: * -> *).
    PandocMonad m =>
    MathType -> Text -> m [Inline]
    texMathToInlines MathType
    mt Text
    inp = do
      res <- (DisplayType -> [Exp] -> Maybe [Inline])
    -> MathType -> Text -> m (Either Inline (Maybe [Inline]))
    forall (m :: * -> *) a.
    PandocMonad m =>
    (DisplayType -> [Exp] -> a)
    -> MathType -> Text -> m (Either Inline a)
    convertMath DisplayType -> [Exp] -> Maybe [Inline]
    writePandoc MathType
    mt Text
    inp
      case res of
           Right (Just [Inline]
    ils)  -> [Inline] -> m [Inline]
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return [Inline]
    ils
           Right Maybe [Inline]
    Nothing   -> do
             LogMessage -> m ()
    forall (m :: * -> *). PandocMonad m => LogMessage -> m ()
    report (LogMessage -> m ()) -> LogMessage -> m ()
    forall a b. (a -> b) -> a -> b
    $ Text -> Text -> LogMessage
    CouldNotConvertTeXMath Text
    inp Text
    ""
             [Inline] -> m [Inline]
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return [MathType -> Text -> Inline
    mkFallback MathType
    mt Text
    inp]
           Left Inline
    il           -> [Inline] -> m [Inline]
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return [Inline
    il]

    mkFallback :: MathType -> T.Text -> Inline
    mkFallback :: MathType -> Text -> Inline
    mkFallback MathType
    mt Text
    str = Text -> Inline
    Str (Text
    delim Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    str Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    delim)
       where delim :: Text
    delim = case MathType
    mt of
                          MathType
    DisplayMath -> Text
    "$$"
                          MathType
    InlineMath  -> Text
    "$"

    -- | Converts a raw TeX math formula using a writer function,
    -- issuing a warning and producing a fallback (a raw string)
    -- on failure.
    convertMath :: PandocMonad m
                => (DisplayType -> [Exp] -> a) -> MathType -> T.Text
                -> m (Either Inline a)
    convertMath :: forall (m :: * -> *) a.
    PandocMonad m =>
    (DisplayType -> [Exp] -> a)
    -> MathType -> Text -> m (Either Inline a)
    convertMath DisplayType -> [Exp] -> a
    writer MathType
    mt Text
    str =
      case DisplayType -> [Exp] -> a
    writer DisplayType
    dt ([Exp] -> a) -> Either Text [Exp] -> Either Text a
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Text -> Either Text [Exp]
    readTeX Text
    str of
           Right a
    r  -> Either Inline a -> m (Either Inline a)
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (a -> Either Inline a
    forall a b. b -> Either a b
    Right a
    r)
           Left Text
    e   -> do
             LogMessage -> m ()
    forall (m :: * -> *). PandocMonad m => LogMessage -> m ()
    report (LogMessage -> m ()) -> LogMessage -> m ()
    forall a b. (a -> b) -> a -> b
    $ Text -> Text -> LogMessage
    CouldNotConvertTeXMath Text
    str Text
    e
             Either Inline a -> m (Either Inline a)
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Inline -> Either Inline a
    forall a b. a -> Either a b
    Left (Inline -> Either Inline a) -> Inline -> Either Inline a
    forall a b. (a -> b) -> a -> b
    $ MathType -> Text -> Inline
    mkFallback MathType
    mt Text
    str)
       where dt :: DisplayType
    dt = case MathType
    mt of
                       MathType
    DisplayMath -> DisplayType
    DisplayBlock
                       MathType
    InlineMath  -> DisplayType
    DisplayInline