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"}
|
``` {.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.
|
a Lua writer.
|
||||||
-}
|
-}
|
||||||
module Text.Pandoc.Writers.Custom ( writeCustom ) where
|
module Text.Pandoc.Writers.Custom ( writeCustom ) where
|
||||||
|
import Control.Applicative (optional)
|
||||||
import Control.Arrow ((***))
|
import Control.Arrow ((***))
|
||||||
import Control.Exception
|
import Control.Exception
|
||||||
import Control.Monad (when)
|
import Control.Monad (when)
|
||||||
import Data.List (intersperse)
|
import Data.List (intersperse)
|
||||||
import qualified Data.Map as M
|
import qualified Data.Map as M
|
||||||
|
import Data.Maybe (fromMaybe)
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import Data.Text (Text, pack)
|
import Data.Text (Text, pack)
|
||||||
import HsLua as Lua hiding (Operation (Div), render)
|
import HsLua as Lua hiding (Operation (Div), render)
|
||||||
import HsLua.Class.Peekable (PeekError)
|
import HsLua.Class.Peekable (PeekError)
|
||||||
import Text.DocLayout (render, literal)
|
import Text.DocLayout (render, literal)
|
||||||
|
import Text.DocTemplates (Context)
|
||||||
import Control.Monad.IO.Class (MonadIO)
|
import Control.Monad.IO.Class (MonadIO)
|
||||||
import Text.Pandoc.Definition
|
import Text.Pandoc.Definition
|
||||||
import Text.Pandoc.Lua (Global (..), runLua, setGlobals)
|
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.Options
|
||||||
import Text.Pandoc.Class (PandocMonad)
|
import Text.Pandoc.Class (PandocMonad)
|
||||||
import Text.Pandoc.Templates (renderTemplate)
|
import Text.Pandoc.Templates (renderTemplate)
|
||||||
|
@ -98,12 +101,12 @@ writeCustom luaFile opts doc@(Pandoc meta _) = do
|
||||||
-- to handle this more gracefully):
|
-- to handle this more gracefully):
|
||||||
when (stat /= Lua.OK)
|
when (stat /= Lua.OK)
|
||||||
Lua.throwErrorAsException
|
Lua.throwErrorAsException
|
||||||
rendered <- docToCustom opts doc
|
(rendered, context) <- docToCustom opts doc
|
||||||
context <- metaToContext opts
|
metaContext <- metaToContext opts
|
||||||
(fmap (literal . pack) . blockListToCustom)
|
(fmap (literal . pack) . blockListToCustom)
|
||||||
(fmap (literal . pack) . inlineListToCustom)
|
(fmap (literal . pack) . inlineListToCustom)
|
||||||
meta
|
meta
|
||||||
return (pack rendered, context)
|
return (pack rendered, context <> metaContext)
|
||||||
case res of
|
case res of
|
||||||
Left msg -> throw msg
|
Left msg -> throw msg
|
||||||
Right (body, context) -> return $
|
Right (body, context) -> return $
|
||||||
|
@ -113,10 +116,19 @@ writeCustom luaFile opts doc@(Pandoc meta _) = do
|
||||||
renderTemplate tpl $ setField "body" body context
|
renderTemplate tpl $ setField "body" body context
|
||||||
|
|
||||||
docToCustom :: forall e. PeekError e
|
docToCustom :: forall e. PeekError e
|
||||||
=> WriterOptions -> Pandoc -> LuaE e String
|
=> WriterOptions -> Pandoc -> LuaE e (String, Context Text)
|
||||||
docToCustom opts (Pandoc (Meta metamap) blocks) = do
|
docToCustom opts (Pandoc (Meta metamap) blocks) = do
|
||||||
body <- blockListToCustom blocks
|
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.
|
-- | Convert Pandoc block element to Custom.
|
||||||
blockToCustom :: forall e. PeekError e
|
blockToCustom :: forall e. PeekError e
|
||||||
|
|
Loading…
Add table
Reference in a new issue