{-
pandoc-crossref is a pandoc filter for numbering figures,
equations, tables and cross-references to them.
Copyright (C) 2015  Nikolay Yakimov <root@livid.pp.ru>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-}

{-# LANGUAGE Rank2Types, OverloadedStrings, FlexibleContexts #-}

module Text.Pandoc.CrossRef.References.Blocks.Math where

import Control.Monad.Reader.Class
import qualified Data.Map as M
import qualified Data.Text as T
import Text.Pandoc.Definition
import Text.Pandoc.Shared (stringify)

import Text.Pandoc.CrossRef.References.Monad
import Text.Pandoc.CrossRef.References.Blocks.Util
import Text.Pandoc.CrossRef.Util.Options
import Text.Pandoc.CrossRef.Util.Template
import Text.Pandoc.CrossRef.Util.Util

runBlockMath :: Attr -> T.Text -> WS (ReplacedResult Block)
runBlockMath :: Attr -> Text -> WS (ReplacedResult Block)
runBlockMath (Text
label, [Text]
cls, [(Text, Text)]
attrs) Text
eq = do
  Options
opts <- forall r (m :: * -> *). MonadReader r m => m r
ask
  if Options -> Bool
tableEqns Options
opts Bool -> Bool -> Bool
&& Bool -> Bool
not (Maybe Format -> Bool
isLatexFormat (Options -> Maybe Format
outFormat Options
opts))
  then do
    (Text
eq', [Inline]
idxStr) <- Attr -> Text -> WS (Text, [Inline])
replaceEqn (Text
label, [Text]
cls, [(Text, Text)]
attrs) Text
eq
    let mathfmt :: MathType
mathfmt = if Options -> Bool
eqnBlockInlineMath Options
opts then MathType
InlineMath else MathType
DisplayMath
    forall (m :: * -> *) a. Monad m => a -> m (ReplacedResult a)
replaceNoRecurse forall a b. (a -> b) -> a -> b
$ Attr -> [Block] -> Block
Div (Text
label,[Text]
cls,Options -> [Inline] -> [(Text, Text)] -> [(Text, Text)]
setLabel Options
opts [Inline]
idxStr [(Text, Text)]
attrs) forall a b. (a -> b) -> a -> b
$
      forall a b. MkTemplate a b => [Inline] -> [Inline] -> b -> [a]
applyTemplate [MathType -> Text -> Inline
Math MathType
mathfmt forall a b. (a -> b) -> a -> b
$ forall a. Walkable Inline a => a -> Text
stringify [Inline]
idxStr] [MathType -> Text -> Inline
Math MathType
mathfmt Text
eq']
        forall a b. (a -> b) -> a -> b
$ Options -> BlockTemplate
eqnBlockTemplate Options
opts
  else forall (m :: * -> *) a. Monad m => m (ReplacedResult a)
noReplaceRecurse

replaceEqn :: Attr -> T.Text -> WS (T.Text, [Inline])
replaceEqn :: Attr -> Text -> WS (Text, [Inline])
replaceEqn (Text
label, [Text]
_, [(Text, Text)]
attrs) Text
eq = do
  Options
opts <- forall r (m :: * -> *). MonadReader r m => m r
ask
  let label' :: Either Text Text
label' | Text -> Bool
T.null Text
label = forall a b. a -> Either a b
Left Text
"eq"
             | Bool
otherwise = forall a b. b -> Either a b
Right Text
label
  [Inline]
idxStrRaw <- Either Text Text
-> [(Text, Text)] -> [Inline] -> SPrefix -> WS [Inline]
replaceAttr Either Text Text
label' [(Text, Text)]
attrs [] SPrefix
SPfxEqn
  let idxStr :: [Inline]
idxStr = forall a b. MkTemplate a b => Map Text [Inline] -> b -> [a]
applyTemplate' (forall k a. [(k, a)] -> Map k a
M.fromDistinctAscList [(Text
"i", [Inline]
idxStrRaw)]) forall a b. (a -> b) -> a -> b
$ Options -> Template
eqnIndexTemplate Options
opts
      eqTxt :: [Inline]
eqTxt = forall a b. MkTemplate a b => Map Text [Inline] -> b -> [a]
applyTemplate' Map Text [Inline]
eqTxtVars forall a b. (a -> b) -> a -> b
$ Options -> Template
eqnInlineTemplate Options
opts :: [Inline]
      eqTxtVars :: Map Text [Inline]
eqTxtVars = forall k a. [(k, a)] -> Map k a
M.fromDistinctAscList
        [ (Text
"e", [Text -> Inline
Str Text
eq])
        , (Text
"i", [Inline]
idxStr)
        , (Text
"ri", [Inline]
idxStrRaw)
        ]
      eq' :: Text
eq' | Options -> Bool
tableEqns Options
opts = Text
eq
          | Bool
otherwise = forall a. Walkable Inline a => a -> Text
stringify [Inline]
eqTxt
  forall (m :: * -> *) a. Monad m => a -> m a
return (Text
eq', [Inline]
idxStr)

splitMath :: [Block] -> [Block]
splitMath :: [Block] -> [Block]
splitMath (Para [Inline]
ils:[Block]
xs)
  | forall (t :: * -> *) a. Foldable t => t a -> Int
length [Inline]
ils forall a. Ord a => a -> a -> Bool
> Int
1 = forall a b. (a -> b) -> [a] -> [b]
map [Inline] -> Block
Para ([[Inline]] -> [Inline] -> [Inline] -> [[Inline]]
split [] [] [Inline]
ils) forall a. Semigroup a => a -> a -> a
<> [Block]
xs
  where
    split :: [[Inline]] -> [Inline] -> [Inline] -> [[Inline]]
split [[Inline]]
res [Inline]
acc [] = forall a. [a] -> [a]
reverse (forall a. [a] -> [a]
reverse [Inline]
acc forall a. a -> [a] -> [a]
: [[Inline]]
res)
    split [[Inline]]
res [Inline]
acc (x :: Inline
x@(Span Attr
_ [Math MathType
DisplayMath Text
_]):[Inline]
ys) =
      [[Inline]] -> [Inline] -> [Inline] -> [[Inline]]
split ([Inline
x] forall a. a -> [a] -> [a]
: forall a. [a] -> [a]
reverse ([Inline] -> [Inline]
dropSpaces [Inline]
acc) forall a. a -> [a] -> [a]
: [[Inline]]
res)
            [] ([Inline] -> [Inline]
dropSpaces [Inline]
ys)
    split [[Inline]]
res [Inline]
acc (Inline
y:[Inline]
ys) = [[Inline]] -> [Inline] -> [Inline] -> [[Inline]]
split [[Inline]]
res (Inline
yforall a. a -> [a] -> [a]
:[Inline]
acc) [Inline]
ys
    dropSpaces :: [Inline] -> [Inline]
dropSpaces = forall a. (a -> Bool) -> [a] -> [a]
dropWhile Inline -> Bool
isSpace
splitMath [Block]
xs = [Block]
xs