summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/custom-writers.md16
-rw-r--r--src/Text/Pandoc/Writers/Custom.hs30
2 files changed, 37 insertions, 9 deletions
diff --git a/doc/custom-writers.md b/doc/custom-writers.md
index 6df603288..fb08cd120 100644
--- a/doc/custom-writers.md
+++ b/doc/custom-writers.md
@@ -50,3 +50,19 @@ the functions in `sample.lua` according to your needs.
``` {.lua include="sample.lua"}
```
+
+# Template variables
+
+New template variables can be added, or existing ones
+modified, by returning a second value from function `Doc`.
+
+For example, the following will add the current date in
+variable `date`, unless `date` is already defined as either a
+metadata value or a variable:
+
+``` lua
+function Doc (body, meta, vars)
+ vars.date = vars.date or meta.data or os.date '%B %e, %Y'
+ return body, vars
+end
+```
diff --git a/src/Text/Pandoc/Writers/Custom.hs b/src/Text/Pandoc/Writers/Custom.hs
index d13fbfb24..95e7355ae 100644
--- a/src/Text/Pandoc/Writers/Custom.hs
+++ b/src/Text/Pandoc/Writers/Custom.hs
@@ -16,20 +16,23 @@ Conversion of 'Pandoc' documents to custom markup using
a Lua writer.
-}
module Text.Pandoc.Writers.Custom ( writeCustom ) where
+import Control.Applicative (optional)
import Control.Arrow ((***))
import Control.Exception
import Control.Monad (when)
import Data.List (intersperse)
import qualified Data.Map as M
+import Data.Maybe (fromMaybe)
import qualified Data.Text as T
import Data.Text (Text, pack)
import HsLua as Lua hiding (Operation (Div), render)
import HsLua.Class.Peekable (PeekError)
import Text.DocLayout (render, literal)
+import Text.DocTemplates (Context)
import Control.Monad.IO.Class (MonadIO)
import Text.Pandoc.Definition
import Text.Pandoc.Lua (Global (..), runLua, setGlobals)
-import Text.Pandoc.Lua.Util (addField, dofileWithTraceback)
+import Text.Pandoc.Lua.Util (addField, dofileWithTraceback, peekViaJSON)
import Text.Pandoc.Options
import Text.Pandoc.Class (PandocMonad)
import Text.Pandoc.Templates (renderTemplate)
@@ -98,12 +101,12 @@ writeCustom luaFile opts doc@(Pandoc meta _) = do
-- to handle this more gracefully):
when (stat /= Lua.OK)
Lua.throwErrorAsException
- rendered <- docToCustom opts doc
- context <- metaToContext opts
- (fmap (literal . pack) . blockListToCustom)
- (fmap (literal . pack) . inlineListToCustom)
- meta
- return (pack rendered, context)
+ (rendered, context) <- docToCustom opts doc
+ metaContext <- metaToContext opts
+ (fmap (literal . pack) . blockListToCustom)
+ (fmap (literal . pack) . inlineListToCustom)
+ meta
+ return (pack rendered, context <> metaContext)
case res of
Left msg -> throw msg
Right (body, context) -> return $
@@ -113,10 +116,19 @@ writeCustom luaFile opts doc@(Pandoc meta _) = do
renderTemplate tpl $ setField "body" body context
docToCustom :: forall e. PeekError e
- => WriterOptions -> Pandoc -> LuaE e String
+ => WriterOptions -> Pandoc -> LuaE e (String, Context Text)
docToCustom opts (Pandoc (Meta metamap) blocks) = do
body <- blockListToCustom blocks
- invoke @e "Doc" body (fmap (Stringify @e) metamap) (writerVariables opts)
+ -- invoke doesn't work with multiple return values, so we have to call
+ -- `Doc` manually.
+ Lua.getglobal "Doc" -- function
+ push body -- argument 1
+ push (fmap (Stringify @e) metamap) -- argument 2
+ push (writerVariables opts) -- argument 3
+ call 3 2
+ rendered <- peek (nth 2) -- first return value
+ context <- forcePeek . optional $ peekViaJSON top -- snd return value
+ return (rendered, fromMaybe mempty context)
-- | Convert Pandoc block element to Custom.
blockToCustom :: forall e. PeekError e