From 0d1d52f0a00753691663572da5f87dd4791d65fd Mon Sep 17 00:00:00 2001
From: Albert Krewinkel <albert@zeitkraut.de>
Date: Fri, 31 Dec 2021 18:59:52 +0100
Subject: [PATCH] Lua: add function `pandoc.write`

---
 doc/lua-filters.md                   | 33 ++++++++++++++++++++++++++++
 src/Text/Pandoc/Lua/Module/Pandoc.hs | 21 +++++++++++++++++-
 2 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/doc/lua-filters.md b/doc/lua-filters.md
index 626ecb59f..5a8705326 100644
--- a/doc/lua-filters.md
+++ b/doc/lua-filters.md
@@ -3280,6 +3280,39 @@ Usage:
 
 [ReaderOptions]: #type-readeroptions
 
+### write {#pandoc.write}
+
+`write (doc[, format[, writer_options]])`
+
+Converts a document to the given target format.
+
+Parameters:
+
+`doc`:
+:   document to convert ([Pandoc](#type-pandoc))
+
+`format`:
+:   format specification, defaults to `'html'` (string)
+
+`writer_options`:
+:   options passed to the writer; may be a WriterOptions object
+    or a table with a subset of the keys and values of a
+    WriterOptions object; defaults to the default values
+    documented in the manual. ([WriterOptions]|table)
+
+Returns:
+-   converted document (string)
+
+Usage:
+
+    local doc = pandoc.Pandoc(
+      {pandoc.Para {pandoc.Strong 'Tea'}}
+    )
+    local html = pandoc.write(doc, 'html')
+    assert(html == "<p><strong>Tea</strong></p>")
+
+[WriterOptions]: #type-writeroptions
+
 # Module pandoc.utils
 
 This module exposes internal pandoc functions and utility
diff --git a/src/Text/Pandoc/Lua/Module/Pandoc.hs b/src/Text/Pandoc/Lua/Module/Pandoc.hs
index 350934b80..e9603f827 100644
--- a/src/Text/Pandoc/Lua/Module/Pandoc.hs
+++ b/src/Text/Pandoc/Lua/Module/Pandoc.hs
@@ -36,9 +36,11 @@ import Text.Pandoc.Lua.Marshal.ReaderOptions ( peekReaderOptions
                                              , pushReaderOptions)
 import Text.Pandoc.Lua.Module.Utils (sha1)
 import Text.Pandoc.Lua.PandocLua (PandocLua (unPandocLua), liftPandocLua)
-import Text.Pandoc.Options (ReaderOptions (readerExtensions))
+import Text.Pandoc.Options ( ReaderOptions (readerExtensions)
+                           , WriterOptions (writerExtensions) )
 import Text.Pandoc.Process (pipeProcess)
 import Text.Pandoc.Readers (Reader (..), getReader)
+import Text.Pandoc.Writers (Writer (..), getWriter)
 
 import qualified HsLua as Lua
 import qualified Data.ByteString.Lazy as BL
@@ -205,6 +207,23 @@ functions =
     <#> parameter peekInlineFuzzy "Inline" "inline" "element to traverse"
     <#> parameter peekFilter "Filter" "lua_filter" "filter functions"
     =#> functionResult pushInline "Inline" "modified Inline"
+
+  , defun "write"
+    ### (\doc mformatspec mwriterOpts -> do
+            let formatSpec = fromMaybe "html" mformatspec
+                writerOpts = fromMaybe def mwriterOpts
+            unPandocLua $ getWriter formatSpec >>= \case
+              (TextWriter w, es)      -> Right <$>
+                w writerOpts{ writerExtensions = es } doc
+              (ByteStringWriter w, es) -> Left <$>
+                w writerOpts{ writerExtensions = es } doc)
+    <#> parameter peekPandoc "Pandoc" "doc" "document to convert"
+    <#> optionalParameter peekText "string" "formatspec"
+          "format and extensions"
+    <#> optionalParameter peekWriterOptions "WriterOptions" "writer_options"
+          "writer options"
+    =#> functionResult (either pushLazyByteString pushText) "string"
+          "result document"
   ]
  where
   walkElement x f =