servant-pandoc (empty) → 0.1
raw patch · 4 files changed
+238/−0 lines, 4 filesdep +basedep +bytestringdep +pandoc-typessetup-changed
Dependencies added: base, bytestring, pandoc-types, servant-docs, text, unordered-containers
Files
- LICENSE +20/−0
- Setup.hs +2/−0
- servant-pandoc.cabal +68/−0
- src/Servant/Docs/Pandoc.hs +148/−0
+ LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2015 Matthew Pickering++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be included+in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ servant-pandoc.cabal view
@@ -0,0 +1,68 @@+-- Initial servant-pandoc.cabal generated by cabal init. For further+-- documentation, see http://haskell.org/cabal/users-guide/++-- The name of the package.+name: servant-pandoc++-- The package version. See the Haskell package versioning policy (PVP)+-- for standards guiding when and how versions should be incremented.+-- http://www.haskell.org/haskellwiki/Package_versioning_policy+-- PVP summary: +-+------- breaking API changes+-- | | +----- non-breaking API additions+-- | | | +--- code changes with no API change+version: 0.1++-- A short (one-line) description of the package.+synopsis: Use Pandoc to render servant API documentation++-- A longer description of the package.+-- description:++-- The license under which the package is released.+license: MIT++-- The file containing the license text.+license-file: LICENSE++-- The package author(s).+author: Matthew Pickering++-- An email address to which users can send suggestions, bug reports, and+-- patches.+maintainer: matthewtpickering@gmail.com++-- A copyright notice.+-- copyright:++category: Web++build-type: Simple++-- Extra files to be distributed with the package, such as examples or a+-- README.+-- extra-source-files:++-- Constraint on the version of Cabal needed to build this package.+cabal-version: >=1.10+++library+ -- Modules exported by the library.+ exposed-modules: Servant.Docs.Pandoc++ -- Modules included in this library but not exported.+ -- other-modules:++ -- LANGUAGE extensions used by modules in this package.+ other-extensions: OverloadedStrings++ -- Other library packages from which modules are imported.+ build-depends: base >=4.7 && <4.8, pandoc-types >=1.12 && <1.13, servant-docs >=0.3 && <0.4, unordered-containers >=0.2 && <0.3, text >=1.2 && <1.3, bytestring >=0.10 && <0.11++ -- Directories containing source files.+ hs-source-dirs: src++ -- Base language which the package is written in.+ default-language: Haskell2010+ ghc-options: -Wall+
+ src/Servant/Docs/Pandoc.hs view
@@ -0,0 +1,148 @@+{-# LANGUAGE OverloadedStrings #-}+----------------------------------+-- | There are two ways in which to use this module.+--+-- The first is to use the renderer directly with the pandoc API.+-- A very simple+-- program to render the API documentation as a mediawiki document might look as+-- follows.+--+-- > import Text.Pandoc+-- > import Sevant.Docs.Pandoc+-- > import Data.Default (def)+-- >+-- > myApi :: Proxy MyAPI+-- > myApi = Proxy+-- >+-- > writeDocs :: API -> IO ()+-- > writeDocs api = writeMediaWiki def (pandoc api) >>= writeFile "api.mw"+--+-- The second approach is to use `makeFilter` to make a filter which can be+-- used directly with pandoc from the command line. This filter will just+-- append the API documentation to the end of the document.+-- Example usage+--+-- > -- api.hs+-- > main :: IO ()+-- > main = makeFilter (docs myApi)+--+-- >> pandoc -o api.pdf --filter=api.hs manual.md+module Servant.Docs.Pandoc (pandoc, makeFilter) where++import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Builder (Blocks, Inlines)+import Text.Pandoc.Definition (Pandoc)+import Text.Pandoc.JSON (toJSONFilter)+import Servant.Docs+import qualified Data.HashMap.Strict as HM+import Data.Text (Text, unpack)+import Data.List (intercalate)+import Data.ByteString.Lazy (ByteString)+import qualified Data.ByteString.Lazy.Char8 as B (unpack)+++-- | Helper function which can be used to make a pandoc filter which+-- appends the generate docs to the end of the document.+--+-- This function is exposed for convenience. More experienced authors can+-- of course define a more complicated filter to inject the API+-- documentation.+makeFilter :: API -> IO ()+makeFilter api = toJSONFilter inject+ where+ inject :: Pandoc -> Pandoc+ inject p = p <> pandoc api+++-- | Generate a `Pandoc` representation of a given+-- `API`.+pandoc :: API -> Pandoc+pandoc = B.doc . mconcat . map (uncurry printEndpoint) . HM.toList++ where printEndpoint :: Endpoint -> Action -> Blocks+ printEndpoint endpoint action =+ B.header 1 str <>+ capturesStr (action ^. captures) <>+ headersStr (action ^. headers) <>+ paramsStr (action ^. params) <>+ rqbodyStr (action ^. rqbody) <>+ responseStr (action ^. response)++ where str :: Inlines+ str = B.str (show (endpoint^.method)) <> B.space <> B.code (intercalate "/" (endpoint ^. path))++ capturesStr :: [DocCapture] -> Blocks+ capturesStr [] = mempty+ capturesStr l =+ B.header 2 "Captures" <>+ B.bulletList (map captureStr l)+ captureStr cap =+ B.plain $ B.emph (B.doubleQuoted . B.str$ (cap ^. capSymbol)) <> ":" <> B.space <> B.str (cap ^. capDesc)++ headersStr :: [Text] -> Blocks+ headersStr [] = mempty+ headersStr l = B.bulletList (map (B.para . headerStr) l)++ where headerStr hname = "This endpoint is sensitive to the value of the" <> B.space <>+ (B.strong . B.str $ unpack hname) <> B.space <> "HTTP header."++ paramsStr :: [DocQueryParam] -> Blocks+ paramsStr [] = mempty+ paramsStr l =+ B.header 2 "GET Parameters" <>+ B.bulletList (map paramStr l)++ paramStr param =+ B.plain (B.str (param ^. paramName)) <>+ B.definitionList (+ [(B.strong "Values",+ [B.plain (B.emph+ (foldr (\a b -> B.str a <> B.str "," <> B.space <> b) mempty values))])+ | not (null values) || param ^. paramKind /= Flag]+ +++ [(B.strong "Description",+ [B.plain $ B.str (param ^. paramDesc)])])+ <>+ B.bulletList (+ [B.plain $ "This parameter is a" <>+ B.space <>+ B.strong "list" <>+ ". All GET parameters with the name" <>+ B.space <>+ B.str (param ^. paramName) <>+ B.space <>+ B.code "[]" <> B.space <>+ "will forward their values in a list to the handler."+ | param ^. paramKind == List]+ +++ [B.plain $ "This parameter is a" <>+ B.space <>+ B.strong "flag." <>+ B.space <>+ "This means no value is expected to be associated to this parameter."+ | param ^. paramKind == Flag]+ )+++ where values = param ^. paramValues++ rqbodyStr :: Maybe ByteString -> Blocks+ rqbodyStr Nothing = mempty+ rqbodyStr (Just b) =+ B.header 2 "Request Body" <>+ jsonStr b++ jsonStr :: ByteString -> Blocks+ jsonStr b =+ B.codeBlockWith ("",["javascript"],[]) (B.unpack b)++ responseStr :: Response -> Blocks+ responseStr resp =+ B.header 2 "Response" <>+ B.bulletList (+ [B.plain $ "Status code" <> B.space <> (B.str . show) (resp ^. respStatus)]+ +++ (resp ^. respBody &+ maybe [B.plain "No response body"]+ (\b -> [B.plain "Response body as below." <> jsonStr b])))+