    {-# OPTIONS_GHC -fno-warn-orphans #-}
    {-# LANGUAGE LambdaCase           #-}
    {- |
       Module      : Text.Pandoc.Lua.Marshaling.AST
       Copyright   : © 2012-2020 John MacFarlane
                     © 2017-2020 Albert Krewinkel
       License     : GNU GPL, version 2 or above

       Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
       Stability   : alpha

    Marshaling/unmarshaling instances for document AST elements.
    -}
    module Text.Pandoc.Lua.Marshaling.AST
      ( LuaAttr (..)
      , LuaListAttributes (..)
      ) where

    import Control.Applicative ((<|>))
    import Foreign.Lua (Lua, Peekable, Pushable, StackIndex)
    import Text.Pandoc.Definition
    import Text.Pandoc.Lua.Util (defineHowTo, pushViaConstructor)
    import Text.Pandoc.Lua.Marshaling.CommonState ()

    import qualified Foreign.Lua as Lua
    import qualified Text.Pandoc.Lua.Util as LuaUtil

    instance Pushable Pandoc where
      push :: Pandoc -> Lua ()
    push (Pandoc meta :: Meta
    meta blocks :: [Block]
    blocks) =
        String -> [Block] -> Meta -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "Pandoc" [Block]
    blocks Meta
    meta

    instance Peekable Pandoc where
      peek :: StackIndex -> Lua Pandoc
    peek idx :: StackIndex
    idx = String -> Lua Pandoc -> Lua Pandoc
    forall a. String -> Lua a -> Lua a
    defineHowTo "get Pandoc value" (Lua Pandoc -> Lua Pandoc) -> Lua Pandoc -> Lua Pandoc
    forall a b. (a -> b) -> a -> b
    $ do
        [Block]
    blocks <- StackIndex -> String -> Lua [Block]
    forall a. Peekable a => StackIndex -> String -> Lua a
    LuaUtil.rawField StackIndex
    idx "blocks"
        Meta
    meta   <- StackIndex -> String -> Lua Meta
    forall a. Peekable a => StackIndex -> String -> Lua a
    LuaUtil.rawField StackIndex
    idx "meta"
        Pandoc -> Lua Pandoc
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Pandoc -> Lua Pandoc) -> Pandoc -> Lua Pandoc
    forall a b. (a -> b) -> a -> b
    $ Meta -> [Block] -> Pandoc
    Pandoc Meta
    meta [Block]
    blocks

    instance Pushable Meta where
      push :: Meta -> Lua ()
    push (Meta mmap :: Map Text MetaValue
    mmap) =
        String -> Map Text MetaValue -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "Meta" Map Text MetaValue
    mmap
    instance Peekable Meta where
      peek :: StackIndex -> Lua Meta
    peek idx :: StackIndex
    idx = String -> Lua Meta -> Lua Meta
    forall a. String -> Lua a -> Lua a
    defineHowTo "get Meta value" (Lua Meta -> Lua Meta) -> Lua Meta -> Lua Meta
    forall a b. (a -> b) -> a -> b
    $
        Map Text MetaValue -> Meta
    Meta (Map Text MetaValue -> Meta)
    -> Lua (Map Text MetaValue) -> Lua Meta
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> StackIndex -> Lua (Map Text MetaValue)
    forall a. Peekable a => StackIndex -> Lua a
    Lua.peek StackIndex
    idx

    instance Pushable MetaValue where
      push :: MetaValue -> Lua ()
    push = MetaValue -> Lua ()
    pushMetaValue
    instance Peekable MetaValue where
      peek :: StackIndex -> Lua MetaValue
    peek = StackIndex -> Lua MetaValue
    peekMetaValue

    instance Pushable Block where
      push :: Block -> Lua ()
    push = Block -> Lua ()
    pushBlock

    instance Peekable Block where
      peek :: StackIndex -> Lua Block
    peek = StackIndex -> Lua Block
    peekBlock

    -- Inline
    instance Pushable Inline where
      push :: Inline -> Lua ()
    push = Inline -> Lua ()
    pushInline

    instance Peekable Inline where
      peek :: StackIndex -> Lua Inline
    peek = StackIndex -> Lua Inline
    peekInline

    -- Citation
    instance Pushable Citation where
      push :: Citation -> Lua ()
    push (Citation cid :: Text
    cid prefix :: [Inline]
    prefix suffix :: [Inline]
    suffix mode :: CitationMode
    mode noteNum :: Int
    noteNum hash :: Int
    hash) =
        String
    -> Text
    -> CitationMode
    -> [Inline]
    -> [Inline]
    -> Int
    -> Int
    -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "Citation" Text
    cid CitationMode
    mode [Inline]
    prefix [Inline]
    suffix Int
    noteNum Int
    hash

    instance Peekable Citation where
      peek :: StackIndex -> Lua Citation
    peek idx :: StackIndex
    idx = do
        Text
    id' <- StackIndex -> String -> Lua Text
    forall a. Peekable a => StackIndex -> String -> Lua a
    LuaUtil.rawField StackIndex
    idx "id"
        [Inline]
    prefix <- StackIndex -> String -> Lua [Inline]
    forall a. Peekable a => StackIndex -> String -> Lua a
    LuaUtil.rawField StackIndex
    idx "prefix"
        [Inline]
    suffix <- StackIndex -> String -> Lua [Inline]
    forall a. Peekable a => StackIndex -> String -> Lua a
    LuaUtil.rawField StackIndex
    idx "suffix"
        CitationMode
    mode <- StackIndex -> String -> Lua CitationMode
    forall a. Peekable a => StackIndex -> String -> Lua a
    LuaUtil.rawField StackIndex
    idx "mode"
        Int
    num <- StackIndex -> String -> Lua Int
    forall a. Peekable a => StackIndex -> String -> Lua a
    LuaUtil.rawField StackIndex
    idx "note_num"
        Int
    hash <- StackIndex -> String -> Lua Int
    forall a. Peekable a => StackIndex -> String -> Lua a
    LuaUtil.rawField StackIndex
    idx "hash"
        Citation -> Lua Citation
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Citation -> Lua Citation) -> Citation -> Lua Citation
    forall a b. (a -> b) -> a -> b
    $ Text
    -> [Inline] -> [Inline] -> CitationMode -> Int -> Int -> Citation
    Citation Text
    id' [Inline]
    prefix [Inline]
    suffix CitationMode
    mode Int
    num Int
    hash

    instance Pushable Alignment where
      push :: Alignment -> Lua ()
    push = String -> Lua ()
    forall a. Pushable a => a -> Lua ()
    Lua.push (String -> Lua ()) -> (Alignment -> String) -> Alignment -> Lua ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Alignment -> String
    forall a. Show a => a -> String
    show
    instance Peekable Alignment where
      peek :: StackIndex -> Lua Alignment
    peek = StackIndex -> Lua Alignment
    forall a. Read a => StackIndex -> Lua a
    Lua.peekRead

    instance Pushable CitationMode where
      push :: CitationMode -> Lua ()
    push = String -> Lua ()
    forall a. Pushable a => a -> Lua ()
    Lua.push (String -> Lua ())
    -> (CitationMode -> String) -> CitationMode -> Lua ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CitationMode -> String
    forall a. Show a => a -> String
    show
    instance Peekable CitationMode where
      peek :: StackIndex -> Lua CitationMode
    peek = StackIndex -> Lua CitationMode
    forall a. Read a => StackIndex -> Lua a
    Lua.peekRead

    instance Pushable Format where
      push :: Format -> Lua ()
    push (Format f :: Text
    f) = Text -> Lua ()
    forall a. Pushable a => a -> Lua ()
    Lua.push Text
    f
    instance Peekable Format where
      peek :: StackIndex -> Lua Format
    peek idx :: StackIndex
    idx = Text -> Format
    Format (Text -> Format) -> Lua Text -> Lua Format
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> StackIndex -> Lua Text
    forall a. Peekable a => StackIndex -> Lua a
    Lua.peek StackIndex
    idx

    instance Pushable ListNumberDelim where
      push :: ListNumberDelim -> Lua ()
    push = String -> Lua ()
    forall a. Pushable a => a -> Lua ()
    Lua.push (String -> Lua ())
    -> (ListNumberDelim -> String) -> ListNumberDelim -> Lua ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ListNumberDelim -> String
    forall a. Show a => a -> String
    show
    instance Peekable ListNumberDelim where
      peek :: StackIndex -> Lua ListNumberDelim
    peek = StackIndex -> Lua ListNumberDelim
    forall a. Read a => StackIndex -> Lua a
    Lua.peekRead

    instance Pushable ListNumberStyle where
      push :: ListNumberStyle -> Lua ()
    push = String -> Lua ()
    forall a. Pushable a => a -> Lua ()
    Lua.push (String -> Lua ())
    -> (ListNumberStyle -> String) -> ListNumberStyle -> Lua ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ListNumberStyle -> String
    forall a. Show a => a -> String
    show
    instance Peekable ListNumberStyle where
      peek :: StackIndex -> Lua ListNumberStyle
    peek = StackIndex -> Lua ListNumberStyle
    forall a. Read a => StackIndex -> Lua a
    Lua.peekRead

    instance Pushable MathType where
      push :: MathType -> Lua ()
    push = String -> Lua ()
    forall a. Pushable a => a -> Lua ()
    Lua.push (String -> Lua ()) -> (MathType -> String) -> MathType -> Lua ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . MathType -> String
    forall a. Show a => a -> String
    show
    instance Peekable MathType where
      peek :: StackIndex -> Lua MathType
    peek = StackIndex -> Lua MathType
    forall a. Read a => StackIndex -> Lua a
    Lua.peekRead

    instance Pushable QuoteType where
      push :: QuoteType -> Lua ()
    push = String -> Lua ()
    forall a. Pushable a => a -> Lua ()
    Lua.push (String -> Lua ()) -> (QuoteType -> String) -> QuoteType -> Lua ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . QuoteType -> String
    forall a. Show a => a -> String
    show
    instance Peekable QuoteType where
      peek :: StackIndex -> Lua QuoteType
    peek = StackIndex -> Lua QuoteType
    forall a. Read a => StackIndex -> Lua a
    Lua.peekRead

    -- | Push an meta value element to the top of the lua stack.
    pushMetaValue :: MetaValue -> Lua ()
    pushMetaValue :: MetaValue -> Lua ()
    pushMetaValue = \case
      MetaBlocks blcks :: [Block]
    blcks  -> String -> [Block] -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "MetaBlocks" [Block]
    blcks
      MetaBool bool :: Bool
    bool     -> Bool -> Lua ()
    forall a. Pushable a => a -> Lua ()
    Lua.push Bool
    bool
      MetaInlines inlns :: [Inline]
    inlns -> String -> [Inline] -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "MetaInlines" [Inline]
    inlns
      MetaList metalist :: [MetaValue]
    metalist -> String -> [MetaValue] -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "MetaList" [MetaValue]
    metalist
      MetaMap metamap :: Map Text MetaValue
    metamap   -> String -> Map Text MetaValue -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "MetaMap" Map Text MetaValue
    metamap
      MetaString str :: Text
    str    -> Text -> Lua ()
    forall a. Pushable a => a -> Lua ()
    Lua.push Text
    str

    -- | Interpret the value at the given stack index as meta value.
    peekMetaValue :: StackIndex -> Lua MetaValue
    peekMetaValue :: StackIndex -> Lua MetaValue
    peekMetaValue idx :: StackIndex
    idx = String -> Lua MetaValue -> Lua MetaValue
    forall a. String -> Lua a -> Lua a
    defineHowTo "get MetaValue" (Lua MetaValue -> Lua MetaValue) -> Lua MetaValue -> Lua MetaValue
    forall a b. (a -> b) -> a -> b
    $ do
      -- Get the contents of an AST element.
      let elementContent :: Peekable a => Lua a
          elementContent :: Lua a
    elementContent = StackIndex -> Lua a
    forall a. Peekable a => StackIndex -> Lua a
    Lua.peek StackIndex
    idx
      Type
    luatype <- StackIndex -> Lua Type
    Lua.ltype StackIndex
    idx
      case Type
    luatype of
        Lua.TypeBoolean -> Bool -> MetaValue
    MetaBool (Bool -> MetaValue) -> Lua Bool -> Lua MetaValue
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> StackIndex -> Lua Bool
    forall a. Peekable a => StackIndex -> Lua a
    Lua.peek StackIndex
    idx
        Lua.TypeString  -> Text -> MetaValue
    MetaString (Text -> MetaValue) -> Lua Text -> Lua MetaValue
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> StackIndex -> Lua Text
    forall a. Peekable a => StackIndex -> Lua a
    Lua.peek StackIndex
    idx
        Lua.TypeTable   -> do
          Either Exception String
    tag <- Lua String -> Lua (Either Exception String)
    forall a. Lua a -> Lua (Either Exception a)
    Lua.try (Lua String -> Lua (Either Exception String))
    -> Lua String -> Lua (Either Exception String)
    forall a b. (a -> b) -> a -> b
    $ StackIndex -> Lua String
    LuaUtil.getTag StackIndex
    idx
          case Either Exception String
    tag of
            Right "MetaBlocks"  -> [Block] -> MetaValue
    MetaBlocks  ([Block] -> MetaValue) -> Lua [Block] -> Lua MetaValue
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua [Block]
    forall a. Peekable a => Lua a
    elementContent
            Right "MetaBool"    -> Bool -> MetaValue
    MetaBool    (Bool -> MetaValue) -> Lua Bool -> Lua MetaValue
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua Bool
    forall a. Peekable a => Lua a
    elementContent
            Right "MetaMap"     -> Map Text MetaValue -> MetaValue
    MetaMap     (Map Text MetaValue -> MetaValue)
    -> Lua (Map Text MetaValue) -> Lua MetaValue
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua (Map Text MetaValue)
    forall a. Peekable a => Lua a
    elementContent
            Right "MetaInlines" -> [Inline] -> MetaValue
    MetaInlines ([Inline] -> MetaValue) -> Lua [Inline] -> Lua MetaValue
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua [Inline]
    forall a. Peekable a => Lua a
    elementContent
            Right "MetaList"    -> [MetaValue] -> MetaValue
    MetaList    ([MetaValue] -> MetaValue) -> Lua [MetaValue] -> Lua MetaValue
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua [MetaValue]
    forall a. Peekable a => Lua a
    elementContent
            Right "MetaString"  -> Text -> MetaValue
    MetaString  (Text -> MetaValue) -> Lua Text -> Lua MetaValue
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua Text
    forall a. Peekable a => Lua a
    elementContent
            Right t :: String
    t             -> String -> Lua MetaValue
    forall a. String -> Lua a
    Lua.throwException ("Unknown meta tag: " String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> String
    t)
            Left _ -> do
              -- no meta value tag given, try to guess.
              Int
    len <- StackIndex -> Lua Int
    Lua.rawlen StackIndex
    idx
              if Int
    len Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= 0
                then Map Text MetaValue -> MetaValue
    MetaMap (Map Text MetaValue -> MetaValue)
    -> Lua (Map Text MetaValue) -> Lua MetaValue
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> StackIndex -> Lua (Map Text MetaValue)
    forall a. Peekable a => StackIndex -> Lua a
    Lua.peek StackIndex
    idx
                else  ([Inline] -> MetaValue
    MetaInlines ([Inline] -> MetaValue) -> Lua [Inline] -> Lua MetaValue
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> StackIndex -> Lua [Inline]
    forall a. Peekable a => StackIndex -> Lua a
    Lua.peek StackIndex
    idx)
                      Lua MetaValue -> Lua MetaValue -> Lua MetaValue
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> ([Block] -> MetaValue
    MetaBlocks ([Block] -> MetaValue) -> Lua [Block] -> Lua MetaValue
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> StackIndex -> Lua [Block]
    forall a. Peekable a => StackIndex -> Lua a
    Lua.peek StackIndex
    idx)
                      Lua MetaValue -> Lua MetaValue -> Lua MetaValue
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> ([MetaValue] -> MetaValue
    MetaList ([MetaValue] -> MetaValue) -> Lua [MetaValue] -> Lua MetaValue
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> StackIndex -> Lua [MetaValue]
    forall a. Peekable a => StackIndex -> Lua a
    Lua.peek StackIndex
    idx)
        _        -> String -> Lua MetaValue
    forall a. String -> Lua a
    Lua.throwException "could not get meta value"

    -- | Push an block element to the top of the lua stack.
    pushBlock :: Block -> Lua ()
    pushBlock :: Block -> Lua ()
    pushBlock = \case
      BlockQuote blcks :: [Block]
    blcks         -> String -> [Block] -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "BlockQuote" [Block]
    blcks
      BulletList items :: [[Block]]
    items         -> String -> [[Block]] -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "BulletList" [[Block]]
    items
      CodeBlock attr :: Attr
    attr code :: Text
    code      -> String -> Text -> LuaAttr -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "CodeBlock" Text
    code (Attr -> LuaAttr
    LuaAttr Attr
    attr)
      DefinitionList items :: [([Inline], [[Block]])]
    items     -> String -> [([Inline], [[Block]])] -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "DefinitionList" [([Inline], [[Block]])]
    items
      Div attr :: Attr
    attr blcks :: [Block]
    blcks           -> String -> [Block] -> LuaAttr -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "Div" [Block]
    blcks (Attr -> LuaAttr
    LuaAttr Attr
    attr)
      Header lvl :: Int
    lvl attr :: Attr
    attr inlns :: [Inline]
    inlns    -> String -> Int -> [Inline] -> LuaAttr -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "Header" Int
    lvl [Inline]
    inlns (Attr -> LuaAttr
    LuaAttr Attr
    attr)
      HorizontalRule           -> String -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "HorizontalRule"
      LineBlock blcks :: [[Inline]]
    blcks          -> String -> [[Inline]] -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "LineBlock" [[Inline]]
    blcks
      OrderedList lstAttr :: ListAttributes
    lstAttr list :: [[Block]]
    list -> String -> [[Block]] -> LuaListAttributes -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "OrderedList" [[Block]]
    list
                                                     (ListAttributes -> LuaListAttributes
    LuaListAttributes ListAttributes
    lstAttr)
      Null                     -> String -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "Null"
      Para blcks :: [Inline]
    blcks               -> String -> [Inline] -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "Para" [Inline]
    blcks
      Plain blcks :: [Inline]
    blcks              -> String -> [Inline] -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "Plain" [Inline]
    blcks
      RawBlock f :: Format
    f cs :: Text
    cs            -> String -> Format -> Text -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "RawBlock" Format
    f Text
    cs
      Table capt :: [Inline]
    capt aligns :: [Alignment]
    aligns widths :: [Double]
    widths headers :: [[Block]]
    headers rows :: [[[Block]]]
    rows ->
        String
    -> [Inline]
    -> [Alignment]
    -> [Double]
    -> [[Block]]
    -> [[[Block]]]
    -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "Table" [Inline]
    capt [Alignment]
    aligns [Double]
    widths [[Block]]
    headers [[[Block]]]
    rows

    -- | Return the value at the given index as block if possible.
    peekBlock :: StackIndex -> Lua Block
    peekBlock :: StackIndex -> Lua Block
    peekBlock idx :: StackIndex
    idx = String -> Lua Block -> Lua Block
    forall a. String -> Lua a -> Lua a
    defineHowTo "get Block value" (Lua Block -> Lua Block) -> Lua Block -> Lua Block
    forall a b. (a -> b) -> a -> b
    $ do
      String
    tag <- StackIndex -> Lua String
    LuaUtil.getTag StackIndex
    idx
      case String
    tag of
          "BlockQuote"     -> [Block] -> Block
    BlockQuote ([Block] -> Block) -> Lua [Block] -> Lua Block
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua [Block]
    forall a. Peekable a => Lua a
    elementContent
          "BulletList"     -> [[Block]] -> Block
    BulletList ([[Block]] -> Block) -> Lua [[Block]] -> Lua Block
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua [[Block]]
    forall a. Peekable a => Lua a
    elementContent
          "CodeBlock"      -> (Attr -> Text -> Block) -> (LuaAttr, Text) -> Block
    forall a b. (Attr -> a -> b) -> (LuaAttr, a) -> b
    withAttr Attr -> Text -> Block
    CodeBlock ((LuaAttr, Text) -> Block) -> Lua (LuaAttr, Text) -> Lua Block
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua (LuaAttr, Text)
    forall a. Peekable a => Lua a
    elementContent
          "DefinitionList" -> [([Inline], [[Block]])] -> Block
    DefinitionList ([([Inline], [[Block]])] -> Block)
    -> Lua [([Inline], [[Block]])] -> Lua Block
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua [([Inline], [[Block]])]
    forall a. Peekable a => Lua a
    elementContent
          "Div"            -> (Attr -> [Block] -> Block) -> (LuaAttr, [Block]) -> Block
    forall a b. (Attr -> a -> b) -> (LuaAttr, a) -> b
    withAttr Attr -> [Block] -> Block
    Div ((LuaAttr, [Block]) -> Block)
    -> Lua (LuaAttr, [Block]) -> Lua Block
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua (LuaAttr, [Block])
    forall a. Peekable a => Lua a
    elementContent
          "Header"         -> (\(lvl :: Int
    lvl, LuaAttr attr :: Attr
    attr, lst :: [Inline]
    lst) -> Int -> Attr -> [Inline] -> Block
    Header Int
    lvl Attr
    attr [Inline]
    lst)
                              ((Int, LuaAttr, [Inline]) -> Block)
    -> Lua (Int, LuaAttr, [Inline]) -> Lua Block
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua (Int, LuaAttr, [Inline])
    forall a. Peekable a => Lua a
    elementContent
          "HorizontalRule" -> Block -> Lua Block
    forall (m :: * -> *) a. Monad m => a -> m a
    return Block
    HorizontalRule
          "LineBlock"      -> [[Inline]] -> Block
    LineBlock ([[Inline]] -> Block) -> Lua [[Inline]] -> Lua Block
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua [[Inline]]
    forall a. Peekable a => Lua a
    elementContent
          "OrderedList"    -> (\(LuaListAttributes lstAttr :: ListAttributes
    lstAttr, lst :: [[Block]]
    lst) ->
                                 ListAttributes -> [[Block]] -> Block
    OrderedList ListAttributes
    lstAttr [[Block]]
    lst)
                              ((LuaListAttributes, [[Block]]) -> Block)
    -> Lua (LuaListAttributes, [[Block]]) -> Lua Block
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua (LuaListAttributes, [[Block]])
    forall a. Peekable a => Lua a
    elementContent
          "Null"           -> Block -> Lua Block
    forall (m :: * -> *) a. Monad m => a -> m a
    return Block
    Null
          "Para"           -> [Inline] -> Block
    Para ([Inline] -> Block) -> Lua [Inline] -> Lua Block
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua [Inline]
    forall a. Peekable a => Lua a
    elementContent
          "Plain"          -> [Inline] -> Block
    Plain ([Inline] -> Block) -> Lua [Inline] -> Lua Block
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua [Inline]
    forall a. Peekable a => Lua a
    elementContent
          "RawBlock"       -> (Format -> Text -> Block) -> (Format, Text) -> Block
    forall a b c. (a -> b -> c) -> (a, b) -> c
    uncurry Format -> Text -> Block
    RawBlock ((Format, Text) -> Block) -> Lua (Format, Text) -> Lua Block
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua (Format, Text)
    forall a. Peekable a => Lua a
    elementContent
          "Table"          -> (\(capt :: [Inline]
    capt, aligns :: [Alignment]
    aligns, widths :: [Double]
    widths, headers :: [[Block]]
    headers, body :: [[[Block]]]
    body) ->
                                      [Inline]
    -> [Alignment] -> [Double] -> [[Block]] -> [[[Block]]] -> Block
    Table [Inline]
    capt [Alignment]
    aligns [Double]
    widths [[Block]]
    headers [[[Block]]]
    body)
                              (([Inline], [Alignment], [Double], [[Block]], [[[Block]]])
     -> Block)
    -> Lua ([Inline], [Alignment], [Double], [[Block]], [[[Block]]])
    -> Lua Block
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua ([Inline], [Alignment], [Double], [[Block]], [[[Block]]])
    forall a. Peekable a => Lua a
    elementContent
          _ -> String -> Lua Block
    forall a. String -> Lua a
    Lua.throwException ("Unknown block type: " String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> String
    tag)
     where
       -- Get the contents of an AST element.
       elementContent :: Peekable a => Lua a
       elementContent :: Lua a
    elementContent = StackIndex -> String -> Lua a
    forall a. Peekable a => StackIndex -> String -> Lua a
    LuaUtil.rawField StackIndex
    idx "c"

    -- | Push an inline element to the top of the lua stack.
    pushInline :: Inline -> Lua ()
    pushInline :: Inline -> Lua ()
    pushInline = \case
      Cite citations :: [Citation]
    citations lst :: [Inline]
    lst       -> String -> [Inline] -> [Citation] -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "Cite" [Inline]
    lst [Citation]
    citations
      Code attr :: Attr
    attr lst :: Text
    lst            -> String -> Text -> LuaAttr -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "Code" Text
    lst (Attr -> LuaAttr
    LuaAttr Attr
    attr)
      Emph inlns :: [Inline]
    inlns               -> String -> [Inline] -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "Emph" [Inline]
    inlns
      Image attr :: Attr
    attr alt :: [Inline]
    alt (src :: Text
    src,tit :: Text
    tit) -> String -> [Inline] -> Text -> Text -> LuaAttr -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "Image" [Inline]
    alt Text
    src Text
    tit (Attr -> LuaAttr
    LuaAttr Attr
    attr)
      LineBreak                -> String -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "LineBreak"
      Link attr :: Attr
    attr lst :: [Inline]
    lst (src :: Text
    src,tit :: Text
    tit)  -> String -> [Inline] -> Text -> Text -> LuaAttr -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "Link" [Inline]
    lst Text
    src Text
    tit (Attr -> LuaAttr
    LuaAttr Attr
    attr)
      Note blcks :: [Block]
    blcks               -> String -> [Block] -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "Note" [Block]
    blcks
      Math mty :: MathType
    mty str :: Text
    str             -> String -> MathType -> Text -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "Math" MathType
    mty Text
    str
      Quoted qt :: QuoteType
    qt inlns :: [Inline]
    inlns          -> String -> QuoteType -> [Inline] -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "Quoted" QuoteType
    qt [Inline]
    inlns
      RawInline f :: Format
    f cs :: Text
    cs           -> String -> Format -> Text -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "RawInline" Format
    f Text
    cs
      SmallCaps inlns :: [Inline]
    inlns          -> String -> [Inline] -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "SmallCaps" [Inline]
    inlns
      SoftBreak                -> String -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "SoftBreak"
      Space                    -> String -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "Space"
      Span attr :: Attr
    attr inlns :: [Inline]
    inlns          -> String -> [Inline] -> LuaAttr -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "Span" [Inline]
    inlns (Attr -> LuaAttr
    LuaAttr Attr
    attr)
      Str str :: Text
    str                  -> String -> Text -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "Str" Text
    str
      Strikeout inlns :: [Inline]
    inlns          -> String -> [Inline] -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "Strikeout" [Inline]
    inlns
      Strong inlns :: [Inline]
    inlns             -> String -> [Inline] -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "Strong" [Inline]
    inlns
      Subscript inlns :: [Inline]
    inlns          -> String -> [Inline] -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "Subscript" [Inline]
    inlns
      Superscript inlns :: [Inline]
    inlns        -> String -> [Inline] -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "Superscript" [Inline]
    inlns

    -- | Return the value at the given index as inline if possible.
    peekInline :: StackIndex -> Lua Inline
    peekInline :: StackIndex -> Lua Inline
    peekInline idx :: StackIndex
    idx = String -> Lua Inline -> Lua Inline
    forall a. String -> Lua a -> Lua a
    defineHowTo "get Inline value" (Lua Inline -> Lua Inline) -> Lua Inline -> Lua Inline
    forall a b. (a -> b) -> a -> b
    $ do
      String
    tag <- StackIndex -> Lua String
    LuaUtil.getTag StackIndex
    idx
      case String
    tag of
        "Cite"       -> ([Citation] -> [Inline] -> Inline)
    -> ([Citation], [Inline]) -> Inline
    forall a b c. (a -> b -> c) -> (a, b) -> c
    uncurry [Citation] -> [Inline] -> Inline
    Cite (([Citation], [Inline]) -> Inline)
    -> Lua ([Citation], [Inline]) -> Lua Inline
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua ([Citation], [Inline])
    forall a. Peekable a => Lua a
    elementContent
        "Code"       -> (Attr -> Text -> Inline) -> (LuaAttr, Text) -> Inline
    forall a b. (Attr -> a -> b) -> (LuaAttr, a) -> b
    withAttr Attr -> Text -> Inline
    Code ((LuaAttr, Text) -> Inline) -> Lua (LuaAttr, Text) -> Lua Inline
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua (LuaAttr, Text)
    forall a. Peekable a => Lua a
    elementContent
        "Emph"       -> [Inline] -> Inline
    Emph ([Inline] -> Inline) -> Lua [Inline] -> Lua Inline
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua [Inline]
    forall a. Peekable a => Lua a
    elementContent
        "Image"      -> (\(LuaAttr attr :: Attr
    attr, lst :: [Inline]
    lst, tgt :: Target
    tgt) -> Attr -> [Inline] -> Target -> Inline
    Image Attr
    attr [Inline]
    lst Target
    tgt)
                        ((LuaAttr, [Inline], Target) -> Inline)
    -> Lua (LuaAttr, [Inline], Target) -> Lua Inline
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua (LuaAttr, [Inline], Target)
    forall a. Peekable a => Lua a
    elementContent
        "Link"       -> (\(LuaAttr attr :: Attr
    attr, lst :: [Inline]
    lst, tgt :: Target
    tgt) -> Attr -> [Inline] -> Target -> Inline
    Link Attr
    attr [Inline]
    lst Target
    tgt)
                        ((LuaAttr, [Inline], Target) -> Inline)
    -> Lua (LuaAttr, [Inline], Target) -> Lua Inline
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua (LuaAttr, [Inline], Target)
    forall a. Peekable a => Lua a
    elementContent
        "LineBreak"  -> Inline -> Lua Inline
    forall (m :: * -> *) a. Monad m => a -> m a
    return Inline
    LineBreak
        "Note"       -> [Block] -> Inline
    Note ([Block] -> Inline) -> Lua [Block] -> Lua Inline
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua [Block]
    forall a. Peekable a => Lua a
    elementContent
        "Math"       -> (MathType -> Text -> Inline) -> (MathType, Text) -> Inline
    forall a b c. (a -> b -> c) -> (a, b) -> c
    uncurry MathType -> Text -> Inline
    Math ((MathType, Text) -> Inline) -> Lua (MathType, Text) -> Lua Inline
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua (MathType, Text)
    forall a. Peekable a => Lua a
    elementContent
        "Quoted"     -> (QuoteType -> [Inline] -> Inline)
    -> (QuoteType, [Inline]) -> Inline
    forall a b c. (a -> b -> c) -> (a, b) -> c
    uncurry QuoteType -> [Inline] -> Inline
    Quoted ((QuoteType, [Inline]) -> Inline)
    -> Lua (QuoteType, [Inline]) -> Lua Inline
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua (QuoteType, [Inline])
    forall a. Peekable a => Lua a
    elementContent
        "RawInline"  -> (Format -> Text -> Inline) -> (Format, Text) -> Inline
    forall a b c. (a -> b -> c) -> (a, b) -> c
    uncurry Format -> Text -> Inline
    RawInline ((Format, Text) -> Inline) -> Lua (Format, Text) -> Lua Inline
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua (Format, Text)
    forall a. Peekable a => Lua a
    elementContent
        "SmallCaps"  -> [Inline] -> Inline
    SmallCaps ([Inline] -> Inline) -> Lua [Inline] -> Lua Inline
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua [Inline]
    forall a. Peekable a => Lua a
    elementContent
        "SoftBreak"  -> Inline -> Lua Inline
    forall (m :: * -> *) a. Monad m => a -> m a
    return Inline
    SoftBreak
        "Space"      -> Inline -> Lua Inline
    forall (m :: * -> *) a. Monad m => a -> m a
    return Inline
    Space
        "Span"       -> (Attr -> [Inline] -> Inline) -> (LuaAttr, [Inline]) -> Inline
    forall a b. (Attr -> a -> b) -> (LuaAttr, a) -> b
    withAttr Attr -> [Inline] -> Inline
    Span ((LuaAttr, [Inline]) -> Inline)
    -> Lua (LuaAttr, [Inline]) -> Lua Inline
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua (LuaAttr, [Inline])
    forall a. Peekable a => Lua a
    elementContent
        "Str"        -> Text -> Inline
    Str (Text -> Inline) -> Lua Text -> Lua Inline
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua Text
    forall a. Peekable a => Lua a
    elementContent
        "Strikeout"  -> [Inline] -> Inline
    Strikeout ([Inline] -> Inline) -> Lua [Inline] -> Lua Inline
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua [Inline]
    forall a. Peekable a => Lua a
    elementContent
        "Strong"     -> [Inline] -> Inline
    Strong ([Inline] -> Inline) -> Lua [Inline] -> Lua Inline
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua [Inline]
    forall a. Peekable a => Lua a
    elementContent
        "Subscript"  -> [Inline] -> Inline
    Subscript ([Inline] -> Inline) -> Lua [Inline] -> Lua Inline
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua [Inline]
    forall a. Peekable a => Lua a
    elementContent
        "Superscript"-> [Inline] -> Inline
    Superscript ([Inline] -> Inline) -> Lua [Inline] -> Lua Inline
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Lua [Inline]
    forall a. Peekable a => Lua a
    elementContent
        _ -> String -> Lua Inline
    forall a. String -> Lua a
    Lua.throwException ("Unknown inline type: " String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> String
    tag)
     where
       -- Get the contents of an AST element.
       elementContent :: Peekable a => Lua a
       elementContent :: Lua a
    elementContent = StackIndex -> String -> Lua a
    forall a. Peekable a => StackIndex -> String -> Lua a
    LuaUtil.rawField StackIndex
    idx "c"

    withAttr :: (Attr -> a -> b) -> (LuaAttr, a) -> b
    withAttr :: (Attr -> a -> b) -> (LuaAttr, a) -> b
    withAttr f :: Attr -> a -> b
    f (attributes :: LuaAttr
    attributes, x :: a
    x) = Attr -> a -> b
    f (LuaAttr -> Attr
    fromLuaAttr LuaAttr
    attributes) a
    x

    -- | Wrapper for Attr
    newtype LuaAttr = LuaAttr { LuaAttr -> Attr
    fromLuaAttr :: Attr }

    instance Pushable LuaAttr where
      push :: LuaAttr -> Lua ()
    push (LuaAttr (id' :: Text
    id', classes :: [Text]
    classes, kv :: [Target]
    kv)) =
        String -> Text -> [Text] -> [Target] -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "Attr" Text
    id' [Text]
    classes [Target]
    kv

    instance Peekable LuaAttr where
      peek :: StackIndex -> Lua LuaAttr
    peek idx :: StackIndex
    idx = String -> Lua LuaAttr -> Lua LuaAttr
    forall a. String -> Lua a -> Lua a
    defineHowTo "get Attr value" (Attr -> LuaAttr
    LuaAttr (Attr -> LuaAttr) -> Lua Attr -> Lua LuaAttr
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> StackIndex -> Lua Attr
    forall a. Peekable a => StackIndex -> Lua a
    Lua.peek StackIndex
    idx)

    -- | Wrapper for ListAttributes
    newtype LuaListAttributes = LuaListAttributes  ListAttributes

    instance Pushable LuaListAttributes where
      push :: LuaListAttributes -> Lua ()
    push (LuaListAttributes (start :: Int
    start, style :: ListNumberStyle
    style, delimiter :: ListNumberDelim
    delimiter)) =
        String -> Int -> ListNumberStyle -> ListNumberDelim -> Lua ()
    forall a. PushViaCall a => String -> a
    pushViaConstructor "ListAttributes" Int
    start ListNumberStyle
    style ListNumberDelim
    delimiter

    instance Peekable LuaListAttributes where
      peek :: StackIndex -> Lua LuaListAttributes
    peek = String -> Lua LuaListAttributes -> Lua LuaListAttributes
    forall a. String -> Lua a -> Lua a
    defineHowTo "get ListAttributes value" (Lua LuaListAttributes -> Lua LuaListAttributes)
    -> (StackIndex -> Lua LuaListAttributes)
    -> StackIndex
    -> Lua LuaListAttributes
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .
             (ListAttributes -> LuaListAttributes)
    -> Lua ListAttributes -> Lua LuaListAttributes
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ListAttributes -> LuaListAttributes
    LuaListAttributes (Lua ListAttributes -> Lua LuaListAttributes)
    -> (StackIndex -> Lua ListAttributes)
    -> StackIndex
    -> Lua LuaListAttributes
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . StackIndex -> Lua ListAttributes
    forall a. Peekable a => StackIndex -> Lua a
    Lua.peek