{-# LANGUAGE RankNTypes #-}
module Text.Pandoc.CrossRef (
crossRefBlocks
, crossRefMeta
, defaultCrossRefAction
, runCrossRef
, runCrossRefIO
, module SG
, defaultMeta
, CrossRefM
, CrossRefEnv(..)
) where
import Control.Monad.State
import qualified Control.Monad.Reader as R
import Text.Pandoc
import Text.Pandoc.CrossRef.References
import Text.Pandoc.CrossRef.Util.Settings
import Text.Pandoc.CrossRef.Util.Options as O
import Text.Pandoc.CrossRef.Util.CodeBlockCaptions
import Text.Pandoc.CrossRef.Util.ModifyMeta
import Text.Pandoc.CrossRef.Util.Settings.Gen as SG
data CrossRefEnv = CrossRefEnv {
CrossRefEnv -> Meta
creSettings :: Meta
, CrossRefEnv -> Options
creOptions :: Options
}
type CrossRefM a = R.Reader CrossRefEnv a
crossRefBlocks :: [Block] -> CrossRefM [Block]
crossRefBlocks :: [Block] -> CrossRefM [Block]
crossRefBlocks [Block]
blocks = do
Options
opts <- (CrossRefEnv -> Options) -> ReaderT CrossRefEnv Identity Options
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
R.asks CrossRefEnv -> Options
creOptions
let
doWalk :: StateT References Identity [Block]
doWalk =
([Block] -> StateT References Identity [Block])
-> [Block] -> StateT References Identity [Block]
forall (m :: * -> *) a b.
(Monad m, Data a, Data b) =>
(a -> m a) -> b -> m b
bottomUpM (Options -> [Block] -> StateT References Identity [Block]
mkCodeBlockCaptions Options
opts) [Block]
blocks
StateT References Identity [Block]
-> ([Block] -> StateT References Identity [Block])
-> StateT References Identity [Block]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Options -> [Block] -> StateT References Identity [Block]
forall a. Data a => Options -> a -> WS a
replaceAll Options
opts
StateT References Identity [Block]
-> ([Block] -> StateT References Identity [Block])
-> StateT References Identity [Block]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ([Inline] -> StateT References Identity [Inline])
-> [Block] -> StateT References Identity [Block]
forall (m :: * -> *) a b.
(Monad m, Data a, Data b) =>
(a -> m a) -> b -> m b
bottomUpM (Options -> [Inline] -> StateT References Identity [Inline]
replaceRefs Options
opts)
StateT References Identity [Block]
-> ([Block] -> StateT References Identity [Block])
-> StateT References Identity [Block]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ([Block] -> StateT References Identity [Block])
-> [Block] -> StateT References Identity [Block]
forall (m :: * -> *) a b.
(Monad m, Data a, Data b) =>
(a -> m a) -> b -> m b
bottomUpM (Options -> [Block] -> StateT References Identity [Block]
listOf Options
opts)
([Block]
result, References
st) = StateT References Identity [Block]
-> References -> ([Block], References)
forall s a. State s a -> s -> (a, s)
runState StateT References Identity [Block]
doWalk References
forall a. Default a => a
def
References
st References -> CrossRefM [Block] -> CrossRefM [Block]
`seq` [Block] -> CrossRefM [Block]
forall (m :: * -> *) a. Monad m => a -> m a
return [Block]
result
crossRefMeta :: CrossRefM Meta
crossRefMeta :: CrossRefM Meta
crossRefMeta = do
Options
opts <- (CrossRefEnv -> Options) -> ReaderT CrossRefEnv Identity Options
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
R.asks CrossRefEnv -> Options
creOptions
Meta
dtv <- (CrossRefEnv -> Meta) -> CrossRefM Meta
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
R.asks CrossRefEnv -> Meta
creSettings
Meta -> CrossRefM Meta
forall (m :: * -> *) a. Monad m => a -> m a
return (Meta -> CrossRefM Meta) -> Meta -> CrossRefM Meta
forall a b. (a -> b) -> a -> b
$ Options -> Meta -> Meta
modifyMeta Options
opts Meta
dtv
defaultCrossRefAction :: Pandoc -> CrossRefM Pandoc
defaultCrossRefAction :: Pandoc -> CrossRefM Pandoc
defaultCrossRefAction (Pandoc Meta
_ [Block]
bs) = do
Meta
meta' <- CrossRefM Meta
crossRefMeta
[Block]
bs' <- [Block] -> CrossRefM [Block]
crossRefBlocks [Block]
bs
Pandoc -> CrossRefM Pandoc
forall (m :: * -> *) a. Monad m => a -> m a
return (Pandoc -> CrossRefM Pandoc) -> Pandoc -> CrossRefM Pandoc
forall a b. (a -> b) -> a -> b
$ Meta -> [Block] -> Pandoc
Pandoc Meta
meta' [Block]
bs'
runCrossRef :: forall a b. Meta -> Maybe Format -> (a -> CrossRefM b) -> a -> b
runCrossRef :: Meta -> Maybe Format -> (a -> CrossRefM b) -> a -> b
runCrossRef Meta
meta Maybe Format
fmt a -> CrossRefM b
action a
arg = CrossRefM b -> CrossRefEnv -> b
forall r a. Reader r a -> r -> a
R.runReader (a -> CrossRefM b
action a
arg) CrossRefEnv
env
where
settings :: Meta
settings = Meta
defaultMeta Meta -> Meta -> Meta
forall a. Semigroup a => a -> a -> a
<> Meta
meta
env :: CrossRefEnv
env = CrossRefEnv :: Meta -> Options -> CrossRefEnv
CrossRefEnv {
creSettings :: Meta
creSettings = Meta
settings
, creOptions :: Options
creOptions = Meta -> Maybe Format -> Options
getOptions Meta
settings Maybe Format
fmt
}
runCrossRefIO :: forall a b. Meta -> Maybe Format -> (a -> CrossRefM b) -> a -> IO b
runCrossRefIO :: Meta -> Maybe Format -> (a -> CrossRefM b) -> a -> IO b
runCrossRefIO Meta
meta Maybe Format
fmt a -> CrossRefM b
action a
arg = do
Meta
settings <- Maybe Format -> Meta -> IO Meta
getSettings Maybe Format
fmt Meta
meta
let
env :: CrossRefEnv
env = CrossRefEnv :: Meta -> Options -> CrossRefEnv
CrossRefEnv {
creSettings :: Meta
creSettings = Meta
settings
, creOptions :: Options
creOptions = Meta -> Maybe Format -> Options
getOptions Meta
settings Maybe Format
fmt
}
b -> IO b
forall (m :: * -> *) a. Monad m => a -> m a
return (b -> IO b) -> b -> IO b
forall a b. (a -> b) -> a -> b
$ CrossRefM b -> CrossRefEnv -> b
forall r a. Reader r a -> r -> a
R.runReader (a -> CrossRefM b
action a
arg) CrossRefEnv
env