{-# LANGUAGE NoImplicitPrelude #-}
module Text.Pandoc.Lua.Module.Utils
( pushModule
) where
import Prelude
import Control.Applicative ((<|>))
import Data.Default (def)
import Data.Version (Version)
import Foreign.Lua (Peekable, Lua, NumResults)
import Text.Pandoc.Class (runIO, setUserDataDir)
import Text.Pandoc.Definition ( Pandoc, Meta, MetaValue (..), Block, Inline
, Citation, Attr, ListAttributes)
import Text.Pandoc.Lua.Marshaling ()
import Text.Pandoc.Lua.Util (addFunction)
import qualified Data.Digest.Pure.SHA as SHA
import qualified Data.ByteString.Lazy as BSL
import qualified Data.Text as T
import qualified Foreign.Lua as Lua
import qualified Text.Pandoc.Builder as B
import qualified Text.Pandoc.Filter.JSON as JSONFilter
import qualified Text.Pandoc.Shared as Shared
pushModule :: Maybe FilePath -> Lua NumResults
pushModule :: Maybe FilePath -> Lua NumResults
pushModule mbDatadir :: Maybe FilePath
mbDatadir = do
Lua ()
Lua.newtable
FilePath
-> ([Block] -> Optional [Inline] -> Lua [Inline]) -> Lua ()
forall a. ToHaskellFunction a => FilePath -> a -> Lua ()
addFunction "blocks_to_inlines" [Block] -> Optional [Inline] -> Lua [Inline]
blocksToInlines
FilePath -> (AstElement -> AstElement -> Lua Bool) -> Lua ()
forall a. ToHaskellFunction a => FilePath -> a -> Lua ()
addFunction "equals" AstElement -> AstElement -> Lua Bool
equals
FilePath
-> (Bool -> Optional Int -> [Block] -> Lua [Block]) -> Lua ()
forall a. ToHaskellFunction a => FilePath -> a -> Lua ()
addFunction "make_sections" Bool -> Optional Int -> [Block] -> Lua [Block]
makeSections
FilePath -> (Text -> Lua (Optional Text)) -> Lua ()
forall a. ToHaskellFunction a => FilePath -> a -> Lua ()
addFunction "normalize_date" Text -> Lua (Optional Text)
normalizeDate
FilePath
-> (Pandoc -> FilePath -> Optional [FilePath] -> Lua NumResults)
-> Lua ()
forall a. ToHaskellFunction a => FilePath -> a -> Lua ()
addFunction "run_json_filter" (Maybe FilePath
-> Pandoc -> FilePath -> Optional [FilePath] -> Lua NumResults
runJSONFilter Maybe FilePath
mbDatadir)
FilePath -> (ByteString -> Lua Text) -> Lua ()
forall a. ToHaskellFunction a => FilePath -> a -> Lua ()
addFunction "sha1" ByteString -> Lua Text
sha1
FilePath -> (AstElement -> Lua Text) -> Lua ()
forall a. ToHaskellFunction a => FilePath -> a -> Lua ()
addFunction "stringify" AstElement -> Lua Text
stringify
FilePath -> (Integer -> Lua Text) -> Lua ()
forall a. ToHaskellFunction a => FilePath -> a -> Lua ()
addFunction "to_roman_numeral" Integer -> Lua Text
toRomanNumeral
FilePath -> (Version -> Lua Version) -> Lua ()
forall a. ToHaskellFunction a => FilePath -> a -> Lua ()
addFunction "Version" (Version -> Lua Version
forall (m :: * -> *) a. Monad m => a -> m a
return :: Version -> Lua Version)
NumResults -> Lua NumResults
forall (m :: * -> *) a. Monad m => a -> m a
return 1
blocksToInlines :: [Block] -> Lua.Optional [Inline] -> Lua [Inline]
blocksToInlines :: [Block] -> Optional [Inline] -> Lua [Inline]
blocksToInlines blks :: [Block]
blks optSep :: Optional [Inline]
optSep = do
let sep :: Many Inline
sep = case Optional [Inline] -> Maybe [Inline]
forall a. Optional a -> Maybe a
Lua.fromOptional Optional [Inline]
optSep of
Just x :: [Inline]
x -> [Inline] -> Many Inline
forall a. [a] -> Many a
B.fromList [Inline]
x
Nothing -> Many Inline
Shared.defaultBlocksSeparator
[Inline] -> Lua [Inline]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Inline] -> Lua [Inline]) -> [Inline] -> Lua [Inline]
forall a b. (a -> b) -> a -> b
$ Many Inline -> [Inline]
forall a. Many a -> [a]
B.toList (Many Inline -> [Block] -> Many Inline
Shared.blocksToInlinesWithSep Many Inline
sep [Block]
blks)
makeSections :: Bool -> Lua.Optional Int -> [Block] -> Lua [Block]
makeSections :: Bool -> Optional Int -> [Block] -> Lua [Block]
makeSections number :: Bool
number baselevel :: Optional Int
baselevel =
[Block] -> Lua [Block]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Block] -> Lua [Block])
-> ([Block] -> [Block]) -> [Block] -> Lua [Block]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Maybe Int -> [Block] -> [Block]
Shared.makeSections Bool
number (Optional Int -> Maybe Int
forall a. Optional a -> Maybe a
Lua.fromOptional Optional Int
baselevel)
normalizeDate :: T.Text -> Lua (Lua.Optional T.Text)
normalizeDate :: Text -> Lua (Optional Text)
normalizeDate = Optional Text -> Lua (Optional Text)
forall (m :: * -> *) a. Monad m => a -> m a
return (Optional Text -> Lua (Optional Text))
-> (Text -> Optional Text) -> Text -> Lua (Optional Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe Text -> Optional Text
forall a. Maybe a -> Optional a
Lua.Optional (Maybe Text -> Optional Text)
-> (Text -> Maybe Text) -> Text -> Optional Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Maybe Text
Shared.normalizeDate
runJSONFilter :: Maybe FilePath
-> Pandoc
-> FilePath
-> Lua.Optional [String]
-> Lua NumResults
runJSONFilter :: Maybe FilePath
-> Pandoc -> FilePath -> Optional [FilePath] -> Lua NumResults
runJSONFilter mbDatadir :: Maybe FilePath
mbDatadir doc :: Pandoc
doc filterFile :: FilePath
filterFile optArgs :: Optional [FilePath]
optArgs = do
[FilePath]
args <- case Optional [FilePath] -> Maybe [FilePath]
forall a. Optional a -> Maybe a
Lua.fromOptional Optional [FilePath]
optArgs of
Just x :: [FilePath]
x -> [FilePath] -> Lua [FilePath]
forall (m :: * -> *) a. Monad m => a -> m a
return [FilePath]
x
Nothing -> do
FilePath -> Lua ()
Lua.getglobal "FORMAT"
(FilePath -> [FilePath] -> [FilePath]
forall a. a -> [a] -> [a]
:[]) (FilePath -> [FilePath]) -> Lua FilePath -> Lua [FilePath]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Lua FilePath
forall a. Peekable a => Lua a
Lua.popValue
Either PandocError Pandoc
filterRes <- IO (Either PandocError Pandoc) -> Lua (Either PandocError Pandoc)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
Lua.liftIO (IO (Either PandocError Pandoc) -> Lua (Either PandocError Pandoc))
-> (PandocIO Pandoc -> IO (Either PandocError Pandoc))
-> PandocIO Pandoc
-> Lua (Either PandocError Pandoc)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PandocIO Pandoc -> IO (Either PandocError Pandoc)
forall a. PandocIO a -> IO (Either PandocError a)
runIO (PandocIO Pandoc -> Lua (Either PandocError Pandoc))
-> PandocIO Pandoc -> Lua (Either PandocError Pandoc)
forall a b. (a -> b) -> a -> b
$ do
Maybe FilePath -> PandocIO ()
forall (m :: * -> *). PandocMonad m => Maybe FilePath -> m ()
setUserDataDir Maybe FilePath
mbDatadir
ReaderOptions
-> [FilePath] -> FilePath -> Pandoc -> PandocIO Pandoc
JSONFilter.apply ReaderOptions
forall a. Default a => a
def [FilePath]
args FilePath
filterFile Pandoc
doc
case Either PandocError Pandoc
filterRes of
Left err :: PandocError
err -> FilePath -> Lua NumResults
forall a. Pushable a => a -> Lua NumResults
Lua.raiseError (PandocError -> FilePath
forall a. Show a => a -> FilePath
show PandocError
err)
Right d :: Pandoc
d -> (1 :: NumResults) NumResults -> Lua () -> Lua NumResults
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Pandoc -> Lua ()
forall a. Pushable a => a -> Lua ()
Lua.push Pandoc
d
sha1 :: BSL.ByteString
-> Lua T.Text
sha1 :: ByteString -> Lua Text
sha1 = Text -> Lua Text
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> Lua Text)
-> (ByteString -> Text) -> ByteString -> Lua Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> Text
T.pack (FilePath -> Text)
-> (ByteString -> FilePath) -> ByteString -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Digest SHA1State -> FilePath
forall t. Digest t -> FilePath
SHA.showDigest (Digest SHA1State -> FilePath)
-> (ByteString -> Digest SHA1State) -> ByteString -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Digest SHA1State
SHA.sha1
stringify :: AstElement -> Lua T.Text
stringify :: AstElement -> Lua Text
stringify el :: AstElement
el = Text -> Lua Text
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> Lua Text) -> Text -> Lua Text
forall a b. (a -> b) -> a -> b
$ case AstElement
el of
PandocElement pd :: Pandoc
pd -> Pandoc -> Text
forall a. Walkable Inline a => a -> Text
Shared.stringify Pandoc
pd
InlineElement i :: Inline
i -> Inline -> Text
forall a. Walkable Inline a => a -> Text
Shared.stringify Inline
i
BlockElement b :: Block
b -> Block -> Text
forall a. Walkable Inline a => a -> Text
Shared.stringify Block
b
MetaElement m :: Meta
m -> Meta -> Text
forall a. Walkable Inline a => a -> Text
Shared.stringify Meta
m
CitationElement c :: Citation
c -> Citation -> Text
forall a. Walkable Inline a => a -> Text
Shared.stringify Citation
c
MetaValueElement m :: MetaValue
m -> MetaValue -> Text
stringifyMetaValue MetaValue
m
_ -> Text
forall a. Monoid a => a
mempty
stringifyMetaValue :: MetaValue -> T.Text
stringifyMetaValue :: MetaValue -> Text
stringifyMetaValue mv :: MetaValue
mv = case MetaValue
mv of
MetaBool b :: Bool
b -> Text -> Text
T.toLower (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ FilePath -> Text
T.pack (Bool -> FilePath
forall a. Show a => a -> FilePath
show Bool
b)
MetaString s :: Text
s -> Text
s
_ -> MetaValue -> Text
forall a. Walkable Inline a => a -> Text
Shared.stringify MetaValue
mv
equals :: AstElement -> AstElement -> Lua Bool
equals :: AstElement -> AstElement -> Lua Bool
equals e1 :: AstElement
e1 e2 :: AstElement
e2 = Bool -> Lua Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (AstElement
e1 AstElement -> AstElement -> Bool
forall a. Eq a => a -> a -> Bool
== AstElement
e2)
data AstElement
= PandocElement Pandoc
| MetaElement Meta
| BlockElement Block
| InlineElement Inline
| MetaValueElement MetaValue
| AttrElement Attr
| ListAttributesElement ListAttributes
| CitationElement Citation
deriving (AstElement -> AstElement -> Bool
(AstElement -> AstElement -> Bool)
-> (AstElement -> AstElement -> Bool) -> Eq AstElement
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AstElement -> AstElement -> Bool
$c/= :: AstElement -> AstElement -> Bool
== :: AstElement -> AstElement -> Bool
$c== :: AstElement -> AstElement -> Bool
Eq, Int -> AstElement -> ShowS
[AstElement] -> ShowS
AstElement -> FilePath
(Int -> AstElement -> ShowS)
-> (AstElement -> FilePath)
-> ([AstElement] -> ShowS)
-> Show AstElement
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
showList :: [AstElement] -> ShowS
$cshowList :: [AstElement] -> ShowS
show :: AstElement -> FilePath
$cshow :: AstElement -> FilePath
showsPrec :: Int -> AstElement -> ShowS
$cshowsPrec :: Int -> AstElement -> ShowS
Show)
instance Peekable AstElement where
peek :: StackIndex -> Lua AstElement
peek idx :: StackIndex
idx = do
Either Exception AstElement
res <- Lua AstElement -> Lua (Either Exception AstElement)
forall a. Lua a -> Lua (Either Exception a)
Lua.try (Lua AstElement -> Lua (Either Exception AstElement))
-> Lua AstElement -> Lua (Either Exception AstElement)
forall a b. (a -> b) -> a -> b
$ (Pandoc -> AstElement
PandocElement (Pandoc -> AstElement) -> Lua Pandoc -> Lua AstElement
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StackIndex -> Lua Pandoc
forall a. Peekable a => StackIndex -> Lua a
Lua.peek StackIndex
idx)
Lua AstElement -> Lua AstElement -> Lua AstElement
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Inline -> AstElement
InlineElement (Inline -> AstElement) -> Lua Inline -> Lua AstElement
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 AstElement -> Lua AstElement -> Lua AstElement
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Block -> AstElement
BlockElement (Block -> AstElement) -> Lua Block -> Lua AstElement
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 AstElement -> Lua AstElement -> Lua AstElement
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Attr -> AstElement
AttrElement (Attr -> AstElement) -> Lua Attr -> Lua AstElement
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)
Lua AstElement -> Lua AstElement -> Lua AstElement
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (ListAttributes -> AstElement
ListAttributesElement (ListAttributes -> AstElement)
-> Lua ListAttributes -> Lua AstElement
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StackIndex -> Lua ListAttributes
forall a. Peekable a => StackIndex -> Lua a
Lua.peek StackIndex
idx)
Lua AstElement -> Lua AstElement -> Lua AstElement
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Meta -> AstElement
MetaElement (Meta -> AstElement) -> Lua Meta -> Lua AstElement
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StackIndex -> Lua Meta
forall a. Peekable a => StackIndex -> Lua a
Lua.peek StackIndex
idx)
Lua AstElement -> Lua AstElement -> Lua AstElement
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (MetaValue -> AstElement
MetaValueElement (MetaValue -> AstElement) -> Lua MetaValue -> Lua AstElement
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)
case Either Exception AstElement
res of
Right x :: AstElement
x -> AstElement -> Lua AstElement
forall (m :: * -> *) a. Monad m => a -> m a
return AstElement
x
Left _ -> FilePath -> Lua AstElement
forall a. FilePath -> Lua a
Lua.throwException
"Expected an AST element, but could not parse value as such."
toRomanNumeral :: Lua.Integer -> Lua T.Text
toRomanNumeral :: Integer -> Lua Text
toRomanNumeral = Text -> Lua Text
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> Lua Text) -> (Integer -> Text) -> Integer -> Lua Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Text
Shared.toRomanNumeral (Int -> Text) -> (Integer -> Int) -> Integer -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral