{-# LANGUAGE LambdaCase        #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes        #-}
{- |
   Module      : Text.Pandoc.Lua.Documentation
   Copyright   : Copyright © 2026 Albert Krewinkel
   License     : GPL-2.0-or-later
   Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>

Render Lua documentation
-}
module Text.Pandoc.Lua.Documentation
  ( renderDocumentation
  ) where

import Data.Default (def)
import Data.List (intersperse)
import Data.Sequence (Seq ((:|>)))
import Data.Version (showVersion)
import HsLua as Lua
import Text.Pandoc.Class (runPure)
import Text.Pandoc.Definition (Pandoc (Pandoc))
import Text.Pandoc.Extensions (extensionsFromList, Extension (..))
import Text.Pandoc.Options (ReaderOptions (readerExtensions))
import Text.Pandoc.Readers (readCommonMark)
import Text.Pandoc.Shared (compactify)
import Text.Pandoc.Walk (walk)

import qualified Data.Text as T
import qualified Text.Pandoc.Builder as B
import qualified Text.Pandoc.UTF8 as UTF8

-- | Render the documentation object as pandoc Blocks
renderDocumentation :: DocumentationObject -> B.Blocks
renderDocumentation :: DocumentationObject -> Blocks
renderDocumentation = \case
  DocObjectFunction FunctionDoc
fn -> Maybe Text -> FunctionDoc -> Blocks
renderFunctionDoc Maybe Text
forall a. Maybe a
Nothing FunctionDoc
fn
  DocObjectModule ModuleDoc
mdl  -> ModuleDoc -> Blocks
renderModuleDoc ModuleDoc
mdl
  DocObjectType TypeDoc
tp     -> Maybe Text -> TypeDoc -> Blocks
renderTypeDoc Maybe Text
forall a. Maybe a
Nothing TypeDoc
tp

renderTypeDoc :: Maybe T.Text -> TypeDoc -> B.Blocks
renderTypeDoc :: Maybe Text -> TypeDoc -> Blocks
renderTypeDoc Maybe Text
mbmodname TypeDoc
td = [Blocks] -> Blocks
forall a. Monoid a => [a] -> a
mconcat
  [ Attr -> Int -> Inlines -> Blocks
B.headerWith (Text
ident, [], []) Int
1 (Text -> Inlines
B.str (Text -> Inlines) -> Text -> Inlines
forall a b. (a -> b) -> a -> b
$ TypeDoc -> Text
typeDocName TypeDoc
td)
  , Text -> Blocks
parseCommonMark (Text -> Blocks) -> Text -> Blocks
forall a b. (a -> b) -> a -> b
$ TypeDoc -> Text
typeDocDescription TypeDoc
td
  , if [FunctionDoc] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ([FunctionDoc] -> Bool) -> [FunctionDoc] -> Bool
forall a b. (a -> b) -> a -> b
$ TypeDoc -> [FunctionDoc]
typeDocMethods TypeDoc
td
    then Blocks
forall a. Monoid a => a
mempty
    else
      Int -> Inlines -> Blocks
B.header Int
2 Inlines
"Methods" Blocks -> Blocks -> Blocks
forall a. Semigroup a => a -> a -> a
<>
      (Int -> Blocks -> Blocks
shiftHeadings Int
2 (Blocks -> Blocks)
-> ([FunctionDoc] -> Blocks) -> [FunctionDoc] -> Blocks
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Blocks] -> Blocks
forall a. Monoid a => [a] -> a
mconcat ([Blocks] -> Blocks)
-> ([FunctionDoc] -> [Blocks]) -> [FunctionDoc] -> Blocks
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FunctionDoc -> Blocks) -> [FunctionDoc] -> [Blocks]
forall a b. (a -> b) -> [a] -> [b]
map (Maybe Text -> FunctionDoc -> Blocks
renderFunctionDoc Maybe Text
forall a. Maybe a
Nothing) ([FunctionDoc] -> Blocks) -> [FunctionDoc] -> Blocks
forall a b. (a -> b) -> a -> b
$
       TypeDoc -> [FunctionDoc]
typeDocMethods TypeDoc
td)
  ]
 where
  ident :: Text
ident = case Maybe Text
mbmodname of
    Just Text
modname  -> [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat [ Text
"type-", Text
modname, Text
".", TypeDoc -> Text
typeDocName TypeDoc
td ]
    Maybe Text
Nothing       -> [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat [ Text
"type-", TypeDoc -> Text
typeDocName TypeDoc
td ]

-- Shift headings
shiftHeadings :: Int -> B.Blocks -> B.Blocks
shiftHeadings :: Int -> Blocks -> Blocks
shiftHeadings Int
incr Blocks
blks = ((Block -> Block) -> Blocks -> Blocks)
-> Blocks -> (Block -> Block) -> Blocks
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Block -> Block) -> Blocks -> Blocks
forall a b. Walkable a b => (a -> a) -> b -> b
walk Blocks
blks ((Block -> Block) -> Blocks) -> (Block -> Block) -> Blocks
forall a b. (a -> b) -> a -> b
$ \case
  B.Header Int
level Attr
attr [Inline]
inner -> Int -> Attr -> [Inline] -> Block
B.Header (Int
level Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
incr) Attr
attr [Inline]
inner
  Block
x -> Block
x

renderModuleDoc :: ModuleDoc -> B.Blocks
renderModuleDoc :: ModuleDoc -> Blocks
renderModuleDoc ModuleDoc
moddoc =
  let modname :: Text
modname = ModuleDoc -> Text
moduleDocName ModuleDoc
moddoc
  in [Blocks] -> Blocks
forall a. Monoid a => [a] -> a
mconcat
  [ Attr -> Int -> Inlines -> Blocks
B.headerWith (Text
"module-" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
modname, [], []) Int
1
      (Text -> Inlines
B.str (Text -> Inlines) -> Text -> Inlines
forall a b. (a -> b) -> a -> b
$ Text
"Module " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
modname)
  , Text -> Blocks
parseCommonMark (ModuleDoc -> Text
moduleDocDescription ModuleDoc
moddoc)
  , if [FieldDoc] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (ModuleDoc -> [FieldDoc]
moduleDocFields ModuleDoc
moddoc)
    then Blocks
forall a. Monoid a => a
mempty
    else
      let ident :: Text
ident = Text
modname Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"-fields"
      in Attr -> Int -> Inlines -> Blocks
B.headerWith (Text
ident, [], []) Int
2 (Text -> Inlines
B.str Text
"Fields") Blocks -> Blocks -> Blocks
forall a. Semigroup a => a -> a -> a
<>
         Int -> Blocks -> Blocks
shiftHeadings Int
0 ([Blocks] -> Blocks
forall a. Monoid a => [a] -> a
mconcat ((FieldDoc -> Blocks) -> [FieldDoc] -> [Blocks]
forall a b. (a -> b) -> [a] -> [b]
map (Text -> FieldDoc -> Blocks
renderFieldDoc Text
modname)
                                   (ModuleDoc -> [FieldDoc]
moduleDocFields ModuleDoc
moddoc)))
  , if [FunctionDoc] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (ModuleDoc -> [FunctionDoc]
moduleDocFunctions ModuleDoc
moddoc)
    then Blocks
forall a. Monoid a => a
mempty
    else
      let ident :: Text
ident = Text
modname Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"-functions"
      in Attr -> Int -> Inlines -> Blocks
B.headerWith (Text
ident, [], []) Int
2 (Text -> Inlines
B.str Text
"Functions") Blocks -> Blocks -> Blocks
forall a. Semigroup a => a -> a -> a
<>
         (Int -> Blocks -> Blocks
shiftHeadings Int
2 (Blocks -> Blocks)
-> ([FunctionDoc] -> Blocks) -> [FunctionDoc] -> Blocks
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Blocks] -> Blocks
forall a. Monoid a => [a] -> a
mconcat ([Blocks] -> Blocks)
-> ([FunctionDoc] -> [Blocks]) -> [FunctionDoc] -> Blocks
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FunctionDoc -> Blocks) -> [FunctionDoc] -> [Blocks]
forall a b. (a -> b) -> [a] -> [b]
map (Maybe Text -> FunctionDoc -> Blocks
renderFunctionDoc (Maybe Text -> FunctionDoc -> Blocks)
-> Maybe Text -> FunctionDoc -> Blocks
forall a b. (a -> b) -> a -> b
$ Text -> Maybe Text
forall a. a -> Maybe a
Just Text
modname) ([FunctionDoc] -> Blocks) -> [FunctionDoc] -> Blocks
forall a b. (a -> b) -> a -> b
$
          ModuleDoc -> [FunctionDoc]
moduleDocFunctions ModuleDoc
moddoc)
  , if [TypeDoc] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (ModuleDoc -> [TypeDoc]
moduleDocTypes ModuleDoc
moddoc)
    then Blocks
forall a. Monoid a => a
mempty
    else
      let ident :: Text
ident = Text
modname Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"-types"
      in Attr -> Int -> Inlines -> Blocks
B.headerWith (Text
ident, [], []) Int
2 (Text -> Inlines
B.str Text
"Types") Blocks -> Blocks -> Blocks
forall a. Semigroup a => a -> a -> a
<>
         (Int -> Blocks -> Blocks
shiftHeadings Int
2 (Blocks -> Blocks) -> ([TypeDoc] -> Blocks) -> [TypeDoc] -> Blocks
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Blocks] -> Blocks
forall a. Monoid a => [a] -> a
mconcat ([Blocks] -> Blocks)
-> ([TypeDoc] -> [Blocks]) -> [TypeDoc] -> Blocks
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TypeDoc -> Blocks) -> [TypeDoc] -> [Blocks]
forall a b. (a -> b) -> [a] -> [b]
map (Maybe Text -> TypeDoc -> Blocks
renderTypeDoc (Maybe Text -> TypeDoc -> Blocks)
-> Maybe Text -> TypeDoc -> Blocks
forall a b. (a -> b) -> a -> b
$ Text -> Maybe Text
forall a. a -> Maybe a
Just Text
modname) ([TypeDoc] -> [Blocks])
-> ([TypeDoc] -> [TypeDoc]) -> [TypeDoc] -> [Blocks]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
          [TypeDoc] -> [TypeDoc]
forall a. [a] -> [a]
reverse ([TypeDoc] -> Blocks) -> [TypeDoc] -> Blocks
forall a b. (a -> b) -> a -> b
$ ModuleDoc -> [TypeDoc]
moduleDocTypes ModuleDoc
moddoc)
  ]

parseCommonMark :: T.Text -> B.Blocks
parseCommonMark :: Text -> Blocks
parseCommonMark Text
txt =
  let exts :: Extensions
exts = [Extension] -> Extensions
extensionsFromList
        [ Extension
Ext_wikilinks_title_after_pipe
        , Extension
Ext_smart
        ]
      result :: Either PandocError Blocks
result = PandocPure Blocks -> Either PandocError Blocks
forall a. PandocPure a -> Either PandocError a
runPure (PandocPure Blocks -> Either PandocError Blocks)
-> PandocPure Blocks -> Either PandocError Blocks
forall a b. (a -> b) -> a -> b
$ do
        Pandoc _ blks <- ReaderOptions -> Text -> PandocPure Pandoc
forall (m :: * -> *) a.
(PandocMonad m, ToSources a) =>
ReaderOptions -> a -> m Pandoc
readCommonMark (ReaderOptions
forall a. Default a => a
def {readerExtensions = exts}) Text
txt
        return $ B.fromList blks
  in (PandocError -> Blocks)
-> (Blocks -> Blocks) -> Either PandocError Blocks -> Blocks
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either PandocError -> Blocks
forall a. Monoid a => a
mempty Blocks -> Blocks
forall a. a -> a
id Either PandocError Blocks
result

appendInlines :: B.Blocks -> B.Inlines -> B.Blocks
appendInlines :: Blocks -> Inlines -> Blocks
appendInlines Blocks
blks Inlines
inlns = case Blocks -> Seq Block
forall a. Many a -> Seq a
B.unMany Blocks
blks of
  Seq Block
front :|> (B.Para [Inline]
xs) -> Seq Block -> Blocks
forall a. Seq a -> Many a
B.Many Seq Block
front Blocks -> Blocks -> Blocks
forall a. Semigroup a => a -> a -> a
<> Inlines -> Blocks
B.para ([Inline] -> Inlines
addTo [Inline]
xs)
  Seq Block
front :|> (B.Plain [Inline]
xs) -> Seq Block -> Blocks
forall a. Seq a -> Many a
B.Many Seq Block
front Blocks -> Blocks -> Blocks
forall a. Semigroup a => a -> a -> a
<> Inlines -> Blocks
B.plain ([Inline] -> Inlines
addTo [Inline]
xs)
  Seq Block
_ -> Blocks
blks Blocks -> Blocks -> Blocks
forall a. Semigroup a => a -> a -> a
<> Inlines -> Blocks
B.para Inlines
inlns
 where addTo :: [Inline] -> Inlines
addTo [Inline]
xs = [Inline] -> Inlines
forall a. [a] -> Many a
B.fromList [Inline]
xs Inlines -> Inlines -> Inlines
forall a. Semigroup a => a -> a -> a
<> Inlines
B.space Inlines -> Inlines -> Inlines
forall a. Semigroup a => a -> a -> a
<> Inlines
inlns

appendType :: B.Blocks -> TypeSpec -> B.Blocks
appendType :: Blocks -> TypeSpec -> Blocks
appendType Blocks
blks TypeSpec
typespec =
  Blocks -> Inlines -> Blocks
appendInlines Blocks
blks (Text -> Inlines
B.str Text
"(" Inlines -> Inlines -> Inlines
forall a. Semigroup a => a -> a -> a
<> TypeSpec -> Inlines
typeToInlines TypeSpec
typespec Inlines -> Inlines -> Inlines
forall a. Semigroup a => a -> a -> a
<> Text -> Inlines
B.str Text
")")

typeToInlines :: TypeSpec -> B.Inlines
typeToInlines :: TypeSpec -> Inlines
typeToInlines = \case
  bt :: TypeSpec
bt@BasicType{}   -> Inlines -> Inlines
builtin (Inlines -> Inlines) -> Inlines -> Inlines
forall a b. (a -> b) -> a -> b
$ TypeSpec -> Inlines
tystr TypeSpec
bt
  NamedType Name
"integer" -> Inlines -> Inlines
builtin Inlines
"integer"
  NamedType Name
name   -> Attr -> Text -> Text -> Inlines -> Inlines
B.linkWith (Text
"", [Text
"documented-type"], [])
                        (Text
"#" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Name -> Text
n2t Name
name) Text
forall a. Monoid a => a
mempty (Inlines -> Inlines) -> Inlines -> Inlines
forall a b. (a -> b) -> a -> b
$ Text -> Inlines
B.str (Name -> Text
n2t Name
name)
  SeqType TypeSpec
itemtype -> Inlines
"{" Inlines -> Inlines -> Inlines
forall a. Semigroup a => a -> a -> a
<> TypeSpec -> Inlines
typeToInlines TypeSpec
itemtype Inlines -> Inlines -> Inlines
forall a. Semigroup a => a -> a -> a
<> Inlines
",...}"
  SumType [TypeSpec]
summands -> [Inlines] -> Inlines
forall a. Monoid a => [a] -> a
mconcat ([Inlines] -> Inlines)
-> ([Inlines] -> [Inlines]) -> [Inlines] -> Inlines
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Inlines -> [Inlines] -> [Inlines]
forall a. a -> [a] -> [a]
intersperse (Text -> Inlines
B.str Text
"|") ([Inlines] -> Inlines) -> [Inlines] -> Inlines
forall a b. (a -> b) -> a -> b
$ (TypeSpec -> Inlines) -> [TypeSpec] -> [Inlines]
forall a b. (a -> b) -> [a] -> [b]
map TypeSpec -> Inlines
typeToInlines [TypeSpec]
summands
  TypeSpec
AnyType          -> Inlines
"any"
  TypeSpec
x                -> TypeSpec -> Inlines
tystr TypeSpec
x
 where
  tystr :: TypeSpec -> Inlines
tystr = Text -> Inlines
B.str (Text -> Inlines) -> (TypeSpec -> Text) -> TypeSpec -> Inlines
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
T.pack (String -> Text) -> (TypeSpec -> String) -> TypeSpec -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TypeSpec -> String
typeSpecToString
  n2t :: Name -> Text
n2t = ByteString -> Text
UTF8.toText (ByteString -> Text) -> (Name -> ByteString) -> Name -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> ByteString
fromName
  builtin :: Inlines -> Inlines
builtin = Attr -> Inlines -> Inlines
B.spanWith (Text
"", [Text
"builtin-lua-type"], [])

renderFunctionDoc :: Maybe T.Text -> FunctionDoc -> B.Blocks
renderFunctionDoc :: Maybe Text -> FunctionDoc -> Blocks
renderFunctionDoc Maybe Text
mbmodule FunctionDoc
fndoc =
  let name :: Text
name = case Maybe Text
mbmodule of
        Just Text
_   ->  (Char -> Bool) -> Text -> Text
T.takeWhileEnd (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'.') (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ FunctionDoc -> Text
funDocName FunctionDoc
fndoc
        Maybe Text
Nothing  -> FunctionDoc -> Text
funDocName FunctionDoc
fndoc
      ident :: Text
ident = FunctionDoc -> Text
funDocName FunctionDoc
fndoc
      level :: Int
level = Int
1
      argsString :: Text
argsString = [ParameterDoc] -> Text
argslist (FunctionDoc -> [ParameterDoc]
funDocParameters FunctionDoc
fndoc)
      paramToDefItem :: ParameterDoc -> (Inlines, [Blocks])
paramToDefItem ParameterDoc
p = ( Text -> Inlines
B.code (Text -> Inlines) -> Text -> Inlines
forall a b. (a -> b) -> a -> b
$ ParameterDoc -> Text
parameterName ParameterDoc
p
                         , [Blocks] -> [Blocks]
compactify
                           [ Blocks -> TypeSpec -> Blocks
appendType
                               (Text -> Blocks
parseCommonMark (Text -> Blocks) -> Text -> Blocks
forall a b. (a -> b) -> a -> b
$ ParameterDoc -> Text
parameterDescription ParameterDoc
p)
                               (ParameterDoc -> TypeSpec
parameterType ParameterDoc
p)
                           ]
                         )
      paramlist :: Blocks
paramlist = [(Inlines, [Blocks])] -> Blocks
B.definitionList ([(Inlines, [Blocks])] -> Blocks)
-> ([ParameterDoc] -> [(Inlines, [Blocks])])
-> [ParameterDoc]
-> Blocks
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ParameterDoc -> (Inlines, [Blocks]))
-> [ParameterDoc] -> [(Inlines, [Blocks])]
forall a b. (a -> b) -> [a] -> [b]
map ParameterDoc -> (Inlines, [Blocks])
paramToDefItem ([ParameterDoc] -> Blocks) -> [ParameterDoc] -> Blocks
forall a b. (a -> b) -> a -> b
$
                  FunctionDoc -> [ParameterDoc]
funDocParameters FunctionDoc
fndoc
  in [Blocks] -> Blocks
forall a. Monoid a => [a] -> a
mconcat
     [ Attr -> Int -> Inlines -> Blocks
B.headerWith (Text
ident, [], []) Int
level (Text -> Inlines
B.str Text
name)
     , Inlines -> Blocks
B.plain (Text -> Inlines
B.code (Text -> Inlines) -> Text -> Inlines
forall a b. (a -> b) -> a -> b
$ Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" (" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
argsString Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")")
     , Text -> Blocks
parseCommonMark (FunctionDoc -> Text
funDocDescription FunctionDoc
fndoc)
     , if [ParameterDoc] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (FunctionDoc -> [ParameterDoc]
funDocParameters FunctionDoc
fndoc)
       then Blocks
forall a. Monoid a => a
mempty
       else Inlines -> Blocks
B.para Inlines
"Parameters:" Blocks -> Blocks -> Blocks
forall a. Semigroup a => a -> a -> a
<> Blocks
paramlist
     , if FunctionDoc -> ResultsDoc
funDocResults FunctionDoc
fndoc ResultsDoc -> ResultsDoc -> Bool
forall a. Eq a => a -> a -> Bool
== [ResultValueDoc] -> ResultsDoc
ResultsDocList []
       then Blocks
forall a. Monoid a => a
mempty
       else Inlines -> Blocks
B.para Inlines
"Returns:" Blocks -> Blocks -> Blocks
forall a. Semigroup a => a -> a -> a
<> ResultsDoc -> Blocks
renderResults (FunctionDoc -> ResultsDoc
funDocResults FunctionDoc
fndoc)
     , case FunctionDoc -> Maybe Version
funDocSince FunctionDoc
fndoc of
         Maybe Version
Nothing -> Blocks
forall a. Monoid a => a
mempty
         Just Version
version ->
           Inlines -> Blocks
B.para (Inlines -> Blocks) -> Inlines -> Blocks
forall a b. (a -> b) -> a -> b
$ Inlines -> Inlines
B.emph (Inlines -> Inlines) -> Inlines -> Inlines
forall a b. (a -> b) -> a -> b
$ Inlines
"Since: " Inlines -> Inlines -> Inlines
forall a. Semigroup a => a -> a -> a
<> (Text -> Inlines
B.str (Text -> Inlines) -> (String -> Text) -> String -> Inlines
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
T.pack (String -> Inlines) -> String -> Inlines
forall a b. (a -> b) -> a -> b
$ Version -> String
showVersion Version
version)
     ]

renderResults :: ResultsDoc -> B.Blocks
renderResults :: ResultsDoc -> Blocks
renderResults (ResultsDocMult Text
descr) = Text -> Blocks
parseCommonMark Text
descr
renderResults (ResultsDocList [ResultValueDoc]
rvd) = [Blocks] -> Blocks
B.bulletList ([Blocks] -> Blocks) -> [Blocks] -> Blocks
forall a b. (a -> b) -> a -> b
$ (ResultValueDoc -> Blocks) -> [ResultValueDoc] -> [Blocks]
forall a b. (a -> b) -> [a] -> [b]
map ResultValueDoc -> Blocks
renderResultVal [ResultValueDoc]
rvd
 where
   renderResultVal :: ResultValueDoc -> Blocks
renderResultVal (ResultValueDoc TypeSpec
typespec Text
descr) =
     Text -> Blocks
parseCommonMark Text
descr Blocks -> TypeSpec -> Blocks
`appendType` TypeSpec
typespec

argslist :: [ParameterDoc] -> T.Text
argslist :: [ParameterDoc] -> Text
argslist [ParameterDoc]
params =
  -- Expect optional values to come after required values.
  let ([ParameterDoc]
required, [ParameterDoc]
optional') = (ParameterDoc -> Bool)
-> [ParameterDoc] -> ([ParameterDoc], [ParameterDoc])
forall a. (a -> Bool) -> [a] -> ([a], [a])
break ParameterDoc -> Bool
parameterIsOptional [ParameterDoc]
params
      reqs :: [Text]
reqs = (ParameterDoc -> Text) -> [ParameterDoc] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map ParameterDoc -> Text
parameterName [ParameterDoc]
required
      opts :: [Text]
opts = (ParameterDoc -> Text) -> [ParameterDoc] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map ParameterDoc -> Text
parameterName [ParameterDoc]
optional'
  in if [Text] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Text]
opts
     then Text -> [Text] -> Text
T.intercalate Text
", " [Text]
reqs
     else Text -> [Text] -> Text
T.intercalate Text
", " [Text]
reqs Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
          (if [ParameterDoc] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [ParameterDoc]
required then Text
"[" else Text
"[, ") Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
          Text -> [Text] -> Text
T.intercalate Text
"[, " [Text]
opts Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text -> Text
T.replicate ([Text] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Text]
opts) Text
"]"

renderFieldDoc :: T.Text -> FieldDoc -> B.Blocks
renderFieldDoc :: Text -> FieldDoc -> Blocks
renderFieldDoc Text
_modname FieldDoc
fd =
  Attr -> Int -> Inlines -> Blocks
B.headerWith (Text
ident, [], []) Int
3 (Text -> Inlines
B.str Text
name) Blocks -> Blocks -> Blocks
forall a. Semigroup a => a -> a -> a
<>
  Blocks -> TypeSpec -> Blocks
appendType (Text -> Blocks
parseCommonMark (Text -> Blocks) -> Text -> Blocks
forall a b. (a -> b) -> a -> b
$ FieldDoc -> Text
fieldDocDescription FieldDoc
fd) (FieldDoc -> TypeSpec
fieldDocType FieldDoc
fd)
 where
  ident :: Text
ident = FieldDoc -> Text
fieldDocName FieldDoc
fd
  name :: Text
name = (Char -> Bool) -> Text -> Text
T.takeWhileEnd (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'.') (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ FieldDoc -> Text
fieldDocName FieldDoc
fd