@@ -91,6 +91,11 @@
91-- > , ("If you use ?capital=false", Greet "Hello, haskeller")
91-- > , ("If you use ?capital=false", Greet "Hello, haskeller")
94+-- > -- We define some introductory sections, these will appear at the top of the
95+-- > -- documentation.
97+-- > -- We pass them in with 'docsWith', below. If you only want to add
98+-- > -- introductions, you may use 'docsWithIntros'
94-- > intro1 :: DocIntro
99-- > intro1 :: DocIntro
95-- > intro1 = DocIntro "On proper introductions." -- The title
100-- > intro1 = DocIntro "On proper introductions." -- The title
96-- > [ "Hello there."
101-- > [ "Hello there."
@@ -117,15 +122,26 @@
117-- > testApi :: Proxy TestApi
122-- > testApi :: Proxy TestApi
118-- > testApi = Proxy
123-- > testApi = Proxy
125+-- > -- Build some extra information for the DELETE /greet/:greetid endpoint. We
126+-- > -- want to add documentation about a secret unicorn header and some extra
128+-- > extra :: ExtraInfo TestApi
130+-- > safeInfo (Proxy :: Proxy ("greet" :> Capture "greetid" Text :> Delete)) $
131+-- > defAction & headers <>~ ["unicorns"]
132+-- > & notes <>~ [ DocNote "Title" ["This is some text"]
133+-- > , DocNote "Second secton" ["And some more"]
120-- > -- Generate the data that lets us have API docs. This
136-- > -- Generate the data that lets us have API docs. This
121-- > -- is derived from the type as well as from
137-- > -- is derived from the type as well as from
122-- > -- the 'ToCapture', 'ToParam' and 'ToSample' instances from above.
138-- > -- the 'ToCapture', 'ToParam' and 'ToSample' instances from above.
124−-- > -- If you didn't want intros you could just call:
140+-- > -- If you didn't want intros and extra information, you could just call:
126−-- > -- > docs testAPI
142+-- > -- > docs testAPI :: API
127-- > docsGreet :: API
143-- > docsGreet :: API
128−-- > docsGreet = docsWithIntros [intro1, intro2] testApi
144+-- > docsGreet = docsWith [intro1, intro2] extra testApi
130-- > main :: IO ()
146-- > main :: IO ()
131-- > main = putStrLn $ markdown docsGreet
147-- > main = putStrLn $ markdown docsGreet
@@ -298,6 +314,17 @@ data DocNote = DocNote
298 , _noteBody :: [String]
314 , _noteBody :: [String]
299 } deriving (Eq, Show)
315 } deriving (Eq, Show)
317+-- | Type of extra information that a user may wish to "union" with their
320+-- These are intended to be built using safeInfo.
321+-- Multiple ExtraInfo may be combined with the monoid instance.
322+newtype ExtraInfo layout = ExtraInfo (HashMap Endpoint Action)
323+instance Monoid (ExtraInfo a) where
324+ mempty = ExtraInfo mempty
325+ ExtraInfo a `mappend` ExtraInfo b =
326+ ExtraInfo $ HM.unionWith combineAction a b
301-- | Type of GET parameter:
328-- | Type of GET parameter:
303-- - Normal corresponds to @QueryParam@, i.e your usual GET parameter
330-- - Normal corresponds to @QueryParam@, i.e your usual GET parameter
@@ -405,13 +432,6 @@ makeLenses ''Action
405docs :: HasDocs layout => Proxy layout -> API
432docs :: HasDocs layout => Proxy layout -> API
406docs p = docsFor p (defEndpoint, defAction)
433docs p = docsFor p (defEndpoint, defAction)
409−newtype ExtraInfo layout = ExtraInfo (HashMap Endpoint Action)
410−instance Monoid (ExtraInfo a) where
411− mempty = ExtraInfo mempty
412− ExtraInfo a `mappend` ExtraInfo b =
413− ExtraInfo $ HM.unionWith combineAction a b
415-- | Closed type family, check if endpoint is exactly within API.
435-- | Closed type family, check if endpoint is exactly within API.
417-- We aren't sure what affects how an Endpoint is built up, so we require an
437-- 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
421 IsIn (e :> sa) (e :> sb) = IsIn sa sb
441 IsIn (e :> sa) (e :> sb) = IsIn sa sb
422 IsIn e e = ()
442 IsIn e e = ()
444+-- | Create an 'ExtraInfo' that is garunteed to be within the given API layout.
446+-- The safety here is to ensure that you only add custom documentation to an
447+-- endpoint that actually exists within your API.
449+-- > extra :: ExtraInfo TestApi
451+-- > safeInfo (Proxy :: Proxy ("greet" :> Capture "greetid" Text :> Delete)) $
452+-- > defAction & headers <>~ ["unicorns"]
453+-- > & notes <>~ [ DocNote "Title" ["This is some text"]
454+-- > , DocNote "Second secton" ["And some more"]
425safeInfo :: (IsIn endpoint layout, HasLink endpoint, HasDocs endpoint)
457safeInfo :: (IsIn endpoint layout, HasLink endpoint, HasDocs endpoint)
426 => Proxy endpoint -> Action -> ExtraInfo layout
458 => Proxy endpoint -> Action -> ExtraInfo layout
@@ -430,12 +462,18 @@ safeInfo p action =
430 -- point at one endpoint.
462 -- point at one endpoint.
431 in ExtraInfo $ api ^. apiEndpoints & traversed .~ action
463 in ExtraInfo $ api ^. apiEndpoints & traversed .~ action
433−-- | Generate documentation given some initial state, in which you may wish to
465+-- | Generate documentation given some extra introductions (in the form of
434−-- note that certain endpoints are special in some way.
466+-- 'DocInfo') and some extra endpoint documentation (in the form of
436−-- If you only want to add an introduction, use 'docsWithIntros'.
469+-- The extra introductions will be prepended to the top of the documentation,
470+-- before the specific endpoint documentation. The extra endpoint documentation
471+-- will be "unioned" with the automatically generated endpoint documentation.
473+-- You are expected to build up the ExtraInfo with the Monoid instance and
438−-- You are expected to build up the SafeMap with safeEntry
476+-- If you only want to add an introduction, use 'docsWithIntros'.
439docsWith :: HasDocs layout
477docsWith :: HasDocs layout
440 => [DocIntro]
478 => [DocIntro]
441 -> ExtraInfo layout
479 -> ExtraInfo layout
@@ -485,7 +523,7 @@ class HasDocs layout where
485-- You can also instantiate this class using 'toSamples' instead of
523-- You can also instantiate this class using 'toSamples' instead of
486-- 'toSample': it lets you specify different responses along with
524-- 'toSample': it lets you specify different responses along with
487-- some context (as 'Text') that explains when you're supposed to
525-- some context (as 'Text') that explains when you're supposed to
488−-- get the corresponding response.
526+-- get the corresponding response.
489class ToJSON a => ToSample a where
527class ToJSON a => ToSample a where
490 {-# MINIMAL (toSample | toSamples) #-}
528 {-# MINIMAL (toSample | toSamples) #-}
491 toSample :: Maybe a
529 toSample :: Maybe a
@@ -588,9 +626,7 @@ markdown api = unlines $
588 mxParamsStr l =
626 mxParamsStr l =
589 "#### Matrix Parameters:" :
627 "#### Matrix Parameters:" :
591− map segmentStr l ++
629+ map segmentStr l
594 segmentStr :: (String, [DocQueryParam]) -> String
630 segmentStr :: (String, [DocQueryParam]) -> String
595 segmentStr (segment, l) = unlines $
631 segmentStr (segment, l) = unlines $
596 ("**" ++ segment ++ "**:") :
632 ("**" ++ segment ++ "**:") :