packages feed

servius (empty) → 0.0.0

raw patch · 4 files changed

+171/−0 lines, 4 filesdep +basedep +blaze-builderdep +blaze-htmlsetup-changed

Dependencies added: base, blaze-builder, blaze-html, bytestring, cmdargs, containers, directory, hamlet, http-types, shakespeare-css, text, transformers, wai, wai-app-static, wai-extra, warp

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c)2011, Michael Snoyman++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Michael Snoyman nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.lhs view
@@ -0,0 +1,7 @@+#!/usr/bin/env runhaskell++> module Main where+> import Distribution.Simple++> main :: IO ()+> main = defaultMain
+ servius.cabal view
@@ -0,0 +1,32 @@+Name:                servius+Version:             0.0.0+Synopsis:            Serve Shakespearean templates via Warp+Homepage:            http://github.com/yesodweb/hamlet+License:             BSD3+License-file:        LICENSE+Author:              Michael Snoyman+Maintainer:          michael@snoyman.com+Category:            Web+Build-type:          Simple+Cabal-version:       >=1.2+Description:         Does not support any variable interpolation. Supports Hamlet and Lucius files (must have .hamlet and .lucius file extensions, respectively).+++Executable servius+  Main-is:       servius.hs+  Build-depends: base            >= 4                  && < 5+               , warp            >= 0.4                && < 0.5+               , wai-app-static  >= 0.3                && < 0.4+               , wai-extra       >= 0.4                && < 0.5+               , cmdargs         >= 0.6.7+               , directory       >= 1.0+               , containers      >= 0.2                && < 0.5+               , bytestring      >= 0.9.1.4+               , text            >= 0.7+               , blaze-builder+               , blaze-html+               , http-types+               , hamlet+               , shakespeare-css+               , transformers+               , wai
+ servius.hs view
@@ -0,0 +1,102 @@+{-# LANGUAGE DeriveDataTypeable, RecordWildCards #-}+{-# LANGUAGE OverloadedStrings #-}+import Network.Wai.Application.Static+    ( StaticSettings (..), staticApp, defaultMimeType, defaultListing+    , defaultMimeTypes, mimeTypeByExt+    , defaultFileServerSettings, fileSystemLookup+    , fileName, toFilePath+    )+import Network.Wai.Handler.Warp (run)+import System.Console.CmdArgs+import Text.Printf (printf)+import System.Directory (canonicalizePath)+import Control.Monad (unless)+import Network.Wai.Middleware.Autohead+import Network.Wai.Middleware.Debug+import Network.Wai.Middleware.Gzip+import qualified Data.Map as Map+import qualified Data.ByteString.Char8 as S8+import Control.Arrow ((***))+import Data.Text (Text, pack)+import qualified Data.Text as T+import Network.Wai+import Data.ByteString (ByteString)+import Control.Monad.IO.Class (liftIO)+import Data.Text.Encoding (decodeUtf8With)+import Data.Text.Encoding.Error (lenientDecode)+import Text.Lucius (luciusRT)+import Text.Hamlet (defaultHamletSettings)+import Text.Hamlet.RT (parseHamletRT, renderHamletRT)+import Network.HTTP.Types (status200)+import Text.Blaze.Renderer.Utf8 (renderHtmlBuilder)+import qualified Data.Text.Lazy as TL+import Blaze.ByteString.Builder.Char.Utf8 (fromLazyText)++data Args = Args+    { docroot :: FilePath+    , index :: [FilePath]+    , port :: Int+    , noindex :: Bool+    , quiet :: Bool+    , verbose :: Bool+    , mime :: [(String, String)]+    }+    deriving (Show, Data, Typeable)++defaultArgs :: Args+defaultArgs = Args "." ["index.html", "index.htm"] 3000 False False False []++main :: IO ()+main = do+    Args {..} <- cmdArgs defaultArgs+    let mime' = map (toFilePath *** S8.pack) mime+    let mimeMap = Map.fromList mime' `Map.union` defaultMimeTypes+    docroot' <- canonicalizePath docroot+    unless quiet $ printf "Serving directory %s on port %d with %s index files.\n" docroot' port (if noindex then "no" else show index)+    let middle = gzip False+               . (if verbose then debug else id)+               . autohead+               . shake docroot+    run port $ middle $ staticApp defaultFileServerSettings+        { ssFolder = fileSystemLookup $ toFilePath docroot+        , ssIndices = if noindex then [] else map pack index+        , ssListing = Just defaultListing+        , ssGetMimeType = return . mimeTypeByExt mimeMap defaultMimeType . fileName+        }++shake :: FilePath -> Middleware+shake docroot app req+    | any unsafe p = app req+    | null p = app req+    | ".hamlet" `T.isSuffixOf` l = liftIO $ hamlet pr+    | ".lucius" `T.isSuffixOf` l = liftIO $ lucius pr+    | otherwise = app req+  where+    p = pathInfo req+    pr = T.intercalate "/" $ T.pack docroot : p+    l = last p++unsafe :: Text -> Bool+unsafe s+    | T.null s = False+    | T.head s == '.' = True+    | otherwise = T.any (== '/') s++readFileUtf8 :: Text -> IO String+readFileUtf8 fp = do+    bs <- S8.readFile $ T.unpack fp+    let t = decodeUtf8With lenientDecode bs+    return $ T.unpack t++hamlet :: Text -> IO Response+hamlet fp = do+    str <- readFileUtf8 fp+    hrt <- parseHamletRT defaultHamletSettings str+    html <- renderHamletRT hrt [] (error "No URLs allowed")+    return $ ResponseBuilder status200 [("Content-Type", "text/html; charset=utf-8")] $ renderHtmlBuilder html++lucius :: Text -> IO Response+lucius fp = do+    str <- readFileUtf8 fp+    let text = either error id $ luciusRT (TL.pack str) []+    return $ ResponseBuilder status200 [("Content-Type", "text/css; charset=utf-8")] $ fromLazyText text