Improve documentation.

I also slipped a change into the Matrix Paramters section markdown generation,
there is one less (superfluous) newline there now.
This commit is contained in:
Christian Marie 2015-02-18 12:49:08 +11:00
parent a008e08dd1
commit b935f28185
3 changed files with 80 additions and 26 deletions

View file

@ -52,6 +52,11 @@ instance ToSample Greet where
, ("If you use ?capital=false", Greet "Hello, haskeller") , ("If you use ?capital=false", Greet "Hello, haskeller")
] ]
-- We define some introductory sections, these will appear at the top of the
-- documentation.
--
-- We pass them in with 'docsWith', below. If you only want to add
-- introductions, you may use 'docsWithIntros'
intro1 :: DocIntro intro1 :: DocIntro
intro1 = DocIntro "On proper introductions." -- The title intro1 = DocIntro "On proper introductions." -- The title
[ "Hello there." [ "Hello there."
@ -78,8 +83,11 @@ type TestApi =
testApi :: Proxy TestApi testApi :: Proxy TestApi
testApi = Proxy testApi = Proxy
extras :: ExtraInfo TestApi -- Build some extra information for the DELETE /greet/:greetid endpoint. We
extras = -- want to add documentation about a secret unicorn header and some extra
-- notes.
extra :: ExtraInfo TestApi
extra =
safeInfo (Proxy :: Proxy ("greet" :> Capture "greetid" Text :> Delete)) $ safeInfo (Proxy :: Proxy ("greet" :> Capture "greetid" Text :> Delete)) $
defAction & headers <>~ ["unicorns"] defAction & headers <>~ ["unicorns"]
& notes <>~ [ DocNote "Title" ["This is some text"] & notes <>~ [ DocNote "Title" ["This is some text"]
@ -90,11 +98,11 @@ extras =
-- is derived from the type as well as from -- is derived from the type as well as from
-- the 'ToCapture', 'ToParam' and 'ToSample' instances from above. -- the 'ToCapture', 'ToParam' and 'ToSample' instances from above.
-- --
-- If you didn't want intros you could just call: -- If you didn't want intros and extra information, you could just call:
-- --
-- > docs testAPI -- > docs testAPI :: API
docsGreet :: API docsGreet :: API
docsGreet = docsWith [intro1, intro2] extras testApi docsGreet = docsWith [intro1, intro2] extra testApi
main :: IO () main :: IO ()
main = putStrLn $ markdown docsGreet main = putStrLn $ markdown docsGreet

View file

@ -37,7 +37,7 @@ You'll also note that multiple intros are possible.
- *name*: name of the person to greet - *name*: name of the person to greet
#### Matrix Parameters**: #### Matrix Parameters:
**hello**: **hello**:
@ -47,7 +47,6 @@ You'll also note that multiple intros are possible.
#### GET Parameters: #### GET Parameters:
- capital - capital
@ -72,13 +71,24 @@ You'll also note that multiple intros are possible.
## DELETE /greet/:greetid ## DELETE /greet/:greetid
#### Title
This is some text
#### Second secton
And some more
#### Captures: #### Captures:
- *greetid*: identifier of the greet msg to remove - *greetid*: identifier of the greet msg to remove
- This endpoint is sensitive to the value of the **unicorns** HTTP header.
#### Response: #### Response:
- Status code 204 - Status code 200
- No response body - No response body

View file

@ -91,6 +91,11 @@
-- > , ("If you use ?capital=false", Greet "Hello, haskeller") -- > , ("If you use ?capital=false", Greet "Hello, haskeller")
-- > ] -- > ]
-- > -- >
-- > -- We define some introductory sections, these will appear at the top of the
-- > -- documentation.
-- > --
-- > -- We pass them in with 'docsWith', below. If you only want to add
-- > -- introductions, you may use 'docsWithIntros'
-- > intro1 :: DocIntro -- > intro1 :: DocIntro
-- > intro1 = DocIntro "On proper introductions." -- The title -- > intro1 = DocIntro "On proper introductions." -- The title
-- > [ "Hello there." -- > [ "Hello there."
@ -117,15 +122,26 @@
-- > testApi :: Proxy TestApi -- > testApi :: Proxy TestApi
-- > testApi = Proxy -- > testApi = Proxy
-- > -- >
-- > -- Build some extra information for the DELETE /greet/:greetid endpoint. We
-- > -- want to add documentation about a secret unicorn header and some extra
-- > -- notes.
-- > extra :: ExtraInfo TestApi
-- > extra =
-- > safeInfo (Proxy :: Proxy ("greet" :> Capture "greetid" Text :> Delete)) $
-- > defAction & headers <>~ ["unicorns"]
-- > & notes <>~ [ DocNote "Title" ["This is some text"]
-- > , DocNote "Second secton" ["And some more"]
-- > ]
-- >
-- > -- Generate the data that lets us have API docs. This -- > -- Generate the data that lets us have API docs. This
-- > -- is derived from the type as well as from -- > -- is derived from the type as well as from
-- > -- the 'ToCapture', 'ToParam' and 'ToSample' instances from above. -- > -- the 'ToCapture', 'ToParam' and 'ToSample' instances from above.
-- > -- -- > --
-- > -- If you didn't want intros you could just call: -- > -- If you didn't want intros and extra information, you could just call:
-- > -- -- > --
-- > -- > docs testAPI -- > -- > docs testAPI :: API
-- > docsGreet :: API -- > docsGreet :: API
-- > docsGreet = docsWithIntros [intro1, intro2] testApi -- > docsGreet = docsWith [intro1, intro2] extra testApi
-- > -- >
-- > main :: IO () -- > main :: IO ()
-- > main = putStrLn $ markdown docsGreet -- > main = putStrLn $ markdown docsGreet
@ -298,6 +314,17 @@ data DocNote = DocNote
, _noteBody :: [String] , _noteBody :: [String]
} deriving (Eq, Show) } deriving (Eq, Show)
-- | Type of extra information that a user may wish to "union" with their
-- documentation.
--
-- These are intended to be built using safeInfo.
-- Multiple ExtraInfo may be combined with the monoid instance.
newtype ExtraInfo layout = ExtraInfo (HashMap Endpoint Action)
instance Monoid (ExtraInfo a) where
mempty = ExtraInfo mempty
ExtraInfo a `mappend` ExtraInfo b =
ExtraInfo $ HM.unionWith combineAction a b
-- | Type of GET parameter: -- | Type of GET parameter:
-- --
-- - Normal corresponds to @QueryParam@, i.e your usual GET parameter -- - Normal corresponds to @QueryParam@, i.e your usual GET parameter
@ -405,13 +432,6 @@ makeLenses ''Action
docs :: HasDocs layout => Proxy layout -> API docs :: HasDocs layout => Proxy layout -> API
docs p = docsFor p (defEndpoint, defAction) docs p = docsFor p (defEndpoint, defAction)
newtype ExtraInfo layout = ExtraInfo (HashMap Endpoint Action)
instance Monoid (ExtraInfo a) where
mempty = ExtraInfo mempty
ExtraInfo a `mappend` ExtraInfo b =
ExtraInfo $ HM.unionWith combineAction a b
-- | Closed type family, check if endpoint is exactly within API. -- | Closed type family, check if endpoint is exactly within API.
-- We aren't sure what affects how an Endpoint is built up, so we require an -- We aren't sure what affects how an Endpoint is built up, so we require an
@ -421,6 +441,18 @@ type family IsIn (endpoint :: *) (api :: *) :: Constraint where
IsIn (e :> sa) (e :> sb) = IsIn sa sb IsIn (e :> sa) (e :> sb) = IsIn sa sb
IsIn e e = () IsIn e e = ()
-- | Create an 'ExtraInfo' that is garunteed to be within the given API layout.
--
-- The safety here is to ensure that you only add custom documentation to an
-- endpoint that actually exists within your API.
--
-- > extra :: ExtraInfo TestApi
-- > extra =
-- > safeInfo (Proxy :: Proxy ("greet" :> Capture "greetid" Text :> Delete)) $
-- > defAction & headers <>~ ["unicorns"]
-- > & notes <>~ [ DocNote "Title" ["This is some text"]
-- > , DocNote "Second secton" ["And some more"]
-- > ]
safeInfo :: (IsIn endpoint layout, HasLink endpoint, HasDocs endpoint) safeInfo :: (IsIn endpoint layout, HasLink endpoint, HasDocs endpoint)
=> Proxy endpoint -> Action -> ExtraInfo layout => Proxy endpoint -> Action -> ExtraInfo layout
@ -430,12 +462,18 @@ safeInfo p action =
-- point at one endpoint. -- point at one endpoint.
in ExtraInfo $ api ^. apiEndpoints & traversed .~ action in ExtraInfo $ api ^. apiEndpoints & traversed .~ action
-- | Generate documentation given some initial state, in which you may wish to -- | Generate documentation given some extra introductions (in the form of
-- note that certain endpoints are special in some way. -- 'DocInfo') and some extra endpoint documentation (in the form of
-- 'ExtraInfo'.
--
-- The extra introductions will be prepended to the top of the documentation,
-- before the specific endpoint documentation. The extra endpoint documentation
-- will be "unioned" with the automatically generated endpoint documentation.
--
-- You are expected to build up the ExtraInfo with the Monoid instance and
-- 'safeInfo'.
-- --
-- If you only want to add an introduction, use 'docsWithIntros'. -- If you only want to add an introduction, use 'docsWithIntros'.
--
-- You are expected to build up the SafeMap with safeEntry
docsWith :: HasDocs layout docsWith :: HasDocs layout
=> [DocIntro] => [DocIntro]
-> ExtraInfo layout -> ExtraInfo layout
@ -588,9 +626,7 @@ markdown api = unlines $
mxParamsStr l = mxParamsStr l =
"#### Matrix Parameters:" : "#### Matrix Parameters:" :
"" : "" :
map segmentStr l ++ map segmentStr l
"" :
[]
segmentStr :: (String, [DocQueryParam]) -> String segmentStr :: (String, [DocQueryParam]) -> String
segmentStr (segment, l) = unlines $ segmentStr (segment, l) = unlines $
("**" ++ segment ++ "**:") : ("**" ++ segment ++ "**:") :