{-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {- | Module : Text.Pandoc.Lua.Walk Copyright : © 2012-2021 John MacFarlane, © 2017-2021 Albert Krewinkel License : GNU GPL, version 2 or above Maintainer : Albert Krewinkel Stability : alpha Walking documents in a filter-suitable way. -} module Text.Pandoc.Lua.Walk ( SingletonsList (..) ) where import Control.Monad ((<=<)) import Text.Pandoc.Definition import Text.Pandoc.Walk -- | Helper type which allows to traverse trees in order, while splicing in -- trees. -- -- The only interesting use of this type is via it's '@Walkable@' instance. That -- instance makes it possible to walk a Pandoc document (or a subset thereof), -- while applying a function on each element of an AST element /list/, and have -- the resulting list spliced back in place of the original element. This is the -- traversal/splicing method used for Lua filters. newtype SingletonsList a = SingletonsList { singletonsList :: [a] } deriving (Functor, Foldable, Traversable) -- -- SingletonsList Inline -- instance {-# OVERLAPPING #-} Walkable (SingletonsList Inline) [Inline] where walkM = walkSingletonsListM query = querySingletonsList instance Walkable (SingletonsList Inline) Pandoc where walkM = walkPandocM query = queryPandoc instance Walkable (SingletonsList Inline) Citation where walkM = walkCitationM query = queryCitation instance Walkable (SingletonsList Inline) Inline where walkM = walkInlineM query = queryInline instance Walkable (SingletonsList Inline) Block where walkM = walkBlockM query = queryBlock instance Walkable (SingletonsList Inline) Row where walkM = walkRowM query = queryRow instance Walkable (SingletonsList Inline) TableHead where walkM = walkTableHeadM query = queryTableHead instance Walkable (SingletonsList Inline) TableBody where walkM = walkTableBodyM query = queryTableBody instance Walkable (SingletonsList Inline) TableFoot where walkM = walkTableFootM query = queryTableFoot instance Walkable (SingletonsList Inline) Caption where walkM = walkCaptionM query = queryCaption instance Walkable (SingletonsList Inline) Cell where walkM = walkCellM query = queryCell instance Walkable (SingletonsList Inline) MetaValue where walkM = walkMetaValueM query = queryMetaValue instance Walkable (SingletonsList Inline) Meta where walkM f (Meta metamap) = Meta <$> walkM f metamap query f (Meta metamap) = query f metamap -- -- SingletonsList Block -- instance {-# OVERLAPPING #-} Walkable (SingletonsList Block) [Block] where walkM = walkSingletonsListM query = querySingletonsList instance Walkable (SingletonsList Block) Pandoc where walkM = walkPandocM query = queryPandoc instance Walkable (SingletonsList Block) Citation where walkM = walkCitationM query = queryCitation instance Walkable (SingletonsList Block) Inline where walkM = walkInlineM query = queryInline instance Walkable (SingletonsList Block) Block where walkM = walkBlockM query = queryBlock instance Walkable (SingletonsList Block) Row where walkM = walkRowM query = queryRow instance Walkable (SingletonsList Block) TableHead where walkM = walkTableHeadM query = queryTableHead instance Walkable (SingletonsList Block) TableBody where walkM = walkTableBodyM query = queryTableBody instance Walkable (SingletonsList Block) TableFoot where walkM = walkTableFootM query = queryTableFoot instance Walkable (SingletonsList Block) Caption where walkM = walkCaptionM query = queryCaption instance Walkable (SingletonsList Block) Cell where walkM = walkCellM query = queryCell instance Walkable (SingletonsList Block) MetaValue where walkM = walkMetaValueM query = queryMetaValue instance Walkable (SingletonsList Block) Meta where walkM f (Meta metamap) = Meta <$> walkM f metamap query f (Meta metamap) = query f metamap walkSingletonsListM :: (Monad m, Walkable (SingletonsList a) a) => (SingletonsList a -> m (SingletonsList a)) -> [a] -> m [a] walkSingletonsListM f = let f' = fmap singletonsList . f . SingletonsList . (:[]) <=< walkM f in fmap mconcat . mapM f' querySingletonsList :: (Monoid c, Walkable (SingletonsList a) a) => (SingletonsList a -> c) -> [a] -> c querySingletonsList f = let f' x = f (SingletonsList [x]) `mappend` query f x in mconcat . map f'