@@ -85,7 +85,7 @@
85-- > main = printMarkdown greetDocs
85-- > main = printMarkdown greetDocs
86module Servant.Docs
86module Servant.Docs
87 ( -- * 'HasDocs' class and key functions
87 ( -- * 'HasDocs' class and key functions
88− HasDocs(..), docs, printMarkdown
88+ HasDocs(..), docs, markdown, printMarkdown
90 , -- * Classes you need to implement for your types
90 , -- * Classes you need to implement for your types
91 ToSample(..), ToParam(..), ToCapture(..)
91 ToSample(..), ToParam(..), ToCapture(..)
@@ -106,7 +106,6 @@ module Servant.Docs
108import Control.Lens hiding (Action)
108import Control.Lens hiding (Action)
109−import Control.Monad (when)
110import Data.Aeson
109import Data.Aeson
111import Data.ByteString.Lazy.Char8 (ByteString)
110import Data.ByteString.Lazy.Char8 (ByteString)
112import Data.Hashable
111import Data.Hashable
@@ -114,9 +113,9 @@ import Data.HashMap.Strict (HashMap)
114import Data.List
113import Data.List
115import Data.Monoid
114import Data.Monoid
116import Data.Proxy
115import Data.Proxy
116+import Data.String.Conversions
117import GHC.Generics
117import GHC.Generics
119−import qualified Data.ByteString.Lazy.Char8 as LB
120import qualified Data.HashMap.Strict as HM
119import qualified Data.HashMap.Strict as HM
122-- | Supported HTTP request methods
121-- | Supported HTTP request methods
@@ -349,69 +348,80 @@ class ToCapture c where
349-- | Print documentation in Markdown format for
348-- | Print documentation in Markdown format for
350-- the given 'API', on standard output.
349-- the given 'API', on standard output.
351printMarkdown :: API -> IO ()
350printMarkdown :: API -> IO ()
352−printMarkdown = imapM_ printEndpoint
351+printMarkdown = print . markdown
353+markdown :: API -> String
354+markdown = unlines . concat . map (uncurry printEndpoint) . HM.toList
354− where printEndpoint endpoint action = do
356+ where printEndpoint :: Endpoint -> Action -> [String]
357+ printEndpoint endpoint action =
355− putStrLn $ str
358+ str :
356− putStrLn $ replicate len '-'
359+ replicate len '-' :
357− putStrLn ""
360+ "" :
358− capturesStr (action ^. captures)
361+ capturesStr (action ^. captures) ++
359− paramsStr (action ^. params)
362+ paramsStr (action ^. params) ++
360− rqbodyStr (action ^. rqbody)
363+ rqbodyStr (action ^. rqbody) ++
361− responseStr (action ^. response)
364+ responseStr (action ^. response) ++
363 where str = show (endpoint^.method) ++ " " ++ endpoint^.path
367 where str = show (endpoint^.method) ++ " " ++ endpoint^.path
364 len = length str
368 len = length str
366− capturesStr :: [DocCapture] -> IO ()
370+ capturesStr :: [DocCapture] -> [String]
367− capturesStr [] = return ()
371+ capturesStr [] = []
368− capturesStr l = do
372+ capturesStr l =
369− putStrLn "**Captures**: "
373+ "**Captures**: " :
370− putStrLn ""
374+ "" :
371− mapM_ captureStr l
375+ map captureStr l ++
372− putStrLn ""
376+ "" :
373 captureStr cap =
378 captureStr cap =
374− putStrLn $ "- *" ++ (cap ^. capSymbol) ++ "*: " ++ (cap ^. capDesc)
379+ "- *" ++ (cap ^. capSymbol) ++ "*: " ++ (cap ^. capDesc)
376− paramsStr :: [DocQueryParam] -> IO ()
381+ paramsStr :: [DocQueryParam] -> [String]
377− paramsStr [] = return ()
382+ paramsStr [] = []
378− paramsStr l = do
383+ paramsStr l =
379− putStrLn "**GET Parameters**: "
384+ "**GET Parameters**: " :
380− putStrLn ""
385+ "" :
381− mapM_ paramStr l
386+ map paramStr l ++
382− putStrLn ""
387+ "" :
383− paramStr param = do
389+ paramStr param = unlines $
384− putStrLn $ " - " ++ param ^. paramName
390+ (" - " ++ param ^. paramName) :
385− when (not (null values) || param ^. paramKind /= Flag) $
391+ (if (not (null values) || param ^. paramKind /= Flag)
386− putStrLn $ " - **Values**: *" ++ intercalate ", " values ++ "*"
392+ then [" - **Values**: *" ++ intercalate ", " values ++ "*"]
387− putStrLn $ " - **Description**: " ++ param ^. paramDesc
394+ (" - **Description**: " ++ param ^. paramDesc) :
388− when (param ^. paramKind == List) $
395+ (if (param ^. paramKind == List)
389− putStrLn $ " - This parameter is a **list**. All GET parameters with the name "
396+ then [" - This parameter is a **list**. All GET parameters with the name "
390− ++ param ^. paramName ++ "[] will forward their values in a list to the handler."
397+ ++ param ^. paramName ++ "[] will forward their values in a list to the handler."]
391− when (param ^. paramKind == Flag) $
399+ (if (param ^. paramKind == Flag)
392− putStrLn $ " - This parameter is a **flag**. This means no value is expected to be associated to this parameter."
400+ then [" - This parameter is a **flag**. This means no value is expected to be associated to this parameter."]
394 where values = param ^. paramValues
404 where values = param ^. paramValues
396− rqbodyStr :: Maybe ByteString -> IO ()
406+ rqbodyStr :: Maybe ByteString -> [String]
397− rqbodyStr Nothing = return ()
407+ rqbodyStr Nothing = []
398− rqbodyStr (Just b) = do
408+ rqbodyStr (Just b) =
399− putStrLn "**Request Body**: "
409+ "**Request Body**: " :
400 jsonStr b
410 jsonStr b
402− jsonStr b = do
412+ jsonStr b =
403− putStrLn ""
413+ "" :
404− putStrLn "``` javascript"
414+ "``` javascript" :
405− LB.putStrLn b
415+ cs b :
406− putStrLn "```"
416+ "```" :
407− putStrLn ""
417+ "" :
409− responseStr :: Response -> IO ()
420+ responseStr :: Response -> [String]
410− responseStr resp = do
421+ responseStr resp =
411− putStrLn $ "**Response**: "
422+ "**Response**: " :
412− putStrLn $ ""
423+ "" :
413− putStrLn $ " - Status code " ++ show (resp ^. respStatus)
424+ (" - Status code " ++ show (resp ^. respStatus)) :
414− resp ^. respBody &
425+ (resp ^. respBody &
415− maybe (putStrLn " - No response body\n")
426+ maybe [" - No response body\n"]
416− (\b -> putStrLn " - Response body as below." >> jsonStr b)
427+ (\b -> " - Response body as below." : jsonStr b))