servant-docs 0.11.7 → 0.11.8
raw patch · 5 files changed
+84/−8 lines, 5 filesdep ~lens
Dependency ranges changed: lens
Files
- CHANGELOG.md +7/−0
- golden/comprehensive.md +22/−0
- servant-docs.cabal +1/−1
- src/Servant/Docs/Internal.hs +52/−7
- test/Servant/DocsSpec.hs +2/−0
CHANGELOG.md view
@@ -1,6 +1,13 @@ [The latest version of this document is on GitHub.](https://github.com/haskell-servant/servant/blob/master/servant-docs/CHANGELOG.md) [Changelog for `servant` package contains significant entries for all core packages.](https://github.com/haskell-servant/servant/blob/master/servant/CHANGELOG.md) +0.11.8+------++### Significant changes++- Support `Fragment` combinator.+ 0.11.7 ------
golden/comprehensive.md view
@@ -182,6 +182,28 @@ ``` +## GET /fragment++### Fragment:++- *foo*: Fragment Int++### Response:++- Status code 200+- Headers: []++- Supported content types are:++ - `application/json;charset=utf-8`+ - `application/json`++- Example (`application/json;charset=utf-8`, `application/json`):++```javascript++```+ ## GET /get-int ### Response:
servant-docs.cabal view
@@ -1,6 +1,6 @@ cabal-version: >=1.10 name: servant-docs-version: 0.11.7+version: 0.11.8 synopsis: generate API docs for your servant webservice category: Servant, Web
src/Servant/Docs/Internal.hs view
@@ -25,8 +25,8 @@ import Control.Arrow (second) import Control.Lens- (makeLenses, mapped, over, traversed, view, (%~), (&), (.~),- (<>~), (^.), (|>))+ (makeLenses, mapped, over, set, traversed, view, (%~), (&),+ (.~), (<>~), (^.), (|>)) import qualified Data.ByteString.Char8 as BSC import Data.ByteString.Lazy.Char8 (ByteString)@@ -64,7 +64,7 @@ import Servant.API.ContentTypes import Servant.API.TypeLevel -import qualified Data.Universe.Helpers as U+import qualified Data.Universe.Helpers as U import qualified Data.HashMap.Strict as HM import qualified Data.Text as T@@ -161,6 +161,20 @@ , _paramKind :: ParamKind } deriving (Eq, Ord, Show) +-- | A type to represent fragment. Holds the name of the fragment and its description.+--+-- Write a 'ToFragment' instance for your fragment types.+data DocFragment = DocFragment+ { _fragSymbol :: String -- type supplied+ , _fragDesc :: String -- user supplied+ } deriving (Eq, Ord, Show)++-- | There should be at most one 'Fragment' per API endpoint.+-- So here we are keeping the first occurrence.+combineFragment :: Maybe DocFragment -> Maybe DocFragment -> Maybe DocFragment+Nothing `combineFragment` mdocFragment = mdocFragment+Just docFragment `combineFragment` _ = Just docFragment+ -- | An introductory paragraph for your documentation. You can pass these to -- 'docsWithIntros'. data DocIntro = DocIntro@@ -283,6 +297,7 @@ , _captures :: [DocCapture] -- type collected + user supplied info , _headers :: [Text] -- type collected , _params :: [DocQueryParam] -- type collected + user supplied info+ , _fragment :: Maybe DocFragment -- type collected + user supplied info , _notes :: [DocNote] -- user supplied , _mxParams :: [(String, [DocQueryParam])] -- type collected + user supplied info , _rqtypes :: [M.MediaType] -- type collected@@ -296,8 +311,9 @@ -- As such, we invent a non-commutative, left associative operation -- 'combineAction' to mush two together taking the response from the very left. combineAction :: Action -> Action -> Action-Action a c h p n m ts body resp `combineAction` Action a' c' h' p' n' m' ts' body' resp' =- Action (a <> a') (c <> c') (h <> h') (p <> p') (n <> n') (m <> m') (ts <> ts') (body <> body') (resp `combineResponse` resp')+Action a c h p f n m ts body resp+ `combineAction` Action a' c' h' p' f' n' m' ts' body' resp' =+ Action (a <> a') (c <> c') (h <> h') (p <> p') (f `combineFragment` f') (n <> n') (m <> m') (ts <> ts') (body <> body') (resp `combineResponse` resp') -- | Default 'Action'. Has no 'captures', no query 'params', expects -- no request body ('rqbody') and the typical response is 'defResponse'.@@ -305,10 +321,10 @@ -- Tweakable with lenses. -- -- >>> defAction--- Action {_authInfo = [], _captures = [], _headers = [], _params = [], _notes = [], _mxParams = [], _rqtypes = [], _rqbody = [], _response = Response {_respStatus = 200, _respTypes = [], _respBody = [], _respHeaders = []}}+-- Action {_authInfo = [], _captures = [], _headers = [], _params = [], _fragment = Nothing, _notes = [], _mxParams = [], _rqtypes = [], _rqbody = [], _response = Response {_respStatus = 200, _respTypes = [], _respBody = [], _respHeaders = []}} -- -- >>> defAction & response.respStatus .~ 201--- Action {_authInfo = [], _captures = [], _headers = [], _params = [], _notes = [], _mxParams = [], _rqtypes = [], _rqbody = [], _response = Response {_respStatus = 201, _respTypes = [], _respBody = [], _respHeaders = []}}+-- Action {_authInfo = [], _captures = [], _headers = [], _params = [], _fragment = Nothing, _notes = [], _mxParams = [], _rqtypes = [], _rqbody = [], _response = Response {_respStatus = 201, _respTypes = [], _respBody = [], _respHeaders = []}} -- defAction :: Action defAction =@@ -316,6 +332,7 @@ [] [] []+ Nothing [] [] []@@ -368,6 +385,7 @@ makeLenses ''Endpoint makeLenses ''DocCapture makeLenses ''DocQueryParam+makeLenses ''DocFragment makeLenses ''DocIntro makeLenses ''DocNote makeLenses ''Response@@ -587,6 +605,15 @@ class ToAuthInfo a where toAuthInfo :: Proxy a -> DocAuthentication +-- | The class that helps us get documentation for URL fragments.+--+-- Example of an instance:+--+-- > instance ToFragment (Fragment a) where+-- > toFragment _ = DocFragment "fragment" "fragment description"+class ToFragment t where+ toFragment :: Proxy t -> DocFragment+ -- | Generate documentation in Markdown format for -- the given 'API'. --@@ -629,6 +656,7 @@ capturesStr (action ^. captures) ++ headersStr (action ^. headers) ++ paramsStr meth (action ^. params) +++ fragmentStr (action ^. fragment) ++ rqbodyStr (action ^. rqtypes) (action ^. rqbody) ++ responseStr (action ^. response) ++ []@@ -730,6 +758,14 @@ where values = param ^. paramValues + fragmentStr :: Maybe DocFragment -> [String]+ fragmentStr Nothing = []+ fragmentStr (Just frag) =+ [ "### Fragment:", ""+ , "- *" ++ (frag ^. fragSymbol) ++ "*: " ++ (frag ^. fragDesc)+ , ""+ ]+ rqbodyStr :: [M.MediaType] -> [(Text, M.MediaType, ByteString)]-> [String] rqbodyStr [] [] = [] rqbodyStr types s =@@ -959,6 +995,15 @@ paramP = Proxy :: Proxy (QueryFlag sym) action' = over params (|> toParam paramP) action +instance (ToFragment (Fragment a), HasDocs api)+ => HasDocs (Fragment a :> api) where++ docsFor Proxy (endpoint, action) =+ docsFor subApiP (endpoint, action')++ where subApiP = Proxy :: Proxy api+ fragmentP = Proxy :: Proxy (Fragment a)+ action' = set fragment (Just (toFragment fragmentP)) action instance HasDocs Raw where docsFor _proxy (endpoint, action) _ =
test/Servant/DocsSpec.hs view
@@ -58,6 +58,8 @@ toCapture _ = DocCapture "foo" "Capture foo Int" instance ToCapture (CaptureAll "foo" Int) where toCapture _ = DocCapture "foo" "Capture all foo Int"+instance ToFragment (Fragment Int) where+ toFragment _ = DocFragment "foo" "Fragment Int" -- * specs