    {-# LANGUAGE CPP #-}
    {-# LANGUAGE OverloadedStrings #-}
    {-|
    Module      : Text.Pandoc.Lua.Module.JSON
    Copyright   : © 2022-2024 Albert Krewinkel
    License     : MIT
    Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>

    Lua module to work with JSON.
    -}
    module Text.Pandoc.Lua.Module.JSON (
      -- * Module
        documentedModule

      -- ** Functions
      , decode
      , encode
      )
    where

    import Prelude hiding (null)
    import Data.Maybe (fromMaybe)
    import Data.Monoid (Alt (..))
    import Data.Version (makeVersion)
    import HsLua.Aeson
    import HsLua.Core
    import HsLua.Marshalling
    import HsLua.Packaging
    import Text.Pandoc.Error (PandocError)
    import Text.Pandoc.Lua.PandocLua ()
    import Text.Pandoc.Lua.Marshal.AST

    import qualified Data.Aeson as Aeson
    import qualified Data.Text as T

    -- | The @aeson@ module specification.
    documentedModule :: Module PandocError
    documentedModule :: Module PandocError
    documentedModule = Name -> Module PandocError
    forall e. Name -> Module e
    defmodule Name
    "pandoc.json"
      Module PandocError -> Text -> Module PandocError
    forall a. HasDescription a => a -> Text -> a
    `withDescription`
        Text
    "JSON module to work with JSON; based on the Aeson Haskell package."
      Module PandocError -> [Field PandocError] -> Module PandocError
    forall e. Module e -> [Field e] -> Module e
    `withFields` [Field PandocError]
    forall e. LuaError e => [Field e]
    fields
      Module PandocError
    -> [DocumentedFunction PandocError] -> Module PandocError
    forall e. Module e -> [DocumentedFunction e] -> Module e
    `withFunctions` [DocumentedFunction PandocError]
    functions

    --
    -- Fields
    --

    -- | Exported fields.
    fields :: LuaError e => [Field e]
    fields :: forall e. LuaError e => [Field e]
    fields =
      [ Field e
    forall e. LuaError e => Field e
    null
      ]

    -- | The value used to represent the JSON @null@.
    null :: LuaError e => Field e
    null :: forall e. LuaError e => Field e
    null = Name -> Field e
    forall e. Name -> Field e
    deffield Name
    "null"
      Field e -> TypeSpec -> Field e
    forall e. Field e -> TypeSpec -> Field e
    `withType` TypeSpec
    "light userdata"
      Field e -> Text -> Field e
    forall a. HasDescription a => a -> Text -> a
    `withDescription` Text
    "Value used to represent the `null` JSON value."
      Field e -> LuaE e () -> Field e
    forall e. Field e -> LuaE e () -> Field e
    `withValue` Pusher e Value
    forall e. LuaError e => Pusher e Value
    pushValue Value
    Aeson.Null

    --
    -- Functions
    --

    functions :: [DocumentedFunction PandocError]
    functions :: [DocumentedFunction PandocError]
    functions =
      [ DocumentedFunction PandocError
    decode DocumentedFunction PandocError
    -> Version -> DocumentedFunction PandocError
    forall e. DocumentedFunction e -> Version -> DocumentedFunction e
    `since` [Int] -> Version
    makeVersion [Int
    3, Int
    1, Int
    1]
      , DocumentedFunction PandocError
    forall e. LuaError e => DocumentedFunction e
    encode DocumentedFunction PandocError
    -> Version -> DocumentedFunction PandocError
    forall e. DocumentedFunction e -> Version -> DocumentedFunction e
    `since` [Int] -> Version
    makeVersion [Int
    3, Int
    1, Int
    1]
      ]

    -- | Decode a JSON string into a Lua object.
    decode :: DocumentedFunction PandocError
    decode :: DocumentedFunction PandocError
    decode = Name
    -> (ByteString -> Maybe Bool -> LuaE PandocError ())
    -> HsFnPrecursor
         PandocError (ByteString -> Maybe Bool -> LuaE PandocError ())
    forall a e. Name -> a -> HsFnPrecursor e a
    defun Name
    "decode"
      ### (\str usePandocTypes ->
             fromMaybe pushnil . getAlt . mconcat . map Alt $
             (if usePandocTypes == Just False
              then []
              else [ pushInline  <$> Aeson.decode str
                   , pushBlock   <$> Aeson.decode str
                   , pushPandoc  <$> Aeson.decode str
                   , pushInlines <$> Aeson.decode str
                   , pushBlocks  <$> Aeson.decode str
                   ])
             ++ [pushValue <$> Aeson.decode str])
      HsFnPrecursor
      PandocError (ByteString -> Maybe Bool -> LuaE PandocError ())
    -> Parameter PandocError ByteString
    -> HsFnPrecursor PandocError (Maybe Bool -> LuaE PandocError ())
    forall e a b.
    HsFnPrecursor e (a -> b) -> Parameter e a -> HsFnPrecursor e b
    <#> Peeker PandocError ByteString
    -> TypeSpec -> Text -> Text -> Parameter PandocError ByteString
    forall e a. Peeker e a -> TypeSpec -> Text -> Text -> Parameter e a
    parameter Peeker PandocError ByteString
    forall e. Peeker e ByteString
    peekLazyByteString TypeSpec
    "string" Text
    "str" Text
    "JSON string"
      HsFnPrecursor PandocError (Maybe Bool -> LuaE PandocError ())
    -> Parameter PandocError (Maybe Bool)
    -> HsFnPrecursor PandocError (LuaE PandocError ())
    forall e a b.
    HsFnPrecursor e (a -> b) -> Parameter e a -> HsFnPrecursor e b
    <#> Parameter PandocError Bool -> Parameter PandocError (Maybe Bool)
    forall e a. Parameter e a -> Parameter e (Maybe a)
    opt (Peeker PandocError Bool
    -> TypeSpec -> Text -> Text -> Parameter PandocError Bool
    forall e a. Peeker e a -> TypeSpec -> Text -> Text -> Parameter e a
    parameter Peeker PandocError Bool
    forall e. Peeker e Bool
    peekBool TypeSpec
    "boolean" Text
    "pandoc_types"
               Text
    "whether to use pandoc types when possible.")
      HsFnPrecursor PandocError (LuaE PandocError ())
    -> FunctionResults PandocError () -> DocumentedFunction PandocError
    forall e a.
    HsFnPrecursor e (LuaE e a)
    -> FunctionResults e a -> DocumentedFunction e
    =#> Pusher PandocError ()
    -> TypeSpec -> Text -> FunctionResults PandocError ()
    forall e a. Pusher e a -> TypeSpec -> Text -> FunctionResults e a
    functionResult Pusher PandocError ()
    forall a. a -> LuaE PandocError a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure TypeSpec
    "any" Text
    "decoded object"
      #? T.unlines
         [ "Creates a Lua object from a JSON string. If the input can be decoded"
         , "as representing an [[Inline]], [[Block]], [[Pandoc]], [[Inlines]],"
         , "or [[Blocks]] element the function will return an object of the"
         , "appropriate type. Otherwise, if the input does not represent any"
         , "of the AST types, the default decoding is applied: Objects and"
         , "arrays are represented as tables, the JSON `null` value becomes"
         , "[null](#pandoc.json.null), and JSON booleans, strings, and numbers"
         , "are converted using the Lua types of the same name."
         , ""
         , "The special handling of AST elements can be disabled by setting"
         , "`pandoc_types` to `false`."
         ]

    -- | Encode a Lua object as JSON.
    encode :: LuaError e => DocumentedFunction e
    encode :: forall e. LuaError e => DocumentedFunction e
    encode = Name
    -> (Value -> LuaE e ByteString)
    -> HsFnPrecursor e (Value -> LuaE e ByteString)
    forall a e. Name -> a -> HsFnPrecursor e a
    defun Name
    "encode"
      ### liftPure Aeson.encode
      HsFnPrecursor e (Value -> LuaE e ByteString)
    -> Parameter e Value -> HsFnPrecursor e (LuaE e ByteString)
    forall e a b.
    HsFnPrecursor e (a -> b) -> Parameter e a -> HsFnPrecursor e b
    <#> Peeker e Value -> TypeSpec -> Text -> Text -> Parameter e Value
    forall e a. Peeker e a -> TypeSpec -> Text -> Text -> Parameter e a
    parameter Peeker e Value
    forall e. LuaError e => Peeker e Value
    peekValue TypeSpec
    "any" Text
    "object" Text
    "object to convert"
      HsFnPrecursor e (LuaE e ByteString)
    -> FunctionResults e ByteString -> DocumentedFunction e
    forall e a.
    HsFnPrecursor e (LuaE e a)
    -> FunctionResults e a -> DocumentedFunction e
    =#> Pusher e ByteString
    -> TypeSpec -> Text -> FunctionResults e ByteString
    forall e a. Pusher e a -> TypeSpec -> Text -> FunctionResults e a
    functionResult Pusher e ByteString
    forall e. Pusher e ByteString
    pushLazyByteString TypeSpec
    "string"
            Text
    "JSON encoding of the given `object`"
      #? T.unlines
         ["Encodes a Lua object as JSON string."
         , ""
         , "If the object has a metamethod with name `__tojson`, then the"
         , "result is that of a call to that method with `object` passed as"
         , "the sole argument. The result of that call is expected to be a"
         , "valid JSON string, but this is not checked."
         ]