{-# 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