Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package ghc-pandoc-lua-engine for 
openSUSE:Factory checked in at 2024-07-22 17:16:35
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-pandoc-lua-engine (Old)
 and      /work/SRC/openSUSE:Factory/.ghc-pandoc-lua-engine.new.17339 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "ghc-pandoc-lua-engine"

Mon Jul 22 17:16:35 2024 rev:8 rq:1188651 version:0.3

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/ghc-pandoc-lua-engine/ghc-pandoc-lua-engine.changes  
    2024-05-22 21:32:14.853475620 +0200
+++ 
/work/SRC/openSUSE:Factory/.ghc-pandoc-lua-engine.new.17339/ghc-pandoc-lua-engine.changes
   2024-07-22 17:17:29.704060565 +0200
@@ -1,0 +2,6 @@
+Mon Jun 24 21:18:37 UTC 2024 - Peter Simons <psim...@suse.com>
+
+- Update pandoc-lua-engine to version 0.3.
+  Upstream does not provide a change log file.
+
+-------------------------------------------------------------------

Old:
----
  pandoc-lua-engine-0.2.1.5.tar.gz
  pandoc-lua-engine.cabal

New:
----
  pandoc-lua-engine-0.3.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ ghc-pandoc-lua-engine.spec ++++++
--- /var/tmp/diff_new_pack.irVyRg/_old  2024-07-22 17:17:31.252122109 +0200
+++ /var/tmp/diff_new_pack.irVyRg/_new  2024-07-22 17:17:31.284123381 +0200
@@ -20,13 +20,12 @@
 %global pkgver %{pkg_name}-%{version}
 %bcond_with tests
 Name:           ghc-%{pkg_name}
-Version:        0.2.1.5
+Version:        0.3
 Release:        0
 Summary:        Lua engine to power custom pandoc conversions
 License:        GPL-2.0-or-later
 URL:            https://hackage.haskell.org/package/%{pkg_name}
 Source0:        
https://hackage.haskell.org/package/%{pkg_name}-%{version}/%{pkg_name}-%{version}.tar.gz
-Source1:        
https://hackage.haskell.org/package/%{pkg_name}-%{version}/revision/1.cabal#/%{pkg_name}.cabal
 BuildRequires:  ghc-Cabal-devel
 BuildRequires:  ghc-SHA-devel
 BuildRequires:  ghc-SHA-prof
@@ -127,7 +126,6 @@
 
 %prep
 %autosetup -n %{pkg_name}-%{version}
-cp -p %{SOURCE1} %{pkg_name}.cabal
 
 %build
 %ghc_lib_build

++++++ pandoc-lua-engine-0.2.1.5.tar.gz -> pandoc-lua-engine-0.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pandoc-lua-engine-0.2.1.5/pandoc-lua-engine.cabal 
new/pandoc-lua-engine-0.3/pandoc-lua-engine.cabal
--- old/pandoc-lua-engine-0.2.1.5/pandoc-lua-engine.cabal       2001-09-09 
03:46:40.000000000 +0200
+++ new/pandoc-lua-engine-0.3/pandoc-lua-engine.cabal   2001-09-09 
03:46:40.000000000 +0200
@@ -1,10 +1,10 @@
 cabal-version:       2.4
 name:                pandoc-lua-engine
-version:             0.2.1.5
+version:             0.3
 build-type:          Simple
 license:             GPL-2.0-or-later
 license-file:        COPYING.md
-copyright:           © 2006-2022 John MacFarlane, 2017-2022 Albert Krewinkel
+copyright:           © 2006-2024 John MacFarlane, 2017-2024 Albert Krewinkel
 author:              John MacFarlane, Albert Krewinkel
 maintainer:          Albert Krewinkel <alb...@hslua.org>
 bug-reports:         https://github.com/jgm/pandoc/issues
@@ -67,9 +67,11 @@
   hs-source-dirs:      src
   exposed-modules:     Text.Pandoc.Lua
   other-modules:       Text.Pandoc.Lua.Custom
+                     , Text.Pandoc.Lua.Engine
                      , Text.Pandoc.Lua.Filter
                      , Text.Pandoc.Lua.Global
                      , Text.Pandoc.Lua.Init
+                     , Text.Pandoc.Lua.Module
                      , Text.Pandoc.Lua.Marshal.Chunks
                      , Text.Pandoc.Lua.Marshal.CommonState
                      , Text.Pandoc.Lua.Marshal.Context
@@ -98,6 +100,7 @@
                      , Text.Pandoc.Lua.Module.Utils
                      , Text.Pandoc.Lua.Orphans
                      , Text.Pandoc.Lua.PandocLua
+                     , Text.Pandoc.Lua.Run
                      , Text.Pandoc.Lua.SourcePos
                      , Text.Pandoc.Lua.Writer.Classic
                      , Text.Pandoc.Lua.Writer.Scaffolding
@@ -121,7 +124,7 @@
                      , hslua-repl            >= 0.1.1   && < 0.2
                      , lpeg                  >= 1.1     && < 1.2
                      , mtl                   >= 2.2     && < 2.4
-                     , pandoc                >= 3.1.4   && < 3.3
+                     , pandoc                >= 3.2.1   && < 3.3
                      , pandoc-lua-marshal    >= 0.2.7   && < 0.3
                      , pandoc-types          >= 1.22    && < 1.24
                      , parsec                >= 3.1     && < 3.2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pandoc-lua-engine-0.2.1.5/src/Text/Pandoc/Lua/Custom.hs 
new/pandoc-lua-engine-0.3/src/Text/Pandoc/Lua/Custom.hs
--- old/pandoc-lua-engine-0.2.1.5/src/Text/Pandoc/Lua/Custom.hs 2001-09-09 
03:46:40.000000000 +0200
+++ new/pandoc-lua-engine-0.3/src/Text/Pandoc/Lua/Custom.hs     2001-09-09 
03:46:40.000000000 +0200
@@ -18,11 +18,11 @@
 import Text.Pandoc.Class (PandocMonad, findFileWithDataFallback)
 import Text.Pandoc.Error (PandocError)
 import Text.Pandoc.Lua.Global (Global (..), setGlobals)
-import Text.Pandoc.Lua.Init (runLuaWith)
 import Text.Pandoc.Lua.Marshal.Format (peekExtensionsConfig)
 import Text.Pandoc.Lua.Marshal.Pandoc (peekPandoc)
 import Text.Pandoc.Lua.Marshal.WriterOptions (pushWriterOptions)
 import Text.Pandoc.Lua.PandocLua (unPandocLua)
+import Text.Pandoc.Lua.Run (runLuaWith)
 import Text.Pandoc.Readers (Reader (..))
 import Text.Pandoc.Sources (ToSources(..))
 import Text.Pandoc.Scripting (CustomComponents (..))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pandoc-lua-engine-0.2.1.5/src/Text/Pandoc/Lua/Engine.hs 
new/pandoc-lua-engine-0.3/src/Text/Pandoc/Lua/Engine.hs
--- old/pandoc-lua-engine-0.2.1.5/src/Text/Pandoc/Lua/Engine.hs 1970-01-01 
01:00:00.000000000 +0100
+++ new/pandoc-lua-engine-0.3/src/Text/Pandoc/Lua/Engine.hs     2001-09-09 
03:46:40.000000000 +0200
@@ -0,0 +1,73 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TypeApplications  #-}
+{- |
+   Module      : Text.Pandoc.Lua.Engine
+   Copyright   : Copyright © 2017-2024 Albert Krewinkel
+   License     : GPL-2.0-or-later
+   Maintainer  : Albert Krewinkel <tarleb+pan...@zeitkraut.de>
+
+Running pandoc Lua filters.
+-}
+module Text.Pandoc.Lua.Engine
+  ( getEngine
+  , applyFilter
+  ) where
+
+import Control.Exception (throw)
+import Control.Monad ((>=>))
+import Control.Monad.IO.Class (MonadIO (liftIO))
+import HsLua.Core (getglobal, openlibs, run, top, tostring)
+import Text.Pandoc.Class (PandocMonad)
+import Text.Pandoc.Definition (Pandoc)
+import Text.Pandoc.Filter (Environment (..))
+import Text.Pandoc.Error (PandocError (PandocFilterError, PandocLuaError))
+import Text.Pandoc.Lua.Custom (loadCustom)
+import Text.Pandoc.Lua.Filter (runFilterFile)
+import Text.Pandoc.Lua.Global (Global (..), setGlobals)
+import Text.Pandoc.Lua.Run (runLua)
+import Text.Pandoc.Lua.Orphans ()
+import Text.Pandoc.Scripting (ScriptingEngine (..))
+import qualified Text.Pandoc.UTF8 as UTF8
+import qualified Data.Text as T
+
+-- | Constructs the Lua scripting engine.
+getEngine :: MonadIO m => m ScriptingEngine
+getEngine = do
+  versionName <- liftIO . run @PandocError $ do
+    openlibs
+    getglobal "_VERSION"
+    tostring top
+  pure $ ScriptingEngine
+    { engineName = maybe "Lua (unknown version)" UTF8.toText versionName
+    , engineApplyFilter = applyFilter
+    , engineLoadCustom = loadCustom
+    }
+
+-- | Run the Lua filter in @filterPath@ for a transformation to the
+-- target format (first element in args). Pandoc uses Lua init files to
+-- setup the Lua interpreter.
+applyFilter :: (PandocMonad m, MonadIO m)
+            => Environment
+            -> [String]
+            -> FilePath
+            -> Pandoc
+            -> m Pandoc
+applyFilter fenv args fp doc = do
+  let globals = [ FORMAT $ case args of
+                    x:_ -> T.pack x
+                    _   -> ""
+                , PANDOC_READER_OPTIONS (envReaderOptions fenv)
+                , PANDOC_WRITER_OPTIONS (envWriterOptions fenv)
+                , PANDOC_SCRIPT_FILE fp
+                ]
+  runLua >=> forceResult fp $ do
+    setGlobals globals
+    runFilterFile fp doc
+
+forceResult :: (PandocMonad m, MonadIO m)
+            => FilePath -> Either PandocError Pandoc -> m Pandoc
+forceResult fp eitherResult = case eitherResult of
+  Right x  -> return x
+  Left err -> throw . PandocFilterError (T.pack fp) $ case err of
+    PandocLuaError msg -> msg
+    _                  -> T.pack $ show err
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pandoc-lua-engine-0.2.1.5/src/Text/Pandoc/Lua/Filter.hs 
new/pandoc-lua-engine-0.3/src/Text/Pandoc/Lua/Filter.hs
--- old/pandoc-lua-engine-0.2.1.5/src/Text/Pandoc/Lua/Filter.hs 2001-09-09 
03:46:40.000000000 +0200
+++ new/pandoc-lua-engine-0.3/src/Text/Pandoc/Lua/Filter.hs     2001-09-09 
03:46:40.000000000 +0200
@@ -1,41 +1,41 @@
-{-# LANGUAGE FlexibleContexts     #-}
-{-# LANGUAGE IncoherentInstances  #-}
-{-# LANGUAGE OverloadedStrings    #-}
-{-# LANGUAGE ScopedTypeVariables  #-}
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE OverloadedStrings #-}
 {- |
 Module      : Text.Pandoc.Lua.Filter
 Copyright   : © 2012-2024 John MacFarlane,
               © 2017-2024 Albert Krewinkel
-License     : GNU GPL, version 2 or above
-Maintainer  : Albert Krewinkel <tarleb+pan...@moltkeplatz.de>
-Stability   : alpha
+License     : GPL-2.0-or-later
+Maintainer  : Albert Krewinkel <pan...@tarleb.com>
 
 Types and functions for running Lua filters.
 -}
 module Text.Pandoc.Lua.Filter
-  ( applyFilter
+  ( runFilterFile
+  , runFilterFile'
   ) where
 import Control.Monad ((>=>), (<$!>))
 import HsLua as Lua
-import Text.Pandoc.Definition
-import Text.Pandoc.Filter (Environment (..))
+import Text.Pandoc.Definition (Pandoc)
+import Text.Pandoc.Error (PandocError)
 import Text.Pandoc.Lua.Marshal.AST
 import Text.Pandoc.Lua.Marshal.Filter
-import Text.Pandoc.Lua.Global (Global (..), setGlobals)
-import Text.Pandoc.Lua.Init (runLua)
 import Text.Pandoc.Lua.PandocLua ()
-import Control.Exception (throw)
-import qualified Data.Text as T
-import Text.Pandoc.Class (PandocMonad)
-import Control.Monad.Trans (MonadIO)
-import Text.Pandoc.Error (PandocError (PandocFilterError, PandocLuaError))
 
 -- | Transform document using the filter defined in the given file.
+-- Runs the filter in the global environment.
 runFilterFile :: FilePath -> Pandoc -> LuaE PandocError Pandoc
 runFilterFile filterPath doc = do
+  Lua.pushglobaltable
+  runFilterFile' Lua.top filterPath doc <* Lua.pop 1
+
+-- | Like 'runFilterFile', but uses the table at the given index as the
+-- environment in which the filter is run.
+runFilterFile' :: StackIndex -> FilePath -> Pandoc
+               -> LuaE PandocError Pandoc
+runFilterFile' envIdx filterPath doc = do
   oldtop <- gettop
-  stat <- dofileTrace (Just filterPath)
-  if stat /= Lua.OK
+  stat <- dofileTrace' envIdx (Just filterPath)
+  if stat /= OK
     then throwErrorAsException
     else do
       newtop <- gettop
@@ -43,39 +43,25 @@
       -- filter if nothing was returned.
       luaFilters <- forcePeek $
         if newtop - oldtop >= 1
-        then peekList peekFilter top
-        else (:[]) <$!> (liftLua pushglobaltable *> peekFilter top)
+        then peekList peekFilter top      -- get from explicit filter table
+        else (:[]) <$!> peekFilter envIdx -- get the implicit filter in _ENV
       settop oldtop
       runAll luaFilters doc
 
+-- | Apply Lua filters to a document
 runAll :: [Filter] -> Pandoc -> LuaE PandocError Pandoc
 runAll = foldr ((>=>) . applyFully) return
 
--- | Run the Lua filter in @filterPath@ for a transformation to the
--- target format (first element in args). Pandoc uses Lua init files to
--- setup the Lua interpreter.
-applyFilter :: (PandocMonad m, MonadIO m)
-            => Environment
-            -> [String]
-            -> FilePath
-            -> Pandoc
-            -> m Pandoc
-applyFilter fenv args fp doc = do
-  let globals = [ FORMAT $ case args of
-                    x:_ -> T.pack x
-                    _   -> ""
-                , PANDOC_READER_OPTIONS (envReaderOptions fenv)
-                , PANDOC_WRITER_OPTIONS (envWriterOptions fenv)
-                , PANDOC_SCRIPT_FILE fp
-                ]
-  runLua >=> forceResult fp $ do
-    setGlobals globals
-    runFilterFile fp doc
-
-forceResult :: (PandocMonad m, MonadIO m)
-            => FilePath -> Either PandocError Pandoc -> m Pandoc
-forceResult fp eitherResult = case eitherResult of
-  Right x  -> return x
-  Left err -> throw . PandocFilterError (T.pack fp) $ case err of
-    PandocLuaError msg -> msg
-    _                  -> T.pack $ show err
+-- | Like 'HsLua.Core.Trace.dofileTrace', but uses a local environment.
+dofileTrace' :: LuaError e
+             => StackIndex     -- ^ stack index of the environment table
+             -> Maybe FilePath -- ^ file to load (or @Nothing@ for stdin)
+             -> LuaE e Status
+dofileTrace' envIdx fp = do
+  absEnv <- Lua.absindex envIdx
+  loadfile fp >>= \case
+    OK -> do
+      Lua.pushvalue absEnv
+      Just (Name "_ENV") <- Lua.setupvalue (Lua.nth 2) 1
+      pcallTrace 0 multret
+    s  -> pure s
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pandoc-lua-engine-0.2.1.5/src/Text/Pandoc/Lua/Init.hs 
new/pandoc-lua-engine-0.3/src/Text/Pandoc/Lua/Init.hs
--- old/pandoc-lua-engine-0.2.1.5/src/Text/Pandoc/Lua/Init.hs   2001-09-09 
03:46:40.000000000 +0200
+++ new/pandoc-lua-engine-0.3/src/Text/Pandoc/Lua/Init.hs       2001-09-09 
03:46:40.000000000 +0200
@@ -2,244 +2,59 @@
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RankNTypes        #-}
 {- |
-   Module      : Text.Pandoc.Lua
-   Copyright   : Copyright © 2017-2024 Albert Krewinkel
-   License     : GNU GPL, version 2 or above
-
+   Module      : Text.Pandoc.Lua.Init
+   Copyright   : © 2017-2024 Albert Krewinkel
+   License     : GPL-2.0-or-later
    Maintainer  : Albert Krewinkel <tarleb+pan...@moltkeplatz.de>
-   Stability   : alpha
 
 Functions to initialize the Lua interpreter.
 -}
 module Text.Pandoc.Lua.Init
-  ( runLua
-  , runLuaNoEnv
-  , runLuaWith
+  ( initLua
+  , userInit
   ) where
 
-import Control.Monad (forM, forM_, when)
-import Control.Monad.Catch (throwM, try)
-import Control.Monad.Trans (MonadIO (..))
-import Data.Maybe (catMaybes)
-import Data.Version (makeVersion)
-import HsLua as Lua hiding (status, try)
-import Text.Pandoc.Class (PandocMonad (..), report)
+import Control.Monad (when)
+import Control.Monad.Catch (throwM)
+import HsLua as Lua hiding (status)
+import Text.Pandoc.Class (report)
 import Text.Pandoc.Data (readDataFile)
 import Text.Pandoc.Error (PandocError (PandocLuaError))
 import Text.Pandoc.Logging (LogMessage (ScriptingWarning))
-import Text.Pandoc.Lua.Global (Global (..), setGlobals)
-import Text.Pandoc.Lua.Marshal.List (newListMetatable, pushListModule)
+import Text.Pandoc.Lua.Module (initModules)
 import Text.Pandoc.Lua.PandocLua (PandocLua (..), liftPandocLua)
 import Text.Pandoc.Lua.SourcePos (luaSourcePos)
-import qualified Data.ByteString.Char8 as Char8
 import qualified Data.Text as T
-import qualified Lua.LPeg as LPeg
-import qualified HsLua.Aeson
-import qualified HsLua.Module.DocLayout as Module.Layout
-import qualified HsLua.Module.Path as Module.Path
-import qualified HsLua.Module.Zip as Module.Zip
-import qualified Text.Pandoc.Lua.Module.CLI as Pandoc.CLI
-import qualified Text.Pandoc.Lua.Module.Format as Pandoc.Format
-import qualified Text.Pandoc.Lua.Module.Image as Pandoc.Image
-import qualified Text.Pandoc.Lua.Module.JSON as Pandoc.JSON
-import qualified Text.Pandoc.Lua.Module.Log as Pandoc.Log
-import qualified Text.Pandoc.Lua.Module.MediaBag as Pandoc.MediaBag
-import qualified Text.Pandoc.Lua.Module.Pandoc as Module.Pandoc
-import qualified Text.Pandoc.Lua.Module.Scaffolding as Pandoc.Scaffolding
-import qualified Text.Pandoc.Lua.Module.Structure as Pandoc.Structure
-import qualified Text.Pandoc.Lua.Module.System as Pandoc.System
-import qualified Text.Pandoc.Lua.Module.Template as Pandoc.Template
-import qualified Text.Pandoc.Lua.Module.Text as Pandoc.Text
-import qualified Text.Pandoc.Lua.Module.Types as Pandoc.Types
-import qualified Text.Pandoc.Lua.Module.Utils as Pandoc.Utils
 import qualified Text.Pandoc.UTF8 as UTF8
 
--- | Run the Lua interpreter, using pandoc's default way of environment
--- initialization.
-runLua :: (PandocMonad m, MonadIO m)
-       => LuaE PandocError a -> m (Either PandocError a)
-runLua action = do
-  runPandocLuaWith Lua.run . try $ do
-    initLuaState
-    liftPandocLua action
-
-runLuaWith :: (PandocMonad m, MonadIO m)
-           => GCManagedState -> LuaE PandocError a -> m (Either PandocError a)
-runLuaWith luaState action = do
-  runPandocLuaWith (withGCManagedState luaState) . try $ do
-    initLuaState
-    liftPandocLua action
-
--- | Like 'runLua', but ignores all environment variables like @LUA_PATH@.
-runLuaNoEnv :: (PandocMonad m, MonadIO m)
-            => LuaE PandocError a -> m (Either PandocError a)
-runLuaNoEnv action = do
-  runPandocLuaWith Lua.run . try $ do
-    liftPandocLua $ do
-      -- This is undocumented, but works -- the code is adapted from the
-      -- `lua.c` sources for the default interpreter.
-      Lua.pushboolean True
-      Lua.setfield Lua.registryindex "LUA_NOENV"
-    initLuaState
-    liftPandocLua action
-
--- | Modules that are loaded at startup and assigned to fields in the
--- pandoc module.
---
--- Note that @pandoc.List@ is not included here for technical reasons;
--- it must be handled separately.
-loadedModules :: [Module PandocError]
-loadedModules =
-  [ Pandoc.CLI.documentedModule
-  , Pandoc.Format.documentedModule
-  , Pandoc.Image.documentedModule
-  , Pandoc.JSON.documentedModule
-  , Pandoc.Log.documentedModule
-  , Pandoc.MediaBag.documentedModule
-  , Pandoc.Scaffolding.documentedModule
-  , Pandoc.Structure.documentedModule
-  , Pandoc.System.documentedModule
-  , Pandoc.Template.documentedModule
-  , Pandoc.Text.documentedModule
-  , Pandoc.Types.documentedModule
-  , Pandoc.Utils.documentedModule
-  , Module.Layout.documentedModule { moduleName = "pandoc.layout" }
-    `allSince` [2,18]
-  , Module.Path.documentedModule { moduleName = "pandoc.path" }
-    `allSince` [2,12]
-  , Module.Zip.documentedModule { moduleName = "pandoc.zip" }
-    `allSince` [3,0]
-  ]
- where
-  allSince mdl version = mdl
-    { moduleFunctions = map (`since` makeVersion version) $ moduleFunctions mdl
-    }
-
--- | Initialize the lua state with all required values
-initLuaState :: PandocLua ()
-initLuaState = do
+-- | Initialize Lua with all default and pandoc-specific libraries and default
+-- globals.
+initLua :: PandocLua ()
+initLua = do
   liftPandocLua Lua.openlibs
   setWarnFunction
-  initJsonMetatable
-  initPandocModule
-  installLpegSearcher
-  setGlobalModules
-  loadInitScript "init.lua"
- where
-  initPandocModule :: PandocLua ()
-  initPandocModule = liftPandocLua $ do
-    -- Push module table
-    registerModule Module.Pandoc.documentedModule
-    -- load modules and add them to the `pandoc` module table.
-    forM_ loadedModules $ \mdl -> do
-      registerModule mdl
-      -- pandoc.text must be require-able as 'text' for backwards compat.
-      when (moduleName mdl == "pandoc.text") $ do
-        getfield registryindex loaded
-        pushvalue (nth  2)
-        setfield (nth 2) "text"
-        pop 1 -- _LOADED
-      -- Shorten name, drop everything before the first dot (if any).
-      let fieldname (Name mdlname) = Name .
-            maybe mdlname snd . Char8.uncons . snd $
-            Char8.break (== '.') mdlname
-      Lua.setfield (nth 2) (fieldname $ moduleName mdl)
-    -- pandoc.List is low-level and must be opened differently.
-    requirehs "pandoc.List" (const pushListModule)
-    setfield (nth 2) "List"
-    -- assign module to global variable
-    Lua.setglobal "pandoc"
-
-  loadInitScript :: FilePath -> PandocLua ()
-  loadInitScript scriptFile = do
-    script <- readDataFile scriptFile
-    status <- liftPandocLua $ Lua.dostring script
-    when (status /= Lua.OK) . liftPandocLua $ do
-      err <- popException
-      let prefix = "Couldn't load '" <> T.pack scriptFile <> "':\n"
-      throwM . PandocLuaError . (prefix <>) $ case err of
-        PandocLuaError msg -> msg
-        _                  -> T.pack $ show err
-
-  setGlobalModules :: PandocLua ()
-  setGlobalModules = liftPandocLua $ do
-    let globalModules =
-          [ ("lpeg", LPeg.luaopen_lpeg_ptr)  -- must be loaded first
-          , ("re", LPeg.luaopen_re_ptr)      -- re depends on lpeg
-          ]
-    loadedBuiltInModules <- fmap catMaybes . forM globalModules $
-      \(pkgname, luaopen) -> do
-        Lua.pushcfunction luaopen
-        usedBuiltIn <- Lua.pcall 0 1 Nothing >>= \case
-          OK -> do               -- all good, loading succeeded
-            -- register as loaded module so later modules can rely on this
-            Lua.getfield Lua.registryindex Lua.loaded
-            Lua.pushvalue (Lua.nth 2)
-            Lua.setfield (Lua.nth 2) pkgname
-            Lua.pop 1  -- pop _LOADED
-            return True
-          _  -> do               -- built-in library failed, load system lib
-            Lua.pop 1  -- ignore error message
-            -- Try loading via the normal package loading mechanism.
-            Lua.getglobal "require"
-            Lua.pushName pkgname
-            Lua.call 1 1  -- Throws an exception if loading failed again!
-            return False
-
-        -- Module on top of stack. Register as global
-        Lua.setglobal pkgname
-        return $ if usedBuiltIn then Just pkgname else Nothing
-
-    -- Remove module entry from _LOADED table in registry if we used a
-    -- built-in library. This ensures that later calls to @require@ will
-    -- prefer the shared library, if any.
-    forM_ loadedBuiltInModules $ \pkgname -> do
-      Lua.getfield Lua.registryindex Lua.loaded
-      Lua.pushnil
-      Lua.setfield (Lua.nth 2) pkgname
-      Lua.pop 1  -- registry
-
-  installLpegSearcher :: PandocLua ()
-  installLpegSearcher = liftPandocLua $ do
-    Lua.getglobal' "package.searchers"
-    Lua.pushHaskellFunction $ Lua.state >>= liftIO . LPeg.lpeg_searcher
-    Lua.rawseti (Lua.nth 2) . (+1) . fromIntegral =<< Lua.rawlen (Lua.nth 2)
-    Lua.pop 1  -- remove 'package.searchers' from stack
-
--- | Setup the metatable that's assigned to Lua tables that were created
--- from/via JSON arrays.
-initJsonMetatable :: PandocLua ()
-initJsonMetatable = liftPandocLua $ do
-  newListMetatable HsLua.Aeson.jsonarray (pure ())
-  Lua.pop 1
-
--- | Evaluate a @'PandocLua'@ computation, running all contained Lua
--- operations.
-runPandocLuaWith :: (PandocMonad m, MonadIO m)
-                 => (forall b. LuaE PandocError b -> IO b)
-                 -> PandocLua a
-                 -> m a
-runPandocLuaWith runner pLua = do
-  origState <- getCommonState
-  globals <- defaultGlobals
-  (result, newState) <- liftIO . runner . unPandocLua $ do
-    putCommonState origState
-    liftPandocLua $ setGlobals globals
-    r <- pLua
-    c <- getCommonState
-    return (r, c)
-  putCommonState newState
-  return result
-
--- | Global variables which should always be set.
-defaultGlobals :: PandocMonad m => m [Global]
-defaultGlobals = do
-  commonState <- getCommonState
-  return
-    [ PANDOC_API_VERSION
-    , PANDOC_STATE commonState
-    , PANDOC_VERSION
-    ]
+  initModules
+  liftPandocLua userInit
+
+-- | User-controlled initialization, e.g., running the user's init script.
+userInit :: LuaE PandocError ()
+userInit = runInitScript
+
+-- | Run the @init.lua@ data file as a Lua script.
+runInitScript :: LuaE PandocError ()
+runInitScript = runDataFileScript "init.lua"
+
+-- | Get a data file and run it as a Lua script.
+runDataFileScript :: FilePath -> LuaE PandocError ()
+runDataFileScript scriptFile = do
+  script <- unPandocLua $ readDataFile scriptFile
+  status <- Lua.dostring script
+  when (status /= Lua.OK) $ do
+    err <- popException
+    let prefix = "Couldn't load '" <> T.pack scriptFile <> "':\n"
+    throwM . PandocLuaError . (prefix <>) $ case err of
+      PandocLuaError msg -> msg
+      _                  -> T.pack $ show err
 
 setWarnFunction :: PandocLua ()
 setWarnFunction = liftPandocLua . setwarnf' $ \msg -> do
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pandoc-lua-engine-0.2.1.5/src/Text/Pandoc/Lua/Marshal/LogMessage.hs 
new/pandoc-lua-engine-0.3/src/Text/Pandoc/Lua/Marshal/LogMessage.hs
--- old/pandoc-lua-engine-0.2.1.5/src/Text/Pandoc/Lua/Marshal/LogMessage.hs     
2001-09-09 03:46:40.000000000 +0200
+++ new/pandoc-lua-engine-0.3/src/Text/Pandoc/Lua/Marshal/LogMessage.hs 
2001-09-09 03:46:40.000000000 +0200
@@ -1,7 +1,7 @@
 {-# LANGUAGE OverloadedStrings    #-}
 {- |
    Module      : Text.Pandoc.Lua.Marshal.LogMessage
-   Copyright   : © 2017-2023 Albert Krewinkel
+   Copyright   : © 2017-2024 Albert Krewinkel
    License     : GPL-2.0-or-later
    Maintainer  : Albert Krewinkel <tarleb+pan...@moltkeplatz.de>
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pandoc-lua-engine-0.2.1.5/src/Text/Pandoc/Lua/Module/Template.hs 
new/pandoc-lua-engine-0.3/src/Text/Pandoc/Lua/Module/Template.hs
--- old/pandoc-lua-engine-0.2.1.5/src/Text/Pandoc/Lua/Module/Template.hs        
2001-09-09 03:46:40.000000000 +0200
+++ new/pandoc-lua-engine-0.3/src/Text/Pandoc/Lua/Module/Template.hs    
2001-09-09 03:46:40.000000000 +0200
@@ -21,7 +21,7 @@
 import Text.Pandoc.Lua.PandocLua (PandocLua (unPandocLua), liftPandocLua)
 import Text.Pandoc.Writers.Shared (metaToContext')
 import Text.Pandoc.Templates
-  ( compileTemplate, getDefaultTemplate, renderTemplate
+  ( compileTemplate, getDefaultTemplate, getTemplate, renderTemplate
   , runWithPartials, runWithDefaultPartials )
 
 import qualified Data.Text as T
@@ -31,7 +31,7 @@
 documentedModule = Module
   { moduleName = "pandoc.template"
   , moduleDescription = T.unlines
-    [ "Lua functions for pandoc templates."
+    [ "Handle pandoc templates."
     ]
   , moduleFields = []
   , moduleOperations = []
@@ -50,7 +50,7 @@
      #? T.unlines
      [ "Applies a context with variable assignments to a template,"
      , "returning the rendered template. The `context` parameter must be a"
-     , "table with variable names as keys and [Doc], string, boolean, or"
+     , "table with variable names as keys and [[Doc]], string, boolean, or"
      , "table as values, where the table can be either be a list of the"
      , "aforementioned types, or a nested context."
      ]
@@ -63,9 +63,22 @@
              Nothing -> runWithDefaultPartials
                         (compileTemplate "templates/default" template))
      <#> parameter peekText "string" "template" "template string"
-     <#> opt (stringParam "templ_path" "template path")
-     =#> functionResult (either failLua pushTemplate) "pandoc Template"
+     <#> opt (stringParam "templates_path"
+              ("parameter to determine a default path and extension for " <>
+               "partials; uses the data files templates path by default."))
+     =#> functionResult (either failLua pushTemplate) "Template"
            "compiled template"
+     #? T.unlines
+     [ "Compiles a template string into a [[Template]] object usable by"
+     , "pandoc."
+     , ""
+     , "If the `templates_path` parameter is specified, then it should be the"
+     , "file path associated with the template. It is used when checking"
+     , "for partials. Partials will be taken only from the default data"
+     , "files if this parameter is omitted."
+     , ""
+     , "An error is raised if compilation fails."
+     ]
     `since` makeVersion [2,17]
 
   , defun "default"
@@ -76,11 +89,29 @@
            format <- maybe getFORMAT pure mformat
            getDefaultTemplate format)
      <#> opt (textParam "writer"
-              "writer for which the template should be returned.")
-     =#> functionResult pushText "string"
-           "string representation of the writer's default template"
+              ("name of the writer for which the template should be " <>
+               "retrieved; defaults to the global `FORMAT`."))
+     =#> functionResult pushText "string" "raw template"
+    #? T.unlines
+    [ "Returns the default template for a given writer as a string. An"
+    , "error is thrown if no such template can be found."
+    ]
     `since` makeVersion [2,17]
 
+  , defun "get"
+     ### (unPandocLua . getTemplate)
+     <#> stringParam "filename" "name of the template"
+     =#> textResult "content of template file"
+     #? T.unlines
+     [ "Retrieve text for a template."
+     , ""
+     , "This function first checks the resource paths for a file of this"
+     , "name; if none is found, the `templates` directory in the user data"
+     , "directory is checked.  Returns the content of the file, or throws"
+     , "an error if no file is found."
+     ]
+    `since` makeVersion [3,2,1]
+
   , defun "meta_to_context"
      ### (\meta blockWriterIdx inlineWriterIdx -> unPandocLua $ do
              let blockWriter blks = liftPandocLua $ do
@@ -96,14 +127,14 @@
              metaToContext' blockWriter inlineWriter meta)
      <#> parameter peekMeta "Meta" "meta" "document metadata"
      <#> parameter pure "function" "blocks_writer"
-           "converter from Blocks to Doc values"
+           "converter from [[Blocks]] to [[Doc]] values"
      <#> parameter pure "function" "inlines_writer"
-           "converter from Inlines to Doc values"
+           "converter from [[Inlines]] to [[Doc]] values"
      =#> functionResult pushContext "table" "template context"
      #? T.unlines
-     [ "Creates template context from the document's [Meta]{#type-meta}"
-     , "data, using the given functions to convert [Blocks] and [Inlines]"
-     , "to [Doc] values."
+     [ "Creates template context from the document's [[Meta]] data, using the"
+     , "given functions to convert [[Blocks]] and [[Inlines]] to [[Doc]]"
+     , "values."
      ]
     `since` makeVersion [3,0]
   ]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pandoc-lua-engine-0.2.1.5/src/Text/Pandoc/Lua/Module/Utils.hs 
new/pandoc-lua-engine-0.3/src/Text/Pandoc/Lua/Module/Utils.hs
--- old/pandoc-lua-engine-0.2.1.5/src/Text/Pandoc/Lua/Module/Utils.hs   
2001-09-09 03:46:40.000000000 +0200
+++ new/pandoc-lua-engine-0.3/src/Text/Pandoc/Lua/Module/Utils.hs       
2001-09-09 03:46:40.000000000 +0200
@@ -29,6 +29,7 @@
 import Text.Pandoc.Definition
 import Text.Pandoc.Error (PandocError)
 import Text.Pandoc.Filter (applyJSONFilter)
+import Text.Pandoc.Lua.Filter (runFilterFile')
 import Text.Pandoc.Lua.Marshal.AST
 import Text.Pandoc.Lua.Marshal.Reference
 import Text.Pandoc.Lua.PandocLua (PandocLua (unPandocLua))
@@ -60,6 +61,7 @@
     , from_simple_table `since` v[2,11]
     , make_sections     `since` v[2,8]
     , references        `since` v[2,17]
+    , run_lua_filter    `since` v[3,2,1]
     , run_json_filter   `since` v[2,1,1]
     , normalize_date    `since` v[2,0,6]
     , sha1              `since` v[2,0,6]
@@ -246,6 +248,39 @@
   , "    end"
   ]
 
+-- | Run a filter from a file.
+run_lua_filter :: DocumentedFunction PandocError
+run_lua_filter = defun "run_lua_filter"
+  ### (\doc fp mbenv -> do
+         envIdx <- maybe copyOfGlobalTable pure mbenv
+         runFilterFile' envIdx fp doc)
+  <#> parameter peekPandoc "Pandoc" "doc" "the Pandoc document to filter"
+  <#> parameter peekString "string" "filter" "filepath of the filter to run"
+  <#> opt (parameter (typeChecked "table" istable pure) "table" "env"
+            "environment to load and run the filter in")
+  =#> functionResult pushPandoc "Pandoc" "filtered document"
+  #? ( "Filter the given doc by passing it through a Lua filter." <>
+       "\n\nThe filter will be run in the current Lua process." <>
+       "\n"
+     )
+  where
+    copynext :: LuaError e => StackIndex -> LuaE e StackIndex
+    copynext to =
+      Lua.next (nth 2) >>= \case
+        False -> pure to
+        True -> do
+          pushvalue (nth 2)
+          insert (nth 2)
+          rawset to
+          copynext to
+    copyOfGlobalTable :: LuaError e => LuaE e StackIndex
+    copyOfGlobalTable = do
+      newtable
+      pushglobaltable
+      pushnil
+      (copynext =<< absindex (nth 3)) <* pop 1 -- pop source table
+
+-- | Process the document with a JSON filter.
 run_json_filter :: DocumentedFunction PandocError
 run_json_filter = defun "run_json_filter"
   ### (\doc filterPath margs -> do
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pandoc-lua-engine-0.2.1.5/src/Text/Pandoc/Lua/Module.hs 
new/pandoc-lua-engine-0.3/src/Text/Pandoc/Lua/Module.hs
--- old/pandoc-lua-engine-0.2.1.5/src/Text/Pandoc/Lua/Module.hs 1970-01-01 
01:00:00.000000000 +0100
+++ new/pandoc-lua-engine-0.3/src/Text/Pandoc/Lua/Module.hs     2001-09-09 
03:46:40.000000000 +0200
@@ -0,0 +1,160 @@
+{-# LANGUAGE LambdaCase        #-}
+{-# LANGUAGE OverloadedStrings #-}
+{- |
+   Module      : Text.Pandoc.Lua.Module
+   Copyright   : © 2017-2024 Albert Krewinkel
+   License     : GPL-2.0-or-later
+   Maintainer  : Albert Krewinkel <pan...@tarleb.com>
+
+Setting up and initializing Lua modules.
+-}
+
+module Text.Pandoc.Lua.Module
+  ( initModules
+  ) where
+
+import Control.Monad (forM, forM_, when)
+import Data.Maybe (catMaybes)
+import Data.Version (makeVersion)
+import HsLua as Lua
+import Text.Pandoc.Error (PandocError)
+import Text.Pandoc.Lua.Marshal.List (pushPandocList, pushListModule)
+import Text.Pandoc.Lua.PandocLua (PandocLua (..), liftPandocLua)
+import qualified Data.ByteString.Char8 as Char8
+import qualified Lua.LPeg as LPeg
+import qualified HsLua.Aeson
+import qualified HsLua.Module.DocLayout as Module.Layout
+import qualified HsLua.Module.Path as Module.Path
+import qualified HsLua.Module.Zip as Module.Zip
+import qualified Text.Pandoc.Lua.Module.CLI as Pandoc.CLI
+import qualified Text.Pandoc.Lua.Module.Format as Pandoc.Format
+import qualified Text.Pandoc.Lua.Module.Image as Pandoc.Image
+import qualified Text.Pandoc.Lua.Module.JSON as Pandoc.JSON
+import qualified Text.Pandoc.Lua.Module.Log as Pandoc.Log
+import qualified Text.Pandoc.Lua.Module.MediaBag as Pandoc.MediaBag
+import qualified Text.Pandoc.Lua.Module.Pandoc as Module.Pandoc
+import qualified Text.Pandoc.Lua.Module.Scaffolding as Pandoc.Scaffolding
+import qualified Text.Pandoc.Lua.Module.Structure as Pandoc.Structure
+import qualified Text.Pandoc.Lua.Module.System as Pandoc.System
+import qualified Text.Pandoc.Lua.Module.Template as Pandoc.Template
+import qualified Text.Pandoc.Lua.Module.Text as Pandoc.Text
+import qualified Text.Pandoc.Lua.Module.Types as Pandoc.Types
+import qualified Text.Pandoc.Lua.Module.Utils as Pandoc.Utils
+
+initModules :: PandocLua ()
+initModules = do
+  initPandocModule
+  initJsonMetatable
+  installLpegSearcher
+  setGlobalModules
+
+initPandocModule :: PandocLua ()
+initPandocModule = liftPandocLua $ do
+  -- Push module table
+  registerModule Module.Pandoc.documentedModule
+  -- load modules and add them to the `pandoc` module table.
+  forM_ submodules $ \mdl -> do
+    registerModule mdl
+    -- pandoc.text must be require-able as 'text' for backwards compat.
+    when (moduleName mdl == "pandoc.text") $ do
+      getfield registryindex loaded
+      pushvalue (nth  2)
+      setfield (nth 2) "text"
+      pop 1 -- _LOADED
+    -- Shorten name, drop everything before the first dot (if any).
+    let fieldname (Name mdlname) = Name .
+          maybe mdlname snd . Char8.uncons . snd $
+          Char8.break (== '.') mdlname
+    Lua.setfield (nth 2) (fieldname $ moduleName mdl)
+  -- pandoc.List is low-level and must be opened differently.
+  requirehs "pandoc.List" (const pushListModule)
+  setfield (nth 2) "List"
+  -- assign module to global variable
+  Lua.setglobal "pandoc"
+
+-- | Modules that are loaded at startup and assigned to fields in the
+-- pandoc module.
+--
+-- Note that @pandoc.List@ is not included here for technical reasons;
+-- it must be handled separately.
+submodules :: [Module PandocError]
+submodules =
+  [ Pandoc.CLI.documentedModule
+  , Pandoc.Format.documentedModule
+  , Pandoc.Image.documentedModule
+  , Pandoc.JSON.documentedModule
+  , Pandoc.Log.documentedModule
+  , Pandoc.MediaBag.documentedModule
+  , Pandoc.Scaffolding.documentedModule
+  , Pandoc.Structure.documentedModule
+  , Pandoc.System.documentedModule
+  , Pandoc.Template.documentedModule
+  , Pandoc.Text.documentedModule
+  , Pandoc.Types.documentedModule
+  , Pandoc.Utils.documentedModule
+  , Module.Layout.documentedModule { moduleName = "pandoc.layout" }
+    `allSince` [2,18]
+  , Module.Path.documentedModule { moduleName = "pandoc.path" }
+    `allSince` [2,12]
+  , Module.Zip.documentedModule { moduleName = "pandoc.zip" }
+    `allSince` [3,0]
+  ]
+ where
+  allSince mdl version = mdl
+    { moduleFunctions = map (`since` makeVersion version) $ moduleFunctions mdl
+    }
+
+-- | Load all global modules and set them to their global variables.
+setGlobalModules :: PandocLua ()
+setGlobalModules = liftPandocLua $ do
+  let globalModules =
+        [ ("lpeg", LPeg.luaopen_lpeg_ptr)  -- must be loaded first
+        , ("re", LPeg.luaopen_re_ptr)      -- re depends on lpeg
+        ]
+  loadedBuiltInModules <- fmap catMaybes . forM globalModules $
+    \(pkgname, luaopen) -> do
+      Lua.pushcfunction luaopen
+      usedBuiltIn <- Lua.pcall 0 1 Nothing >>= \case
+        OK -> do               -- all good, loading succeeded
+          -- register as loaded module so later modules can rely on this
+          Lua.getfield Lua.registryindex Lua.loaded
+          Lua.pushvalue (Lua.nth 2)
+          Lua.setfield (Lua.nth 2) pkgname
+          Lua.pop 1  -- pop _LOADED
+          return True
+        _  -> do               -- built-in library failed, load system lib
+          Lua.pop 1  -- ignore error message
+          -- Try loading via the normal package loading mechanism.
+          Lua.getglobal "require"
+          Lua.pushName pkgname
+          Lua.call 1 1  -- Throws an exception if loading failed again!
+          return False
+
+      -- Module on top of stack. Register as global
+      Lua.setglobal pkgname
+      return $ if usedBuiltIn then Just pkgname else Nothing
+
+  -- Remove module entry from _LOADED table in registry if we used a
+  -- built-in library. This ensures that later calls to @require@ will
+  -- prefer the shared library, if any.
+  forM_ loadedBuiltInModules $ \pkgname -> do
+    Lua.getfield Lua.registryindex Lua.loaded
+    Lua.pushnil
+    Lua.setfield (Lua.nth 2) pkgname
+    Lua.pop 1  -- registry
+
+installLpegSearcher :: PandocLua ()
+installLpegSearcher = liftPandocLua $ do
+  Lua.getglobal' "package.searchers"
+  Lua.pushHaskellFunction $ Lua.state >>= liftIO . LPeg.lpeg_searcher
+  Lua.rawseti (Lua.nth 2) . (+1) . fromIntegral =<< Lua.rawlen (Lua.nth 2)
+  Lua.pop 1  -- remove 'package.searchers' from stack
+
+-- | Setup the metatable that's assigned to Lua tables that were created
+-- from/via JSON arrays.
+initJsonMetatable :: PandocLua ()
+initJsonMetatable = liftPandocLua $ do
+  pushPandocList (const pushnil) []
+  getmetatable top
+  setfield registryindex HsLua.Aeson.jsonarray
+  Lua.pop 1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pandoc-lua-engine-0.2.1.5/src/Text/Pandoc/Lua/PandocLua.hs 
new/pandoc-lua-engine-0.3/src/Text/Pandoc/Lua/PandocLua.hs
--- old/pandoc-lua-engine-0.2.1.5/src/Text/Pandoc/Lua/PandocLua.hs      
2001-09-09 03:46:40.000000000 +0200
+++ new/pandoc-lua-engine-0.3/src/Text/Pandoc/Lua/PandocLua.hs  2001-09-09 
03:46:40.000000000 +0200
@@ -77,10 +77,12 @@
   getModificationTime = IO.getModificationTime
 
   getCommonState = PandocLua $ do
-    Lua.getglobal "PANDOC_STATE"
+    Lua.getfield registryindex "PANDOC_STATE"
     forcePeek $ peekCommonState Lua.top `lastly` pop 1
   putCommonState cst = PandocLua $ do
     pushCommonState cst
+    Lua.pushvalue Lua.top
+    Lua.setfield registryindex "PANDOC_STATE"
     Lua.setglobal "PANDOC_STATE"
 
   logOutput = IO.logOutput
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pandoc-lua-engine-0.2.1.5/src/Text/Pandoc/Lua/Run.hs 
new/pandoc-lua-engine-0.3/src/Text/Pandoc/Lua/Run.hs
--- old/pandoc-lua-engine-0.2.1.5/src/Text/Pandoc/Lua/Run.hs    1970-01-01 
01:00:00.000000000 +0100
+++ new/pandoc-lua-engine-0.3/src/Text/Pandoc/Lua/Run.hs        2001-09-09 
03:46:40.000000000 +0200
@@ -0,0 +1,82 @@
+{-# LANGUAGE LambdaCase        #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RankNTypes        #-}
+{- |
+   Module      : Text.Pandoc.Lua.Run
+   Copyright   : Copyright © 2017-2024 Albert Krewinkel
+   License     : GPL-2.0-or-later
+   Maintainer  : Albert Krewinkel <tarleb+pan...@moltkeplatz.de>
+
+Run code in the Lua interpreter.
+-}
+module Text.Pandoc.Lua.Run
+  ( runLua
+  , runLuaNoEnv
+  , runLuaWith
+  ) where
+
+import Control.Monad.Catch (try)
+import Control.Monad.Trans (MonadIO (..))
+import HsLua as Lua hiding (try)
+import Text.Pandoc.Class (PandocMonad (..))
+import Text.Pandoc.Error (PandocError)
+import Text.Pandoc.Lua.Global (Global (..), setGlobals)
+import Text.Pandoc.Lua.Init (initLua)
+import Text.Pandoc.Lua.PandocLua (PandocLua (..), liftPandocLua)
+
+-- | Run the Lua interpreter, using pandoc's default way of environment
+-- initialization.
+runLua :: (PandocMonad m, MonadIO m)
+       => LuaE PandocError a -> m (Either PandocError a)
+runLua action = do
+  runPandocLuaWith Lua.run . try $ do
+    initLua
+    liftPandocLua action
+
+runLuaWith :: (PandocMonad m, MonadIO m)
+           => GCManagedState -> LuaE PandocError a -> m (Either PandocError a)
+runLuaWith luaState action = do
+  runPandocLuaWith (withGCManagedState luaState) . try $ do
+    initLua
+    liftPandocLua action
+
+-- | Like 'runLua', but ignores all environment variables like @LUA_PATH@.
+runLuaNoEnv :: (PandocMonad m, MonadIO m)
+            => LuaE PandocError a -> m (Either PandocError a)
+runLuaNoEnv action = do
+  runPandocLuaWith Lua.run . try $ do
+    liftPandocLua $ do
+      -- This is undocumented, but works -- the code is adapted from the
+      -- `lua.c` sources for the default interpreter.
+      Lua.pushboolean True
+      Lua.setfield Lua.registryindex "LUA_NOENV"
+    initLua
+    liftPandocLua action
+
+-- | Evaluate a @'PandocLua'@ computation, running all contained Lua
+-- operations.
+runPandocLuaWith :: (PandocMonad m, MonadIO m)
+                 => (forall b. LuaE PandocError b -> IO b)
+                 -> PandocLua a
+                 -> m a
+runPandocLuaWith runner pLua = do
+  origState <- getCommonState
+  globals <- defaultGlobals
+  (result, newState) <- liftIO . runner . unPandocLua $ do
+    putCommonState origState
+    liftPandocLua $ setGlobals globals
+    r <- pLua
+    c <- getCommonState
+    return (r, c)
+  putCommonState newState
+  return result
+
+-- | Global variables which should always be set.
+defaultGlobals :: PandocMonad m => m [Global]
+defaultGlobals = do
+  commonState <- getCommonState
+  return
+    [ PANDOC_API_VERSION
+    , PANDOC_STATE commonState
+    , PANDOC_VERSION
+    ]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pandoc-lua-engine-0.2.1.5/src/Text/Pandoc/Lua.hs 
new/pandoc-lua-engine-0.3/src/Text/Pandoc/Lua.hs
--- old/pandoc-lua-engine-0.2.1.5/src/Text/Pandoc/Lua.hs        2001-09-09 
03:46:40.000000000 +0200
+++ new/pandoc-lua-engine-0.3/src/Text/Pandoc/Lua.hs    2001-09-09 
03:46:40.000000000 +0200
@@ -1,5 +1,3 @@
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE TypeApplications  #-}
 {- |
    Module      : Text.Pandoc.Lua
    Copyright   : Copyright © 2017-2024 Albert Krewinkel
@@ -23,26 +21,8 @@
   , getEngine
   ) where
 
-import Control.Monad.IO.Class (MonadIO (liftIO))
-import HsLua.Core (getglobal, openlibs, run, top, tostring)
-import Text.Pandoc.Error (PandocError)
-import Text.Pandoc.Lua.Filter (applyFilter)
-import Text.Pandoc.Lua.Global (Global (..), setGlobals)
-import Text.Pandoc.Lua.Init (runLua, runLuaNoEnv)
 import Text.Pandoc.Lua.Custom (loadCustom)
+import Text.Pandoc.Lua.Engine (getEngine, applyFilter)
+import Text.Pandoc.Lua.Global (Global (..), setGlobals)
+import Text.Pandoc.Lua.Run (runLua, runLuaNoEnv)
 import Text.Pandoc.Lua.Orphans ()
-import Text.Pandoc.Scripting (ScriptingEngine (..))
-import qualified Text.Pandoc.UTF8 as UTF8
-
--- | Constructs the Lua scripting engine.
-getEngine :: MonadIO m => m ScriptingEngine
-getEngine = do
-  versionName <- liftIO . run @PandocError $ do
-    openlibs
-    getglobal "_VERSION"
-    tostring top
-  pure $ ScriptingEngine
-    { engineName = maybe "Lua (unknown version)" UTF8.toText versionName
-    , engineApplyFilter = applyFilter
-    , engineLoadCustom = loadCustom
-    }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pandoc-lua-engine-0.2.1.5/test/lua/module/globals.lua 
new/pandoc-lua-engine-0.3/test/lua/module/globals.lua
--- old/pandoc-lua-engine-0.2.1.5/test/lua/module/globals.lua   2001-09-09 
03:46:40.000000000 +0200
+++ new/pandoc-lua-engine-0.3/test/lua/module/globals.lua       2001-09-09 
03:46:40.000000000 +0200
@@ -107,5 +107,51 @@
     test('wrap_text', function ()
       assert.are_equal(type(PANDOC_WRITER_OPTIONS.wrap_text), 'string')
     end),
-  }
+  },
+
+  group 'PANDOC_STATE' {
+    test('is a userdata object', function ()
+      assert.are_equal(type(PANDOC_STATE), 'userdata')
+    end),
+    test('has property "input_files"', function ()
+      assert.are_equal(type(PANDOC_STATE.input_files), 'table')
+    end),
+    test('has optional property "output_file"', function ()
+      -- property may be nil
+      if PANDOC_STATE.output_file then
+        assert.are_equal(type(PANDOC_STATE.output_file), 'string')
+      end
+    end),
+    test('has property "log"', function ()
+      assert.are_equal(type(PANDOC_STATE.log), 'table')
+    end),
+    test('has property "request_headers"', function ()
+      assert.are_equal(type(PANDOC_STATE.request_headers), 'table')
+    end),
+    test('has property "resource_path"', function ()
+      assert.are_equal(type(PANDOC_STATE.resource_path), 'table')
+    end),
+    test('has optional property "source_url"', function ()
+      if PANDOC_STATE.source_url then
+        assert.are_equal(type(PANDOC_STATE.source_url), 'string')
+      end
+    end),
+    test('has property "trace"', function ()
+      assert.are_equal(type(PANDOC_STATE.trace), 'boolean')
+    end),
+    test('has optional property "user_data_dir"', function ()
+      if PANDOC_STATE.user_data_dir then
+        assert.are_equal(type(PANDOC_STATE.user_data_dir), 'string')
+      end
+    end),
+    test('has property "verbosity"', function ()
+      assert.are_equal(type(PANDOC_STATE.verbosity), 'string')
+    end),
+    test('can be deleted without breaking PandocLua monad functions', 
function()
+      local state = PANDOC_STATE
+      PANDOC_STATE = nil
+      assert.is_nil(pandoc.mediabag.lookup('does-not-exist'))
+      PANDOC_STATE = state
+    end),
+  },
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pandoc-lua-engine-0.2.1.5/test/lua/module/pandoc-json.lua 
new/pandoc-lua-engine-0.3/test/lua/module/pandoc-json.lua
--- old/pandoc-lua-engine-0.2.1.5/test/lua/module/pandoc-json.lua       
2001-09-09 03:46:40.000000000 +0200
+++ new/pandoc-lua-engine-0.3/test/lua/module/pandoc-json.lua   2001-09-09 
03:46:40.000000000 +0200
@@ -1,6 +1,7 @@
 --
 -- Tests for the system module
 --
+local pandoc = require 'pandoc'
 local json = require 'pandoc.json'
 local tasty = require 'tasty'
 
@@ -33,19 +34,26 @@
       local obj = setmetatable(
         {title = 23},
         {
-          __tojson = function (obj)
+          __tojson = function (_)
             return '"Nichts ist so wie es scheint"'
           end
         }
       )
       assert.are_same(json.encode(obj), [["Nichts ist so wie es scheint"]])
     end),
-    test('Inline (Space)', function ()
+    test('pandoc.List', function ()
+      local list = pandoc.List {'foo', 'bar', 'baz'}
       assert.are_equal(
-        json.encode(pandoc.Space()),
-        '{"t":"Space"}'
+        json.encode(list),
+        '["foo","bar","baz"]'
       )
     end),
+    test('Inline (Space)', function ()
+           assert.are_equal(
+             json.encode(pandoc.Space()),
+             '{"t":"Space"}'
+           )
+    end),
     test('Block (HorizontalRule)', function ()
       assert.are_equal(
         json.encode(pandoc.HorizontalRule()),
@@ -85,6 +93,9 @@
     test('object', function ()
       assert.are_same(json.decode '{"a":5}', {a = 5})
     end),
+    test('list of strings', function ()
+      assert.are_equal(json.decode '["foo", "bar"]', pandoc.List{"foo", "bar"})
+    end),
     test('Inline (Space)', function ()
       assert.are_equal(json.decode '{"t":"Space"}', pandoc.Space())
     end),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pandoc-lua-engine-0.2.1.5/test/lua/module/pandoc-template.lua 
new/pandoc-lua-engine-0.3/test/lua/module/pandoc-template.lua
--- old/pandoc-lua-engine-0.2.1.5/test/lua/module/pandoc-template.lua   
2001-09-09 03:46:40.000000000 +0200
+++ new/pandoc-lua-engine-0.3/test/lua/module/pandoc-template.lua       
2001-09-09 03:46:40.000000000 +0200
@@ -1,4 +1,5 @@
 local tasty = require 'tasty'
+local pandoc = require 'pandoc'
 local template = require 'pandoc.template'
 
 local assert = tasty.assert
@@ -24,8 +25,25 @@
       )
     end),
     test('fails on unknown format', function ()
+           local success, msg = pcall(function ()
+               return pandoc.utils.type(template.default 'nosuchformat')
+           end)
+           assert.is_falsy(success)
+    end),
+                  },
+  group 'get' {
+    test('is function', function ()
+           assert.are_equal(type(template.get), 'function')
+    end),
+    test('searches the template data directory', function ()
+      assert.are_equal(
+        template.default 'html5',
+        template.get 'default.html5'
+      )
+    end),
+    test('fails on non-existent file', function ()
       local success, msg = pcall(function ()
-          return pandoc.utils.type(template.default 'nosuchformat')
+        return pandoc.utils.type(template.get 'nosuchfile.nope')
       end)
       assert.is_falsy(success)
     end),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pandoc-lua-engine-0.2.1.5/test/lua/module/pandoc-utils.lua 
new/pandoc-lua-engine-0.3/test/lua/module/pandoc-utils.lua
--- old/pandoc-lua-engine-0.2.1.5/test/lua/module/pandoc-utils.lua      
2001-09-09 03:46:40.000000000 +0200
+++ new/pandoc-lua-engine-0.3/test/lua/module/pandoc-utils.lua  2001-09-09 
03:46:40.000000000 +0200
@@ -1,5 +1,7 @@
 local tasty = require 'tasty'
+local pandoc = require 'pandoc'
 local utils = require 'pandoc.utils'
+local io = require 'io'
 
 local assert = tasty.assert
 local test = tasty.test_case
@@ -127,6 +129,48 @@
     end)
   },
 
+  group 'run_lua_filter' {
+    test('runs a filter', function ()
+      local doc = pandoc.Pandoc("indivisible words")
+      pandoc.system.with_temporary_directory('lua-filter', function (dir)
+        local filter_path = pandoc.path.join{dir, 'test.lua'}
+        local filter = 'function Space() return " " end'
+        local fh = io.open(filter_path, 'wb')
+        fh:write(filter)
+        fh:close()
+        assert.are_equal(
+          utils.run_lua_filter(doc, filter_path),
+          pandoc.Pandoc(
+            pandoc.Plain(pandoc.Inlines{"indivisible", " ", "words"})
+          )
+        )
+      end)
+    end),
+    test("doesn't change the local environment by default", function ()
+      pandoc.system.with_temporary_directory('lua-filter', function (dir)
+        local filter_path = pandoc.path.join{dir, 'test.lua'}
+        local foo
+        local filter = 'foo = 42'
+        local fh = io.open(filter_path, 'wb')
+        fh:write(filter)
+        fh:close()
+        utils.run_lua_filter(pandoc.Pandoc{}, filter_path)
+        assert.is_nil(foo)
+      end)
+    end),
+    test("accepts an environment in which the filter is executed", function ()
+      pandoc.system.with_temporary_directory('lua-filter', function (dir)
+        local filter_path = pandoc.path.join{dir, 'test.lua'}
+        local filter = 'foo = 42'
+        local fh = io.open(filter_path, 'wb')
+        fh:write(filter)
+        fh:close()
+        utils.run_lua_filter(pandoc.Pandoc{}, filter_path, _ENV)
+        assert.are_equal(_ENV.foo, 42)
+      end)
+    end)
+  },
+
   group 'sha1' {
     test('hashing', function ()
       local ref_hash = '0a0a9f2a6772942557ab5355d76af442f8f65e01'

Reply via email to