From e58a5ceed8bb629efbfd670bf162b65b7853ab7f Mon Sep 17 00:00:00 2001
From: Albert Krewinkel <albert@zeitkraut.de>
Date: Sat, 1 Jan 2022 01:11:41 +0100
Subject: [PATCH] Lua: marshal ReaderOptions field `extensions`,
 `track_changes` via JSON

Extensions are now available as a list of strings; the track-changes
settings are given as the kebab-case representation used in JSON.
---
 doc/lua-filters.md                           |  6 +++---
 pandoc.cabal                                 |  1 +
 src/Text/Pandoc/Lua/Marshal/ReaderOptions.hs | 15 +++++++-------
 src/Text/Pandoc/Lua/Util.hs                  | 21 ++++++++++++++++++++
 4 files changed, 33 insertions(+), 10 deletions(-)

diff --git a/doc/lua-filters.md b/doc/lua-filters.md
index 29fa7b9e4..bacdabe00 100644
--- a/doc/lua-filters.md
+++ b/doc/lua-filters.md
@@ -1988,7 +1988,7 @@ Fields:
 
 `extensions`
 :   string representation of the syntax extensions bit field
-    (string)
+    (sequence of strings)
 
 `indented_code_classes`
 :   default classes for indented code blocks (list of strings)
@@ -2006,8 +2006,8 @@ Fields:
     (integer)
 
 `track_changes`
-:   track changes setting for docx; one of `AcceptChanges`,
-    `RejectChanges`, and `AllChanges` (string)
+:   track changes setting for docx; one of `accept-changes`,
+    `reject-changes`, and `all-changes` (string)
 
 ## CommonState {#type-commonstate}
 
diff --git a/pandoc.cabal b/pandoc.cabal
index 58aa37cba..738b2450b 100644
--- a/pandoc.cabal
+++ b/pandoc.cabal
@@ -474,6 +474,7 @@ library
                  filepath              >= 1.1      && < 1.5,
                  haddock-library       >= 1.10     && < 1.11,
                  hslua                 >= 2.0.1    && < 2.1,
+                 hslua-aeson           >= 2.0.1    && < 2.1,
                  hslua-marshalling     >= 2.0.1    && < 2.1,
                  hslua-module-path     >= 1.0      && < 1.1,
                  hslua-module-system   >= 1.0      && < 1.1,
diff --git a/src/Text/Pandoc/Lua/Marshal/ReaderOptions.hs b/src/Text/Pandoc/Lua/Marshal/ReaderOptions.hs
index 225dcf116..5da42fd9e 100644
--- a/src/Text/Pandoc/Lua/Marshal/ReaderOptions.hs
+++ b/src/Text/Pandoc/Lua/Marshal/ReaderOptions.hs
@@ -22,6 +22,7 @@ module Text.Pandoc.Lua.Marshal.ReaderOptions
 import Data.Default (def)
 import HsLua as Lua
 import Text.Pandoc.Lua.Marshal.List (pushPandocList)
+import Text.Pandoc.Lua.Util (peekViaJSON, pushViaJSON)
 import Text.Pandoc.Options (ReaderOptions (..))
 
 --
@@ -87,23 +88,23 @@ readerOptionsMembers =
       (pushText, readerDefaultImageExtension)
       (peekText, \opts x -> opts{ readerDefaultImageExtension = x })
   , property "extensions" ""
-      (pushString . show, readerExtensions)
-      (peekRead, \opts x -> opts{ readerExtensions = x })
+      (pushViaJSON, readerExtensions)
+      (peekViaJSON, \opts x -> opts{ readerExtensions = x })
   , property "indented_code_classes" ""
       (pushPandocList pushText, readerIndentedCodeClasses)
       (peekList peekText, \opts x -> opts{ readerIndentedCodeClasses = x })
-  , property "strip_comments" ""
-      (pushBool, readerStripComments)
-      (peekBool, \opts x -> opts{ readerStripComments = x })
   , property "standalone" ""
       (pushBool, readerStandalone)
       (peekBool, \opts x -> opts{ readerStandalone = x })
+  , property "strip_comments" ""
+      (pushBool, readerStripComments)
+      (peekBool, \opts x -> opts{ readerStripComments = x })
   , property "tab_stop" ""
       (pushIntegral, readerTabStop)
       (peekIntegral, \opts x -> opts{ readerTabStop = x })
   , property "track_changes" ""
-      (pushString . show, readerTrackChanges)
-      (peekRead, \opts x -> opts{ readerTrackChanges = x })
+      (pushViaJSON, readerTrackChanges)
+      (choice [peekRead, peekViaJSON], \opts x -> opts{ readerTrackChanges = x })
   ]
 
 -- | Retrieves a 'ReaderOptions' object from a table on the stack, using
diff --git a/src/Text/Pandoc/Lua/Util.hs b/src/Text/Pandoc/Lua/Util.hs
index 9c6f42b2b..c663efb6f 100644
--- a/src/Text/Pandoc/Lua/Util.hs
+++ b/src/Text/Pandoc/Lua/Util.hs
@@ -15,11 +15,16 @@ module Text.Pandoc.Lua.Util
   , callWithTraceback
   , pcallWithTraceback
   , dofileWithTraceback
+  , peekViaJSON
+  , pushViaJSON
   ) where
 
 import Control.Monad (when)
 import HsLua
+import HsLua.Aeson (peekValue, pushValue)
+import qualified Data.Aeson as Aeson
 import qualified HsLua as Lua
+import qualified Text.Pandoc.UTF8 as UTF8
 
 -- | Add a value to the table at the top of the stack at a string-index.
 addField :: (LuaError e, Pushable a) => String -> a -> LuaE e ()
@@ -60,3 +65,19 @@ dofileWithTraceback fp = do
   case loadRes of
     Lua.OK -> pcallWithTraceback 0 Lua.multret
     _ -> return loadRes
+
+
+-- These will become part of hslua-aeson in future versions.
+
+-- | Retrieves a value from the Lua stack via JSON.
+peekViaJSON :: (Aeson.FromJSON a, LuaError e) => Peeker e a
+peekViaJSON idx = do
+  value <- peekValue idx
+  case Aeson.fromJSON value of
+    Aeson.Success x -> pure x
+    Aeson.Error msg -> failPeek $ "failed to decode: " <>
+                       UTF8.fromString msg
+
+-- | Pushes a value to the Lua stack as a JSON-like value.
+pushViaJSON :: (Aeson.ToJSON a, LuaError e) => Pusher e a
+pushViaJSON = pushValue . Aeson.toJSON