pandoc-builder-monadic-1.0.0: src/Text/Pandoc/Builder/Monadic/Internal.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleInstances #-}
{-|
Internal module, exposing the Builder(..) type, you should
prefer using 'Text.Pandoc.Builder.Monadic.Utils.mapBuilder',
or adding something to 'Text.Pandoc.Builder.Monadic.Utils'.
-}
module Text.Pandoc.Builder.Monadic.Internal
( BuilderM(..)
, Builder
, buildMany
, runToList
, runToDList
, runToMany
, tellOne
, tellAll
) where
import Control.Monad.Writer.Strict (Writer, execWriter, tell)
import Data.DList (DList)
import Data.Foldable (traverse_)
import Text.Pandoc.Builder (Inline)
#if __GLASGOW_HASKELL__ < 804
import Data.Semigroup
#endif
import qualified Text.Pandoc.Builder as B
import qualified Data.DList as DList
-- | The pandoc element builder type. It wraps a writer monad.
-- Chances are, you only need t'Builder' (a 'BuilderM el ()').
-- All builders in this library have an `el` type in the set
-- {'B.Inline', 'B.Block'}.
newtype BuilderM el a = Builder { unBuilder :: Writer (DList el) a }
-- | Pandoc element builder. Stores written pandoc elements.
type Builder el = BuilderM el ()
instance Functor (BuilderM el) where
fmap f = Builder . fmap f . unBuilder
instance Applicative (BuilderM el) where
pure a = Builder $ pure a
Builder f <*> Builder a = Builder $ f <*> a
instance Monad (BuilderM el) where
Builder a >>= f = Builder $ do
a' <- a
unBuilder $ f a'
instance Semigroup (BuilderM el a) where
Builder a <> Builder b = Builder $ a >> b
instance Monoid a => Monoid (BuilderM el a) where
mempty = Builder $ pure mempty
instance B.ToMetaValue (Builder Inline) where
toMetaValue = B.MetaInlines . runToList
-- | Useful for setting authors
instance B.ToMetaValue (Builder (Builder Inline)) where
toMetaValue = B.MetaList . map B.toMetaValue . runToList
-- | Get elements written in the t'Builder' as a difference list
runToDList :: Builder el -> DList el
runToDList = execWriter . unBuilder
-- | Get elements written in the t'Builder' as a list
runToList :: Builder el -> [el]
runToList = DList.toList . runToDList
-- | Get elements written in a t'Builder' as a 'B.Many'.
-- This might be useful if you need to interact with pandoc-types.
runToMany :: Builder a -> B.Many a
runToMany = B.fromList . DList.toList . execWriter . unBuilder
-- | Get pandoc-types' 'B.Many' as a t'Builder'.
buildMany :: B.Many a -> Builder a
buildMany = Builder . traverse_ (tell . pure)
-- | Write a single element to a t'Builder'.
tellOne :: a -> Builder a
tellOne = Builder . tell . DList.singleton
-- | Write multiple element to a t'Builder'.
tellAll :: DList a -> Builder a
tellAll = Builder . tell