@@ -73,6 +73,13 @@
73-- > \Default is false."
73-- > \Default is false."
74-- > Normal
74-- > Normal
76+-- > instance ToParam (MatrixParam "lang" String) where
78+-- > DocQueryParam "lang"
79+-- > ["en", "sv", "fr"]
80+-- > "Get the greeting message selected language. Default is en."
76-- > instance ToSample Greet where
83-- > instance ToSample Greet where
77-- > toSample = Just $ Greet "Hello, haskeller!"
84-- > toSample = Just $ Greet "Hello, haskeller!"
@@ -95,7 +102,7 @@
95-- > -- API specification
102-- > -- API specification
96-- > type TestApi =
103-- > type TestApi =
97-- > -- GET /hello/:name?capital={true, false} returns a Greet as JSON
104-- > -- GET /hello/:name?capital={true, false} returns a Greet as JSON
98−-- > "hello" :> Capture "name" Text :> QueryParam "capital" Bool :> Get Greet
105+-- > "hello" :> MatrixParam "lang" String :> Capture "name" Text :> QueryParam "capital" Bool :> Get Greet
100-- > -- POST /greet with a Greet as JSON in the request body,
107-- > -- POST /greet with a Greet as JSON in the request body,
101-- > -- returns a Greet as JSON
108-- > -- returns a Greet as JSON
@@ -116,6 +123,7 @@
116-- > -- > docs testAPI
123-- > -- > docs testAPI
117-- > docsGreet :: API
124-- > docsGreet :: API
118-- > docsGreet = docsWithIntros [intro1, intro2] testApi
125-- > docsGreet = docsWithIntros [intro1, intro2] testApi
119-- > main :: IO ()
127-- > main :: IO ()
120-- > main = putStrLn $ markdown docsGreet
128-- > main = putStrLn $ markdown docsGreet
121module Servant.Docs
129module Servant.Docs
@@ -332,12 +340,13 @@ defResponse = Response 200 []
332-- You can tweak an 'Action' (like the default 'defAction') with these lenses
340-- You can tweak an 'Action' (like the default 'defAction') with these lenses
333-- to transform an action and add some information to it.
341-- to transform an action and add some information to it.
334data Action = Action
342data Action = Action
335− { _captures :: [DocCapture] -- type collected + user supplied info
343+ { _captures :: [DocCapture] -- type collected + user supplied info
336− , _headers :: [Text] -- type collected
344+ , _headers :: [Text] -- type collected
337− , _params :: [DocQueryParam] -- type collected + user supplied info
345+ , _params :: [DocQueryParam] -- type collected + user supplied info
338 , _notes :: [DocNote] -- user supplied
346 , _notes :: [DocNote] -- user supplied
347+ , _mxParams :: [(String, [DocQueryParam])] -- type collected + user supplied info
339− , _rqbody :: Maybe ByteString -- user supplied
348+ , _rqbody :: Maybe ByteString -- user supplied
340− , _response :: Response -- user supplied
349+ , _response :: Response -- user supplied
341 } deriving (Eq, Show)
350 } deriving (Eq, Show)
343-- Default 'Action'. Has no 'captures', no GET 'params', expects
352-- Default 'Action'. Has no 'captures', no GET 'params', expects
@@ -346,15 +355,16 @@ data Action = Action
346-- Tweakable with lenses.
355-- Tweakable with lenses.
348-- > λ> defAction
357-- > λ> defAction
349−-- > Action {_captures = [], _params = [], _rqbody = Nothing, _response = Response {_respStatus = 200, _respBody = Nothing}}
358+-- > Action {_captures = [], _headers = [], _params = [], _mxParams = [], _rqbody = Nothing, _response = Response {_respStatus = 200, _respBody = Nothing}}
350-- > λ> defAction & response.respStatus .~ 201
359-- > λ> defAction & response.respStatus .~ 201
351−-- > Action {_captures = [], _params = [], _rqbody = Nothing, _response = Response {_respStatus = 201, _respBody = Nothing}}
360+-- > Action {_captures = [], _headers = [], _params = [], _mxParams = [], _rqbody = Nothing, _response = Response {_respStatus = 201, _respBody = Nothing}}
352defAction :: Action
361defAction :: Action
353defAction =
362defAction =
354 Action []
363 Action []
359 defResponse
369 defResponse
@@ -473,6 +483,7 @@ markdown api = unlines $
474 notesStr (action ^. notes) ++
484 notesStr (action ^. notes) ++
475 capturesStr (action ^. captures) ++
485 capturesStr (action ^. captures) ++
486+ mxParamsStr (action ^. mxParams) ++
476 headersStr (action ^. headers) ++
487 headersStr (action ^. headers) ++
477 paramsStr (action ^. params) ++
488 paramsStr (action ^. params) ++
478 rqbodyStr (action ^. rqbody) ++
489 rqbodyStr (action ^. rqbody) ++
@@ -515,6 +526,22 @@ markdown api = unlines $
515 captureStr cap =
526 captureStr cap =
516 "- *" ++ (cap ^. capSymbol) ++ "*: " ++ (cap ^. capDesc)
527 "- *" ++ (cap ^. capSymbol) ++ "*: " ++ (cap ^. capDesc)
529+ mxParamsStr :: [(String, [DocQueryParam])] -> [String]
532+ "#### Matrix Parameters:" :
537+ segmentStr :: (String, [DocQueryParam]) -> String
538+ segmentStr (segment, l) = unlines $
539+ ("**" ++ segment ++ "**:") :
518 headersStr :: [Text] -> [String]
545 headersStr :: [Text] -> [String]
519 headersStr [] = []
546 headersStr [] = []
520 headersStr l = [""] ++ map headerStr l ++ [""]
547 headersStr l = [""] ++ map headerStr l ++ [""]
@@ -685,6 +712,50 @@ instance (KnownSymbol sym, ToParam (QueryFlag sym), HasDocs sublayout)
685 paramP = Proxy :: Proxy (QueryFlag sym)
712 paramP = Proxy :: Proxy (QueryFlag sym)
686 action' = over params (|> toParam paramP) action
713 action' = over params (|> toParam paramP) action
716+instance (KnownSymbol sym, ToParam (MatrixParam sym a), HasDocs sublayout)
717+ => HasDocs (MatrixParam sym a :> sublayout) where
719+ docsFor Proxy (endpoint, action) =
720+ docsFor sublayoutP (endpoint', action')
722+ where sublayoutP = Proxy :: Proxy sublayout
723+ paramP = Proxy :: Proxy (MatrixParam sym a)
724+ segment = endpoint ^. (path._last)
725+ segment' = action ^. (mxParams._last._1)
726+ endpoint' = over (path._last) (\p -> p ++ ";" ++ symbolVal symP ++ "=<value>") endpoint
728+ action' = if segment' /= segment
729+ -- This is the first matrix parameter for this segment, insert a new entry into the mxParams list
730+ then over mxParams (|> (segment, [toParam paramP])) action
731+ -- We've already inserted a matrix parameter for this segment, append to the existing list
732+ else action & mxParams._last._2 <>~ [toParam paramP]
733+ symP = Proxy :: Proxy sym
736+instance (KnownSymbol sym, {- ToParam (MatrixParams sym a), -} HasDocs sublayout)
737+ => HasDocs (MatrixParams sym a :> sublayout) where
739+ docsFor Proxy (endpoint, action) =
740+ docsFor sublayoutP (endpoint', action)
742+ where sublayoutP = Proxy :: Proxy sublayout
743+ endpoint' = over path (\p -> p ++ [";" ++ symbolVal symP ++ "=<value>"]) endpoint
744+ symP = Proxy :: Proxy sym
747+instance (KnownSymbol sym, {- ToParam (MatrixFlag sym), -} HasDocs sublayout)
748+ => HasDocs (MatrixFlag sym :> sublayout) where
750+ docsFor Proxy (endpoint, action) =
751+ docsFor sublayoutP (endpoint', action)
753+ where sublayoutP = Proxy :: Proxy sublayout
755+ endpoint' = over path (\p -> p ++ [";" ++ symbolVal symP]) endpoint
756+ symP = Proxy :: Proxy sym
688instance HasDocs Raw where
759instance HasDocs Raw where
689 docsFor _proxy (endpoint, action) =
760 docsFor _proxy (endpoint, action) =
690 single endpoint action
761 single endpoint action