    {-# LANGUAGE FlexibleContexts     #-}
    {-# LANGUAGE LambdaCase           #-}
    {-# LANGUAGE OverloadedStrings    #-}
    {-# LANGUAGE TypeApplications     #-}
    {- |
    Copyright               : © 2021-2025 Albert Krewinkel
    SPDX-License-Identifier : MIT
    Maintainer              : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>

    Marshaling/unmarshaling functions of 'Pandoc' values.
    -}
    module Text.Pandoc.Lua.Marshal.Pandoc
      ( -- * Pandoc
        typePandoc
      , peekPandoc
      , pushPandoc
      , mkPandoc
        -- * Meta
      , peekMeta
      , pushMeta
      , mkMeta
        -- * Filtering
      , applyFully
      ) where

    import Control.Applicative (optional)
    import Control.Monad ((<$!>))
    import Data.Aeson (encode)
    import Data.Maybe (fromMaybe)
    import HsLua
    import Text.Pandoc.Definition (Pandoc (..), Meta (..), nullMeta)
    import Text.Pandoc.Lua.Marshal.Block (peekBlocksFuzzy, pushBlocks)
    import Text.Pandoc.Lua.Marshal.Filter
    import Text.Pandoc.Lua.Marshal.MetaValue (peekMetaValue, pushMetaValue)
    import Text.Pandoc.Lua.Marshal.Shared (walkBlocksAndInlines)
    import Text.Pandoc.Lua.Walk (applyStraight)
    import Text.Pandoc.Walk (Walkable (walk))
    import qualified Text.Pandoc.Builder as B

    -- | Pushes a 'Pandoc' value as userdata.
    pushPandoc :: LuaError e => Pusher e Pandoc
    pushPandoc :: forall e. LuaError e => Pusher e Pandoc
    pushPandoc = DocumentedTypeWithList e Pandoc Void -> Pandoc -> LuaE e ()
    forall e a itemtype.
    LuaError e =>
    DocumentedTypeWithList e a itemtype -> a -> LuaE e ()
    pushUD DocumentedTypeWithList e Pandoc Void
    forall e. LuaError e => DocumentedType e Pandoc
    typePandoc

    -- | Retrieves a 'Pandoc' document from a userdata value.
    peekPandoc :: LuaError e => Peeker e Pandoc
    peekPandoc :: forall e. LuaError e => Peeker e Pandoc
    peekPandoc = Name -> Peek e Pandoc -> Peek e Pandoc
    forall e a. Name -> Peek e a -> Peek e a
    retrieving Name
    "Pandoc" (Peek e Pandoc -> Peek e Pandoc)
    -> (StackIndex -> Peek e Pandoc) -> StackIndex -> Peek e Pandoc
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . DocumentedTypeWithList e Pandoc Void -> StackIndex -> Peek e Pandoc
    forall e a itemtype.
    LuaError e =>
    DocumentedTypeWithList e a itemtype -> Peeker e a
    peekUD DocumentedTypeWithList e Pandoc Void
    forall e. LuaError e => DocumentedType e Pandoc
    typePandoc

    -- | Pandoc object type.
    typePandoc :: LuaError e => DocumentedType e Pandoc
    typePandoc :: forall e. LuaError e => DocumentedType e Pandoc
    typePandoc = Name
    -> [(Operation, DocumentedFunction e)]
    -> [Member e (DocumentedFunction e) Pandoc]
    -> DocumentedType e Pandoc
    forall e a.
    LuaError e =>
    Name
    -> [(Operation, DocumentedFunction e)]
    -> [Member e (DocumentedFunction e) a]
    -> DocumentedType e a
    deftype Name
    "Pandoc"
      [ Operation
    -> DocumentedFunction e -> (Operation, DocumentedFunction e)
    forall e.
    Operation
    -> DocumentedFunction e -> (Operation, DocumentedFunction e)
    operation Operation
    Concat (DocumentedFunction e -> (Operation, DocumentedFunction e))
    -> DocumentedFunction e -> (Operation, DocumentedFunction e)
    forall a b. (a -> b) -> a -> b
    $ (Pandoc -> Pandoc -> LuaE e Pandoc)
    -> HsFnPrecursor e (Pandoc -> Pandoc -> LuaE e Pandoc)
    forall a e. a -> HsFnPrecursor e a
    lambda
         ### liftPure2 (<>)
         HsFnPrecursor e (Pandoc -> Pandoc -> LuaE e Pandoc)
    -> Parameter e Pandoc -> HsFnPrecursor e (Pandoc -> LuaE e Pandoc)
    forall e a b.
    HsFnPrecursor e (a -> b) -> Parameter e a -> HsFnPrecursor e b
    <#> Peeker e Pandoc -> TypeSpec -> Text -> Text -> Parameter e Pandoc
    forall e a. Peeker e a -> TypeSpec -> Text -> Text -> Parameter e a
    parameter Peeker e Pandoc
    forall e. LuaError e => Peeker e Pandoc
    peekPandoc TypeSpec
    "Pandoc" Text
    "a" Text
    ""
         HsFnPrecursor e (Pandoc -> LuaE e Pandoc)
    -> Parameter e Pandoc -> HsFnPrecursor e (LuaE e Pandoc)
    forall e a b.
    HsFnPrecursor e (a -> b) -> Parameter e a -> HsFnPrecursor e b
    <#> Peeker e Pandoc -> TypeSpec -> Text -> Text -> Parameter e Pandoc
    forall e a. Peeker e a -> TypeSpec -> Text -> Text -> Parameter e a
    parameter Peeker e Pandoc
    forall e. LuaError e => Peeker e Pandoc
    peekPandoc TypeSpec
    "Pandoc" Text
    "b" Text
    ""
         HsFnPrecursor e (LuaE e Pandoc)
    -> FunctionResults e Pandoc -> DocumentedFunction e
    forall e a.
    HsFnPrecursor e (LuaE e a)
    -> FunctionResults e a -> DocumentedFunction e
    =#> Pusher e Pandoc -> TypeSpec -> Text -> FunctionResults e Pandoc
    forall e a. Pusher e a -> TypeSpec -> Text -> FunctionResults e a
    functionResult Pusher e Pandoc
    forall e. LuaError e => Pusher e Pandoc
    pushPandoc TypeSpec
    "Pandoc" Text
    "combined documents"
      , Operation
    -> DocumentedFunction e -> (Operation, DocumentedFunction e)
    forall e.
    Operation
    -> DocumentedFunction e -> (Operation, DocumentedFunction e)
    operation Operation
    Eq (DocumentedFunction e -> (Operation, DocumentedFunction e))
    -> DocumentedFunction e -> (Operation, DocumentedFunction e)
    forall a b. (a -> b) -> a -> b
    $ Name
    -> (Maybe Pandoc -> Maybe Pandoc -> LuaE e Bool)
    -> HsFnPrecursor e (Maybe Pandoc -> Maybe Pandoc -> LuaE e Bool)
    forall a e. Name -> a -> HsFnPrecursor e a
    defun Name
    "__eq"
         ### liftPure2 (\a b -> fromMaybe False ((==) <$> a <*> b))
         HsFnPrecursor e (Maybe Pandoc -> Maybe Pandoc -> LuaE e Bool)
    -> Parameter e (Maybe Pandoc)
    -> HsFnPrecursor e (Maybe Pandoc -> LuaE e Bool)
    forall e a b.
    HsFnPrecursor e (a -> b) -> Parameter e a -> HsFnPrecursor e b
    <#> Peeker e (Maybe Pandoc)
    -> TypeSpec -> Text -> Text -> Parameter e (Maybe Pandoc)
    forall e a. Peeker e a -> TypeSpec -> Text -> Text -> Parameter e a
    parameter (Peek e Pandoc -> Peek e (Maybe Pandoc)
    forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
    optional (Peek e Pandoc -> Peek e (Maybe Pandoc))
    -> Peeker e Pandoc -> Peeker e (Maybe Pandoc)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Peeker e Pandoc
    forall e. LuaError e => Peeker e Pandoc
    peekPandoc) TypeSpec
    "doc1" Text
    "pandoc" Text
    ""
         HsFnPrecursor e (Maybe Pandoc -> LuaE e Bool)
    -> Parameter e (Maybe Pandoc) -> HsFnPrecursor e (LuaE e Bool)
    forall e a b.
    HsFnPrecursor e (a -> b) -> Parameter e a -> HsFnPrecursor e b
    <#> Peeker e (Maybe Pandoc)
    -> TypeSpec -> Text -> Text -> Parameter e (Maybe Pandoc)
    forall e a. Peeker e a -> TypeSpec -> Text -> Text -> Parameter e a
    parameter (Peek e Pandoc -> Peek e (Maybe Pandoc)
    forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
    optional (Peek e Pandoc -> Peek e (Maybe Pandoc))
    -> Peeker e Pandoc -> Peeker e (Maybe Pandoc)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Peeker e Pandoc
    forall e. LuaError e => Peeker e Pandoc
    peekPandoc) TypeSpec
    "doc2" Text
    "pandoc" Text
    ""
         HsFnPrecursor e (LuaE e Bool)
    -> FunctionResults e Bool -> DocumentedFunction e
    forall e a.
    HsFnPrecursor e (LuaE e a)
    -> FunctionResults e a -> DocumentedFunction e
    =#> Pusher e Bool -> TypeSpec -> Text -> FunctionResults e Bool
    forall e a. Pusher e a -> TypeSpec -> Text -> FunctionResults e a
    functionResult Pusher e Bool
    forall e. Pusher e Bool
    pushBool TypeSpec
    "boolean" Text
    "true iff the two values are equal"
      , Operation
    -> DocumentedFunction e -> (Operation, DocumentedFunction e)
    forall e.
    Operation
    -> DocumentedFunction e -> (Operation, DocumentedFunction e)
    operation Operation
    Tostring (DocumentedFunction e -> (Operation, DocumentedFunction e))
    -> DocumentedFunction e -> (Operation, DocumentedFunction e)
    forall a b. (a -> b) -> a -> b
    $ (Pandoc -> LuaE e String)
    -> HsFnPrecursor e (Pandoc -> LuaE e String)
    forall a e. a -> HsFnPrecursor e a
    lambda
        ### liftPure show
        HsFnPrecursor e (Pandoc -> LuaE e String)
    -> Parameter e Pandoc -> HsFnPrecursor e (LuaE e String)
    forall e a b.
    HsFnPrecursor e (a -> b) -> Parameter e a -> HsFnPrecursor e b
    <#> Peeker e Pandoc -> TypeSpec -> Text -> Text -> Parameter e Pandoc
    forall e a. Peeker e a -> TypeSpec -> Text -> Text -> Parameter e a
    parameter Peeker e Pandoc
    forall e. LuaError e => Peeker e Pandoc
    peekPandoc TypeSpec
    "Pandoc" Text
    "doc" Text
    ""
        HsFnPrecursor e (LuaE e String)
    -> FunctionResults e String -> DocumentedFunction e
    forall e a.
    HsFnPrecursor e (LuaE e a)
    -> FunctionResults e a -> DocumentedFunction e
    =#> Pusher e String -> TypeSpec -> Text -> FunctionResults e String
    forall e a. Pusher e a -> TypeSpec -> Text -> FunctionResults e a
    functionResult Pusher e String
    forall e. String -> LuaE e ()
    pushString TypeSpec
    "string" Text
    "native Haskell representation"
      , Operation
    -> DocumentedFunction e -> (Operation, DocumentedFunction e)
    forall e.
    Operation
    -> DocumentedFunction e -> (Operation, DocumentedFunction e)
    operation (Name -> Operation
    CustomOperation Name
    "__tojson") (DocumentedFunction e -> (Operation, DocumentedFunction e))
    -> DocumentedFunction e -> (Operation, DocumentedFunction e)
    forall a b. (a -> b) -> a -> b
    $ (Pandoc -> LuaE e ByteString)
    -> HsFnPrecursor e (Pandoc -> LuaE e ByteString)
    forall a e. a -> HsFnPrecursor e a
    lambda
        ### liftPure encode
        HsFnPrecursor e (Pandoc -> LuaE e ByteString)
    -> Parameter e Pandoc -> HsFnPrecursor e (LuaE e ByteString)
    forall e a b.
    HsFnPrecursor e (a -> b) -> Parameter e a -> HsFnPrecursor e b
    <#> DocumentedType e Pandoc -> Text -> Text -> Parameter e Pandoc
    forall e a itemtype.
    LuaError e =>
    DocumentedTypeWithList e a itemtype
    -> Text -> Text -> Parameter e a
    udparam DocumentedType e Pandoc
    forall e. LuaError e => DocumentedType e Pandoc
    typePandoc Text
    "self" Text
    ""
        HsFnPrecursor e (LuaE e ByteString)
    -> FunctionResults e ByteString -> DocumentedFunction e
    forall e a.
    HsFnPrecursor e (LuaE e a)
    -> FunctionResults e a -> DocumentedFunction e
    =#> Pusher e ByteString
    -> TypeSpec -> Text -> FunctionResults e ByteString
    forall e a. Pusher e a -> TypeSpec -> Text -> FunctionResults e a
    functionResult Pusher e ByteString
    forall e. Pusher e ByteString
    pushLazyByteString TypeSpec
    "string" Text
    "JSON representation"
      ]
      [ Name
    -> Text
    -> (Pusher e [Block], Pandoc -> [Block])
    -> (Peeker e [Block], Pandoc -> [Block] -> Pandoc)
    -> Member e (DocumentedFunction e) Pandoc
    forall e b a fn.
    LuaError e =>
    Name
    -> Text
    -> (Pusher e b, a -> b)
    -> (Peeker e b, a -> b -> a)
    -> Member e fn a
    property Name
    "blocks" Text
    "list of blocks"
          (Pusher e [Block]
    forall e. LuaError e => Pusher e [Block]
    pushBlocks, \(Pandoc Meta
    _ [Block]
    blks) -> [Block]
    blks)
          (Peeker e [Block]
    forall e. LuaError e => Peeker e [Block]
    peekBlocksFuzzy, \(Pandoc Meta
    m [Block]
    _) [Block]
    blks -> Meta -> [Block] -> Pandoc
    Pandoc Meta
    m [Block]
    blks)
      , Name
    -> Text
    -> (Pusher e Meta, Pandoc -> Meta)
    -> (Peeker e Meta, Pandoc -> Meta -> Pandoc)
    -> Member e (DocumentedFunction e) Pandoc
    forall e b a fn.
    LuaError e =>
    Name
    -> Text
    -> (Pusher e b, a -> b)
    -> (Peeker e b, a -> b -> a)
    -> Member e fn a
    property Name
    "meta" Text
    "document metadata"
          (Pusher e Meta
    forall e. LuaError e => Pusher e Meta
    pushMeta, \(Pandoc Meta
    meta [Block]
    _) -> Meta
    meta)
          (Peeker e Meta
    forall e. LuaError e => Peeker e Meta
    peekMeta, \(Pandoc Meta
    _ [Block]
    blks) Meta
    meta -> Meta -> [Block] -> Pandoc
    Pandoc Meta
    meta [Block]
    blks)

      , DocumentedFunction e -> Member e (DocumentedFunction e) Pandoc
    forall e a.
    DocumentedFunction e -> Member e (DocumentedFunction e) a
    method (DocumentedFunction e -> Member e (DocumentedFunction e) Pandoc)
    -> DocumentedFunction e -> Member e (DocumentedFunction e) Pandoc
    forall a b. (a -> b) -> a -> b
    $ Name
    -> (Pandoc -> LuaE e Pandoc)
    -> HsFnPrecursor e (Pandoc -> LuaE e Pandoc)
    forall a e. Name -> a -> HsFnPrecursor e a
    defun Name
    "clone"
          ### return
          HsFnPrecursor e (Pandoc -> LuaE e Pandoc)
    -> Parameter e Pandoc -> HsFnPrecursor e (LuaE e Pandoc)
    forall e a b.
    HsFnPrecursor e (a -> b) -> Parameter e a -> HsFnPrecursor e b
    <#> Peeker e Pandoc -> TypeSpec -> Text -> Text -> Parameter e Pandoc
    forall e a. Peeker e a -> TypeSpec -> Text -> Text -> Parameter e a
    parameter Peeker e Pandoc
    forall e. LuaError e => Peeker e Pandoc
    peekPandoc TypeSpec
    "Pandoc" Text
    "doc" Text
    "self"
          HsFnPrecursor e (LuaE e Pandoc)
    -> FunctionResults e Pandoc -> DocumentedFunction e
    forall e a.
    HsFnPrecursor e (LuaE e a)
    -> FunctionResults e a -> DocumentedFunction e
    =#> Pusher e Pandoc -> TypeSpec -> Text -> FunctionResults e Pandoc
    forall e a. Pusher e a -> TypeSpec -> Text -> FunctionResults e a
    functionResult Pusher e Pandoc
    forall e. LuaError e => Pusher e Pandoc
    pushPandoc TypeSpec
    "Pandoc" Text
    "cloned Pandoc document"

      , DocumentedFunction e -> Member e (DocumentedFunction e) Pandoc
    forall e a.
    DocumentedFunction e -> Member e (DocumentedFunction e) a
    method (DocumentedFunction e -> Member e (DocumentedFunction e) Pandoc)
    -> DocumentedFunction e -> Member e (DocumentedFunction e) Pandoc
    forall a b. (a -> b) -> a -> b
    $ Name
    -> (Pandoc -> LuaE e Pandoc)
    -> HsFnPrecursor e (Pandoc -> LuaE e Pandoc)
    forall a e. Name -> a -> HsFnPrecursor e a
    defun Name
    "normalize"
          ### liftPure normalize
          HsFnPrecursor e (Pandoc -> LuaE e Pandoc)
    -> Parameter e Pandoc -> HsFnPrecursor e (LuaE e Pandoc)
    forall e a b.
    HsFnPrecursor e (a -> b) -> Parameter e a -> HsFnPrecursor e b
    <#> DocumentedType e Pandoc -> Text -> Text -> Parameter e Pandoc
    forall e a itemtype.
    LuaError e =>
    DocumentedTypeWithList e a itemtype
    -> Text -> Text -> Parameter e a
    udparam DocumentedType e Pandoc
    forall e. LuaError e => DocumentedType e Pandoc
    typePandoc Text
    "self" Text
    ""
          HsFnPrecursor e (LuaE e Pandoc)
    -> FunctionResults e Pandoc -> DocumentedFunction e
    forall e a.
    HsFnPrecursor e (LuaE e a)
    -> FunctionResults e a -> DocumentedFunction e
    =#> DocumentedType e Pandoc -> Text -> FunctionResults e Pandoc
    forall e a itemtype.
    LuaError e =>
    DocumentedTypeWithList e a itemtype -> Text -> FunctionResults e a
    udresult DocumentedType e Pandoc
    forall e. LuaError e => DocumentedType e Pandoc
    typePandoc Text
    "cloned and normalized document"

      , DocumentedFunction e -> Member e (DocumentedFunction e) Pandoc
    forall e a.
    DocumentedFunction e -> Member e (DocumentedFunction e) a
    method (DocumentedFunction e -> Member e (DocumentedFunction e) Pandoc)
    -> DocumentedFunction e -> Member e (DocumentedFunction e) Pandoc
    forall a b. (a -> b) -> a -> b
    $ Name
    -> (Pandoc -> Filter -> LuaE e Pandoc)
    -> HsFnPrecursor e (Pandoc -> Filter -> LuaE e Pandoc)
    forall a e. Name -> a -> HsFnPrecursor e a
    defun Name
    "walk"
        ### flip applyFully
        HsFnPrecursor e (Pandoc -> Filter -> LuaE e Pandoc)
    -> Parameter e Pandoc -> HsFnPrecursor e (Filter -> LuaE e Pandoc)
    forall e a b.
    HsFnPrecursor e (a -> b) -> Parameter e a -> HsFnPrecursor e b
    <#> Peeker e Pandoc -> TypeSpec -> Text -> Text -> Parameter e Pandoc
    forall e a. Peeker e a -> TypeSpec -> Text -> Text -> Parameter e a
    parameter Peeker e Pandoc
    forall e. LuaError e => Peeker e Pandoc
    peekPandoc TypeSpec
    "Pandoc" Text
    "self" Text
    ""
        HsFnPrecursor e (Filter -> LuaE e Pandoc)
    -> Parameter e Filter -> HsFnPrecursor e (LuaE e Pandoc)
    forall e a b.
    HsFnPrecursor e (a -> b) -> Parameter e a -> HsFnPrecursor e b
    <#> Peeker e Filter -> TypeSpec -> Text -> Text -> Parameter e Filter
    forall e a. Peeker e a -> TypeSpec -> Text -> Text -> Parameter e a
    parameter Peeker e Filter
    forall e. LuaError e => Peeker e Filter
    peekFilter TypeSpec
    "Filter" Text
    "lua_filter" Text
    "table of filter functions"
        HsFnPrecursor e (LuaE e Pandoc)
    -> FunctionResults e Pandoc -> DocumentedFunction e
    forall e a.
    HsFnPrecursor e (LuaE e a)
    -> FunctionResults e a -> DocumentedFunction e
    =#> Pusher e Pandoc -> TypeSpec -> Text -> FunctionResults e Pandoc
    forall e a. Pusher e a -> TypeSpec -> Text -> FunctionResults e a
    functionResult Pusher e Pandoc
    forall e. LuaError e => Pusher e Pandoc
    pushPandoc TypeSpec
    "Pandoc" Text
    "modified element"
      ]

    -- | Pushes a 'Meta' value as a string-indexed table.
    pushMeta :: LuaError e => Pusher e Meta
    pushMeta :: forall e. LuaError e => Pusher e Meta
    pushMeta (Meta Map Text MetaValue
    mmap) = do
      Pusher e Text
    -> Pusher e MetaValue -> Pusher e (Map Text MetaValue)
    forall e a b.
    LuaError e =>
    Pusher e a -> Pusher e b -> Pusher e (Map a b)
    pushMap Pusher e Text
    forall e. Pusher e Text
    pushText Pusher e MetaValue
    forall e. LuaError e => Pusher e MetaValue
    pushMetaValue Map Text MetaValue
    mmap
      _ <- Name -> LuaE e Bool
    forall e. Name -> LuaE e Bool
    newmetatable Name
    "Meta"
      setmetatable (nth 2)

    -- | Retrieves a 'Meta' value from a string-indexed table.
    peekMeta :: LuaError e => Peeker e Meta
    peekMeta :: forall e. LuaError e => Peeker e Meta
    peekMeta StackIndex
    idx = Name -> Peek e Meta -> Peek e Meta
    forall e a. Name -> Peek e a -> Peek e a
    retrieving Name
    "Meta" (Peek e Meta -> Peek e Meta) -> Peek e Meta -> Peek e Meta
    forall a b. (a -> b) -> a -> b
    $
      Map Text MetaValue -> Meta
    Meta (Map Text MetaValue -> Meta)
    -> Peek e (Map Text MetaValue) -> Peek e Meta
    forall (m :: * -> *) a b. Monad m => (a -> b) -> m a -> m b
    <$!> Peeker e Text
    -> Peeker e MetaValue -> Peeker e (Map Text MetaValue)
    forall e a b.
    (LuaError e, Ord a) =>
    Peeker e a -> Peeker e b -> Peeker e (Map a b)
    peekMap Peeker e Text
    forall e. Peeker e Text
    peekText Peeker e MetaValue
    forall e. LuaError e => Peeker e MetaValue
    peekMetaValue StackIndex
    idx

    -- | Constructor function for 'Pandoc' values.
    mkPandoc :: LuaError e => DocumentedFunction e
    mkPandoc :: forall e. LuaError e => DocumentedFunction e
    mkPandoc = Name
    -> ([Block] -> Maybe Meta -> LuaE e Pandoc)
    -> HsFnPrecursor e ([Block] -> Maybe Meta -> LuaE e Pandoc)
    forall a e. Name -> a -> HsFnPrecursor e a
    defun Name
    "Pandoc"
      ### liftPure2 (\blocks mMeta -> Pandoc (fromMaybe nullMeta mMeta) blocks)
      HsFnPrecursor e ([Block] -> Maybe Meta -> LuaE e Pandoc)
    -> Parameter e [Block]
    -> HsFnPrecursor e (Maybe Meta -> LuaE e Pandoc)
    forall e a b.
    HsFnPrecursor e (a -> b) -> Parameter e a -> HsFnPrecursor e b
    <#> Peeker e [Block] -> TypeSpec -> Text -> Text -> Parameter e [Block]
    forall e a. Peeker e a -> TypeSpec -> Text -> Text -> Parameter e a
    parameter Peeker e [Block]
    forall e. LuaError e => Peeker e [Block]
    peekBlocksFuzzy TypeSpec
    "Blocks" Text
    "blocks" Text
    "document contents"
      HsFnPrecursor e (Maybe Meta -> LuaE e Pandoc)
    -> Parameter e (Maybe Meta) -> HsFnPrecursor e (LuaE e Pandoc)
    forall e a b.
    HsFnPrecursor e (a -> b) -> Parameter e a -> HsFnPrecursor e b
    <#> Parameter e Meta -> Parameter e (Maybe Meta)
    forall e a. Parameter e a -> Parameter e (Maybe a)
    opt (Peeker e Meta -> TypeSpec -> Text -> Text -> Parameter e Meta
    forall e a. Peeker e a -> TypeSpec -> Text -> Text -> Parameter e a
    parameter Peeker e Meta
    forall e. LuaError e => Peeker e Meta
    peekMeta TypeSpec
    "Meta" Text
    "meta" Text
    "document metadata")
      HsFnPrecursor e (LuaE e Pandoc)
    -> FunctionResults e Pandoc -> DocumentedFunction e
    forall e a.
    HsFnPrecursor e (LuaE e a)
    -> FunctionResults e a -> DocumentedFunction e
    =#> Pusher e Pandoc -> TypeSpec -> Text -> FunctionResults e Pandoc
    forall e a. Pusher e a -> TypeSpec -> Text -> FunctionResults e a
    functionResult Pusher e Pandoc
    forall e. LuaError e => Pusher e Pandoc
    pushPandoc TypeSpec
    "Pandoc" Text
    "new Pandoc document"

    -- | Constructor for 'Meta' values.
    mkMeta :: LuaError e => DocumentedFunction e
    mkMeta :: forall e. LuaError e => DocumentedFunction e
    mkMeta = Name
    -> (Meta -> LuaE e Meta) -> HsFnPrecursor e (Meta -> LuaE e Meta)
    forall a e. Name -> a -> HsFnPrecursor e a
    defun Name
    "Meta"
      ### liftPure id
      HsFnPrecursor e (Meta -> LuaE e Meta)
    -> Parameter e Meta -> HsFnPrecursor e (LuaE e Meta)
    forall e a b.
    HsFnPrecursor e (a -> b) -> Parameter e a -> HsFnPrecursor e b
    <#> Peeker e Meta -> TypeSpec -> Text -> Text -> Parameter e Meta
    forall e a. Peeker e a -> TypeSpec -> Text -> Text -> Parameter e a
    parameter Peeker e Meta
    forall e. LuaError e => Peeker e Meta
    peekMeta TypeSpec
    "table" Text
    "meta" Text
    "table containing meta information"
      HsFnPrecursor e (LuaE e Meta)
    -> FunctionResults e Meta -> DocumentedFunction e
    forall e a.
    HsFnPrecursor e (LuaE e a)
    -> FunctionResults e a -> DocumentedFunction e
    =#> Pusher e Meta -> TypeSpec -> Text -> FunctionResults e Meta
    forall e a. Pusher e a -> TypeSpec -> Text -> FunctionResults e a
    functionResult Pusher e Meta
    forall e. LuaError e => Pusher e Meta
    pushMeta TypeSpec
    "table" Text
    "new Meta table"

    -- | Applies a filter function to a Pandoc value.
    applyPandocFunction :: LuaError e
                              => Filter
                              -> Pandoc -> LuaE e Pandoc
    applyPandocFunction :: forall e. LuaError e => Filter -> Pandoc -> LuaE e Pandoc
    applyPandocFunction = Pusher e Pandoc
    -> Peeker e Pandoc -> Filter -> Pandoc -> LuaE e Pandoc
    forall e a.
    (LuaError e, Data a) =>
    Pusher e a -> Peeker e a -> Filter -> a -> LuaE e a
    applyStraight Pusher e Pandoc
    forall e. LuaError e => Pusher e Pandoc
    pushPandoc Peeker e Pandoc
    forall e. LuaError e => Peeker e Pandoc
    peekPandoc

    -- | Applies a filter function to a Meta value.
    applyMetaFunction :: LuaError e
                            => Filter
                            -> Pandoc -> LuaE e Pandoc
    applyMetaFunction :: forall e. LuaError e => Filter -> Pandoc -> LuaE e Pandoc
    applyMetaFunction Filter
    filter' (Pandoc Meta
    meta [Block]
    blocks) = do
      meta' <- Pusher e Meta -> Peeker e Meta -> Filter -> Meta -> LuaE e Meta
    forall e a.
    (LuaError e, Data a) =>
    Pusher e a -> Peeker e a -> Filter -> a -> LuaE e a
    applyStraight Pusher e Meta
    forall e. LuaError e => Pusher e Meta
    pushMeta Peeker e Meta
    forall e. LuaError e => Peeker e Meta
    peekMeta Filter
    filter' Meta
    meta
      pure (Pandoc meta' blocks)

    -- | Apply all components of a Lua filter.
    --
    -- These operations are run in order:
    --
    -- - Inline filter functions are applied to Inline elements, splicing
    --   the result back into the list of Inline elements
    --
    -- - The @Inlines@ function is applied to all lists of Inlines.
    --
    -- - Block filter functions are applied to Block elements, splicing the
    --   result back into the list of Block elements
    --
    -- - The @Blocks@ function is applied to all lists of Blocks.
    --
    -- - The @Meta@ function is applied to the 'Meta' part.
    --
    -- - The @Pandoc@ function is applied to the full 'Pandoc' element.
    applyFully :: LuaError e
               => Filter
               -> Pandoc -> LuaE e Pandoc
    applyFully :: forall e. LuaError e => Filter -> Pandoc -> LuaE e Pandoc
    applyFully Filter
    filter' Pandoc
    doc = case Filter -> WalkingOrder
    filterWalkingOrder Filter
    filter' of
      WalkingOrder
    WalkForEachType -> Filter -> Pandoc -> LuaE e Pandoc
    forall e a.
    (LuaError e, Walkable (SpliceList Block) a,
     Walkable (SpliceList Inline) a, Walkable [Block] a,
     Walkable [Inline] a, Walkable Topdown a) =>
    Filter -> a -> LuaE e a
    walkBlocksAndInlines Filter
    filter' Pandoc
    doc
                     LuaE e Pandoc -> (Pandoc -> LuaE e Pandoc) -> LuaE e Pandoc
    forall a b. LuaE e a -> (a -> LuaE e b) -> LuaE e b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Filter -> Pandoc -> LuaE e Pandoc
    forall e. LuaError e => Filter -> Pandoc -> LuaE e Pandoc
    applyMetaFunction Filter
    filter'
                     LuaE e Pandoc -> (Pandoc -> LuaE e Pandoc) -> LuaE e Pandoc
    forall a b. LuaE e a -> (a -> LuaE e b) -> LuaE e b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Filter -> Pandoc -> LuaE e Pandoc
    forall e. LuaError e => Filter -> Pandoc -> LuaE e Pandoc
    applyPandocFunction Filter
    filter'
      WalkingOrder
    WalkTopdown     -> Filter -> Pandoc -> LuaE e Pandoc
    forall e. LuaError e => Filter -> Pandoc -> LuaE e Pandoc
    applyPandocFunction Filter
    filter' Pandoc
    doc
                     LuaE e Pandoc -> (Pandoc -> LuaE e Pandoc) -> LuaE e Pandoc
    forall a b. LuaE e a -> (a -> LuaE e b) -> LuaE e b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Filter -> Pandoc -> LuaE e Pandoc
    forall e. LuaError e => Filter -> Pandoc -> LuaE e Pandoc
    applyMetaFunction Filter
    filter'
                     LuaE e Pandoc -> (Pandoc -> LuaE e Pandoc) -> LuaE e Pandoc
    forall a b. LuaE e a -> (a -> LuaE e b) -> LuaE e b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Filter -> Pandoc -> LuaE e Pandoc
    forall e a.
    (LuaError e, Walkable (SpliceList Block) a,
     Walkable (SpliceList Inline) a, Walkable [Block] a,
     Walkable [Inline] a, Walkable Topdown a) =>
    Filter -> a -> LuaE e a
    walkBlocksAndInlines Filter
    filter'

    -- | Normalize a document
    normalize :: (Walkable [B.Inline] a, Walkable B.Block a) => a -> a
    normalize :: forall a. (Walkable [Inline] a, Walkable Block a) => a -> a
    normalize =
      let normalizeBlock :: Block -> Block
    normalizeBlock = \case
            B.Table Attr
    attr Caption
    capt [ColSpec]
    specs TableHead
    th [TableBody]
    tbs TableFoot
    tf ->
              let twidth :: Int
    twidth = [ColSpec] -> Int
    forall a. [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length [ColSpec]
    specs
                  th' :: TableHead
    th'  = Int -> TableHead -> TableHead
    B.normalizeTableHead Int
    twidth TableHead
    th
                  tbs' :: [TableBody]
    tbs' = (TableBody -> TableBody) -> [TableBody] -> [TableBody]
    forall a b. (a -> b) -> [a] -> [b]
    map (Int -> TableBody -> TableBody
    B.normalizeTableBody Int
    twidth) [TableBody]
    tbs
                  tf' :: TableFoot
    tf'  = Int -> TableFoot -> TableFoot
    B.normalizeTableFoot Int
    twidth TableFoot
    tf
              in Attr
    -> Caption
    -> [ColSpec]
    -> TableHead
    -> [TableBody]
    -> TableFoot
    -> Block
    B.Table Attr
    attr Caption
    capt [ColSpec]
    specs TableHead
    th' [TableBody]
    tbs' TableFoot
    tf'
            Block
    x -> Block
    x
      in (Block -> Block) -> a -> a
    forall a b. Walkable a b => (a -> a) -> b -> b
    walk Block -> Block
    normalizeBlock (a -> a) -> (a -> a) -> a -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .
         ([Inline] -> [Inline]) -> a -> a
    forall a b. Walkable a b => (a -> a) -> b -> b
    walk (Many Inline -> [Inline]
    forall a. Many a -> [a]
    B.toList (Many Inline -> [Inline])
    -> ([Inline] -> Many Inline) -> [Inline] -> [Inline]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [Many Inline] -> Many Inline
    forall a. Monoid a => [a] -> a
    mconcat ([Many Inline] -> Many Inline)
    -> ([Inline] -> [Many Inline]) -> [Inline] -> Many Inline
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Inline -> Many Inline) -> [Inline] -> [Many Inline]
    forall a b. (a -> b) -> [a] -> [b]
    map (forall a. a -> Many a
    B.singleton @B.Inline))