packages feed

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 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])))+