packages feed

apiary 0.12.7 → 0.12.8

raw patch · 8 files changed

+79/−49 lines, 8 filesdep +blaze-markupPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: blaze-markup

API changes (from Hackage documentation)

- Control.Monad.Apiary.Action: defaultHeader :: ApiaryConfig -> ResponseHeaders
+ Control.Monad.Apiary.Action: DefaultDocumentConfig :: Text -> Maybe Html -> DefaultDocumentConfig
+ Control.Monad.Apiary.Action: data DefaultDocumentConfig
+ Control.Monad.Apiary.Action: defaultHeaders :: ApiaryConfig -> ResponseHeaders
+ Control.Monad.Apiary.Action: documentDescription :: DefaultDocumentConfig -> Maybe Html
+ Control.Monad.Apiary.Action: documentTitle :: DefaultDocumentConfig -> Text
+ Control.Monad.Apiary.Action: failHeaders :: ApiaryConfig -> ResponseHeaders
+ Control.Monad.Apiary.Action: failStatus :: ApiaryConfig -> Status
+ Data.Apiary.Document: DefaultDocumentConfig :: Text -> Maybe Html -> DefaultDocumentConfig
+ Data.Apiary.Document: data DefaultDocumentConfig
+ Data.Apiary.Document: documentDescription :: DefaultDocumentConfig -> Maybe Html
+ Data.Apiary.Document: documentTitle :: DefaultDocumentConfig -> Text
+ Data.Apiary.Document: instance Default DefaultDocumentConfig
- Control.Monad.Apiary.Action: ApiaryConfig :: Application -> Status -> ResponseHeaders -> [ByteString] -> (FilePath -> ByteString) -> (Documents -> ActionT IO ()) -> ApiaryConfig
+ Control.Monad.Apiary.Action: ApiaryConfig :: Application -> Status -> ResponseHeaders -> Status -> ResponseHeaders -> [ByteString] -> (FilePath -> ByteString) -> Maybe (Documents -> ActionT IO ()) -> ApiaryConfig
- Control.Monad.Apiary.Action: defaultDocumentationAction :: Monad m => ByteString -> Text -> Maybe Html -> Documents -> ActionT m ()
+ Control.Monad.Apiary.Action: defaultDocumentationAction :: Monad m => ByteString -> DefaultDocumentConfig -> Documents -> ActionT m ()
- Control.Monad.Apiary.Action: documentationAction :: ApiaryConfig -> Documents -> ActionT IO ()
+ Control.Monad.Apiary.Action: documentationAction :: ApiaryConfig -> Maybe (Documents -> ActionT IO ())
- Data.Apiary.Document: defaultDocumentToHtml :: Text -> Maybe Html -> Documents -> Html
+ Data.Apiary.Document: defaultDocumentToHtml :: DefaultDocumentConfig -> Documents -> Html

Files

apiary.cabal view
@@ -1,5 +1,5 @@ name:                apiary-version:             0.12.7+version:             0.12.8 synopsis:            Simple and type safe web framework that can be automatically generate API documentation. description:   Simple and type safe web framework that can be automatically generate API documentation.@@ -35,9 +35,9 @@   .     * type safe route filter.   .-    * auto generate API documentation(example: <https://github.com/philopon/apiary/blob/v0.12.7/examples/api.hs>, <https://rawgit.com/philopon/apiary/v0.12.7/examples/api.html>).+    * auto generate API documentation(example: <https://github.com/philopon/apiary/blob/v0.12.8/examples/api.hs>, <https://rawgit.com/philopon/apiary/v0.12.8/examples/api.html>).   .-  more examples: <https://github.com/philopon/apiary/blob/v0.12.7/examples/>+  more examples: <https://github.com/philopon/apiary/blob/v0.12.8/examples/>  license:             MIT license-file:        LICENSE@@ -49,7 +49,9 @@ category:            Web build-type:          Simple stability:           experimental--- extra-source-files:  +extra-source-files:  static/api-documentation.min.js+                   , static/jquery.cookie-1.4.1.min.js+                   , static/api-documentation.min.css cabal-version:       >=1.10  flag wai3@@ -99,6 +101,7 @@                      , mime-types           >=0.1   && <0.2                      , exceptions           >=0.6   && <0.7                      , blaze-html           >=0.7   && <0.8+                     , blaze-markup         >=0.6   && <0.7    if impl(ghc < 7.8)     build-depends:     tagged               >=0.7   && <0.8
src/Control/Monad/Apiary/Action.hs view
@@ -4,6 +4,7 @@     ( ActionT     , ApiaryConfig(..)     , defaultDocumentationAction+    , DefaultDocumentConfig(..)     -- * actions     , stop, stopWith @@ -45,6 +46,7 @@ import Control.Monad.Apiary.Action.Internal import Data.Default.Class import Data.Apiary.Param+import Data.Apiary.Document import Network.HTTP.Types.Status hiding (mkStatus)  #ifdef WAI3
src/Control/Monad/Apiary/Action/Internal.hs view
@@ -30,10 +30,10 @@ import Data.Apiary.Document import Data.Default.Class import Blaze.ByteString.Builder-import Text.Blaze.Html import Text.Blaze.Html.Renderer.Utf8 import qualified Data.ByteString as S import qualified Data.ByteString.Lazy as L+import qualified Data.ByteString.Lazy.Char8 as LC import qualified Data.Text as T  #ifndef WAI3@@ -46,19 +46,21 @@       -- | used unless call 'status' function.     , defaultStatus       :: Status       -- | initial headers.-    , defaultHeader       :: ResponseHeaders+    , defaultHeaders      :: ResponseHeaders+    , failStatus          :: Status+    , failHeaders         :: ResponseHeaders       -- | used by 'Control.Monad.Apiary.Filter.root' filter.     , rootPattern         :: [S.ByteString]     , mimeType            :: FilePath -> S.ByteString-    , documentationAction :: Documents -> ActionT IO ()+    , documentationAction :: Maybe (Documents -> ActionT IO ())     } -defaultDocumentationAction :: Monad m => S.ByteString -> T.Text -> Maybe Html -> Documents -> ActionT m ()-defaultDocumentationAction r t md d = do+defaultDocumentationAction :: Monad m => S.ByteString -> DefaultDocumentConfig -> Documents -> ActionT m ()+defaultDocumentationAction r conf d = do     p <- rawPathInfo <$> getRequest     guard $ p == r     contentType "text/html"-    builder . renderHtmlBuilder $ defaultDocumentToHtml t md d+    builder . renderHtmlBuilder $ defaultDocumentToHtml conf d  defNotFound :: Application #ifdef WAI3@@ -71,10 +73,13 @@     def = ApiaryConfig          { notFound            = defNotFound         , defaultStatus       = ok200-        , defaultHeader       = []+        , defaultHeaders      = []+        , failStatus          = internalServerError500+        , failHeaders         = []         , rootPattern         = ["", "/", "/index.html", "/index.htm"]         , mimeType            = defaultMimeLookup . T.pack-        , documentationAction = defaultDocumentationAction "/api/documentation" "API documentation" Nothing+        , documentationAction = Just $ defaultDocumentationAction+            "/api/documentation" def         }  convFile :: (S.ByteString, P.FileInfo L.ByteString) -> File@@ -90,9 +95,9 @@  initialState :: ApiaryConfig -> Request -> ActionState initialState conf req = ActionState-    { actionResponse = responseLBS (defaultStatus conf) (defaultHeader conf) ""-    , actionStatus   = defaultStatus conf-    , actionHeaders  = defaultHeader conf+    { actionResponse = responseLBS (defaultStatus conf) (defaultHeaders conf) ""+    , actionStatus   = defaultStatus  conf+    , actionHeaders  = defaultHeaders conf     , actionReqBody  = Nothing     , actionPathInfo = pathInfo req     }@@ -130,7 +135,8 @@     m >>= k  = ActionT $ \conf req st cont ->         unActionT m conf req st $ \a st' ->         st' `seq` unActionT (k a) conf req st' cont-    fail _ = ActionT $ \_ _ _ _ -> return Pass+    fail s = ActionT $ \c _ _ _ -> return $+        Stop (responseLBS (failStatus c) (failHeaders c) $ LC.pack s)  instance MonadIO m => MonadIO (ActionT m) where     liftIO m = ActionT $ \_ _ st cont ->
src/Control/Monad/Apiary/Internal.hs view
@@ -108,7 +108,8 @@             -> ApiaryT '[] n m a -> m (Application, Documents) runApiaryT' run conf m = unApiaryT m (initialReader conf) (\_ w -> return w) >>= \wtr -> do     let doc = docsToDocuments $ writerDoc wtr-        app = execActionT conf $ hoistActionT run (writerHandler wtr) `mplus` documentationAction conf doc+        da  = maybe mzero (\f -> f doc) $ documentationAction conf+        app = execActionT conf $ hoistActionT run (writerHandler wtr) `mplus` da     return (app, doc)  runApiaryT :: (Monad n, Monad m) => (forall b. n b -> IO b) -> ApiaryConfig
src/Data/Apiary/Document.hs view
@@ -1,10 +1,12 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE TupleSections #-}-{-# LANGUAGE NoMonomorphismRestriction #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE RecordWildCards #-}  module Data.Apiary.Document where +import Language.Haskell.TH import Control.Applicative import qualified Data.Text as T import qualified Data.Text.Encoding as T@@ -14,9 +16,11 @@ import Data.Apiary.Param import qualified Network.HTTP.Types as HT import Text.Blaze.Html+import Text.Blaze.Internal(attribute) import qualified Text.Blaze.Html5 as H import qualified Text.Blaze.Html5.Attributes as A import Data.Monoid+import Data.Default.Class import Data.List import Data.Function @@ -113,7 +117,7 @@     loop _ r p End =         (r, if null p             then mempty-            else H.table ! A.class_ "table table-condensed" $+            else H.table ! A.class_ "table table-condensed route-parameters" $                  H.tr (mconcat                      [ H.th ! A.class_ "col-sm-1 com-md-1" $ "#"                     , H.th ! A.class_ "col-sm-1 com-md-1" $ "type"@@ -122,27 +126,29 @@         )  -defaultDocumentToHtml :: T.Text -> Maybe Html -> Documents -> Html-defaultDocumentToHtml title desc docs = H.docTypeHtml $ H.head headH <> H.body body <> footer+data DefaultDocumentConfig = DefaultDocumentConfig+    { documentTitle       :: T.Text+    , documentDescription :: Maybe Html+    }++instance Default DefaultDocumentConfig where+    def = DefaultDocumentConfig "API documentation" Nothing++defaultDocumentToHtml :: DefaultDocumentConfig -> Documents -> Html+defaultDocumentToHtml DefaultDocumentConfig{..} docs =+    H.docTypeHtml $ H.head headH <> H.body body <> footer   where     css u = H.link ! A.rel "stylesheet" ! A.href u+    js  u = H.script ! A.src u $ mempty+     headH = mconcat -        [ H.title (toHtml title)+        [ H.title (toHtml documentTitle)         , css "//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css"-        , H.style . toHtml $ T.concat-            [ ".fetch{color:gray}"-            , "footer{padding-top:40px;"-            ,        "padding-bottom:40px;"-            ,        "margin-top:20px;"-            ,        "text-align:center;"-            ,        "color:#777;"-            ,        "border-top:1px solid #ddd"-            ,       "}"-            , ".description{margin-bottom:20px}"-            , "table{margin-top:15px !important;margin-bottom:0px !important}"-            , ".method{margin-bottom:20px;padding-bottom:10px;border-bottom:1px solid #ddd}"-            , ".method:last-child{margin-bottom:0;padding-bottom:0;border-bottom:none}"-            ]+        , js  "//code.jquery.com/jquery-2.1.1.min.js"+        , js  "//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"+        , $(runIO (readFile "static/jquery.cookie-1.4.1.min.js") >>= \c -> [|H.script $ preEscapedToHtml (c::String)|])+        , $(runIO (readFile "static/api-documentation.min.js")   >>= \c -> [|H.script $ preEscapedToHtml (c::String)|])+        , $(runIO (readFile "static/api-documentation.min.css")     >>= \c -> [|H.style  $ preEscapedToHtml (c::String)|])         ]      htmlQR (Strict   r) = toHtml (show r)@@ -178,26 +184,34 @@         , queriesH qs         ] -    pathH (PathDoc r ms) =+    dataToggle = attribute "data-toggle" " data-toggle=\""+    dataTarget = attribute "data-target" " data-target=\""++    pathH i (PathDoc r ms) =         let (route, rdoc) = routeToHtml r-            in H.div ! A.class_ "panel panel-default" $ mconcat-            [ H.div ! A.class_ "panel-heading" $ mconcat-                [ H.h3 ! A.class_ "panel-title" $ route-                , rdoc+        in H.div ! A.class_ "panel panel-default" $ mconcat+            [ H.div ! A.class_ "panel-heading clearfix"+                ! dataToggle "collapse" ! dataTarget (toValue $ "#collapse-" ++ show (i::Int)) $ mconcat+                [ H.h3 ! A.class_ "panel-title pull-left" $ route+                , H.div ! A.class_ "methods" $+                    mcMap ((\m -> H.div ! A.class_ "pull-right" $ toHtml (T.decodeUtf8 m)) . fst) (reverse ms)                 ]-            , H.div ! A.class_ "panel-body" $ mcMap method ms+            , H.div ! A.id (toValue $ "collapse-" ++ show i) ! A.class_ "panel-collapse collapse" $+                rdoc <> (H.div ! A.class_ "panel-body" $ mcMap method ms)             ] -    groupH (g, p) = H.div $ mconcat [H.h2 $ toHtml g, mcMap pathH p]+    groupH i (g, p) =+        let (i', gs) = mapAccumL (\ii a -> (succ ii, pathH ii a)) i p+        in (i', H.div ! A.id (toValue $ T.append "group-" g) $ mconcat [H.h2 $ toHtml g, mconcat gs]) -    doc (Documents n g) = mconcat-        [ H.div $ mcMap pathH n-        , mcMap groupH g-        ]+    doc (Documents n g) =+        let (i, ng) = mapAccumL (\i' a -> (succ i', pathH  i' a)) (0::Int) n+            (_, gs) = mapAccumL groupH i g+        in (H.div ! A.id "no-group") (mconcat ng) <> mconcat gs      body  = H.div ! A.class_ "container" $ mconcat-        [ H.div ! A.class_ "page-header" $ H.h1 (toHtml title)-        , maybe mempty (H.div ! A.class_ "description") desc+        [ H.div ! A.class_ "page-header" $ H.h1 (toHtml documentTitle)+        , maybe mempty (H.div ! A.class_ "description") documentDescription         , doc docs         ] 
+ static/api-documentation.min.css view
@@ -0,0 +1,1 @@+.fetch{color:gray}footer{padding-top:30px;padding-bottom:50px;margin-top:20px;text-align:center;color:#777;border-top:1px solid #e5e5e5}.description{margin-bottom:20px}table{margin-top:15px !important;margin-bottom:0 !important}table.route-parameters{margin-top:0 !important;border-bottom:1px solid #ddd;background-color:#f5f5f5}.method{margin-bottom:20px;padding-bottom:10px;border-bottom:1px solid #ddd}.method:last-child{margin-bottom:0;padding-bottom:0;border-bottom:0}.methods div{margin-left:10px;color:#999}.panel-heading,h1{cursor:pointer}
+ static/api-documentation.min.js view
@@ -0,0 +1,1 @@+(function(){var unique=function(input){var u={},a=[];for(var i=0,l=input.length;i<l;++i){if(u.hasOwnProperty(input[i]))continue;a.push(input[i]);u[input[i]]=1}return a};var remove=function(input,v){var a=[];for(var i=0;i<input.length;i++){if(input[i]!=v)a.push(input[i])}return a};$.cookie.json=true;$.cookie.defaults.expires=365;$(function(){var current=$.cookie("open")||[];$(".collapse").on("show.bs.collapse",function(e){var cur=parseInt(e.target.id.slice(9));current.push(cur);current=unique(current);current.sort();$.cookie("open",current)}).on("hide.bs.collapse",function(e){var cur=parseInt(e.target.id.slice(9));current=remove(current,cur);$.cookie("open",current)});$("h1").click(function(){if(current.length==0){$(".collapse").each(function(i,e){$(e).collapse("show");var cur=parseInt(e.id.slice(9));current.push(cur)}).promise().done(function(){current=unique(current);current.sort();$.cookie("open",current)})}else{$(".collapse").each(function(i,e){$(e).collapse("hide")});current=[];$.cookie("open",[])}});for(var i=0;i<current.length;i++){$("#collapse-"+current[i]).addClass("in")}})})();
+ static/jquery.cookie-1.4.1.min.js view
@@ -0,0 +1,2 @@+/*! jquery.cookie v1.4.1 | MIT */+!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports?require("jquery"):jQuery)}(function(a){function b(a){return h.raw?a:encodeURIComponent(a)}function c(a){return h.raw?a:decodeURIComponent(a)}function d(a){return b(h.json?JSON.stringify(a):String(a))}function e(a){0===a.indexOf('"')&&(a=a.slice(1,-1).replace(/\\"/g,'"').replace(/\\\\/g,"\\"));try{return a=decodeURIComponent(a.replace(g," ")),h.json?JSON.parse(a):a}catch(b){}}function f(b,c){var d=h.raw?b:e(b);return a.isFunction(c)?c(d):d}var g=/\+/g,h=a.cookie=function(e,g,i){if(arguments.length>1&&!a.isFunction(g)){if(i=a.extend({},h.defaults,i),"number"==typeof i.expires){var j=i.expires,k=i.expires=new Date;k.setTime(+k+864e5*j)}return document.cookie=[b(e),"=",d(g),i.expires?"; expires="+i.expires.toUTCString():"",i.path?"; path="+i.path:"",i.domain?"; domain="+i.domain:"",i.secure?"; secure":""].join("")}for(var l=e?void 0:{},m=document.cookie?document.cookie.split("; "):[],n=0,o=m.length;o>n;n++){var p=m[n].split("="),q=c(p.shift()),r=p.join("=");if(e&&e===q){l=f(r,g);break}e||void 0===(r=f(r))||(l[q]=r)}return l};h.defaults={},a.removeCookie=function(b,c){return void 0===a.cookie(b)?!1:(a.cookie(b,"",a.extend({},c,{expires:-1})),!a.cookie(b))}});