Lua writer: allow variables to be set via second return value of Doc
New templates variables can be added by giving variable-value pairs as a second return value of the global function `Doc`. Example: function Doc (body, meta, vars) vars.date = vars.date or os.date '%B %e, %Y' return body, vars end Closes: #6731
This commit is contained in:
parent
60fc05e2ce
commit
efdba79ad1
2 changed files with 37 additions and 9 deletions
|
@ -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
|
||||
```
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue