diff --git a/static/docs/0.1.1/heist/Text-Templating-Heist-Splices-Apply.html b/static/docs/0.1.1/heist/Text-Templating-Heist-Splices-Apply.html deleted file mode 100644 index f794d47..0000000 --- a/static/docs/0.1.1/heist/Text-Templating-Heist-Splices-Apply.html +++ /dev/null @@ -1,225 +0,0 @@ - - -Text.Templating.Heist.Splices.Apply
 heist-0.1.1: An xhtml templating systemSource codeContentsIndex
Text.Templating.Heist.Splices.Apply
Synopsis
applyTag :: ByteString
applyAttr :: ByteString
applyImpl :: Monad m => Splice m
Documentation
applyTag :: ByteStringSource
Default name for the apply splice. -
applyAttr :: ByteStringSource
Default attribute name for the apply tag. -
applyImpl :: Monad m => Splice mSource
Implementation of the apply splice. -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.1/heist/Text-Templating-Heist-Splices-Bind.html b/static/docs/0.1.1/heist/Text-Templating-Heist-Splices-Bind.html deleted file mode 100644 index 888055c..0000000 --- a/static/docs/0.1.1/heist/Text-Templating-Heist-Splices-Bind.html +++ /dev/null @@ -1,225 +0,0 @@ - - -Text.Templating.Heist.Splices.Bind
 heist-0.1.1: An xhtml templating systemSource codeContentsIndex
Text.Templating.Heist.Splices.Bind
Synopsis
bindTag :: ByteString
bindAttr :: ByteString
bindImpl :: Monad m => Splice m
Documentation
bindTag :: ByteStringSource
Default name for the bind splice. -
bindAttr :: ByteStringSource
Default attribute name for the bind tag. -
bindImpl :: Monad m => Splice mSource
Implementation of the bind splice. -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.1/heist/Text-Templating-Heist-Splices-Ignore.html b/static/docs/0.1.1/heist/Text-Templating-Heist-Splices-Ignore.html deleted file mode 100644 index 4adaff9..0000000 --- a/static/docs/0.1.1/heist/Text-Templating-Heist-Splices-Ignore.html +++ /dev/null @@ -1,183 +0,0 @@ - - -Text.Templating.Heist.Splices.Ignore
 heist-0.1.1: An xhtml templating systemSource codeContentsIndex
Text.Templating.Heist.Splices.Ignore
Synopsis
ignoreTag :: ByteString
ignoreImpl :: Monad m => Splice m
Documentation
ignoreTag :: ByteStringSource
Default name for the ignore splice. -
ignoreImpl :: Monad m => Splice mSource
The ignore tag and everything it surrounds disappears in the - rendered output. -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.1/heist/Text-Templating-Heist-Splices-Markdown.html b/static/docs/0.1.1/heist/Text-Templating-Heist-Splices-Markdown.html deleted file mode 100644 index 60e5f65..0000000 --- a/static/docs/0.1.1/heist/Text-Templating-Heist-Splices-Markdown.html +++ /dev/null @@ -1,592 +0,0 @@ - - -Text.Templating.Heist.Splices.Markdown
 heist-0.1.1: An xhtml templating systemSource codeContentsIndex
Text.Templating.Heist.Splices.Markdown
Synopsis
data PandocMissingException = PandocMissingException
data MarkdownException = MarkdownException ByteString
markdownTag :: ByteString
markdownSplice :: MonadIO m => Splice m
pandoc :: FilePath -> FilePath -> IO ByteString
pandocBS :: FilePath -> ByteString -> IO ByteString
readProcessWithExitCode' :: FilePath -> [String] -> ByteString -> IO (ExitCode, ByteString, ByteString)
Documentation
data PandocMissingException Source
Constructors
PandocMissingException
show/hide Instances
data MarkdownException Source
Constructors
MarkdownException ByteString
show/hide Instances
markdownTag :: ByteStringSource
Default name for the markdown splice. -
markdownSplice :: MonadIO m => Splice mSource
Implementation of the markdown splice. -
pandoc :: FilePath -> FilePath -> IO ByteStringSource
pandocBS :: FilePath -> ByteString -> IO ByteStringSource
readProcessWithExitCode'Source
:: FilePathcommand to run -
-> [String]any arguments -
-> ByteStringstandard input -
-> IO (ExitCode, ByteString, ByteString)exitcode, stdout, stderr -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.1/heist/Text-Templating-Heist-Splices-Static.html b/static/docs/0.1.1/heist/Text-Templating-Heist-Splices-Static.html deleted file mode 100644 index d53c06a..0000000 --- a/static/docs/0.1.1/heist/Text-Templating-Heist-Splices-Static.html +++ /dev/null @@ -1,253 +0,0 @@ - - -Text.Templating.Heist.Splices.Static
 heist-0.1.1: An xhtml templating systemSource codeContentsIndex
Text.Templating.Heist.Splices.Static
Synopsis
data StaticTagState
bindStaticTag :: MonadIO m => TemplateState m -> IO (TemplateState m, StaticTagState)
clearStaticTagCache :: StaticTagState -> IO ()
Documentation
data StaticTagState Source
State for storing static tag information -
bindStaticTag :: MonadIO m => TemplateState m -> IO (TemplateState m, StaticTagState)Source
Modifies a TemplateState to include a static tag. -
clearStaticTagCache :: StaticTagState -> IO ()Source
Clears the static tag state. -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.1/heist/Text-Templating-Heist-Splices.html b/static/docs/0.1.1/heist/Text-Templating-Heist-Splices.html deleted file mode 100644 index 33180ea..0000000 --- a/static/docs/0.1.1/heist/Text-Templating-Heist-Splices.html +++ /dev/null @@ -1,132 +0,0 @@ - - -Text.Templating.Heist.Splices
 heist-0.1.1: An xhtml templating systemSource codeContentsIndex
Text.Templating.Heist.Splices
Documentation
module Text.Templating.Heist.Splices.Apply
module Text.Templating.Heist.Splices.Bind
module Text.Templating.Heist.Splices.Ignore
module Text.Templating.Heist.Splices.Markdown
module Text.Templating.Heist.Splices.Static
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.1/heist/Text-Templating-Heist.html b/static/docs/0.1.1/heist/Text-Templating-Heist.html deleted file mode 100644 index 90b1afc..0000000 --- a/static/docs/0.1.1/heist/Text-Templating-Heist.html +++ /dev/null @@ -1,2303 +0,0 @@ - - -Text.Templating.Heist
 heist-0.1.1: An xhtml templating systemSource codeContentsIndex
Text.Templating.Heist
Contents
Types -
Functions and declarations on TemplateState values -
Hook functions -
TemplateMonad functions -
Functions for running splices and templates -
Misc functions -
Description

This module contains the core definitions for the Heist template system. -

The Heist template system is based on XML/xhtml. It allows you to build - custom XML-based markup languages. With Heist you can define your own - domain-specific XML tags implemented with Haskell and use them in your - templates. -

The most important concept in Heist is the Splice. Splices can be thought - of as functions that transform a node into a list of nodes. Heist then - substitutes the resulting list of nodes into your template in place of the - input node. Splice is implemented as a type synonym type Splice m = - TemplateMonad m [Node], and TemplateMonad has a function getParamNode - that lets you get the input node. -

Suppose you have a place on your page where you want to display a link with - the text "Logout username" if the user is currently logged in or a link to - the login page if no user is logged in. Assume you have a function - getUser :: MyAppMonad (Maybe ByteString) that gets the current user. - You can implement this functionality with a Splice as follows: -

- import Text.XML.Expat.Tree
-
- link :: ByteString -> ByteString -> Node
- link target text = X.Element "a" [("href", target)] [X.Text text]
- 
- loginLink :: Node
- loginLink = link "/login" "Login"
- 
- logoutLink :: ByteString -> Node
- logoutLink user = link "/logout" (B.append "Logout " user)
- 
- loginLogoutSplice :: Splice MyAppMonad
- loginLogoutSplice = do
-     user <- lift getUser
-     return $ [maybe loginLink logoutLink user]
-
-

Next, you need to bind that splice to an XML tag. Heist stores information - about splices and templates in the TemplateState data structure. The - following code demonstrates how this splice would be used. -

 mySplices = [ ("loginLogout", loginLogoutSplice) ]
- 
- main = do
-     ets <- loadTemplates "templates" $
-            foldr (uncurry bindSplice) emptyTemplateState mySplices
-     let ts = either error id ets
-     t <- runMyAppMonad $ renderTemplate ts "index"
-     print $ maybe "Page not found" id t
-

Here we build up our TemplateState by starting with emptyTemplateState and - applying bindSplice for all the splices we want to add. Then we pass this - to loadTemplates our final TemplateState wrapped in an Either to handle - errors. Then we use this TemplateState to render our templates. -

Synopsis
type Node = Node ByteString ByteString
type Splice m = TemplateMonad m Template
type Template = [Node]
data TemplateMonad m a
data TemplateState m
addTemplate :: Monad m => ByteString -> Template -> TemplateState m -> TemplateState m
emptyTemplateState :: MonadIO m => TemplateState m
bindSplice :: Monad m => ByteString -> Splice m -> TemplateState m -> TemplateState m
lookupSplice :: Monad m => ByteString -> TemplateState m -> Maybe (Splice m)
setTemplates :: Monad m => TemplateMap -> TemplateState m -> TemplateState m
loadTemplates :: Monad m => FilePath -> TemplateState m -> IO (Either String (TemplateState m))
addOnLoadHook :: Monad m => (Template -> IO Template) -> TemplateState m -> TemplateState m
addPreRunHook :: Monad m => (Template -> m Template) -> TemplateState m -> TemplateState m
addPostRunHook :: Monad m => (Template -> m Template) -> TemplateState m -> TemplateState m
stopRecursion :: Monad m => TemplateMonad m ()
getParamNode :: Monad m => TemplateMonad m Node
runNodeList :: Monad m => [Node] -> Splice m
getContext :: Monad m => TemplateMonad m TPath
runTemplate :: Monad m => TemplateState m -> ByteString -> m (Maybe [Node])
evalTemplate :: Monad m => ByteString -> TemplateMonad m (Maybe [Node])
callTemplate :: Monad m => ByteString -> [(ByteString, ByteString)] -> TemplateMonad m (Maybe Template)
renderTemplate :: Monad m => TemplateState m -> ByteString -> m (Maybe ByteString)
bindStrings :: Monad m => [(ByteString, ByteString)] -> TemplateState m -> TemplateState m
runSplice :: Monad m => TemplateState m -> Node -> Splice m -> m [Node]
runRawTemplate :: Monad m => TemplateState m -> Template -> m [Node]
getDoc :: String -> IO (Either String Template)
bindStaticTag :: MonadIO m => TemplateState m -> IO (TemplateState m, StaticTagState)
heistExpatOptions :: ParserOptions ByteString ByteString
htmlEntityLookupTable :: Map ByteString ByteString
Types -
type Node = Node ByteString ByteStringSource
Heist templates are XML documents. The hexpat library is polymorphic over - the type of strings, so here we define a Node alias to fix the string - types of the tag names and tag bodies to ByteString. -
type Splice m = TemplateMonad m TemplateSource
A Splice is a TemplateMonad computation that returns [Node]. -
type Template = [Node]Source
A Template is a forest of XML nodes. -
data TemplateMonad m a Source
TemplateMonad is a monad transformer that gives you access to the Node - being processed (using the MonadReader instance) as well as holding the - TemplateState that contains splice and template mappings (accessible - using the MonadState instance. -
show/hide Instances
data TemplateState m Source

Holds all the state information needed for template processing: -

  • a collection of named templates. If you use the <apply - template="foo"> tag to include another template by name, "foo" - is looked up in here. -
  • the mapping from tag names to Splices. -
  • a flag to control whether we will recurse during splice processing. -

We'll illustrate the recursion flag with a small example template: -

 <foo>
-   <bar>
-     ...
-   </bar>
- </foo>
-

Assume that "foo" is bound to a splice procedure. Running the foo - splice will result in a list of nodes L; if the recursion flag is on we - will recursively scan L for splices, otherwise L will be included in the - output verbatim. -

show/hide Instances
Functions and declarations on TemplateState values -
addTemplate :: Monad m => ByteString -> Template -> TemplateState m -> TemplateState mSource
Adds a template to the template state. -
emptyTemplateState :: MonadIO m => TemplateState mSource
An empty template state, with Heist's default splices (<bind> and - <apply>) mapped. -
bindSpliceSource
:: Monad m
=> ByteStringtag name -
-> Splice msplice action -
-> TemplateState msource state -
-> TemplateState m
Bind a new splice declaration to a tag name within a TemplateState. -
lookupSplice :: Monad m => ByteString -> TemplateState m -> Maybe (Splice m)Source
Convenience function for looking up a splice. -
setTemplates :: Monad m => TemplateMap -> TemplateState m -> TemplateState mSource
Sets the templateMap in a TemplateState. -
loadTemplates :: Monad m => FilePath -> TemplateState m -> IO (Either String (TemplateState m))Source
Traverses the specified directory structure and builds a - TemplateState by loading all the files with a .tpl extension. -
Hook functions -

Heist hooks allow you to modify templates when they are loaded and before - and after they are run. Every time you call one of the addAbcHook - functions the hook is added to onto the processing pipeline. The hooks - processes the template in the order that they were added to the - TemplateState. -

The pre-run and post-run hooks are run before and after every template is - run/rendered. You should be careful what code you put in these hooks - because it can significantly affect the performance of your site. -

addOnLoadHook :: Monad m => (Template -> IO Template) -> TemplateState m -> TemplateState mSource
Adds an on-load hook to a TemplateState. -
addPreRunHook :: Monad m => (Template -> m Template) -> TemplateState m -> TemplateState mSource
Adds a pre-run hook to a TemplateState. -
addPostRunHook :: Monad m => (Template -> m Template) -> TemplateState m -> TemplateState mSource
Adds a post-run hook to a TemplateState. -
TemplateMonad functions -
stopRecursion :: Monad m => TemplateMonad m ()Source
Stops the recursive processing of splices. -
getParamNode :: Monad m => TemplateMonad m NodeSource
Gets the node currently being processed. -
runNodeList :: Monad m => [Node] -> Splice mSource
Performs splice processing on a list of nodes. -
getContext :: Monad m => TemplateMonad m TPathSource
Gets the current context -
Functions for running splices and templates -
runTemplate :: Monad m => TemplateState m -> ByteString -> m (Maybe [Node])Source
Looks up a template name in the supplied TemplateState and runs - it in the underlying monad. -
evalTemplate :: Monad m => ByteString -> TemplateMonad m (Maybe [Node])Source
Looks up a template name evaluates it. Same as runTemplate except it - runs in TemplateMonad instead of m. -
callTemplateSource
:: Monad m
=> ByteStringThe name of the template -
-> [(ByteString, ByteString)]Association list of - (name,value) parameter pairs -
-> TemplateMonad m (Maybe Template)
Renders a template with the specified parameters. This is the function - to use when you want to call a template and pass in parameters from code. -
renderTemplate :: Monad m => TemplateState m -> ByteString -> m (Maybe ByteString)Source
Renders a template from the specified TemplateState. -
bindStrings :: Monad m => [(ByteString, ByteString)] -> TemplateState m -> TemplateState mSource
Binds a list of constant string splices -
Misc functions -
runSpliceSource
:: Monad m
=> TemplateState mThe initial template state -
-> NodeThe splice's input node -
-> Splice mThe splice -
-> m [Node]
Runs a splice in the underlying monad. Splices require two - parameters, the template state, and an input node. -
runRawTemplate :: Monad m => TemplateState m -> Template -> m [Node]Source
Runs a template in the underlying monad. Similar to runSplice - except that templates don't require a Node as a parameter. -
getDoc :: String -> IO (Either String Template)Source
Reads an XML document from disk. -
bindStaticTag :: MonadIO m => TemplateState m -> IO (TemplateState m, StaticTagState)Source
Modifies a TemplateState to include a static tag. -
heistExpatOptions :: ParserOptions ByteString ByteStringSource
htmlEntityLookupTable :: Map ByteString ByteStringSource
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.1/heist/doc-index.html b/static/docs/0.1.1/heist/doc-index.html deleted file mode 100644 index 2253f89..0000000 --- a/static/docs/0.1.1/heist/doc-index.html +++ /dev/null @@ -1,438 +0,0 @@ - - -heist-0.1.1: An xhtml templating system (Index)
 heist-0.1.1: An xhtml templating systemContentsIndex
addOnLoadHook
addPostRunHook
addPreRunHook
addTemplate
applyAttr
applyImpl
applyTag
bindAttr
bindImpl
bindSplice
bindStaticTag
bindStrings
bindTag
callTemplate
clearStaticTagCache
emptyTemplateState
evalTemplate
getContext
getDoc
getParamNode
heistExpatOptions
htmlEntityLookupTable
ignoreImpl
ignoreTag
loadTemplates
lookupSplice
MarkdownException
1 (Type/Class)
2 (Data Constructor)
markdownSplice
markdownTag
Node
pandoc
pandocBS
PandocMissingException
1 (Type/Class)
2 (Data Constructor)
readProcessWithExitCode'
renderTemplate
runNodeList
runRawTemplate
runSplice
runTemplate
setTemplates
Splice
StaticTagState
stopRecursion
Template
TemplateMonad
TemplateState
diff --git a/static/docs/0.1.1/heist/fonts/DroidSerif-Bold.eot b/static/docs/0.1.1/heist/fonts/DroidSerif-Bold.eot deleted file mode 100644 index 01b9e1f..0000000 Binary files a/static/docs/0.1.1/heist/fonts/DroidSerif-Bold.eot and /dev/null differ diff --git a/static/docs/0.1.1/heist/fonts/DroidSerif-Bold.svg b/static/docs/0.1.1/heist/fonts/DroidSerif-Bold.svg deleted file mode 100644 index 1f7f2d2..0000000 --- a/static/docs/0.1.1/heist/fonts/DroidSerif-Bold.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.1.1/heist/fonts/DroidSerif-Bold.ttf b/static/docs/0.1.1/heist/fonts/DroidSerif-Bold.ttf deleted file mode 100644 index da0ea11..0000000 Binary files a/static/docs/0.1.1/heist/fonts/DroidSerif-Bold.ttf and /dev/null differ diff --git a/static/docs/0.1.1/heist/fonts/DroidSerif-Bold.woff b/static/docs/0.1.1/heist/fonts/DroidSerif-Bold.woff deleted file mode 100644 index 91549cd..0000000 Binary files a/static/docs/0.1.1/heist/fonts/DroidSerif-Bold.woff and /dev/null differ diff --git a/static/docs/0.1.1/heist/fonts/DroidSerif-BoldItalic.eot b/static/docs/0.1.1/heist/fonts/DroidSerif-BoldItalic.eot deleted file mode 100644 index 47dd0a0..0000000 Binary files a/static/docs/0.1.1/heist/fonts/DroidSerif-BoldItalic.eot and /dev/null differ diff --git a/static/docs/0.1.1/heist/fonts/DroidSerif-BoldItalic.svg b/static/docs/0.1.1/heist/fonts/DroidSerif-BoldItalic.svg deleted file mode 100644 index 1a57dbb..0000000 --- a/static/docs/0.1.1/heist/fonts/DroidSerif-BoldItalic.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.1.1/heist/fonts/DroidSerif-BoldItalic.ttf b/static/docs/0.1.1/heist/fonts/DroidSerif-BoldItalic.ttf deleted file mode 100644 index 8be3fb4..0000000 Binary files a/static/docs/0.1.1/heist/fonts/DroidSerif-BoldItalic.ttf and /dev/null differ diff --git a/static/docs/0.1.1/heist/fonts/DroidSerif-BoldItalic.woff b/static/docs/0.1.1/heist/fonts/DroidSerif-BoldItalic.woff deleted file mode 100644 index 6d5fa3d..0000000 Binary files a/static/docs/0.1.1/heist/fonts/DroidSerif-BoldItalic.woff and /dev/null differ diff --git a/static/docs/0.1.1/heist/fonts/DroidSerif-Italic.eot b/static/docs/0.1.1/heist/fonts/DroidSerif-Italic.eot deleted file mode 100644 index 2d4850c..0000000 Binary files a/static/docs/0.1.1/heist/fonts/DroidSerif-Italic.eot and /dev/null differ diff --git a/static/docs/0.1.1/heist/fonts/DroidSerif-Italic.svg b/static/docs/0.1.1/heist/fonts/DroidSerif-Italic.svg deleted file mode 100644 index 356c374..0000000 --- a/static/docs/0.1.1/heist/fonts/DroidSerif-Italic.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.1.1/heist/fonts/DroidSerif-Italic.ttf b/static/docs/0.1.1/heist/fonts/DroidSerif-Italic.ttf deleted file mode 100644 index 3719dc2..0000000 Binary files a/static/docs/0.1.1/heist/fonts/DroidSerif-Italic.ttf and /dev/null differ diff --git a/static/docs/0.1.1/heist/fonts/DroidSerif-Italic.woff b/static/docs/0.1.1/heist/fonts/DroidSerif-Italic.woff deleted file mode 100644 index b64436f..0000000 Binary files a/static/docs/0.1.1/heist/fonts/DroidSerif-Italic.woff and /dev/null differ diff --git a/static/docs/0.1.1/heist/fonts/DroidSerif-Regular.eot b/static/docs/0.1.1/heist/fonts/DroidSerif-Regular.eot deleted file mode 100644 index 0d17523..0000000 Binary files a/static/docs/0.1.1/heist/fonts/DroidSerif-Regular.eot and /dev/null differ diff --git a/static/docs/0.1.1/heist/fonts/DroidSerif-Regular.svg b/static/docs/0.1.1/heist/fonts/DroidSerif-Regular.svg deleted file mode 100644 index b9b65fb..0000000 --- a/static/docs/0.1.1/heist/fonts/DroidSerif-Regular.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.1.1/heist/fonts/DroidSerif-Regular.ttf b/static/docs/0.1.1/heist/fonts/DroidSerif-Regular.ttf deleted file mode 100644 index 066dcaa..0000000 Binary files a/static/docs/0.1.1/heist/fonts/DroidSerif-Regular.ttf and /dev/null differ diff --git a/static/docs/0.1.1/heist/fonts/DroidSerif-Regular.woff b/static/docs/0.1.1/heist/fonts/DroidSerif-Regular.woff deleted file mode 100644 index cfd3d67..0000000 Binary files a/static/docs/0.1.1/heist/fonts/DroidSerif-Regular.woff and /dev/null differ diff --git a/static/docs/0.1.1/heist/frames.html b/static/docs/0.1.1/heist/frames.html deleted file mode 100644 index 9e904fc..0000000 --- a/static/docs/0.1.1/heist/frames.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/static/docs/0.1.1/heist/haddock-util.js b/static/docs/0.1.1/heist/haddock-util.js deleted file mode 100644 index 364081f..0000000 --- a/static/docs/0.1.1/heist/haddock-util.js +++ /dev/null @@ -1,139 +0,0 @@ -// Haddock JavaScript utilities -function toggle(button,id) -{ - var n = document.getElementById(id).style; - if (n.display == "none") - { - button.src = "minus.gif"; - n.display = "block"; - } - else - { - button.src = "plus.gif"; - n.display = "none"; - } -} - - -var max_results = 75; // 50 is not enough to search for map in the base libraries -var shown_range = null; -var last_search = null; - -function quick_search() -{ - perform_search(false); -} - -function full_search() -{ - perform_search(true); -} - - -function perform_search(full) -{ - var text = document.getElementById("searchbox").value.toLowerCase(); - if (text == last_search && !full) return; - last_search = text; - - var table = document.getElementById("indexlist"); - var status = document.getElementById("searchmsg"); - var children = table.firstChild.childNodes; - - // first figure out the first node with the prefix - var first = bisect(-1); - var last = (first == -1 ? -1 : bisect(1)); - - if (first == -1) - { - table.className = ""; - status.innerHTML = "No results found, displaying all"; - } - else if (first == 0 && last == children.length - 1) - { - table.className = ""; - status.innerHTML = ""; - } - else if (last - first >= max_results && !full) - { - table.className = ""; - status.innerHTML = "More than " + max_results + ", press Search to display"; - } - else - { - // decide what you need to clear/show - if (shown_range) - setclass(shown_range[0], shown_range[1], "indexrow"); - setclass(first, last, "indexshow"); - shown_range = [first, last]; - table.className = "indexsearch"; - status.innerHTML = ""; - } - - - function setclass(first, last, status) - { - for (var i = first; i <= last; i++) - { - children[i].className = status; - } - } - - - // do a binary search, treating 0 as ... - // return either -1 (no 0's found) or location of most far match - function bisect(dir) - { - var first = 0, finish = children.length - 1; - var mid, success = false; - - while (finish - first > 3) - { - mid = Math.floor((finish + first) / 2); - - var i = checkitem(mid); - if (i == 0) i = dir; - if (i == -1) - finish = mid; - else - first = mid; - } - var a = (dir == 1 ? first : finish); - var b = (dir == 1 ? finish : first); - for (var i = b; i != a - dir; i -= dir) - { - if (checkitem(i) == 0) return i; - } - return -1; - } - - - // from an index, decide what the result is - // 0 = match, -1 is lower, 1 is higher - function checkitem(i) - { - var s = getitem(i).toLowerCase().substr(0, text.length); - if (s == text) return 0; - else return (s > text ? -1 : 1); - } - - - // from an index, get its string - // this abstracts over alternates - function getitem(i) - { - for ( ; i >= 0; i--) - { - var s = children[i].firstChild.firstChild.data; - if (s.indexOf(' ') == -1) - return s; - } - return ""; // should never be reached - } -} - -function setSynopsis(filename) { - if (parent.window.synopsis) { - parent.window.synopsis.location = filename; - } -} diff --git a/static/docs/0.1.1/heist/haddock.css b/static/docs/0.1.1/heist/haddock.css deleted file mode 100644 index bbe9dac..0000000 --- a/static/docs/0.1.1/heist/haddock.css +++ /dev/null @@ -1,478 +0,0 @@ -/* -------- Global things --------- */ - -@font-face { - font-family: 'DroidSerif'; - src: url('fonts/DroidSerif-Regular.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Regular.woff') format('woff'), - url('fonts/DroidSerif-Regular.ttf') format('truetype'), - url('fonts/DroidSerif-Regular.svg#DroidSerif') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - font-style: italic; - src: url('fonts/DroidSerif-Italic.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Italic.woff') format('woff'), - url('fonts/DroidSerif-Italic.ttf') format('truetype'), - url('fonts/DroidSerif-Italic.svg#DroidSerif-Italic') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - font-weight: bold; - src: url('fonts/DroidSerif-Bold.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Bold.woff') format('woff'), - url('fonts/DroidSerif-Bold.ttf') format('truetype'), - url('fonts/DroidSerif-Bold.svg#DroidSerif-Bold') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - src: url('fonts/DroidSerif-BoldItalic.eot'); - font-weight: bold; - font-style: italic; - src: local('Droid Serif'), - url('fonts/DroidSerif-BoldItalic.woff') format('woff'), - url('fonts/DroidSerif-BoldItalic.ttf') format('truetype'), - url('fonts/DroidSerif-BoldItalic.svg#DroidSerif-BoldItalic') format('svg'); -} - - - -HTML { - background-color: #f0f3ff; - width: 100%; -} - -BODY { - -moz-border-radius:5px; - -webkit-border-radius:5px; - width: 90ex; - margin: 2em auto; - padding: 0; - background-color: #ffffff; - color: #000000; - font-size: 110%; - font-family: DroidSerif, Georgia, serif; - } - -A:link { color: #5200A3; text-decoration: none } -A:visited { color: #5200A3; text-decoration: none } -A:hover { color: #5200A3; text-decoration: none; border-bottom:#5200A3 dashed 1px; } - -TABLE.vanilla { - width: 100%; - border-width: 0px; - /* I can't seem to specify cellspacing or cellpadding properly using CSS... */ -} - -DL { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - letter-spacing: -0.01em; - margin: 0; -} - -.vanilla .vanilla dl { font-size: 80%; } -.vanilla .vanilla dl dl { padding-left: 0; font-size: 95%; } - -TD.section1, TD.section2, TD.section3, TD.section4, TD.doc, DL { - padding: 0 30px 0 34px; -} - -TABLE.vanilla2 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - border-width: 0px; -} - -/* font is a little too small in MSIE */ -TT, PRE, CODE { - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - font-size: 90%; -} - -LI P { margin: 0pt } - -P { margin-top: 0; margin-bottom: 0.75em; } - -TD { - border-width: 0px; -} - -TABLE.narrow { - border-width: 0px; -} - -TD.s8 { height: 0; margin:0; padding: 0 } -TD.s15 { height: 20px; } - -SPAN.keyword { text-decoration: underline; } - -/* Resize the buttom image to match the text size */ -IMG.coll { width : 0.75em; height: 0.75em; margin-bottom: 0; margin-right: 0.5em } - -/* --------- Contents page ---------- */ - -DIV.node { - padding-left: 3em; -} - -DIV.cnode { - padding-left: 1.75em; -} - -SPAN.pkg { - position: absolute; - left: 50em; -} - -/* --------- Documentation elements ---------- */ - -TD FONT { font-weight: bold; letter-spacing: -0.02em; } - -TD.children { - padding-left: 25px; - } - -TD.synopsis { - padding: 2px; - background-color: #f0f0f0; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - } - -TD.decl { - padding: 4px 8px; - background-color: #FAFAFA; - border-bottom: #F2F2F2 solid 1px; - border-top: #FCFCFC solid 1px; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - vertical-align: top; - } - -TD.decl TD.decl { - font-size: 100%; - padding: 4px 0; - border: 0; -} - -TD.topdecl { - padding: 20px 30px 0.5ex 30px; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; -; - vertical-align: top; -} - -.vanilla .vanilla .vanilla .topdecl { - padding-left: 0; - padding-right: 0; -} - -.vanilla .vanilla .vanilla { - padding-left: 30px; -} - -.decl .vanilla { - padding-left: 0px !important; -} - -.body .vanilla .body { - padding-left: 0; - padding-right: 0; -} - -.body .vanilla .body .decl { - padding-left: 12px; -} - -.body .vanilla .body div .vanilla .decl { - padding-left: 12px; -} - -TABLE.declbar { - background-color: #f0f0f0; - border-spacing: 0px; - border-bottom:1px solid #d7d7df; - border-right:1px solid #d7d7df; - border-top:1px solid #f4f4f9; - border-left:1px solid #f4f4f9; - padding: 4px; - } - -TD.declname { - width: 100%; - padding-right: 4px; - } - -TD.declbut { - padding-left: 8px; - padding-right: 5px; - border-left-width: 1px; - border-left-color: #000099; - border-left-style: solid; - white-space: nowrap; - font-size: x-small; - } - -/* - arg is just like decl, except that wrapping is not allowed. It is - used for function and constructor arguments which have a text box - to the right, where if wrapping is allowed the text box squashes up - the declaration by wrapping it. -*/ -TD.arg { - padding: 2px 12px; - background-color: #f0f0f0; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - vertical-align: top; - white-space: nowrap; - } - -TD.recfield { padding-left: 20px } - -TD.doc { - padding-left: 38px; - font-size: 95%; - line-height: 1.66; - } - -TD.ndoc { - font-size: 95%; - line-height: 1.66; - padding: 2px 4px 2px 8px; - } - -TD.rdoc { - padding: 2px; - padding-left: 30px; - width: 100%; - font-size: 80%; - font-style: italic; - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - } - -TD.body { - padding: 0 30px; - } - -TD.pkg { - width: 100%; - padding-left: 30px -} - -TABLE.indexsearch TR.indexrow { - display: none; -} -TABLE.indexsearch TR.indexshow { - display: table-row; -} - -TD.indexentry { - vertical-align: top; - padding: 0 30px - } - -TD.indexannot { - vertical-align: top; - padding-left: 20px; - white-space: nowrap - } - -TD.indexlinks { - width: 100% - } - -/* ------- Section Headings ------- */ - -TD.section1, TD.section2, TD.section3, TD.section4, TD.section5 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; -} - -TD.section1 { - padding-top: 14px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 140% - } - -TD.section2 { - padding-top: 4px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 120% - } - -TD.section3 { - padding-top: 5px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 105% - } - -TD.section4 { - font-weight: bold; - padding-top: 12px; - padding-bottom: 4px; - letter-spacing: -0.02em; - font-size: 90% - } - -/* -------------- The title bar at the top of the page */ - -TD.infohead { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - font-weight: bold; - padding: 0 30px; - text-align: left; -} - -TD.infoval { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - padding: 0 30px; - text-align: left; -} - -TD.topbar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - background-color: #3465a4; - padding: 5px; - -moz-border-radius-topleft:5px; - -moz-border-radius-topright:5px; - -webkit-border-radius-topleft:5px; - -webkit-border-radius-topright:5px; -} - -TD.title { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - padding-left: 30px; - letter-spacing: -0.02em; - font-weight: bold; - width: 100% - } - -TD.topbut { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - padding-left: 5px; - padding-right: 5px; - border-left-width: 1px; - border-left-color: #ffffff; - border-left-style: solid; - letter-spacing: -0.02em; - font-weight: bold; - white-space: nowrap; - } - -TD.topbut A:link { - color: #ffffff - } - -TD.topbut A:visited { - color: #ffff00 - } - -TD.topbut A:hover { - background-color: #C9D3DE; - } - -TD.topbut:hover { - background-color: #C9D3DE; - } - -TD.modulebar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #141B24; - background-color: #C9D3DE; - padding: 5px; - border-top-width: 1px; - border-top-color: #ffffff; - border-top-style: solid; - -moz-border-radius-bottomleft:5px; - -moz-border-radius-bottomright:5px; - -webkit-border-radius-bottomleft:5px; - -webkit-border-radius-bottomright:5px; - - } - -/* --------- The page footer --------- */ - -TD.botbar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - -moz-border-radius:5px; - -webkit-border-radius:5px; - background-color: #3465a4; - color: #ffffff; - padding: 5px - } -TD.botbar A:link { - color: #ffffff; - text-decoration: underline - } -TD.botbar A:visited { - color: #ffff00 - } -TD.botbar A:hover { - background-color: #6060ff - } - -/* --------- Mini Synopsis for Frame View --------- */ - -.outer { - margin: 0 0; - padding: 0 0; -} - -.mini-synopsis { - padding: 0.25em 0.25em; -} - -.mini-synopsis H1 { font-size: 120%; } -.mini-synopsis H2 { font-size: 107%; } -.mini-synopsis H3 { font-size: 100%; } -.mini-synopsis H1, .mini-synopsis H2, .mini-synopsis H3 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - margin-top: 0.5em; - margin-bottom: 0.25em; - padding: 0 0; - font-weight: bold; letter-spacing: -0.02em; -} - -.mini-synopsis H1 { border-bottom: 1px solid #ccc; } - -.mini-topbar { - font-size: 120%; - background: #0077dd; - padding: 0.25em; -} - - diff --git a/static/docs/0.1.1/heist/haskell_icon.gif b/static/docs/0.1.1/heist/haskell_icon.gif deleted file mode 100644 index cb2a815..0000000 Binary files a/static/docs/0.1.1/heist/haskell_icon.gif and /dev/null differ diff --git a/static/docs/0.1.1/heist/heist.haddock b/static/docs/0.1.1/heist/heist.haddock deleted file mode 100644 index 30d6ef2..0000000 Binary files a/static/docs/0.1.1/heist/heist.haddock and /dev/null differ diff --git a/static/docs/0.1.1/heist/index-frames.html b/static/docs/0.1.1/heist/index-frames.html deleted file mode 100644 index a285836..0000000 --- a/static/docs/0.1.1/heist/index-frames.html +++ /dev/null @@ -1,40 +0,0 @@ - - -heist-0.1.1: An xhtml templating system

Text.Templating.Heist
Text.Templating.Heist.Splices
Text.Templating.Heist.Splices.Apply
Text.Templating.Heist.Splices.Bind
Text.Templating.Heist.Splices.Ignore
Text.Templating.Heist.Splices.Markdown
Text.Templating.Heist.Splices.Static

diff --git a/static/docs/0.1.1/heist/index.html b/static/docs/0.1.1/heist/index.html deleted file mode 100644 index f58c200..0000000 --- a/static/docs/0.1.1/heist/index.html +++ /dev/null @@ -1,181 +0,0 @@ - - -heist-0.1.1: An xhtml templating system
 heist-0.1.1: An xhtml templating systemContentsIndex
heist-0.1.1: An xhtml templating system
An xhtml templating system -
Modules
show/hideText
show/hideTemplating
show/hideText.Templating.Heist
show/hideText.Templating.Heist.Splices
Text.Templating.Heist.Splices.Apply
Text.Templating.Heist.Splices.Bind
Text.Templating.Heist.Splices.Ignore
Text.Templating.Heist.Splices.Markdown
Text.Templating.Heist.Splices.Static
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.1/heist/mini_Text-Templating-Heist-Splices-Apply.html b/static/docs/0.1.1/heist/mini_Text-Templating-Heist-Splices-Apply.html deleted file mode 100644 index b3a2987..0000000 --- a/static/docs/0.1.1/heist/mini_Text-Templating-Heist-Splices-Apply.html +++ /dev/null @@ -1,33 +0,0 @@ - - -Text.Templating.Heist.Splices.Apply
Text.Templating.Heist.Splices.Apply
diff --git a/static/docs/0.1.1/heist/mini_Text-Templating-Heist-Splices-Bind.html b/static/docs/0.1.1/heist/mini_Text-Templating-Heist-Splices-Bind.html deleted file mode 100644 index 347bf97..0000000 --- a/static/docs/0.1.1/heist/mini_Text-Templating-Heist-Splices-Bind.html +++ /dev/null @@ -1,33 +0,0 @@ - - -Text.Templating.Heist.Splices.Bind
Text.Templating.Heist.Splices.Bind
diff --git a/static/docs/0.1.1/heist/mini_Text-Templating-Heist-Splices-Ignore.html b/static/docs/0.1.1/heist/mini_Text-Templating-Heist-Splices-Ignore.html deleted file mode 100644 index cf11fd3..0000000 --- a/static/docs/0.1.1/heist/mini_Text-Templating-Heist-Splices-Ignore.html +++ /dev/null @@ -1,29 +0,0 @@ - - -Text.Templating.Heist.Splices.Ignore
Text.Templating.Heist.Splices.Ignore
diff --git a/static/docs/0.1.1/heist/mini_Text-Templating-Heist-Splices-Markdown.html b/static/docs/0.1.1/heist/mini_Text-Templating-Heist-Splices-Markdown.html deleted file mode 100644 index 70738c6..0000000 --- a/static/docs/0.1.1/heist/mini_Text-Templating-Heist-Splices-Markdown.html +++ /dev/null @@ -1,53 +0,0 @@ - - -Text.Templating.Heist.Splices.Markdown
Text.Templating.Heist.Splices.Markdown
diff --git a/static/docs/0.1.1/heist/mini_Text-Templating-Heist-Splices-Static.html b/static/docs/0.1.1/heist/mini_Text-Templating-Heist-Splices-Static.html deleted file mode 100644 index 482ea55..0000000 --- a/static/docs/0.1.1/heist/mini_Text-Templating-Heist-Splices-Static.html +++ /dev/null @@ -1,35 +0,0 @@ - - -Text.Templating.Heist.Splices.Static
Text.Templating.Heist.Splices.Static
diff --git a/static/docs/0.1.1/heist/mini_Text-Templating-Heist-Splices.html b/static/docs/0.1.1/heist/mini_Text-Templating-Heist-Splices.html deleted file mode 100644 index f3e9a96..0000000 --- a/static/docs/0.1.1/heist/mini_Text-Templating-Heist-Splices.html +++ /dev/null @@ -1,21 +0,0 @@ - - -Text.Templating.Heist.Splices
Text.Templating.Heist.Splices
diff --git a/static/docs/0.1.1/heist/mini_Text-Templating-Heist.html b/static/docs/0.1.1/heist/mini_Text-Templating-Heist.html deleted file mode 100644 index d0342ea..0000000 --- a/static/docs/0.1.1/heist/mini_Text-Templating-Heist.html +++ /dev/null @@ -1,165 +0,0 @@ - - -Text.Templating.Heist
Text.Templating.Heist

Types -

type Node
type Splice m
type Template
data TemplateMonad m a

Functions and declarations on TemplateState values -

Hook functions -

TemplateMonad functions -

Functions for running splices and templates -

Misc functions -

diff --git a/static/docs/0.1.1/heist/minus.gif b/static/docs/0.1.1/heist/minus.gif deleted file mode 100644 index 1deac2f..0000000 Binary files a/static/docs/0.1.1/heist/minus.gif and /dev/null differ diff --git a/static/docs/0.1.1/heist/plus.gif b/static/docs/0.1.1/heist/plus.gif deleted file mode 100644 index 2d15c14..0000000 Binary files a/static/docs/0.1.1/heist/plus.gif and /dev/null differ diff --git a/static/docs/0.1.1/heist/src/Text-Templating-Heist-Constants.html b/static/docs/0.1.1/heist/src/Text-Templating-Heist-Constants.html deleted file mode 100644 index 1f8683a..0000000 --- a/static/docs/0.1.1/heist/src/Text-Templating-Heist-Constants.html +++ /dev/null @@ -1,265 +0,0 @@ - - - - -src/Text/Templating/Heist/Constants.hs - - - -
{-# LANGUAGE OverloadedStrings #-}
-module Text.Templating.Heist.Constants where
-
-import           Data.ByteString.Char8 (ByteString)
-import qualified Data.Map as Map
-import           Data.Map (Map)
-
-htmlEntityLookupTable :: Map ByteString ByteString
-htmlEntityLookupTable = Map.fromList [
-                         ("acute"      , "\xc2\xb4")
-                       , ("cedil"      , "\xc2\xb8")
-                       , ("circ"       , "\xcb\x86")
-                       , ("macr"       , "\xc2\xaf")
-                       , ("middot"     , "\xc2\xb7")
-                       , ("tilde"      , "\xcb\x9c")
-                       , ("uml"        , "\xc2\xa8")
-                       , ("Aacute"     , "\xc3\x81")
-                       , ("aacute"     , "\xc3\xa1")
-                       , ("Acirc"      , "\xc3\x82")
-                       , ("acirc"      , "\xc3\xa2")
-                       , ("AElig"      , "\xc3\x86")
-                       , ("aelig"      , "\xc3\xa6")
-                       , ("Agrave"     , "\xc3\x80")
-                       , ("agrave"     , "\xc3\xa0")
-                       , ("Aring"      , "\xc3\x85")
-                       , ("aring"      , "\xc3\xa5")
-                       , ("Atilde"     , "\xc3\x83")
-                       , ("atilde"     , "\xc3\xa3")
-                       , ("Auml"       , "\xc3\x84")
-                       , ("auml"       , "\xc3\xa4")
-                       , ("Ccedil"     , "\xc3\x87")
-                       , ("ccedil"     , "\xc3\xa7")
-                       , ("Eacute"     , "\xc3\x89")
-                       , ("eacute"     , "\xc3\xa9")
-                       , ("Ecirc"      , "\xc3\x8a")
-                       , ("ecirc"      , "\xc3\xaa")
-                       , ("Egrave"     , "\xc3\x88")
-                       , ("egrave"     , "\xc3\xa8")
-                       , ("ETH"        , "\xc3\x90")
-                       , ("eth"        , "\xc3\xb0")
-                       , ("Euml"       , "\xc3\x8b")
-                       , ("euml"       , "\xc3\xab")
-                       , ("Iacute"     , "\xc3\x8d")
-                       , ("iacute"     , "\xc3\xad")
-                       , ("Icirc"      , "\xc3\x8e")
-                       , ("icirc"      , "\xc3\xae")
-                       , ("Igrave"     , "\xc3\x8c")
-                       , ("igrave"     , "\xc3\xac")
-                       , ("Iuml"       , "\xc3\x8f")
-                       , ("iuml"       , "\xc3\xaf")
-                       , ("Ntilde"     , "\xc3\x91")
-                       , ("ntilde"     , "\xc3\xb1")
-                       , ("Oacute"     , "\xc3\x93")
-                       , ("oacute"     , "\xc3\xb3")
-                       , ("Ocirc"      , "\xc3\x94")
-                       , ("ocirc"      , "\xc3\xb4")
-                       , ("OElig"      , "\xc5\x92")
-                       , ("oelig"      , "\xc5\x93")
-                       , ("Ograve"     , "\xc3\x92")
-                       , ("ograve"     , "\xc3\xb2")
-                       , ("Oslash"     , "\xc3\x98")
-                       , ("oslash"     , "\xc3\xb8")
-                       , ("Otilde"     , "\xc3\x95")
-                       , ("otilde"     , "\xc3\xb5")
-                       , ("Ouml"       , "\xc3\x96")
-                       , ("ouml"       , "\xc3\xb6")
-                       , ("Scaron"     , "\xc5\xa0")
-                       , ("scaron"     , "\xc5\xa1")
-                       , ("szlig"      , "\xc3\x9f")
-                       , ("THORN"      , "\xc3\x9e")
-                       , ("thorn"      , "\xc3\xbe")
-                       , ("Uacute"     , "\xc3\x9a")
-                       , ("uacute"     , "\xc3\xba")
-                       , ("Ucirc"      , "\xc3\x9b")
-                       , ("ucirc"      , "\xc3\xbb")
-                       , ("Ugrave"     , "\xc3\x99")
-                       , ("ugrave"     , "\xc3\xb9")
-                       , ("Uuml"       , "\xc3\x9c")
-                       , ("uuml"       , "\xc3\xbc")
-                       , ("Yacute"     , "\xc3\x9d")
-                       , ("yacute"     , "\xc3\xbd")
-                       , ("yuml"       , "\xc3\xbf")
-                       , ("Yuml"       , "\xc5\xb8")
-                       , ("cent"       , "\xc2\xa2")
-                       , ("curren"     , "\xc2\xa4")
-                       , ("euro"       , "\xe2\x82\xac")
-                       , ("pound"      , "\xc2\xa3")
-                       , ("yen"        , "\xc2\xa5")
-                       , ("brvbar"     , "\xc2\xa6")
-                       , ("bull"       , "\xe2\x80\xa2")
-                       , ("copy"       , "\xc2\xa9")
-                       , ("dagger"     , "\xe2\x80\xa0")
-                       , ("Dagger"     , "\xe2\x80\xa1")
-                       , ("frasl"      , "\xe2\x81\x84")
-                       , ("hellip"     , "\xe2\x80\xa6")
-                       , ("iexcl"      , "\xc2\xa1")
-                       , ("image"      , "\xe2\x84\x91")
-                       , ("iquest"     , "\xc2\xbf")
-                       , ("mdash"      , "\xe2\x80\x94")
-                       , ("ndash"      , "\xe2\x80\x93")
-                       , ("not"        , "\xc2\xac")
-                       , ("oline"      , "\xe2\x80\xbe")
-                       , ("ordf"       , "\xc2\xaa")
-                       , ("ordm"       , "\xc2\xba")
-                       , ("para"       , "\xc2\xb6")
-                       , ("permil"     , "\xe2\x80\xb0")
-                       , ("prime"      , "\xe2\x80\xb2")
-                       , ("Prime"      , "\xe2\x80\xb3")
-                       , ("real"       , "\xe2\x84\x9c")
-                       , ("reg"        , "\xc2\xae")
-                       , ("sect"       , "\xc2\xa7")
-                       , ("shy"        , "\173")
-                       , ("sup1"       , "\xc2\xb9")
-                       , ("trade"      , "\xe2\x84\xa2")
-                       , ("weierp"     , "\xe2\x84\x98")
-                       , ("bdquo"      , "\xe2\x80\x9e")
-                       , ("laquo"      , "\xc2\xab")
-                       , ("ldquo"      , "\xe2\x80\x9c")
-                       , ("lsaquo"     , "\xe2\x80\xb9")
-                       , ("lsquo"      , "\xe2\x80\x98")
-                       , ("raquo"      , "\xc2\xbb")
-                       , ("rdquo"      , "\xe2\x80\x9d")
-                       , ("rsaquo"     , "\xe2\x80\xba")
-                       , ("rsquo"      , "\xe2\x80\x99")
-                       , ("sbquo"      , "\xe2\x80\x9a")
-                       , ("emsp"       , "\xe2\x80\x83")
-                       , ("ensp"       , "\xe2\x80\x82")
-                       , ("nbsp"       , "\x20")
-                       , ("thinsp"     , "\xe2\x80\x89")
-                       , ("zwj"        , "\xe2\x80\x8d")
-                       , ("zwnj"       , "\xe2\x80\x8c")
-                       , ("deg"        , "\xc2\xb0")
-                       , ("divide"     , "\xc3\xb7")
-                       , ("frac12"     , "\xc2\xbd")
-                       , ("frac14"     , "\xc2\xbc")
-                       , ("frac34"     , "\xc2\xbe")
-                       , ("ge"         , "\xe2\x89\xa5")
-                       , ("le"         , "\xe2\x89\xa4")
-                       , ("minus"      , "\xe2\x88\x92")
-                       , ("sup2"       , "\xc2\xb2")
-                       , ("sup3"       , "\xc2\xb3")
-                       , ("times"      , "\xc3\x97")
-                       , ("alefsym"    , "\xe2\x84\xb5")
-                       , ("and"        , "\xe2\x88\xa7")
-                       , ("ang"        , "\xe2\x88\xa0")
-                       , ("asymp"      , "\xe2\x89\x88")
-                       , ("cap"        , "\xe2\x88\xa9")
-                       , ("cong"       , "\xe2\x89\x85")
-                       , ("cup"        , "\xe2\x88\xaa")
-                       , ("empty"      , "\xe2\x88\x85")
-                       , ("equiv"      , "\xe2\x89\xa1")
-                       , ("exist"      , "\xe2\x88\x83")
-                       , ("fnof"       , "\xc6\x92")
-                       , ("forall"     , "\xe2\x88\x80")
-                       , ("infin"      , "\xe2\x88\x9e")
-                       , ("int"        , "\xe2\x88\xab")
-                       , ("isin"       , "\xe2\x88\x88")
-                       , ("lang"       , "\xe3\x80\x88")
-                       , ("lceil"      , "\xe2\x8c\x88")
-                       , ("lfloor"     , "\xe2\x8c\x8a")
-                       , ("lowast"     , "\xe2\x88\x97")
-                       , ("micro"      , "\xc2\xb5")
-                       , ("nabla"      , "\xe2\x88\x87")
-                       , ("ne"         , "\xe2\x89\xa0")
-                       , ("ni"         , "\xe2\x88\x8b")
-                       , ("notin"      , "\xe2\x88\x89")
-                       , ("nsub"       , "\xe2\x8a\x84")
-                       , ("oplus"      , "\xe2\x8a\x95")
-                       , ("or"         , "\xe2\x88\xa8")
-                       , ("otimes"     , "\xe2\x8a\x97")
-                       , ("part"       , "\xe2\x88\x82")
-                       , ("perp"       , "\xe2\x8a\xa5")
-                       , ("plusmn"     , "\xc2\xb1")
-                       , ("prod"       , "\xe2\x88\x8f")
-                       , ("prop"       , "\xe2\x88\x9d")
-                       , ("radic"      , "\xe2\x88\x9a")
-                       , ("rang"       , "\xe3\x80\x89")
-                       , ("rceil"      , "\xe2\x8c\x89")
-                       , ("rfloor"     , "\xe2\x8c\x8b")
-                       , ("sdot"       , "\xe2\x8b\x85")
-                       , ("sim"        , "\xe2\x88\xbc")
-                       , ("sub"        , "\xe2\x8a\x82")
-                       , ("sube"       , "\xe2\x8a\x86")
-                       , ("sum"        , "\xe2\x88\x91")
-                       , ("sup"        , "\xe2\x8a\x83")
-                       , ("supe"       , "\xe2\x8a\x87")
-                       , ("there4"     , "\xe2\x88\xb4")
-                       , ("Alpha"      , "\xce\x91")
-                       , ("alpha"      , "\xce\xb1")
-                       , ("Beta"       , "\xce\x92")
-                       , ("beta"       , "\xce\xb2")
-                       , ("Chi"        , "\xce\xa7")
-                       , ("chi"        , "\xcf\x87")
-                       , ("Delta"      , "\xce\x94")
-                       , ("delta"      , "\xce\xb4")
-                       , ("Epsilon"    , "\xce\x95")
-                       , ("epsilon"    , "\xce\xb5")
-                       , ("Eta"        , "\xce\x97")
-                       , ("eta"        , "\xce\xb7")
-                       , ("Gamma"      , "\xce\x93")
-                       , ("gamma"      , "\xce\xb3")
-                       , ("Iota"       , "\xce\x99")
-                       , ("iota"       , "\xce\xb9")
-                       , ("Kappa"      , "\xce\x9a")
-                       , ("kappa"      , "\xce\xba")
-                       , ("Lambda"     , "\xce\x9b")
-                       , ("lambda"     , "\xce\xbb")
-                       , ("Mu"         , "\xce\x9c")
-                       , ("mu"         , "\xce\xbc")
-                       , ("Nu"         , "\xce\x9d")
-                       , ("nu"         , "\xce\xbd")
-                       , ("Omega"      , "\xce\xa9")
-                       , ("omega"      , "\xcf\x89")
-                       , ("Omicron"    , "\xce\x9f")
-                       , ("omicron"    , "\xce\xbf")
-                       , ("Phi"        , "\xce\xa6")
-                       , ("phi"        , "\xcf\x86")
-                       , ("Pi"         , "\xce\xa0")
-                       , ("pi"         , "\xcf\x80")
-                       , ("piv"        , "\xcf\x96")
-                       , ("Psi"        , "\xce\xa8")
-                       , ("psi"        , "\xcf\x88")
-                       , ("Rho"        , "\xce\xa1")
-                       , ("rho"        , "\xcf\x81")
-                       , ("Sigma"      , "\xce\xa3")
-                       , ("sigma"      , "\xcf\x83")
-                       , ("sigmaf"     , "\xcf\x82")
-                       , ("Tau"        , "\xce\xa4")
-                       , ("tau"        , "\xcf\x84")
-                       , ("Theta"      , "\xce\x98")
-                       , ("theta"      , "\xce\xb8")
-                       , ("thetasym"   , "\xcf\x91")
-                       , ("upsih"      , "\xcf\x92")
-                       , ("Upsilon"    , "\xce\xa5")
-                       , ("upsilon"    , "\xcf\x85")
-                       , ("Xi"         , "\xce\x9e")
-                       , ("xi"         , "\xce\xbe")
-                       , ("Zeta"       , "\xce\x96")
-                       , ("zeta"       , "\xce\xb6")
-                       , ("crarr"      , "\xe2\x86\xb5")
-                       , ("darr"       , "\xe2\x86\x93")
-                       , ("dArr"       , "\xe2\x87\x93")
-                       , ("harr"       , "\xe2\x86\x94")
-                       , ("hArr"       , "\xe2\x87\x94")
-                       , ("larr"       , "\xe2\x86\x90")
-                       , ("lArr"       , "\xe2\x87\x90")
-                       , ("rarr"       , "\xe2\x86\x92")
-                       , ("rArr"       , "\xe2\x87\x92")
-                       , ("uarr"       , "\xe2\x86\x91")
-                       , ("uArr"       , "\xe2\x87\x91")
-                       , ("clubs"      , "\xe2\x99\xa3")
-                       , ("diams"      , "\xe2\x99\xa6")
-                       , ("hearts"     , "\xe2\x99\xa5")
-                       , ("spades"     , "\xe2\x99\xa0")
-                       , ("loz"        , "\xe2\x97\x8a") ]
-
- diff --git a/static/docs/0.1.1/heist/src/Text-Templating-Heist-Internal.html b/static/docs/0.1.1/heist/src/Text-Templating-Heist-Internal.html deleted file mode 100644 index fa22e13..0000000 --- a/static/docs/0.1.1/heist/src/Text-Templating-Heist-Internal.html +++ /dev/null @@ -1,503 +0,0 @@ - - - - -src/Text/Templating/Heist/Internal.hs - - - -
{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-
-module Text.Templating.Heist.Internal where
-
-------------------------------------------------------------------------------
-import           Control.Exception (SomeException)
-import           Control.Monad.CatchIO
-import           Control.Monad.RWS.Strict
-import           Data.ByteString.Char8 (ByteString)
-import qualified Data.ByteString.Char8 as B
-import qualified Data.ByteString.Lazy as L
-import           Data.Either
-import qualified Data.Foldable as F
-import           Data.List
-import qualified Data.Map as Map
-import           Data.Map (Map)
-import           Prelude hiding (catch)
-import           System.Directory.Tree hiding (name)
-import           Text.XML.Expat.Format
-import qualified Text.XML.Expat.Tree as X
-
-------------------------------------------------------------------------------
-import           Text.Templating.Heist.Constants
-
-------------------------------------------------------------------------------
--- Types
-------------------------------------------------------------------------------
-
--- | Heist templates are XML documents. The hexpat library is polymorphic over
--- the type of strings, so here we define a 'Node' alias to fix the string
--- types of the tag names and tag bodies to 'ByteString'.
-type Node = X.Node ByteString ByteString
-
-
-------------------------------------------------------------------------------
--- | A 'Template' is a forest of XML nodes.
-type Template = [Node]
-
-
-------------------------------------------------------------------------------
--- | Reversed list of directories
-type TPath = [ByteString]
-
-
-------------------------------------------------------------------------------
-type TemplateMap = Map TPath Template
-
-
-------------------------------------------------------------------------------
--- | Holds all the state information needed for template processing:
---
---     * a collection of named templates. If you use the @\<apply
---       template=\"foo\"\>@ tag to include another template by name, @\"foo\"@
---       is looked up in here.
---
---     * the mapping from tag names to 'Splice's.
---
---     * a flag to control whether we will recurse during splice processing.
---
--- We'll illustrate the recursion flag with a small example template:
---
---   > <foo>
---   >   <bar>
---   >     ...
---   >   </bar>
---   > </foo>
---
--- Assume that @\"foo\"@ is bound to a splice procedure. Running the @foo@
--- splice will result in a list of nodes @L@; if the recursion flag is on we
--- will recursively scan @L@ for splices, otherwise @L@ will be included in the
--- output verbatim.
-data TemplateState m = TemplateState {
-    -- | A mapping of splice names to splice actions
-      _spliceMap      :: SpliceMap m
-    -- | A mapping of template names to templates
-    , _templateMap    :: TemplateMap
-    -- | A flag to control splice recursion
-    , _recurse        :: Bool
-    , _curContext     :: TPath
-    , _recursionDepth :: Int
-    , _onLoadHook     :: Template -> IO Template
-    , _preRunHook     :: Template -> m Template
-    , _postRunHook    :: Template -> m Template
-}
-
-
-------------------------------------------------------------------------------
-instance Eq (TemplateState m) where
-    a == b = (_recurse a == _recurse b) &&
-             (_templateMap a == _templateMap b) &&
-             (_curContext a == _curContext b)
-
-
-------------------------------------------------------------------------------
--- | 'TemplateMonad' is a monad transformer that gives you access to the 'Node'
---   being processed (using the 'MonadReader' instance) as well as holding the
---   'TemplateState' that contains splice and template mappings (accessible
---   using the 'MonadState' instance.
-newtype TemplateMonad m a = TemplateMonad (RWST Node () (TemplateState m) m a)
-  deriving ( Monad
-           , MonadIO
-           , MonadCatchIO
-           , MonadReader Node
-           , MonadState (TemplateState m) )
-
-
-------------------------------------------------------------------------------
-instance (Monad m) => Monoid (TemplateState m) where
-    mempty = TemplateState Map.empty Map.empty True [] 0
-                           return return return
-
-    (TemplateState s1 t1 r1 _ d1 o1 b1 a1) `mappend`
-        (TemplateState s2 t2 r2 c2 d2 o2 b2 a2) =
-        TemplateState s t r c2 d (o1 >=> o2) (b1 >=> b2) (a1 >=> a2)
-      where
-        s = s1 `mappend` s2
-        t = t1 `mappend` t2
-        r = r1 && r2
-        d = max d1 d2
-
-
-------------------------------------------------------------------------------
-instance MonadTrans TemplateMonad where
-  lift = TemplateMonad . lift
-
-------------------------------------------------------------------------------
--- | A Splice is a TemplateMonad computation that returns [Node].
-type Splice m = TemplateMonad m Template
-
-
-------------------------------------------------------------------------------
--- | SpliceMap associates a name and a Splice.
-type SpliceMap m = Map ByteString (Splice m)
-
-
-------------------------------------------------------------------------------
--- TemplateState functions
-------------------------------------------------------------------------------
-
-
-------------------------------------------------------------------------------
--- | Adds an on-load hook to a `TemplateState`.
-addOnLoadHook :: (Monad m) =>
-                 (Template -> IO Template)
-              -> TemplateState m
-              -> TemplateState m
-addOnLoadHook hook ts = ts { _onLoadHook = _onLoadHook ts >=> hook }
-
-
-------------------------------------------------------------------------------
--- | Adds a pre-run hook to a `TemplateState`.
-addPreRunHook :: (Monad m) =>
-                 (Template -> m Template)
-              -> TemplateState m
-              -> TemplateState m
-addPreRunHook hook ts = ts { _preRunHook = _preRunHook ts >=> hook }
-
-
-------------------------------------------------------------------------------
--- | Adds a post-run hook to a `TemplateState`.
-addPostRunHook :: (Monad m) =>
-                  (Template -> m Template)
-               -> TemplateState m
-               -> TemplateState m
-addPostRunHook hook ts = ts { _postRunHook = _postRunHook ts >=> hook }
-
-
-------------------------------------------------------------------------------
--- | Bind a new splice declaration to a tag name within a 'TemplateState'.
-bindSplice :: Monad m =>
-              ByteString        -- ^ tag name
-           -> Splice m          -- ^ splice action
-           -> TemplateState m   -- ^ source state
-           -> TemplateState m
-bindSplice n v ts = ts {_spliceMap = Map.insert n v (_spliceMap ts)}
-
-
-------------------------------------------------------------------------------
--- | Convenience function for looking up a splice.
-lookupSplice :: Monad m =>
-                ByteString
-             -> TemplateState m
-             -> Maybe (Splice m)
-lookupSplice nm ts = Map.lookup nm $ _spliceMap ts
-
-
-------------------------------------------------------------------------------
--- | Converts a path into an array of the elements in reverse order.
-splitPaths :: ByteString -> TPath
-splitPaths = reverse . B.split '/'
-
-
-------------------------------------------------------------------------------
--- | Does a single template lookup without cascading up.
-singleLookup :: TemplateMap
-             -> TPath
-             -> ByteString
-             -> Maybe (Template, TPath)
-singleLookup tm path name = fmap (\a -> (a,path)) $ Map.lookup (name:path) tm
-
-
-------------------------------------------------------------------------------
--- | Searches for a template by looking in the full path then backing up into each
--- of the parent directories until the template is found.
-traversePath :: TemplateMap
-             -> TPath
-             -> ByteString
-             -> Maybe (Template, TPath)
-traversePath tm [] name = fmap (\a -> (a,[])) (Map.lookup [name] tm)
-traversePath tm path name =
-    singleLookup tm path name `mplus`
-    traversePath tm (tail path) name
-
-
-------------------------------------------------------------------------------
--- | Convenience function for looking up a template.
-lookupTemplate :: Monad m =>
-                  ByteString
-               -> TemplateState m
-               -> Maybe (Template, TPath)
-lookupTemplate nameStr ts = 
-    f (_templateMap ts) path name
-  where (name:p) = case splitPaths nameStr of
-                       [] -> [""]
-                       ps -> ps
-        path = p ++ (_curContext ts)
-        f = if '/' `B.elem` nameStr
-                then singleLookup
-                else traversePath
-
-
-------------------------------------------------------------------------------
--- | Sets the templateMap in a TemplateState.
-setTemplates :: Monad m => TemplateMap -> TemplateState m -> TemplateState m
-setTemplates m ts = ts { _templateMap = m }
-
-
-------------------------------------------------------------------------------
--- | Adds a template to the template state.
-insertTemplate :: Monad m =>
-               TPath
-            -> Template
-            -> TemplateState m
-            -> TemplateState m
-insertTemplate p t st =
-    setTemplates (Map.insert p t (_templateMap st)) st
-
-
-------------------------------------------------------------------------------
--- | Adds a template to the template state.
-addTemplate :: Monad m =>
-               ByteString
-            -> Template
-            -> TemplateState m
-            -> TemplateState m
-addTemplate n t st = insertTemplate (splitPaths n) t st
-
-
-------------------------------------------------------------------------------
--- | Gets the node currently being processed.
-getParamNode :: Monad m => TemplateMonad m Node
-getParamNode = ask
-
-
-------------------------------------------------------------------------------
--- | Stops the recursive processing of splices.
-stopRecursion :: Monad m => TemplateMonad m ()
-stopRecursion = modify (\st -> st { _recurse = False })
-
-
-------------------------------------------------------------------------------
--- | Sets the current context
-setContext :: Monad m => TPath -> TemplateMonad m ()
-setContext c = modify (\st -> st { _curContext = c })
-
-
-------------------------------------------------------------------------------
--- | Gets the current context
-getContext :: Monad m => TemplateMonad m TPath
-getContext = gets _curContext
-  
-
-------------------------------------------------------------------------------
--- | Performs splice processing on a list of nodes.
-runNodeList :: Monad m => [Node] -> Splice m
-runNodeList nodes = liftM concat $ sequence (map runNode nodes)
-
-
-------------------------------------------------------------------------------
--- | Performs splice processing on a single node.
-runNode :: Monad m => Node -> Splice m
-runNode n@(X.Text _)          = return [n]
-runNode n@(X.Element nm _ ch) = do
-    s <- liftM (lookupSplice nm) get
-    maybe runChildren (recurseSplice n) s
-
-  where
-    runChildren = do
-        newKids <- runNodeList ch
-        return [X.modifyChildren (const newKids) n]
-
-
-------------------------------------------------------------------------------
--- | The maximum recursion depth.  (Used to prevent infinite loops.)
-mAX_RECURSION_DEPTH :: Int
-mAX_RECURSION_DEPTH = 20
-
-
-------------------------------------------------------------------------------
--- | Checks the recursion flag and recurses accordingly.  Does not recurse
--- deeper than mAX_RECURSION_DEPTH to avoid infinite loops.
-recurseSplice :: Monad m => Node -> Splice m -> Splice m
-recurseSplice node splice = do
-    result <- local (const node) splice
-    ts' <- get
-    if _recurse ts' && _recursionDepth ts' < mAX_RECURSION_DEPTH
-        then do modify (\st -> st { _recursionDepth = _recursionDepth st + 1 })
-                res <- runNodeList result
-                put ts'
-                return res
-        else return result
-
-
-------------------------------------------------------------------------------
--- | Runs a splice in the underlying monad.  Splices require two
--- parameters, the template state, and an input node.
-runSplice :: Monad m =>
-             TemplateState m -- ^ The initial template state
-          -> Node            -- ^ The splice's input node
-          -> Splice m        -- ^ The splice
-          -> m [Node]
-runSplice ts node (TemplateMonad splice) = do
-    (result,_,_) <- runRWST splice node ts
-    return result
-
-
-------------------------------------------------------------------------------
--- | Runs a template in the underlying monad.  Similar to runSplice
--- except that templates don't require a Node as a parameter.
-runRawTemplate :: Monad m => TemplateState m -> Template -> m [Node]
-runRawTemplate ts template =
-    _preRunHook ts template >>=
-    runSplice ts (X.Text "") . runNodeList >>=
-    _postRunHook ts
-
-
-------------------------------------------------------------------------------
--- | Looks up a template name in the supplied 'TemplateState' and runs
--- it in the underlying monad.
-runTemplate :: Monad m
-            => TemplateState m
-            -> ByteString
-            -> m (Maybe [Node])
-runTemplate ts name =
-    maybe (return Nothing)
-          (\(t,ctx) ->
-              return . Just =<<
-              runRawTemplate (ts {_curContext = ctx}) t)
-          (lookupTemplate name ts)
-
-
-------------------------------------------------------------------------------
--- | Looks up a template name evaluates it.  Same as runTemplate except it
--- runs in TemplateMonad instead of m.
-evalTemplate :: Monad m
-            => ByteString
-            -> TemplateMonad m (Maybe [Node])
-evalTemplate name = do
-    ts <- get
-    lift $ runTemplate ts name
-
-
-------------------------------------------------------------------------------
--- | Binds a list of constant string splices
-bindStrings :: Monad m
-            => [(ByteString, ByteString)]
-            -> TemplateState m
-            -> TemplateState m
-bindStrings pairs ts = foldr add ts pairs
-  where
-    add (n,v) = bindSplice n (return [X.Text v])
-
-
-------------------------------------------------------------------------------
--- | Renders a template with the specified parameters.  This is the function
--- to use when you want to "call" a template and pass in parameters from code.
-callTemplate :: Monad m
-             => ByteString                 -- ^ The name of the template
-             -> [(ByteString, ByteString)] -- ^ Association list of
-                                           -- (name,value) parameter pairs
-             -> TemplateMonad m (Maybe Template)
-callTemplate name params = do
-    modify $ bindStrings params
-    evalTemplate name
-
-
-------------------------------------------------------------------------------
--- | Renders a template from the specified TemplateState.
-renderTemplate :: Monad m
-               => TemplateState m
-               -> ByteString
-               -> m (Maybe ByteString)
-renderTemplate ts name = do
-    ns <- runTemplate ts name
-    return $ (Just . formatList') =<< ns
-
-
-------------------------------------------------------------------------------
-heistExpatOptions :: X.ParserOptions ByteString ByteString
-heistExpatOptions =
-    X.defaultParserOptions {
-           X.parserEncoding = Just X.UTF8
-         , X.entityDecoder  = Just (\k -> Map.lookup k htmlEntityLookupTable)
-         }
-
-------------------------------------------------------------------------------
--- Template loading
-------------------------------------------------------------------------------
-
--- | Reads an XML document from disk.
-getDoc :: String -> IO (Either String Template)
-getDoc f = do
-    bs <- catch (liftM Right $ B.readFile f)
-                (\(e::SomeException) -> return $ Left $ show e)
-    let wrap b = "<snap:root>\n" `B.append` b `B.append` "\n</snap:root>"
-    return $ (mapRight X.getChildren .
-              mapLeft genErrorMsg .
-              X.parse' heistExpatOptions . wrap) =<< bs
-  where
-    genErrorMsg (X.XMLParseError str loc) = f ++ " " ++ locMsg loc ++ ": " ++ translate str
-    locMsg (X.XMLParseLocation line col _ _) =
-        "(line " ++ show (line-1) ++ ", col " ++ show col ++ ")"
-    translate "junk after document element" = "document must have a single root element"
-    translate s = s
-
-------------------------------------------------------------------------------
-mapLeft :: (a -> b) -> Either a c -> Either b c
-mapLeft g = either (Left . g) Right
-mapRight :: (b -> c) -> Either a b -> Either a c
-mapRight g = either Left (Right . g)
-
-
-------------------------------------------------------------------------------
--- | Loads a template with the specified path and filename.  The
--- template is only loaded if it has a ".tpl" extension.
-loadTemplate :: String -> String -> IO [Either String (TPath, Template)] --TemplateMap
-loadTemplate path fname
-    | ".tpl" `isSuffixOf` fname = do
-        c <- getDoc fname
-        return [fmap (\t -> (splitPaths $ B.pack tName, t)) c]
-    | otherwise = return []
-  where tName = drop ((length path)+1) $
-                take ((length fname) - 4) fname
-
-
-------------------------------------------------------------------------------
--- | Traverses the specified directory structure and builds a
--- TemplateState by loading all the files with a ".tpl" extension.
-loadTemplates :: Monad m => FilePath -> TemplateState m -> IO (Either String (TemplateState m))
-loadTemplates dir ts = do
-    d <- readDirectoryWith (loadTemplate dir) dir
-    let tlist = F.fold (free d)
-        errs = lefts tlist
-    case errs of
-        [] -> liftM Right $ foldM loadHook ts $ rights tlist
-        _  -> return $ Left $ unlines errs
-
-
-------------------------------------------------------------------------------
--- | Runs the onLoad hook on the template and returns the `TemplateState`
--- with the result inserted.
-loadHook :: Monad m => TemplateState m -> (TPath, Template) -> IO (TemplateState m)
-loadHook ts (tp, t) = do
-    t' <- _onLoadHook ts t
-    return $ insertTemplate tp t' ts
-
-
-------------------------------------------------------------------------------
--- These are here until we can get them into hexpat.
-------------------------------------------------------------------------------
-
-formatList :: (X.GenericXMLString tag, X.GenericXMLString text) =>
-              [X.Node tag text]
-           -> L.ByteString
-formatList nodes = foldl L.append L.empty $ map formatNode nodes
-
-formatList' :: (X.GenericXMLString tag, X.GenericXMLString text) =>
-               [X.Node tag text]
-            -> B.ByteString
-formatList' = B.concat . L.toChunks . formatList
-
-
- diff --git a/static/docs/0.1.1/heist/src/Text-Templating-Heist-Splices-Apply.html b/static/docs/0.1.1/heist/src/Text-Templating-Heist-Splices-Apply.html deleted file mode 100644 index 83efe53..0000000 --- a/static/docs/0.1.1/heist/src/Text-Templating-Heist-Splices-Apply.html +++ /dev/null @@ -1,57 +0,0 @@ - - - - -src/Text/Templating/Heist/Splices/Apply.hs - - - -
{-# LANGUAGE OverloadedStrings #-}
-
-module Text.Templating.Heist.Splices.Apply where
-
-------------------------------------------------------------------------------
-import           Control.Monad.RWS.Strict
-import           Data.ByteString.Char8 (ByteString)
-import qualified Data.ByteString.Char8 as B
-import qualified Text.XML.Expat.Tree as X
-
-------------------------------------------------------------------------------
-import           Text.Templating.Heist.Internal
-
-------------------------------------------------------------------------------
--- | Default name for the apply splice.
-applyTag :: ByteString
-applyTag = "apply"
-
-
-------------------------------------------------------------------------------
--- | Default attribute name for the apply tag.
-applyAttr :: ByteString
-applyAttr = "template"
-
-
-------------------------------------------------------------------------------
--- | Implementation of the apply splice.
-applyImpl :: Monad m => Splice m
-applyImpl = do
-    node <- getParamNode
-    case X.getAttribute node applyAttr of
-        Nothing   -> return [] -- TODO: error handling
-        Just attr -> do 
-            st <- get
-            processedChildren <- runNodeList $ X.getChildren node
-            modify (bindSplice "content" $ return processedChildren)
-            maybe (return []) -- TODO: error handling
-                  (\(t,ctx) -> do setContext ctx
-                                  result <- runNodeList t
-                                  put st
-                                  return result)
-                  (lookupTemplate attr (st {_curContext = nextCtx attr st}))
-  where nextCtx name st
-            | B.isPrefixOf "/" name = []
-            | otherwise             = _curContext st
-
-
-
- diff --git a/static/docs/0.1.1/heist/src/Text-Templating-Heist-Splices-Bind.html b/static/docs/0.1.1/heist/src/Text-Templating-Heist-Splices-Bind.html deleted file mode 100644 index 27c602f..0000000 --- a/static/docs/0.1.1/heist/src/Text-Templating-Heist-Splices-Bind.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - -src/Text/Templating/Heist/Splices/Bind.hs - - - -
{-# LANGUAGE OverloadedStrings #-}
-
-module Text.Templating.Heist.Splices.Bind where
-
-------------------------------------------------------------------------------
-import           Control.Monad.RWS.Strict
-import           Data.ByteString.Char8 (ByteString)
-import qualified Text.XML.Expat.Tree as X
-
-------------------------------------------------------------------------------
-import           Text.Templating.Heist.Internal
-
--- | Default name for the bind splice.
-bindTag :: ByteString
-bindTag = "bind"
-
-
-------------------------------------------------------------------------------
--- | Default attribute name for the bind tag.
-bindAttr :: ByteString
-bindAttr = "tag"
-
-
-------------------------------------------------------------------------------
--- | Implementation of the bind splice.
-bindImpl :: Monad m => Splice m
-bindImpl = do
-    node <- getParamNode
-    maybe (return ())
-          (add node)
-          (X.getAttribute node bindAttr)
-    return []
-
-  where
-    add node nm = modify $ bindSplice nm (return $ X.getChildren node)
-
-
-
- diff --git a/static/docs/0.1.1/heist/src/Text-Templating-Heist-Splices-Ignore.html b/static/docs/0.1.1/heist/src/Text-Templating-Heist-Splices-Ignore.html deleted file mode 100644 index 94cfc79..0000000 --- a/static/docs/0.1.1/heist/src/Text-Templating-Heist-Splices-Ignore.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - -src/Text/Templating/Heist/Splices/Ignore.hs - - - -
{-# LANGUAGE OverloadedStrings #-}
-
-module Text.Templating.Heist.Splices.Ignore where
-
-------------------------------------------------------------------------------
-import           Data.ByteString.Char8 (ByteString)
-
-------------------------------------------------------------------------------
-import           Text.Templating.Heist.Internal
-
-
-------------------------------------------------------------------------------
--- | Default name for the ignore splice.
-ignoreTag :: ByteString
-ignoreTag = "ignore"
-
-
-------------------------------------------------------------------------------
--- | The ignore tag and everything it surrounds disappears in the
--- rendered output.
-ignoreImpl :: Monad m => Splice m
-ignoreImpl = return []
-
-
-
- diff --git a/static/docs/0.1.1/heist/src/Text-Templating-Heist-Splices-Markdown.html b/static/docs/0.1.1/heist/src/Text-Templating-Heist-Splices-Markdown.html deleted file mode 100644 index dcc4dce..0000000 --- a/static/docs/0.1.1/heist/src/Text-Templating-Heist-Splices-Markdown.html +++ /dev/null @@ -1,152 +0,0 @@ - - - - -src/Text/Templating/Heist/Splices/Markdown.hs - - - -
{-# LANGUAGE OverloadedStrings, DeriveDataTypeable #-}
-
-module Text.Templating.Heist.Splices.Markdown where
-
-import           Data.ByteString.Char8 (ByteString)
-import qualified Data.ByteString.Char8 as B
-import qualified Data.ByteString.Lazy.Char8 as L
-import           Data.Maybe
-import           Control.Concurrent
-import           Control.Exception (evaluate, throwIO)
-import           Control.Monad
-import           Control.Monad.CatchIO
-import           Control.Monad.Trans
-import           Data.Typeable
-import           Prelude hiding (catch)
-import           System.Directory
-import           System.Exit
-import           System.IO
-import           System.Process
-import           Text.Templating.Heist.Internal
-import           Text.XML.Expat.Tree hiding (Node)
-
-
-data PandocMissingException = PandocMissingException
-   deriving (Typeable)
-
-instance Show PandocMissingException where
-    show PandocMissingException =
-        "Cannot find the \"pandoc\" executable; is it on your $PATH?"
-
-instance Exception PandocMissingException
-
-
-data MarkdownException = MarkdownException L.ByteString
-   deriving (Typeable)
-
-instance Show MarkdownException where
-    show (MarkdownException e) =
-        "Markdown error: pandoc replied:\n\n" ++ L.unpack e
-
-instance Exception MarkdownException
-
-
-------------------------------------------------------------------------------
--- | Default name for the markdown splice.
-markdownTag :: ByteString
-markdownTag = "markdown"
-
-------------------------------------------------------------------------------
--- | Implementation of the markdown splice.
-markdownSplice :: MonadIO m => Splice m
-markdownSplice = do
-    pdMD <- liftIO $ findExecutable "pandoc"
-
-    when (isNothing pdMD) $ liftIO $ throwIO PandocMissingException
-
-    tree <- getParamNode
-    markup <- liftIO $
-        case getAttribute tree "file" of
-            Just f  -> pandoc (fromJust pdMD) $ B.unpack f
-            Nothing -> pandocBS (fromJust pdMD) $ textContent tree
-
-    let ee = parse' heistExpatOptions markup
-    case ee of
-      (Left e) -> throw $ MarkdownException
-                        $ L.pack ("Error parsing markdown output: " ++ show e)
-      (Right n) -> return [n]
-
-
-pandoc :: FilePath -> FilePath -> IO ByteString
-pandoc pandocPath inputFile = do
-    (ex, sout, serr) <- readProcessWithExitCode' pandocPath args ""
-
-    when (isFail ex) $ throw $ MarkdownException serr
-    return $ B.concat $ L.toChunks
-           $ L.concat [ "<div class=\"markdown\">\n"
-                      , sout
-                      , "\n</div>" ]
-
-  where
-    isFail ExitSuccess = False
-    isFail _           = True
-
-    -- FIXME: hardcoded path
-    args = [ "-S", "--no-wrap", "templates/"++inputFile ]
-
-
-pandocBS :: FilePath -> ByteString -> IO ByteString
-pandocBS pandocPath s = do
-    -- using the crummy string functions for convenience here
-    (ex, sout, serr) <- readProcessWithExitCode' pandocPath args s
-
-    when (isFail ex) $ throw $ MarkdownException serr
-    return $ B.concat $ L.toChunks
-           $ L.concat [ "<div class=\"markdown\">\n"
-                      , sout
-                      , "\n</div>" ]
-
-  where
-    isFail ExitSuccess = False
-    isFail _           = True
-    args = [ "-S", "--no-wrap" ]
-
-
--- a version of readProcessWithExitCode that does I/O properly
-readProcessWithExitCode'
-    :: FilePath                 -- ^ command to run
-    -> [String]                 -- ^ any arguments
-    -> ByteString               -- ^ standard input
-    -> IO (ExitCode,L.ByteString,L.ByteString) -- ^ exitcode, stdout, stderr
-readProcessWithExitCode' cmd args input = do
-    (Just inh, Just outh, Just errh, pid) <-
-        createProcess (proc cmd args){ std_in  = CreatePipe,
-                                       std_out = CreatePipe,
-                                       std_err = CreatePipe }
-    outMVar <- newEmptyMVar
-
-    -- fork off a thread to start consuming stdout
-    out <- L.hGetContents outh
-    forkIO $ evaluate (L.length out) >> putMVar outMVar ()
-
-    -- fork off a thread to start consuming stderr
-    err  <- L.hGetContents errh
-    forkIO $ evaluate (L.length err) >> putMVar outMVar ()
-
-    -- now write and flush any input
-    when (not (B.null input)) $ do B.hPutStr inh input; hFlush inh
-    hClose inh -- done with stdin
-
-    -- wait on the output
-    takeMVar outMVar
-    takeMVar outMVar
-    hClose outh
-
-    -- wait on the process
-    ex <- waitForProcess pid
-
-    return (ex, out, err)
-
-
-
-
-
- diff --git a/static/docs/0.1.1/heist/src/Text-Templating-Heist-Splices-Static.html b/static/docs/0.1.1/heist/src/Text-Templating-Heist-Splices-Static.html deleted file mode 100644 index 734781d..0000000 --- a/static/docs/0.1.1/heist/src/Text-Templating-Heist-Splices-Static.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - -src/Text/Templating/Heist/Splices/Static.hs - - - -
{-# LANGUAGE OverloadedStrings #-}
-
-module Text.Templating.Heist.Splices.Static 
-  ( StaticTagState
-  , bindStaticTag
-  , clearStaticTagCache
-  ) where
-
-------------------------------------------------------------------------------
-import           Control.Concurrent
-import           Control.Monad
-import           Control.Monad.Trans
-import           Data.ByteString.Char8 (ByteString)
-import qualified Data.ByteString.Char8 as B
-import           Data.IORef
-import qualified Data.Map as Map
-import           Data.Map (Map)
-import           Data.Maybe
-import qualified Data.Set as Set
-import           System.Random
-import           Text.XML.Expat.Cursor
-import           Text.XML.Expat.Tree hiding (Node)
-
-
-------------------------------------------------------------------------------
-import           Text.Templating.Heist.Internal
-
-
-------------------------------------------------------------------------------
--- | State for storing static tag information
-newtype StaticTagState = STS (MVar (Map ByteString Template))
-
-
-------------------------------------------------------------------------------
--- | Clears the static tag state.
-clearStaticTagCache :: StaticTagState -> IO ()
-clearStaticTagCache (STS staticMVar) =
-    modifyMVar_ staticMVar (const $ return Map.empty)
-
-
-------------------------------------------------------------------------------
--- | The "static" splice ensures that its contents are evaluated once and then
--- cached.  The cached contents are returned every time the splice is
--- referenced.
-staticImpl :: (MonadIO m)
-           => StaticTagState
-           -> TemplateMonad m Template
-staticImpl (STS mv) = do
-    tree <- getParamNode
-    let i = fromJust $ getAttribute tree "id"
-
-    mp <- liftIO $ readMVar mv
-
-    (mp',ns) <- do
-                   let mbn = Map.lookup i mp
-                   case mbn of
-                       Nothing -> do
-                           nodes' <- runNodeList $ getChildren tree
-                           return $! (Map.insert i nodes' mp, nodes')
-                       (Just n) -> do
-                           stopRecursion
-                           return $! (mp,n)
-
-    liftIO $ modifyMVar_ mv (const $ return mp')
-
-    return ns
-
-
-------------------------------------------------------------------------------
--- | Modifies a TemplateState to include a "static" tag.
-bindStaticTag :: MonadIO m
-              => TemplateState m
-              -> IO (TemplateState m, StaticTagState)
-bindStaticTag ts = do
-    sr <- newIORef $ Set.empty
-    mv <- liftM STS $ newMVar Map.empty
-
-    return $ (addOnLoadHook (assignIds sr) $
-                bindSplice "static" (staticImpl mv) ts,
-              mv)
-
-  where
-    generateId :: IO Int
-    generateId = getStdRandom random
-
-    assignIds setref = mapM f
-        where
-          f node = g $ fromTree node
-
-          getId = do
-              i  <- liftM (B.pack . show) generateId
-              st <- readIORef setref
-              if Set.member i st
-                then getId
-                else do
-                    writeIORef setref $ Set.insert i st
-                    return i
-
-          g curs = do
-              let node = current curs
-              curs' <- if getName node == "static"
-                         then do
-                             i <- getId
-                             return $ modifyContent (setAttribute "id" i) curs
-                         else return curs
-              let mbc = nextDF curs'
-              maybe (return $ toTree curs') g mbc
-
-
-
-
-
- diff --git a/static/docs/0.1.1/heist/src/Text-Templating-Heist-Splices.html b/static/docs/0.1.1/heist/src/Text-Templating-Heist-Splices.html deleted file mode 100644 index 9919a2e..0000000 --- a/static/docs/0.1.1/heist/src/Text-Templating-Heist-Splices.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - -src/Text/Templating/Heist/Splices.hs - - - -
module Text.Templating.Heist.Splices
-  ( module Text.Templating.Heist.Splices.Apply
-  , module Text.Templating.Heist.Splices.Bind
-  , module Text.Templating.Heist.Splices.Ignore
-  , module Text.Templating.Heist.Splices.Markdown
-  , module Text.Templating.Heist.Splices.Static
-  ) where
-
-import Text.Templating.Heist.Splices.Apply
-import Text.Templating.Heist.Splices.Bind
-import Text.Templating.Heist.Splices.Ignore
-import Text.Templating.Heist.Splices.Markdown
-import Text.Templating.Heist.Splices.Static
-
-
- diff --git a/static/docs/0.1.1/heist/src/Text-Templating-Heist.html b/static/docs/0.1.1/heist/src/Text-Templating-Heist.html deleted file mode 100644 index e38d59b..0000000 --- a/static/docs/0.1.1/heist/src/Text-Templating-Heist.html +++ /dev/null @@ -1,166 +0,0 @@ - - - - -src/Text/Templating/Heist.hs - - - -
{-# LANGUAGE OverloadedStrings, GeneralizedNewtypeDeriving #-}
-
-{-|
-
-  This module contains the core definitions for the Heist template system.
-
-  The Heist template system is based on XML\/xhtml.  It allows you to build
-  custom XML-based markup languages.  With Heist you can define your own
-  domain-specific XML tags implemented with Haskell and use them in your
-  templates.  
-
-  The most important concept in Heist is the 'Splice'.  Splices can be thought
-  of as functions that transform a node into a list of nodes.  Heist then
-  substitutes the resulting list of nodes into your template in place of the
-  input node.  'Splice' is implemented as a type synonym @type Splice m =
-  TemplateMonad m [Node]@, and 'TemplateMonad' has a function 'getParamNode'
-  that lets you get the input node.
-
-  Suppose you have a place on your page where you want to display a link with
-  the text \"Logout username\" if the user is currently logged in or a link to
-  the login page if no user is logged in.  Assume you have a function
-  @getUser :: MyAppMonad (Maybe ByteString)@ that gets the current user.
-  You can implement this functionality with a 'Splice' as follows:
-
-  >
-  > import Text.XML.Expat.Tree
-  >
-  > link :: ByteString -> ByteString -> Node
-  > link target text = X.Element "a" [("href", target)] [X.Text text]
-  > 
-  > loginLink :: Node
-  > loginLink = link "/login" "Login"
-  > 
-  > logoutLink :: ByteString -> Node
-  > logoutLink user = link "/logout" (B.append "Logout " user)
-  > 
-  > loginLogoutSplice :: Splice MyAppMonad
-  > loginLogoutSplice = do
-  >     user <- lift getUser
-  >     return $ [maybe loginLink logoutLink user]
-  >
-
-  Next, you need to bind that splice to an XML tag.  Heist stores information
-  about splices and templates in the 'TemplateState' data structure.  The
-  following code demonstrates how this splice would be used.
-
-  > mySplices = [ ("loginLogout", loginLogoutSplice) ]
-  > 
-  > main = do
-  >     ets <- loadTemplates "templates" $
-  >            foldr (uncurry bindSplice) emptyTemplateState mySplices
-  >     let ts = either error id ets
-  >     t <- runMyAppMonad $ renderTemplate ts "index"
-  >     print $ maybe "Page not found" id t
-
-  Here we build up our 'TemplateState' by starting with emptyTemplateState and
-  applying bindSplice for all the splices we want to add.  Then we pass this
-  to loadTemplates our final 'TemplateState' wrapped in an Either to handle
-  errors.  Then we use this 'TemplateState' to render our templates.
-
--}
-
-module Text.Templating.Heist
-  (
-    -- * Types
-    Node
-  , Splice
-  , Template
-  , TemplateMonad
-  , TemplateState
-
-    -- * Functions and declarations on TemplateState values
-  , addTemplate
-  , emptyTemplateState
-  , bindSplice
-  , lookupSplice
-  , setTemplates
-  , loadTemplates
-
-    -- * Hook functions
-    -- $hookDoc
-  , addOnLoadHook
-  , addPreRunHook
-  , addPostRunHook
-
-    -- * TemplateMonad functions
-  , stopRecursion
-  , getParamNode
-  , runNodeList
-  , getContext
-
-    -- * Functions for running splices and templates
-  , runTemplate
-  , evalTemplate
-  , callTemplate
-  , renderTemplate
-  , bindStrings
-
-    -- * Misc functions
-  , runSplice
-  , runRawTemplate
-  , getDoc
-  , bindStaticTag
-
-  , heistExpatOptions
-  , module Text.Templating.Heist.Constants
-  ) where
-
-import           Control.Monad.Trans
-import qualified Data.Map as Map
-import           Text.Templating.Heist.Internal
-import           Text.Templating.Heist.Constants
-import           Text.Templating.Heist.Splices
-
-
-------------------------------------------------------------------------------
--- | The default set of built-in splices.
-defaultSpliceMap :: MonadIO m => SpliceMap m
-defaultSpliceMap = Map.fromList
-    [(applyTag, applyImpl)
-    ,(bindTag, bindImpl)
-    ,(ignoreTag, ignoreImpl)
-    ,(markdownTag, markdownSplice)
-    ]
-
-
-------------------------------------------------------------------------------
--- | An empty template state, with Heist's default splices (@\<bind\>@ and
--- @\<apply\>@) mapped.
-emptyTemplateState :: MonadIO m => TemplateState m
-emptyTemplateState = TemplateState defaultSpliceMap Map.empty True [] 0
-                                   return return return
-
-
-------------------------------------------------------------------------------
--- | Reloads the templates from disk and renders the specified
--- template.  (Old convenience code.)
---renderTemplate' :: FilePath -> ByteString -> IO (Maybe ByteString)
---renderTemplate' baseDir name = do
---    etm <- loadTemplates baseDir emptyTemplateState
---    let ts = either (const emptyTemplateState) id etm
---    ns <- runTemplate ts name
---    return $ (Just . formatList') =<< ns
-
-
--- $hookDoc
--- Heist hooks allow you to modify templates when they are loaded and before
--- and after they are run.  Every time you call one of the addAbcHook
--- functions the hook is added to onto the processing pipeline.  The hooks
--- processes the template in the order that they were added to the
--- TemplateState.
---
--- The pre-run and post-run hooks are run before and after every template is
--- run/rendered.  You should be careful what code you put in these hooks
--- because it can significantly affect the performance of your site.
-
-
- diff --git a/static/docs/0.1.1/heist/src/hscolour.css b/static/docs/0.1.1/heist/src/hscolour.css deleted file mode 100644 index 150e4d0..0000000 --- a/static/docs/0.1.1/heist/src/hscolour.css +++ /dev/null @@ -1,15 +0,0 @@ -body { font-size: 90%; } - -pre, code, body { - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; -} - -.hs-keyglyph, .hs-layout {color: #5200A3;} -.hs-keyword {color: #3465a4; font-weight: bold;} -.hs-comment, .hs-comment a {color: #579; } -.hs-str, .hs-chr {color: #141B24;} -.hs-keyword, .hs-conid, .hs-varid, .hs-conop, .hs-varop, .hs-num, .hs-cpp, .hs-sel, .hs-definition {} diff --git a/static/docs/0.1.1/snap-core/Data-CIByteString.html b/static/docs/0.1.1/snap-core/Data-CIByteString.html deleted file mode 100644 index 45f6c03..0000000 --- a/static/docs/0.1.1/snap-core/Data-CIByteString.html +++ /dev/null @@ -1,324 +0,0 @@ - - -Data.CIByteString
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Data.CIByteString
Description

Data.CIByteString is a module containing CIByteString, a wrapper for - ByteString which provides case-insensitive (ASCII-wise) Ord and Eq - instances. -

CIByteString also has an IsString instance, so if you use the - "OverloadedStrings" LANGUAGE pragma you can write case-insensitive string - literals, e.g.: -

- > let a = "Foo" in
-   putStrLn $ (show $ unCI a) ++ "==\"FoO\" is " ++ show (a == "FoO")
- "Foo"=="FoO" is True
-
Synopsis
data CIByteString
toCI :: ByteString -> CIByteString
unCI :: CIByteString -> ByteString
Documentation
data CIByteString Source
A case-insensitive newtype wrapper for ByteString -
show/hide Instances
toCI :: ByteString -> CIByteStringSource
unCI :: CIByteString -> ByteStringSource
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.1/snap-core/Snap-Internal-Debug.html b/static/docs/0.1.1/snap-core/Snap-Internal-Debug.html deleted file mode 100644 index 806425b..0000000 --- a/static/docs/0.1.1/snap-core/Snap-Internal-Debug.html +++ /dev/null @@ -1,169 +0,0 @@ - - -Snap.Internal.Debug
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Snap.Internal.Debug
Description

An internal Snap module for (optionally) printing debugging - messages. Normally debug does nothing, but you can pass "-fdebug" to - cabal install to build a snap-core which debugs to stderr. -

N.B. this is an internal interface, please don't write external code that - depends on it. -

Documentation
debug :: MonadIO m => String -> m ()Source
debugErrno :: MonadIO m => String -> m ()Source
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.1/snap-core/Snap-Internal-Http-Types.html b/static/docs/0.1.1/snap-core/Snap-Internal-Http-Types.html deleted file mode 100644 index 431901b..0000000 --- a/static/docs/0.1.1/snap-core/Snap-Internal-Http-Types.html +++ /dev/null @@ -1,3854 +0,0 @@ - - -Snap.Internal.Http.Types
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Snap.Internal.Http.Types
Description

An internal Snap module containing HTTP types. -

N.B. this is an internal interface, please don't write user code that - depends on it. Most of these declarations (except for the - unsafe/encapsulation-breaking ones) are re-exported from Snap.Types. -

Synopsis
set_c_locale :: IO ()
c_parse_http_time :: CString -> IO CTime
c_format_http_time :: CTime -> CString -> IO ()
type Enumerator a = Enumerator IO a
type Headers = Map CIByteString [ByteString]
class HasHeaders a where
updateHeaders :: (Headers -> Headers) -> a -> a
headers :: a -> Headers
addHeader :: HasHeaders a => CIByteString -> ByteString -> a -> a
setHeader :: HasHeaders a => CIByteString -> ByteString -> a -> a
getHeaders :: HasHeaders a => CIByteString -> a -> Maybe [ByteString]
getHeader :: HasHeaders a => CIByteString -> a -> Maybe ByteString
data Method
= GET
| HEAD
| POST
| PUT
| DELETE
| TRACE
| OPTIONS
| CONNECT
type HttpVersion = (Int, Int)
data Cookie = Cookie {
cookieName :: !ByteString
cookieValue :: !ByteString
cookieExpires :: !(Maybe UTCTime)
cookieDomain :: !(Maybe ByteString)
cookiePath :: !(Maybe ByteString)
}
type Params = Map ByteString [ByteString]
data SomeEnumerator = SomeEnumerator (forall a. Enumerator a)
data Request = Request {
rqServerName :: !ByteString
rqServerPort :: !Int
rqRemoteAddr :: !ByteString
rqRemotePort :: !Int
rqLocalAddr :: !ByteString
rqLocalPort :: !Int
rqLocalHostname :: !ByteString
rqIsSecure :: !Bool
rqHeaders :: Headers
rqBody :: IORef SomeEnumerator
rqContentLength :: !(Maybe Int)
rqMethod :: !Method
rqVersion :: !HttpVersion
rqCookies :: [Cookie]
rqSnapletPath :: !ByteString
rqPathInfo :: !ByteString
rqContextPath :: !ByteString
rqURI :: !ByteString
rqQueryString :: !ByteString
rqParams :: Params
}
data ResponseBody
= Enum (forall a. Enumerator a)
| SendFile FilePath
rspBodyMap :: (forall a. Enumerator a -> Enumerator a) -> ResponseBody -> ResponseBody
rspBodyToEnum :: ResponseBody -> Enumerator a
data Response = Response {
rspHeaders :: Headers
rspHttpVersion :: !HttpVersion
rspContentLength :: !(Maybe Int)
rspBody :: ResponseBody
rspStatus :: !Int
rspStatusReason :: !ByteString
}
rqParam :: ByteString -> Request -> Maybe [ByteString]
rqModifyParams :: (Params -> Params) -> Request -> Request
rqSetParam :: ByteString -> [ByteString] -> Request -> Request
emptyResponse :: Response
setResponseBody :: (forall a. Enumerator a) -> Response -> Response
setResponseStatus :: Int -> ByteString -> Response -> Response
modifyResponseBody :: (forall a. Enumerator a -> Enumerator a) -> Response -> Response
setContentType :: ByteString -> Response -> Response
addCookie :: Cookie -> Response -> Response
setContentLength :: Int -> Response -> Response
clearContentLength :: Response -> Response
formatHttpTime :: CTime -> IO ByteString
parseHttpTime :: ByteString -> IO CTime
parseToCompletion :: Parser a -> ByteString -> Maybe a
pUrlEscaped :: Parser ByteString
urlDecode :: ByteString -> Maybe ByteString
urlEncode :: ByteString -> ByteString
hexd :: Word8 -> Builder
finish :: Result a -> Result a
fromStr :: String -> ByteString
toStr :: ByteString -> String
Documentation
set_c_locale :: IO ()Source
c_parse_http_time :: CString -> IO CTimeSource
c_format_http_time :: CTime -> CString -> IO ()Source
type Enumerator a = Enumerator IO aSource
type Headers = Map CIByteString [ByteString]Source
A type alias for a case-insensitive key-value mapping. -
class HasHeaders a whereSource
A typeclass for datatypes which contain HTTP headers. -
Methods
updateHeaders :: (Headers -> Headers) -> a -> aSource
Modify the datatype's headers. -
headers :: a -> HeadersSource
Retrieve the headers from a datatype that has headers. -
show/hide Instances
addHeader :: HasHeaders a => CIByteString -> ByteString -> a -> aSource
Adds a header key-value-pair to the HasHeaders datatype. If a header with - the same name already exists, the new value is appended to the headers list. -
setHeader :: HasHeaders a => CIByteString -> ByteString -> a -> aSource
Sets a header key-value-pair in a HasHeaders datatype. If a header with - the same name already exists, it is overwritten with the new value. -
getHeaders :: HasHeaders a => CIByteString -> a -> Maybe [ByteString]Source
Gets all of the values for a given header. -
getHeader :: HasHeaders a => CIByteString -> a -> Maybe ByteStringSource
Gets a header value out of a HasHeaders datatype. If many headers came - in with the same name, they will be catenated together. -
data Method Source
Enumerates the HTTP method values (see - http://tools.ietf.org/html/rfc2068.html#section-5.1.1). -
Constructors
GET
HEAD
POST
PUT
DELETE
TRACE
OPTIONS
CONNECT
show/hide Instances
type HttpVersion = (Int, Int)Source
data Cookie Source
A datatype representing an HTTP cookie. -
Constructors
Cookie
cookieName :: !ByteStringThe name of the cookie. -
cookieValue :: !ByteStringThe cookie's string value. -
cookieExpires :: !(Maybe UTCTime)The cookie's expiration value, if it has one. -
cookieDomain :: !(Maybe ByteString)The cookie's "domain" value, if it has one. -
cookiePath :: !(Maybe ByteString)The cookie path. -
show/hide Instances
type Params = Map ByteString [ByteString]Source
A type alias for the HTTP parameters mapping. Each parameter - key maps to a list of ByteString values; if a parameter is specified - multiple times (e.g.: "GET /foo?param=bar1&param=bar2"), looking up - "param" in the mapping will give you ["bar1", "bar2"]. -
data SomeEnumerator Source
Constructors
SomeEnumerator (forall a. Enumerator a)
data Request Source
Contains all of the information about an incoming HTTP request. -
Constructors
Request
rqServerName :: !ByteStringThe server name of the request, as it came in from the request's - Host: header. -
rqServerPort :: !IntReturns the port number the HTTP server is listening on. -
rqRemoteAddr :: !ByteStringThe remote IP address. -
rqRemotePort :: !IntThe remote TCP port number. -
rqLocalAddr :: !ByteStringThe local IP address for this request. -
rqLocalPort :: !IntReturns the port number the HTTP server is listening on. -
rqLocalHostname :: !ByteStringReturns the HTTP server's idea of its local hostname. -
rqIsSecure :: !BoolReturns True if this is an HTTPS session (currently always - False). -
rqHeaders :: Headers
rqBody :: IORef SomeEnumerator
rqContentLength :: !(Maybe Int)Returns the Content-Length of the HTTP request body. -
rqMethod :: !MethodReturns the HTTP request method. -
rqVersion :: !HttpVersionReturns the HTTP version used by the client. -
rqCookies :: [Cookie]Returns a list of the cookies that came in from the HTTP request - headers. -
rqSnapletPath :: !ByteString

We'll be doing web components (or "snaplets") for version 0.2. The - "snaplet path" refers to the place on the URL where your containing - snaplet is hung. The value of rqSnapletPath is either "" (at the - top-level context) or is a path beginning with a slash, but not ending - with one. -

An identity is that: -

 rqURI r == 'S.concat' [ rqSnapletPath r
-                       , rqContextPath r
-                       , rqPathInfo r ]
-

note that until we introduce snaplets in v0.2, rqSnapletPath will be - "" -

rqPathInfo :: !ByteStringHandlers can (will be; --ed) be hung on a URI "entry point"; - this is called the "context path". If a handler is hung on the - context path "/foo/", and you request "/foo/bar", the value - of rqPathInfo will be "bar". -
rqContextPath :: !ByteStringThe "context path" of the request; catenating rqContextPath, and - rqPathInfo should get you back to the original rqURI. The - rqContextPath always begins and ends with a slash ("/") - character, and represents the path (relative to your - component/snaplet) you took to get to your handler. -
rqURI :: !ByteStringReturns the URI requested by the client. -
rqQueryString :: !ByteStringReturns the HTTP query string for this Request. -
rqParams :: ParamsReturns the Params mapping for this Request. "Parameters" are - automatically decoded from the query string and POST body and - entered into this mapping. -
show/hide Instances
data ResponseBody Source
Constructors
Enum (forall a. Enumerator a)output body is enumerator -
SendFile FilePathoutput body is sendfile() -
rspBodyMap :: (forall a. Enumerator a -> Enumerator a) -> ResponseBody -> ResponseBodySource
rspBodyToEnum :: ResponseBody -> Enumerator aSource
data Response Source
Represents an HTTP response. -
Constructors
Response
rspHeaders :: Headers
rspHttpVersion :: !HttpVersion
rspContentLength :: !(Maybe Int)We will need to inspect the content length no matter what, and - looking up "content-length" in the headers and parsing the number - out of the text will be too expensive. -
rspBody :: ResponseBody
rspStatus :: !IntReturns the HTTP status code. -
rspStatusReason :: !ByteStringReturns the HTTP status explanation string. -
show/hide Instances
rqParamSource
:: ByteStringparameter name to look up -
-> RequestHTTP request -
-> Maybe [ByteString]
Looks up the value(s) for the given named parameter. Parameters initially - come from the request's query string and any decoded POST body (if the - request's Content-Type is application/x-www-form-urlencoded). Parameter - values can be modified within handlers using rqModifyParams. -
rqModifyParams :: (Params -> Params) -> Request -> RequestSource
Modifies the parameters mapping (which is a Map ByteString ByteString) in - a Request using the given function. -
rqSetParamSource
:: ByteStringparameter name -
-> [ByteString]parameter values -
-> Requestrequest -
-> Request
Writes a key-value pair to the parameters mapping within the given request. -
emptyResponse :: ResponseSource
An empty Response. -
setResponseBodySource
:: forall a. Enumerator anew response body - enumerator -
-> Responseresponse to modify -
-> Response
Sets an HTTP response body to the given Enumerator value. -
setResponseStatusSource
:: IntHTTP response integer code -
-> ByteStringHTTP response explanation -
-> ResponseResponse to be modified -
-> Response
Sets the HTTP response status. -
modifyResponseBody :: (forall a. Enumerator a -> Enumerator a) -> Response -> ResponseSource
Modifies a response body. -
setContentType :: ByteString -> Response -> ResponseSource
Sets the Content-Type in the Response headers. -
addCookieSource
:: Cookiecookie value -
-> Responseresponse to modify -
-> Response
Adds an HTTP Cookie to the Response headers. -
setContentLength :: Int -> Response -> ResponseSource

A note here: if you want to set the Content-Length for the response, - Snap forces you to do it with this function rather than by setting it in the - headers; the Content-Length in the headers will be ignored. -

The reason for this is that Snap needs to look up the value of - Content-Length for each request, and looking the string value up in the - headers and parsing the number out of the text will be too expensive. -

If you don't set a content length in your response, HTTP keep-alive will be - disabled for HTTP/1.0 clients, forcing a Connection: close. For HTTP/1.1 - clients, Snap will switch to the chunked transfer encoding if - Content-Length is not specified. -

clearContentLength :: Response -> ResponseSource
Removes any Content-Length set in the Response. -
formatHttpTime :: CTime -> IO ByteStringSource
Converts a CTime into an HTTP timestamp. -
parseHttpTime :: ByteString -> IO CTimeSource
Converts an HTTP timestamp into a CTime. -
parseToCompletion :: Parser a -> ByteString -> Maybe aSource
pUrlEscaped :: Parser ByteStringSource
urlDecode :: ByteString -> Maybe ByteStringSource
Decodes an URL-escaped string (see - http://tools.ietf.org/html/rfc2396.html#section-2.4) -
urlEncode :: ByteString -> ByteStringSource
URL-escapes a string (see - http://tools.ietf.org/html/rfc2396.html#section-2.4) -
hexd :: Word8 -> BuilderSource
finish :: Result a -> Result aSource
fromStr :: String -> ByteStringSource
toStr :: ByteString -> StringSource
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.1/snap-core/Snap-Internal-Iteratee-Debug.html b/static/docs/0.1.1/snap-core/Snap-Internal-Iteratee-Debug.html deleted file mode 100644 index b0b4717..0000000 --- a/static/docs/0.1.1/snap-core/Snap-Internal-Iteratee-Debug.html +++ /dev/null @@ -1,129 +0,0 @@ - - -Snap.Internal.Iteratee.Debug
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Snap.Internal.Iteratee.Debug
Description

An internal Snap module for debugging iteratees. -

N.B. this is an internal interface, please don't write user code that - depends on it. -

Documentation
debugIteratee :: Iteratee IO ()Source
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.1/snap-core/Snap-Iteratee.html b/static/docs/0.1.1/snap-core/Snap-Iteratee.html deleted file mode 100644 index 4e953d3..0000000 --- a/static/docs/0.1.1/snap-core/Snap-Iteratee.html +++ /dev/null @@ -1,971 +0,0 @@ - - -Snap.Iteratee
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Snap.Iteratee
Contents
Convenience aliases around types from Data.Iteratee -
Re-export types and functions from Data.Iteratee -
Helper functions -
Enumerators -
Conversion to/from WrappedByteString -
Iteratee utilities -
Description

Snap Framework type aliases and utilities for iteratees. Note that as a - convenience, this module also exports everything from Data.Iteratee in the - iteratee library. -

WARNING: Note that all of these types are scheduled to change in the - darcs head version of the iteratee library; John Lato et al. are working - on a much improved iteratee formulation. -

Synopsis
type Stream = StreamG WrappedByteString Word8
type IterV m = IterGV WrappedByteString Word8 m
type Iteratee m = IterateeG WrappedByteString Word8 m
type Enumerator m a = Iteratee m a -> m (Iteratee m a)
module Data.Iteratee
enumBS :: Monad m => ByteString -> Enumerator m a
enumLBS :: Monad m => ByteString -> Enumerator m a
enumFile :: FilePath -> Iteratee IO a -> IO (Iteratee IO a)
fromWrap :: WrappedByteString Word8 -> ByteString
toWrap :: ByteString -> WrappedByteString Word8
takeExactly :: (StreamChunk s el, Monad m) => Int -> EnumeratorN s el s el m a
takeNoMoreThan :: (StreamChunk s el, Monad m) => Int -> EnumeratorN s el s el m a
countBytes :: Monad m => Iteratee m a -> Iteratee m (a, Int)
bufferIteratee :: Monad m => Enumerator m a
Convenience aliases around types from Data.Iteratee -
type Stream = StreamG WrappedByteString Word8Source
type IterV m = IterGV WrappedByteString Word8 mSource
type Iteratee m = IterateeG WrappedByteString Word8 mSource
type Enumerator m a = Iteratee m a -> m (Iteratee m a)Source
Re-export types and functions from Data.Iteratee -
module Data.Iteratee
Helper functions -
Enumerators -
enumBS :: Monad m => ByteString -> Enumerator m aSource
Enumerates a strict bytestring. -
enumLBS :: Monad m => ByteString -> Enumerator m aSource
Enumerates a lazy bytestring. -
enumFile :: FilePath -> Iteratee IO a -> IO (Iteratee IO a)Source
Conversion to/from WrappedByteString -
fromWrap :: WrappedByteString Word8 -> ByteStringSource
Converts a wrapped bytestring to a lazy bytestring. -
toWrap :: ByteString -> WrappedByteString Word8Source
Converts a lazy bytestring to a wrapped bytestring. -
Iteratee utilities -
takeExactly :: (StreamChunk s el, Monad m) => Int -> EnumeratorN s el s el m aSource
Reads n elements from a stream and applies the given iteratee to - the stream of the read elements. Reads exactly n elements, and if - the stream is short propagates an error. -
takeNoMoreThan :: (StreamChunk s el, Monad m) => Int -> EnumeratorN s el s el m aSource
Reads up to n elements from a stream and applies the given iteratee to the - stream of the read elements. If more than n elements are read, propagates an - error. -
countBytes :: Monad m => Iteratee m a -> Iteratee m (a, Int)Source
Wraps an Iteratee, counting the number of bytes consumed by it. -
bufferIteratee :: Monad m => Enumerator m aSource

Buffers an iteratee. -

Our enumerators produce a lot of little strings; rather than spending all - our time doing kernel context switches for 4-byte write() calls, we buffer - the iteratee to send 2KB at a time. -

Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.1/snap-core/Snap-Types.html b/static/docs/0.1.1/snap-core/Snap-Types.html deleted file mode 100644 index e2f662f..0000000 --- a/static/docs/0.1.1/snap-core/Snap-Types.html +++ /dev/null @@ -1,5874 +0,0 @@ - - -Snap.Types
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Snap.Types
Contents
The Snap Monad -
Functions for control flow and early termination -
Routing -
Access to state -
Grabbing request bodies -
HTTP Datatypes and Functions -
Headers -
Requests -
Responses -
Response I/O -
Iteratee -
HTTP utilities -
Description
This module contains the core type definitions, class instances, and functions -for HTTP as well as the Snap monad, which is used for web handlers. -
Synopsis
data Snap a
runSnap :: Snap a -> Request -> Iteratee IO (Request, Response)
data NoHandlerException = NoHandlerException
finishWith :: Response -> Snap ()
pass :: Snap a
method :: Method -> Snap a -> Snap a
path :: ByteString -> Snap a -> Snap a
dir :: ByteString -> Snap a -> Snap a
ifTop :: Snap a -> Snap a
route :: [(ByteString, Snap a)] -> Snap a
routeLocal :: [(ByteString, Snap a)] -> Snap a
getRequest :: Snap Request
getResponse :: Snap Response
putRequest :: Request -> Snap ()
putResponse :: Response -> Snap ()
modifyRequest :: (Request -> Request) -> Snap ()
modifyResponse :: (Response -> Response) -> Snap ()
localRequest :: (Request -> Request) -> Snap a -> Snap a
withRequest :: (Request -> Snap a) -> Snap a
withResponse :: (Response -> Snap a) -> Snap a
runRequestBody :: Iteratee IO a -> Snap a
getRequestBody :: Snap ByteString
unsafeDetachRequestBody :: Snap (Enumerator a)
data Request
data Response
type Headers = Map CIByteString [ByteString]
class HasHeaders a where
updateHeaders :: (Headers -> Headers) -> a -> a
headers :: a -> Headers
type Params = Map ByteString [ByteString]
data Method
= GET
| HEAD
| POST
| PUT
| DELETE
| TRACE
| OPTIONS
| CONNECT
data Cookie = Cookie {
cookieName :: !ByteString
cookieValue :: !ByteString
cookieExpires :: !(Maybe UTCTime)
cookieDomain :: !(Maybe ByteString)
cookiePath :: !(Maybe ByteString)
}
type HttpVersion = (Int, Int)
addHeader :: HasHeaders a => CIByteString -> ByteString -> a -> a
setHeader :: HasHeaders a => CIByteString -> ByteString -> a -> a
getHeader :: HasHeaders a => CIByteString -> a -> Maybe ByteString
rqServerName :: Request -> ByteString
rqServerPort :: Request -> Int
rqRemoteAddr :: Request -> ByteString
rqRemotePort :: Request -> Int
rqLocalAddr :: Request -> ByteString
rqLocalHostname :: Request -> ByteString
rqIsSecure :: Request -> Bool
rqContentLength :: Request -> Maybe Int
rqMethod :: Request -> Method
rqVersion :: Request -> HttpVersion
rqCookies :: Request -> [Cookie]
rqPathInfo :: Request -> ByteString
rqContextPath :: Request -> ByteString
rqURI :: Request -> ByteString
rqQueryString :: Request -> ByteString
rqParams :: Request -> Params
rqParam :: ByteString -> Request -> Maybe [ByteString]
getParam :: ByteString -> Snap (Maybe ByteString)
rqModifyParams :: (Params -> Params) -> Request -> Request
rqSetParam :: ByteString -> [ByteString] -> Request -> Request
emptyResponse :: Response
setResponseStatus :: Int -> ByteString -> Response -> Response
rspStatus :: Response -> Int
rspStatusReason :: Response -> ByteString
setContentType :: ByteString -> Response -> Response
addCookie :: Cookie -> Response -> Response
setContentLength :: Int -> Response -> Response
clearContentLength :: Response -> Response
setResponseBody :: (forall a. Enumerator a) -> Response -> Response
modifyResponseBody :: (forall a. Enumerator a -> Enumerator a) -> Response -> Response
addToOutput :: (forall a. Enumerator a) -> Snap ()
writeBS :: ByteString -> Snap ()
writeLazyText :: Text -> Snap ()
writeText :: Text -> Snap ()
writeLBS :: ByteString -> Snap ()
sendFile :: FilePath -> Snap ()
type Enumerator a = Enumerator IO a
formatHttpTime :: CTime -> IO ByteString
parseHttpTime :: ByteString -> IO CTime
urlEncode :: ByteString -> ByteString
urlDecode :: ByteString -> Maybe ByteString
The Snap Monad -
data Snap a Source

Snap is the Monad that user web handlers run in. Snap gives you: -

1. stateful access to fetch or modify an HTTP Request -

2. stateful access to fetch or modify an HTTP Response -

3. failure / Alternative / MonadPlus semantics: a Snap handler can - choose not to handle a given request, using empty or its synonym pass, - and you can try alternative handlers with the <|> operator: -

 a :: Snap String
- a = pass
-
- b :: Snap String
- b = return "foo"
-
- c :: Snap String
- c = a <|> b             -- try running a, if it fails then try b
-

4. convenience functions (writeBS, writeLBS, writeText, writeLazyText, - addToOutput) for writing output to the Response: -

 a :: (forall a . Enumerator a) -> Snap ()
- a someEnumerator = do
-     writeBS "I'm a strict bytestring"
-     writeLBS "I'm a lazy bytestring"
-     addToOutput someEnumerator
-

5. early termination: if you call finishWith: -

 a :: Snap ()
- a = do
-   modifyResponse $ setResponseStatus 500 "Internal Server Error"
-   writeBS "500 error"
-   r <- getResponse
-   finishWith r
-

then any subsequent processing will be skipped and supplied Response value - will be returned from runSnap as-is. -

6. access to the IO monad through a MonadIO instance: -

 a :: Snap ()
- a = liftIO fireTheMissiles
-
show/hide Instances
runSnap :: Snap a -> Request -> Iteratee IO (Request, Response)Source
Runs a Snap monad action in the 'Iteratee IO' monad. -
data NoHandlerException Source
This exception is thrown if the handler you supply to runSnap fails. -
Constructors
NoHandlerException
show/hide Instances
Functions for control flow and early termination -
finishWith :: Response -> Snap ()Source
Short-circuits a Snap monad action early, storing the given - Response value in its state. -
pass :: Snap aSource
Fails out of a Snap monad action. This is used to indicate - that you choose not to handle the given request within the given - handler. -
Routing -
method :: Method -> Snap a -> Snap aSource
Runs a Snap monad action only if the request's HTTP method matches - the given method. -
pathSource
:: ByteStringpath to match against -
-> Snap ahandler to run -
-> Snap a
Runs a Snap monad action only for requests where rqPathInfo is exactly - equal to the given string. If the path matches, locally sets rqContextPath - to the old value of rqPathInfo, sets rqPathInfo="", and runs the given - handler. -
dirSource
:: ByteStringpath component to match -
-> Snap ahandler to run -
-> Snap a

Runs a Snap monad action only when the rqPathInfo of the request - starts with the given path. For example, -

 dir "foo" handler
-

Will fail if rqPathInfo is not "/foo" or "/foo/...", and will - add "foo/" to the handler's local rqContextPath. -

ifTop :: Snap a -> Snap aSource
Runs a Snap monad action only when rqPathInfo is empty. -
route :: [(ByteString, Snap a)] -> Snap aSource

A web handler which, given a mapping from URL entry points to web - handlers, efficiently routes requests to the correct handler. -

The URL entry points are given as relative paths, for example: -

 route [ ("foo/bar/quux", fooBarQuux) ]
-

If the URI of the incoming request is -

 /foo/bar/quux
-

or -

 /foo/bar/quux/...anything...
-

then the request will be routed to "fooBarQuux", with rqContextPath - set to "/foo/bar/quux/" and rqPathInfo set to - "...anything...". -

FIXME/TODO: we need a version with and without the context path setting - behaviour; if the route is "article/:id/print", we probably want the - contextPath to be "/article" instead of "/article/whatever/print". -

A path component within an URL entry point beginning with a colon (":") - is treated as a variable capture; the corresponding path component within - the request URI will be entered into the rqParams parameters mapping with - the given name. For instance, if the routes were: -

 route [ ("foo/:bar/baz", fooBazHandler) ]
-

Then a request for "/foo/saskatchewan/baz" would be routed to - fooBazHandler with a mapping for: -

 "bar" => "saskatchewan"
-

in its parameters table. -

Longer paths are matched first, and specific routes are matched before - captures. That is, if given routes: -

 [ ("a", h1), ("a/b", h2), ("a/:x", h3) ]
-

a request for "/a/b" will go to h2, "/a/s" for any s will go - to h3, and "/a" will go to h1. -

The following example matches "/article" to an article index, - "/login" to a login, and "/article/..." to an article renderer. -

 route [ ("article",     renderIndex)
-       , ("article/:id", renderArticle)
-       , ("login",       method POST doLogin) ]
-
routeLocal :: [(ByteString, Snap a)] -> Snap aSource
The routeLocal function is the same as route, except it doesn't change - the request's context path. This is useful if you want to route to a - particular handler but you want that handler to receive the rqPathInfo as - it is. -
Access to state -
getRequest :: Snap RequestSource
Grabs the Request object out of the Snap monad. -
getResponse :: Snap ResponseSource
Grabs the Response object out of the Snap monad. -
putRequest :: Request -> Snap ()Source
Puts a new Request object into the Snap monad. -
putResponse :: Response -> Snap ()Source
Puts a new Response object into the Snap monad. -
modifyRequest :: (Request -> Request) -> Snap ()Source
Modifies the Request object stored in a Snap monad. -
modifyResponse :: (Response -> Response) -> Snap ()Source
Modifes the Response object stored in a Snap monad. -
localRequest :: (Request -> Request) -> Snap a -> Snap aSource
Runs a Snap action with a locally-modified Request state - object. The Request object in the Snap monad state after the call - to localRequest will be unchanged. -
withRequest :: (Request -> Snap a) -> Snap aSource
Fetches the Request from state and hands it to the given action. -
withResponse :: (Response -> Snap a) -> Snap aSource
Fetches the Response from state and hands it to the given action. -
Grabbing request bodies -
runRequestBody :: Iteratee IO a -> Snap aSource
Sends the request body through an iteratee (data consumer) and - returns the result. -
getRequestBody :: Snap ByteStringSource
Returns the request body as a bytestring. -
unsafeDetachRequestBody :: Snap (Enumerator a)Source

Detaches the request body's Enumerator from the Request and - returns it. You would want to use this if you needed to send the - HTTP request body (transformed or otherwise) through to the output - in O(1) space. (Examples: transcoding, "echo", etc) -

Normally Snap is careful to ensure that the request body is fully - consumed after your web handler runs; this function is marked - "unsafe" because it breaks this guarantee and leaves the - responsibility up to you. If you don't fully consume the - Enumerator you get here, the next HTTP request in the pipeline - (if any) will misparse. Be careful with exception handlers. -

HTTP Datatypes and Functions -
HTTP-related datatypes: Request, Response, Cookie, etc. -
data Request Source
Contains all of the information about an incoming HTTP request. -
show/hide Instances
data Response Source
Represents an HTTP response. -
show/hide Instances
type Headers = Map CIByteString [ByteString]Source
A type alias for a case-insensitive key-value mapping. -
class HasHeaders a whereSource
A typeclass for datatypes which contain HTTP headers. -
Methods
updateHeaders :: (Headers -> Headers) -> a -> aSource
Modify the datatype's headers. -
headers :: a -> HeadersSource
Retrieve the headers from a datatype that has headers. -
show/hide Instances
type Params = Map ByteString [ByteString]Source
A type alias for the HTTP parameters mapping. Each parameter - key maps to a list of ByteString values; if a parameter is specified - multiple times (e.g.: "GET /foo?param=bar1&param=bar2"), looking up - "param" in the mapping will give you ["bar1", "bar2"]. -
data Method Source
Enumerates the HTTP method values (see - http://tools.ietf.org/html/rfc2068.html#section-5.1.1). -
Constructors
GET
HEAD
POST
PUT
DELETE
TRACE
OPTIONS
CONNECT
show/hide Instances
data Cookie Source
A datatype representing an HTTP cookie. -
Constructors
Cookie
cookieName :: !ByteStringThe name of the cookie. -
cookieValue :: !ByteStringThe cookie's string value. -
cookieExpires :: !(Maybe UTCTime)The cookie's expiration value, if it has one. -
cookieDomain :: !(Maybe ByteString)The cookie's "domain" value, if it has one. -
cookiePath :: !(Maybe ByteString)The cookie path. -
show/hide Instances
type HttpVersion = (Int, Int)Source
Headers -
addHeader :: HasHeaders a => CIByteString -> ByteString -> a -> aSource
Adds a header key-value-pair to the HasHeaders datatype. If a header with - the same name already exists, the new value is appended to the headers list. -
setHeader :: HasHeaders a => CIByteString -> ByteString -> a -> aSource
Sets a header key-value-pair in a HasHeaders datatype. If a header with - the same name already exists, it is overwritten with the new value. -
getHeader :: HasHeaders a => CIByteString -> a -> Maybe ByteStringSource
Gets a header value out of a HasHeaders datatype. If many headers came - in with the same name, they will be catenated together. -
Requests -
rqServerName :: Request -> ByteStringSource
The server name of the request, as it came in from the request's - Host: header. -
rqServerPort :: Request -> IntSource
Returns the port number the HTTP server is listening on. -
rqRemoteAddr :: Request -> ByteStringSource
The remote IP address. -
rqRemotePort :: Request -> IntSource
The remote TCP port number. -
rqLocalAddr :: Request -> ByteStringSource
The local IP address for this request. -
rqLocalHostname :: Request -> ByteStringSource
Returns the HTTP server's idea of its local hostname. -
rqIsSecure :: Request -> BoolSource
Returns True if this is an HTTPS session (currently always - False). -
rqContentLength :: Request -> Maybe IntSource
Returns the Content-Length of the HTTP request body. -
rqMethod :: Request -> MethodSource
Returns the HTTP request method. -
rqVersion :: Request -> HttpVersionSource
Returns the HTTP version used by the client. -
rqCookies :: Request -> [Cookie]Source
Returns a list of the cookies that came in from the HTTP request - headers. -
rqPathInfo :: Request -> ByteStringSource
Handlers can (will be; --ed) be hung on a URI "entry point"; - this is called the "context path". If a handler is hung on the - context path "/foo/", and you request "/foo/bar", the value - of rqPathInfo will be "bar". -
rqContextPath :: Request -> ByteStringSource
The "context path" of the request; catenating rqContextPath, and - rqPathInfo should get you back to the original rqURI. The - rqContextPath always begins and ends with a slash ("/") - character, and represents the path (relative to your - component/snaplet) you took to get to your handler. -
rqURI :: Request -> ByteStringSource
Returns the URI requested by the client. -
rqQueryString :: Request -> ByteStringSource
Returns the HTTP query string for this Request. -
rqParams :: Request -> ParamsSource
Returns the Params mapping for this Request. "Parameters" are - automatically decoded from the query string and POST body and - entered into this mapping. -
rqParamSource
:: ByteStringparameter name to look up -
-> RequestHTTP request -
-> Maybe [ByteString]
Looks up the value(s) for the given named parameter. Parameters initially - come from the request's query string and any decoded POST body (if the - request's Content-Type is application/x-www-form-urlencoded). Parameter - values can be modified within handlers using rqModifyParams. -
getParamSource
:: ByteStringparameter name to look up -
-> Snap (Maybe ByteString)

See rqParam. Looks up a value for the given named parameter in the - Request. If more than one value was entered for the given parameter name, - getParam gloms the values together with: -

    intercalate " "
rqModifyParams :: (Params -> Params) -> Request -> RequestSource
Modifies the parameters mapping (which is a Map ByteString ByteString) in - a Request using the given function. -
rqSetParamSource
:: ByteStringparameter name -
-> [ByteString]parameter values -
-> Requestrequest -
-> Request
Writes a key-value pair to the parameters mapping within the given request. -
Responses -
emptyResponse :: ResponseSource
An empty Response. -
setResponseStatusSource
:: IntHTTP response integer code -
-> ByteStringHTTP response explanation -
-> ResponseResponse to be modified -
-> Response
Sets the HTTP response status. -
rspStatus :: Response -> IntSource
Returns the HTTP status code. -
rspStatusReason :: Response -> ByteStringSource
Returns the HTTP status explanation string. -
setContentType :: ByteString -> Response -> ResponseSource
Sets the Content-Type in the Response headers. -
addCookieSource
:: Cookiecookie value -
-> Responseresponse to modify -
-> Response
Adds an HTTP Cookie to the Response headers. -
setContentLength :: Int -> Response -> ResponseSource

A note here: if you want to set the Content-Length for the response, - Snap forces you to do it with this function rather than by setting it in the - headers; the Content-Length in the headers will be ignored. -

The reason for this is that Snap needs to look up the value of - Content-Length for each request, and looking the string value up in the - headers and parsing the number out of the text will be too expensive. -

If you don't set a content length in your response, HTTP keep-alive will be - disabled for HTTP/1.0 clients, forcing a Connection: close. For HTTP/1.1 - clients, Snap will switch to the chunked transfer encoding if - Content-Length is not specified. -

clearContentLength :: Response -> ResponseSource
Removes any Content-Length set in the Response. -
Response I/O -
setResponseBodySource
:: forall a. Enumerator anew response body - enumerator -
-> Responseresponse to modify -
-> Response
Sets an HTTP response body to the given Enumerator value. -
modifyResponseBody :: (forall a. Enumerator a -> Enumerator a) -> Response -> ResponseSource
Modifies a response body. -
addToOutputSource
:: forall a. Enumerator aoutput to add -
-> Snap ()
Adds the output from the given enumerator to the Response - stored in the Snap monad state. -
writeBS :: ByteString -> Snap ()Source
Adds the given strict ByteString to the body of the Response stored in - the Snap monad state. -
writeLazyText :: Text -> Snap ()Source
Adds the given lazy Text to the body of the Response stored in the - Snap monad state. -
writeText :: Text -> Snap ()Source
Adds the given strict Text to the body of the Response stored in the - Snap monad state. -
writeLBS :: ByteString -> Snap ()Source
Adds the given lazy ByteString to the body of the Response stored in - the Snap monad state. -
sendFile :: FilePath -> Snap ()Source

Sets the output to be the contents of the specified file. -

Calling sendFile will overwrite any output queued to be sent in the - Response. If the response body is not modified after the call to - sendFile, Snap will use the efficient sendfile() system call on - platforms that support it. -

If the response body is modified (using modifyResponseBody), the file will - be read using mmap(). -

Iteratee -
type Enumerator a = Enumerator IO aSource
HTTP utilities -
formatHttpTime :: CTime -> IO ByteStringSource
Converts a CTime into an HTTP timestamp. -
parseHttpTime :: ByteString -> IO CTimeSource
Converts an HTTP timestamp into a CTime. -
urlEncode :: ByteString -> ByteStringSource
URL-escapes a string (see - http://tools.ietf.org/html/rfc2396.html#section-2.4) -
urlDecode :: ByteString -> Maybe ByteStringSource
Decodes an URL-escaped string (see - http://tools.ietf.org/html/rfc2396.html#section-2.4) -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.1/snap-core/Snap-Util-FileServe.html b/static/docs/0.1.1/snap-core/Snap-Util-FileServe.html deleted file mode 100644 index 0291b14..0000000 --- a/static/docs/0.1.1/snap-core/Snap-Util-FileServe.html +++ /dev/null @@ -1,651 +0,0 @@ - - -Snap.Util.FileServe
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Snap.Util.FileServe
Description
Contains web handlers to serve files from a directory. -
Synopsis
getSafePath :: Snap FilePath
fileServe :: FilePath -> Snap ()
fileServe' :: MimeMap -> FilePath -> Snap ()
fileServeSingle :: FilePath -> Snap ()
fileServeSingle' :: ByteString -> FilePath -> Snap ()
defaultMimeTypes :: MimeMap
type MimeMap = Map FilePath ByteString
Documentation
getSafePath :: Snap FilePathSource
Gets a path from the Request using rqPathInfo and makes sure it is - safe to use for opening files. A path is safe if it is a relative path - and has no .. elements to escape the intended directory structure. -
fileServeSource
:: FilePathroot directory -
-> Snap ()

Serves files out of the given directory. The relative path given in - rqPathInfo is searched for the given file, and the file is served with the - appropriate mime type if it is found. Absolute paths and ".." are prohibited - to prevent files from being served from outside the sandbox. -

Uses defaultMimeTypes to determine the Content-Type based on the file's - extension. -

fileServe'Source
:: MimeMapMIME type mapping -
-> FilePathroot directory -
-> Snap ()
Same as fileServe, with control over the MIME mapping used. -
fileServeSingleSource
:: FilePathpath to file -
-> Snap ()
Serves a single file specified by a full or relative path. The - path restrictions on fileServe don't apply to this function since - the path is not being supplied by the user. -
fileServeSingle'Source
:: ByteStringMIME type mapping -
-> FilePathpath to file -
-> Snap ()
Same as fileServeSingle, with control over the MIME mapping used. -
defaultMimeTypes :: MimeMapSource

The default set of mime type mappings we use when serving files. Its - value: -

 Map.fromList [
-   ( ".asc"     , "text/plain"                        ),
-   ( ".asf"     , "video/x-ms-asf"                    ),
-   ( ".asx"     , "video/x-ms-asf"                    ),
-   ( ".avi"     , "video/x-msvideo"                   ),
-   ( ".bz2"     , "application/x-bzip"                ),
-   ( ".c"       , "text/plain"                        ),
-   ( ".class"   , "application/octet-stream"          ),
-   ( ".conf"    , "text/plain"                        ),
-   ( ".cpp"     , "text/plain"                        ),
-   ( ".css"     , "text/css"                          ),
-   ( ".cxx"     , "text/plain"                        ),
-   ( ".dtd"     , "text/xml"                          ),
-   ( ".dvi"     , "application/x-dvi"                 ),
-   ( ".gif"     , "image/gif"                         ),
-   ( ".gz"      , "application/x-gzip"                ),
-   ( ".hs"      , "text/plain"                        ),
-   ( ".htm"     , "text/html"                         ),
-   ( ".html"    , "text/html"                         ),
-   ( ".jar"     , "application/x-java-archive"        ),
-   ( ".jpeg"    , "image/jpeg"                        ),
-   ( ".jpg"     , "image/jpeg"                        ),
-   ( ".js"      , "text/javascript"                   ),
-   ( ".log"     , "text/plain"                        ),
-   ( ".m3u"     , "audio/x-mpegurl"                   ),
-   ( ".mov"     , "video/quicktime"                   ),
-   ( ".mp3"     , "audio/mpeg"                        ),
-   ( ".mpeg"    , "video/mpeg"                        ),
-   ( ".mpg"     , "video/mpeg"                        ),
-   ( ".ogg"     , "application/ogg"                   ),
-   ( ".pac"     , "application/x-ns-proxy-autoconfig" ),
-   ( ".pdf"     , "application/pdf"                   ),
-   ( ".png"     , "image/png"                         ),
-   ( ".ps"      , "application/postscript"            ),
-   ( ".qt"      , "video/quicktime"                   ),
-   ( ".sig"     , "application/pgp-signature"         ),
-   ( ".spl"     , "application/futuresplash"          ),
-   ( ".swf"     , "application/x-shockwave-flash"     ),
-   ( ".tar"     , "application/x-tar"                 ),
-   ( ".tar.bz2" , "application/x-bzip-compressed-tar" ),
-   ( ".tar.gz"  , "application/x-tgz"                 ),
-   ( ".tbz"     , "application/x-bzip-compressed-tar" ),
-   ( ".text"    , "text/plain"                        ),
-   ( ".tgz"     , "application/x-tgz"                 ),
-   ( ".torrent" , "application/x-bittorrent"          ),
-   ( ".txt"     , "text/plain"                        ),
-   ( ".wav"     , "audio/x-wav"                       ),
-   ( ".wax"     , "audio/x-ms-wax"                    ),
-   ( ".wma"     , "audio/x-ms-wma"                    ),
-   ( ".wmv"     , "video/x-ms-wmv"                    ),
-   ( ".xbm"     , "image/x-xbitmap"                   ),
-   ( ".xml"     , "text/xml"                          ),
-   ( ".xpm"     , "image/x-xpixmap"                   ),
-   ( ".xwd"     , "image/x-xwindowdump"               ),
-   ( ".zip"     , "application/zip"                   ) ]
-
type MimeMap = Map FilePath ByteStringSource
A type alias for MIME type -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.1/snap-core/Snap-Util-GZip.html b/static/docs/0.1.1/snap-core/Snap-Util-GZip.html deleted file mode 100644 index 1caef5b..0000000 --- a/static/docs/0.1.1/snap-core/Snap-Util-GZip.html +++ /dev/null @@ -1,328 +0,0 @@ - - -Snap.Util.GZip
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Snap.Util.GZip
Synopsis
withCompression :: Snap a -> Snap ()
withCompression' :: Set ByteString -> Snap a -> Snap ()
Documentation
withCompressionSource
:: Snap athe web handler to run -
-> Snap ()

Runs a Snap web handler with compression if available. -

If the client has indicated support for gzip or compress in its - Accept-Encoding header, and the Content-Type in the response is one of - the following types: -

  • application/x-javascript
  • text/css
  • text/html
  • text/javascript
  • text/plain
  • text/xml
  • application/x-font-truetype

Then the given handler's output stream will be compressed, - Content-Encoding will be set in the output headers, and the - Content-Length will be cleared if it was set. (We can't process the stream - in O(1) space if the length is known beforehand.) -

The wrapped handler will be run to completion, and then the Response - that's contained within the Snap monad state will be passed to - finishWith to prevent further processing. -

withCompression'Source
:: Set ByteStringset of compressible MIME types -
-> Snap athe web handler to run -
-> Snap ()
The same as withCompression, with control over which MIME types to - compress. -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.1/snap-core/doc-index-62.html b/static/docs/0.1.1/snap-core/doc-index-62.html deleted file mode 100644 index 568776f..0000000 --- a/static/docs/0.1.1/snap-core/doc-index-62.html +++ /dev/null @@ -1,144 +0,0 @@ - - -snap-core-0.1.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (>)
>.
diff --git a/static/docs/0.1.1/snap-core/doc-index-A.html b/static/docs/0.1.1/snap-core/doc-index-A.html deleted file mode 100644 index 2ba3ab2..0000000 --- a/static/docs/0.1.1/snap-core/doc-index-A.html +++ /dev/null @@ -1,166 +0,0 @@ - - -snap-core-0.1.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (A)
addCookie
addHeader
addToOutput
diff --git a/static/docs/0.1.1/snap-core/doc-index-B.html b/static/docs/0.1.1/snap-core/doc-index-B.html deleted file mode 100644 index dffc62c..0000000 --- a/static/docs/0.1.1/snap-core/doc-index-B.html +++ /dev/null @@ -1,152 +0,0 @@ - - -snap-core-0.1.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (B)
break
bufferIteratee
diff --git a/static/docs/0.1.1/snap-core/doc-index-C.html b/static/docs/0.1.1/snap-core/doc-index-C.html deleted file mode 100644 index f2deb53..0000000 --- a/static/docs/0.1.1/snap-core/doc-index-C.html +++ /dev/null @@ -1,294 +0,0 @@ - - -snap-core-0.1.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (C)
checkErr
checkIfDone
Chunk
CIByteString
clearContentLength
CONNECT
Cont
convStream
Cookie
1 (Type/Class)
2 (Data Constructor)
cookieDomain
cookieExpires
cookieName
cookiePath
cookieValue
countBytes
c_format_http_time
c_parse_http_time
diff --git a/static/docs/0.1.1/snap-core/doc-index-D.html b/static/docs/0.1.1/snap-core/doc-index-D.html deleted file mode 100644 index 899fb77..0000000 --- a/static/docs/0.1.1/snap-core/doc-index-D.html +++ /dev/null @@ -1,206 +0,0 @@ - - -snap-core-0.1.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (D)
debug
debugErrno
debugIteratee
defaultMimeTypes
DELETE
dir
Done
drop
dropWhile
diff --git a/static/docs/0.1.1/snap-core/doc-index-E.html b/static/docs/0.1.1/snap-core/doc-index-E.html deleted file mode 100644 index 0ff5587..0000000 --- a/static/docs/0.1.1/snap-core/doc-index-E.html +++ /dev/null @@ -1,292 +0,0 @@ - - -snap-core-0.1.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (E)
emptyResponse
Endian
endianRead2
endianRead3
endianRead4
Enum
enumBS
enumEof
Enumerator
1 (Type/Class)
2 (Type/Class)
EnumeratorGM
EnumeratorGMM
EnumeratorN
enumErr
enumFile
enumLBS
enumPair
enumPure1Chunk
enumPureNChunk
EOF
Err
ErrMsg
diff --git a/static/docs/0.1.1/snap-core/doc-index-F.html b/static/docs/0.1.1/snap-core/doc-index-F.html deleted file mode 100644 index 927dc71..0000000 --- a/static/docs/0.1.1/snap-core/doc-index-F.html +++ /dev/null @@ -1,254 +0,0 @@ - - -snap-core-0.1.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (F)
fileDriver
fileDriverRandom
FileOffset
fileServe
fileServe'
fileServeSingle
fileServeSingle'
filter
finish
finishWith
foldl
foldl'
foldl1
formatHttpTime
fromStr
fromWrap
diff --git a/static/docs/0.1.1/snap-core/doc-index-G.html b/static/docs/0.1.1/snap-core/doc-index-G.html deleted file mode 100644 index ea3dce4..0000000 --- a/static/docs/0.1.1/snap-core/doc-index-G.html +++ /dev/null @@ -1,206 +0,0 @@ - - -snap-core-0.1.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (G)
GET
getHeader
getHeaders
getParam
getRequest
getRequestBody
getResponse
getSafePath
diff --git a/static/docs/0.1.1/snap-core/doc-index-H.html b/static/docs/0.1.1/snap-core/doc-index-H.html deleted file mode 100644 index 8f4a66e..0000000 --- a/static/docs/0.1.1/snap-core/doc-index-H.html +++ /dev/null @@ -1,208 +0,0 @@ - - -snap-core-0.1.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (H)
HasHeaders
HEAD
head
Headers
headers
heads
hexd
HttpVersion
diff --git a/static/docs/0.1.1/snap-core/doc-index-I.html b/static/docs/0.1.1/snap-core/doc-index-I.html deleted file mode 100644 index 80f1c61..0000000 --- a/static/docs/0.1.1/snap-core/doc-index-I.html +++ /dev/null @@ -1,196 +0,0 @@ - - -snap-core-0.1.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (I)
identity
ifTop
isFinished
Iteratee
IterateeG
1 (Data Constructor)
2 (Type/Class)
IterGV
IterV
diff --git a/static/docs/0.1.1/snap-core/doc-index-J.html b/static/docs/0.1.1/snap-core/doc-index-J.html deleted file mode 100644 index d73d1b7..0000000 --- a/static/docs/0.1.1/snap-core/doc-index-J.html +++ /dev/null @@ -1,150 +0,0 @@ - - -snap-core-0.1.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (J)
joinI
joinIM
diff --git a/static/docs/0.1.1/snap-core/doc-index-L.html b/static/docs/0.1.1/snap-core/doc-index-L.html deleted file mode 100644 index c8b4e2b..0000000 --- a/static/docs/0.1.1/snap-core/doc-index-L.html +++ /dev/null @@ -1,188 +0,0 @@ - - -snap-core-0.1.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (L)
length
liftI
liftInner
localRequest
LooseMap
looseMap
looseMapStream
LSB
diff --git a/static/docs/0.1.1/snap-core/doc-index-M.html b/static/docs/0.1.1/snap-core/doc-index-M.html deleted file mode 100644 index 04d1147..0000000 --- a/static/docs/0.1.1/snap-core/doc-index-M.html +++ /dev/null @@ -1,202 +0,0 @@ - - -snap-core-0.1.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (M)
mapStream
Method
method
MimeMap
modifyRequest
modifyResponse
modifyResponseBody
MSB
diff --git a/static/docs/0.1.1/snap-core/doc-index-N.html b/static/docs/0.1.1/snap-core/doc-index-N.html deleted file mode 100644 index c45e07f..0000000 --- a/static/docs/0.1.1/snap-core/doc-index-N.html +++ /dev/null @@ -1,158 +0,0 @@ - - -snap-core-0.1.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (N)
NoHandlerException
1 (Type/Class)
2 (Data Constructor)
diff --git a/static/docs/0.1.1/snap-core/doc-index-O.html b/static/docs/0.1.1/snap-core/doc-index-O.html deleted file mode 100644 index d059d16..0000000 --- a/static/docs/0.1.1/snap-core/doc-index-O.html +++ /dev/null @@ -1,148 +0,0 @@ - - -snap-core-0.1.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (O)
OPTIONS
diff --git a/static/docs/0.1.1/snap-core/doc-index-P.html b/static/docs/0.1.1/snap-core/doc-index-P.html deleted file mode 100644 index c71c0ef..0000000 --- a/static/docs/0.1.1/snap-core/doc-index-P.html +++ /dev/null @@ -1,238 +0,0 @@ - - -snap-core-0.1.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (P)
Params
parseHttpTime
parseToCompletion
pass
path
peek
POST
product
pUrlEscaped
PUT
putRequest
putResponse
diff --git a/static/docs/0.1.1/snap-core/doc-index-R.html b/static/docs/0.1.1/snap-core/doc-index-R.html deleted file mode 100644 index 7c9f34c..0000000 --- a/static/docs/0.1.1/snap-core/doc-index-R.html +++ /dev/null @@ -1,530 +0,0 @@ - - -snap-core-0.1.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (R)
Request
1 (Type/Class)
2 (Data Constructor)
Response
1 (Type/Class)
2 (Data Constructor)
ResponseBody
rigidMapStream
route
routeLocal
rqBody
rqContentLength
rqContextPath
rqCookies
rqHeaders
rqIsSecure
rqLocalAddr
rqLocalHostname
rqLocalPort
rqMethod
rqModifyParams
rqParam
rqParams
rqPathInfo
rqQueryString
rqRemoteAddr
rqRemotePort
rqServerName
rqServerPort
rqSetParam
rqSnapletPath
rqURI
rqVersion
rspBody
rspBodyMap
rspBodyToEnum
rspContentLength
rspHeaders
rspHttpVersion
rspStatus
rspStatusReason
run
runIter
runRequestBody
runSnap
diff --git a/static/docs/0.1.1/snap-core/doc-index-S.html b/static/docs/0.1.1/snap-core/doc-index-S.html deleted file mode 100644 index 18abe24..0000000 --- a/static/docs/0.1.1/snap-core/doc-index-S.html +++ /dev/null @@ -1,296 +0,0 @@ - - -snap-core-0.1.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (S)
Seek
seek
SendFile
sendFile
setContentLength
setContentType
setEOF
setHeader
setResponseBody
setResponseStatus
set_c_locale
skipToEof
Snap
SomeEnumerator
1 (Type/Class)
2 (Data Constructor)
Stream
stream2list
stream2stream
StreamG
sum
diff --git a/static/docs/0.1.1/snap-core/doc-index-T.html b/static/docs/0.1.1/snap-core/doc-index-T.html deleted file mode 100644 index e6c652e..0000000 --- a/static/docs/0.1.1/snap-core/doc-index-T.html +++ /dev/null @@ -1,206 +0,0 @@ - - -snap-core-0.1.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (T)
take
takeExactly
takeNoMoreThan
takeR
throwErr
toCI
toStr
toWrap
TRACE
diff --git a/static/docs/0.1.1/snap-core/doc-index-U.html b/static/docs/0.1.1/snap-core/doc-index-U.html deleted file mode 100644 index 4e545c7..0000000 --- a/static/docs/0.1.1/snap-core/doc-index-U.html +++ /dev/null @@ -1,184 +0,0 @@ - - -snap-core-0.1.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (U)
unCI
unsafeDetachRequestBody
updateHeaders
urlDecode
urlEncode
diff --git a/static/docs/0.1.1/snap-core/doc-index-W.html b/static/docs/0.1.1/snap-core/doc-index-W.html deleted file mode 100644 index 202bf84..0000000 --- a/static/docs/0.1.1/snap-core/doc-index-W.html +++ /dev/null @@ -1,202 +0,0 @@ - - -snap-core-0.1.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (W)
withCompression
withCompression'
withRequest
withResponse
writeBS
writeLazyText
writeLBS
writeText
diff --git a/static/docs/0.1.1/snap-core/doc-index.html b/static/docs/0.1.1/snap-core/doc-index.html deleted file mode 100644 index d9c73e8..0000000 --- a/static/docs/0.1.1/snap-core/doc-index.html +++ /dev/null @@ -1,134 +0,0 @@ - - -snap-core-0.1.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)ContentsIndex
Index
ABCDEFGHIJLMNOPRSTUW>
diff --git a/static/docs/0.1.1/snap-core/fonts/DroidSerif-Bold.eot b/static/docs/0.1.1/snap-core/fonts/DroidSerif-Bold.eot deleted file mode 100644 index 01b9e1f..0000000 Binary files a/static/docs/0.1.1/snap-core/fonts/DroidSerif-Bold.eot and /dev/null differ diff --git a/static/docs/0.1.1/snap-core/fonts/DroidSerif-Bold.svg b/static/docs/0.1.1/snap-core/fonts/DroidSerif-Bold.svg deleted file mode 100644 index 1f7f2d2..0000000 --- a/static/docs/0.1.1/snap-core/fonts/DroidSerif-Bold.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.1.1/snap-core/fonts/DroidSerif-Bold.ttf b/static/docs/0.1.1/snap-core/fonts/DroidSerif-Bold.ttf deleted file mode 100644 index da0ea11..0000000 Binary files a/static/docs/0.1.1/snap-core/fonts/DroidSerif-Bold.ttf and /dev/null differ diff --git a/static/docs/0.1.1/snap-core/fonts/DroidSerif-Bold.woff b/static/docs/0.1.1/snap-core/fonts/DroidSerif-Bold.woff deleted file mode 100644 index 91549cd..0000000 Binary files a/static/docs/0.1.1/snap-core/fonts/DroidSerif-Bold.woff and /dev/null differ diff --git a/static/docs/0.1.1/snap-core/fonts/DroidSerif-BoldItalic.eot b/static/docs/0.1.1/snap-core/fonts/DroidSerif-BoldItalic.eot deleted file mode 100644 index 47dd0a0..0000000 Binary files a/static/docs/0.1.1/snap-core/fonts/DroidSerif-BoldItalic.eot and /dev/null differ diff --git a/static/docs/0.1.1/snap-core/fonts/DroidSerif-BoldItalic.svg b/static/docs/0.1.1/snap-core/fonts/DroidSerif-BoldItalic.svg deleted file mode 100644 index 1a57dbb..0000000 --- a/static/docs/0.1.1/snap-core/fonts/DroidSerif-BoldItalic.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.1.1/snap-core/fonts/DroidSerif-BoldItalic.ttf b/static/docs/0.1.1/snap-core/fonts/DroidSerif-BoldItalic.ttf deleted file mode 100644 index 8be3fb4..0000000 Binary files a/static/docs/0.1.1/snap-core/fonts/DroidSerif-BoldItalic.ttf and /dev/null differ diff --git a/static/docs/0.1.1/snap-core/fonts/DroidSerif-BoldItalic.woff b/static/docs/0.1.1/snap-core/fonts/DroidSerif-BoldItalic.woff deleted file mode 100644 index 6d5fa3d..0000000 Binary files a/static/docs/0.1.1/snap-core/fonts/DroidSerif-BoldItalic.woff and /dev/null differ diff --git a/static/docs/0.1.1/snap-core/fonts/DroidSerif-Italic.eot b/static/docs/0.1.1/snap-core/fonts/DroidSerif-Italic.eot deleted file mode 100644 index 2d4850c..0000000 Binary files a/static/docs/0.1.1/snap-core/fonts/DroidSerif-Italic.eot and /dev/null differ diff --git a/static/docs/0.1.1/snap-core/fonts/DroidSerif-Italic.svg b/static/docs/0.1.1/snap-core/fonts/DroidSerif-Italic.svg deleted file mode 100644 index 356c374..0000000 --- a/static/docs/0.1.1/snap-core/fonts/DroidSerif-Italic.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.1.1/snap-core/fonts/DroidSerif-Italic.ttf b/static/docs/0.1.1/snap-core/fonts/DroidSerif-Italic.ttf deleted file mode 100644 index 3719dc2..0000000 Binary files a/static/docs/0.1.1/snap-core/fonts/DroidSerif-Italic.ttf and /dev/null differ diff --git a/static/docs/0.1.1/snap-core/fonts/DroidSerif-Italic.woff b/static/docs/0.1.1/snap-core/fonts/DroidSerif-Italic.woff deleted file mode 100644 index b64436f..0000000 Binary files a/static/docs/0.1.1/snap-core/fonts/DroidSerif-Italic.woff and /dev/null differ diff --git a/static/docs/0.1.1/snap-core/fonts/DroidSerif-Regular.eot b/static/docs/0.1.1/snap-core/fonts/DroidSerif-Regular.eot deleted file mode 100644 index 0d17523..0000000 Binary files a/static/docs/0.1.1/snap-core/fonts/DroidSerif-Regular.eot and /dev/null differ diff --git a/static/docs/0.1.1/snap-core/fonts/DroidSerif-Regular.svg b/static/docs/0.1.1/snap-core/fonts/DroidSerif-Regular.svg deleted file mode 100644 index b9b65fb..0000000 --- a/static/docs/0.1.1/snap-core/fonts/DroidSerif-Regular.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.1.1/snap-core/fonts/DroidSerif-Regular.ttf b/static/docs/0.1.1/snap-core/fonts/DroidSerif-Regular.ttf deleted file mode 100644 index 066dcaa..0000000 Binary files a/static/docs/0.1.1/snap-core/fonts/DroidSerif-Regular.ttf and /dev/null differ diff --git a/static/docs/0.1.1/snap-core/fonts/DroidSerif-Regular.woff b/static/docs/0.1.1/snap-core/fonts/DroidSerif-Regular.woff deleted file mode 100644 index cfd3d67..0000000 Binary files a/static/docs/0.1.1/snap-core/fonts/DroidSerif-Regular.woff and /dev/null differ diff --git a/static/docs/0.1.1/snap-core/frames.html b/static/docs/0.1.1/snap-core/frames.html deleted file mode 100644 index 9e904fc..0000000 --- a/static/docs/0.1.1/snap-core/frames.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/static/docs/0.1.1/snap-core/haddock-util.js b/static/docs/0.1.1/snap-core/haddock-util.js deleted file mode 100644 index 364081f..0000000 --- a/static/docs/0.1.1/snap-core/haddock-util.js +++ /dev/null @@ -1,139 +0,0 @@ -// Haddock JavaScript utilities -function toggle(button,id) -{ - var n = document.getElementById(id).style; - if (n.display == "none") - { - button.src = "minus.gif"; - n.display = "block"; - } - else - { - button.src = "plus.gif"; - n.display = "none"; - } -} - - -var max_results = 75; // 50 is not enough to search for map in the base libraries -var shown_range = null; -var last_search = null; - -function quick_search() -{ - perform_search(false); -} - -function full_search() -{ - perform_search(true); -} - - -function perform_search(full) -{ - var text = document.getElementById("searchbox").value.toLowerCase(); - if (text == last_search && !full) return; - last_search = text; - - var table = document.getElementById("indexlist"); - var status = document.getElementById("searchmsg"); - var children = table.firstChild.childNodes; - - // first figure out the first node with the prefix - var first = bisect(-1); - var last = (first == -1 ? -1 : bisect(1)); - - if (first == -1) - { - table.className = ""; - status.innerHTML = "No results found, displaying all"; - } - else if (first == 0 && last == children.length - 1) - { - table.className = ""; - status.innerHTML = ""; - } - else if (last - first >= max_results && !full) - { - table.className = ""; - status.innerHTML = "More than " + max_results + ", press Search to display"; - } - else - { - // decide what you need to clear/show - if (shown_range) - setclass(shown_range[0], shown_range[1], "indexrow"); - setclass(first, last, "indexshow"); - shown_range = [first, last]; - table.className = "indexsearch"; - status.innerHTML = ""; - } - - - function setclass(first, last, status) - { - for (var i = first; i <= last; i++) - { - children[i].className = status; - } - } - - - // do a binary search, treating 0 as ... - // return either -1 (no 0's found) or location of most far match - function bisect(dir) - { - var first = 0, finish = children.length - 1; - var mid, success = false; - - while (finish - first > 3) - { - mid = Math.floor((finish + first) / 2); - - var i = checkitem(mid); - if (i == 0) i = dir; - if (i == -1) - finish = mid; - else - first = mid; - } - var a = (dir == 1 ? first : finish); - var b = (dir == 1 ? finish : first); - for (var i = b; i != a - dir; i -= dir) - { - if (checkitem(i) == 0) return i; - } - return -1; - } - - - // from an index, decide what the result is - // 0 = match, -1 is lower, 1 is higher - function checkitem(i) - { - var s = getitem(i).toLowerCase().substr(0, text.length); - if (s == text) return 0; - else return (s > text ? -1 : 1); - } - - - // from an index, get its string - // this abstracts over alternates - function getitem(i) - { - for ( ; i >= 0; i--) - { - var s = children[i].firstChild.firstChild.data; - if (s.indexOf(' ') == -1) - return s; - } - return ""; // should never be reached - } -} - -function setSynopsis(filename) { - if (parent.window.synopsis) { - parent.window.synopsis.location = filename; - } -} diff --git a/static/docs/0.1.1/snap-core/haddock.css b/static/docs/0.1.1/snap-core/haddock.css deleted file mode 100644 index bbe9dac..0000000 --- a/static/docs/0.1.1/snap-core/haddock.css +++ /dev/null @@ -1,478 +0,0 @@ -/* -------- Global things --------- */ - -@font-face { - font-family: 'DroidSerif'; - src: url('fonts/DroidSerif-Regular.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Regular.woff') format('woff'), - url('fonts/DroidSerif-Regular.ttf') format('truetype'), - url('fonts/DroidSerif-Regular.svg#DroidSerif') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - font-style: italic; - src: url('fonts/DroidSerif-Italic.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Italic.woff') format('woff'), - url('fonts/DroidSerif-Italic.ttf') format('truetype'), - url('fonts/DroidSerif-Italic.svg#DroidSerif-Italic') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - font-weight: bold; - src: url('fonts/DroidSerif-Bold.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Bold.woff') format('woff'), - url('fonts/DroidSerif-Bold.ttf') format('truetype'), - url('fonts/DroidSerif-Bold.svg#DroidSerif-Bold') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - src: url('fonts/DroidSerif-BoldItalic.eot'); - font-weight: bold; - font-style: italic; - src: local('Droid Serif'), - url('fonts/DroidSerif-BoldItalic.woff') format('woff'), - url('fonts/DroidSerif-BoldItalic.ttf') format('truetype'), - url('fonts/DroidSerif-BoldItalic.svg#DroidSerif-BoldItalic') format('svg'); -} - - - -HTML { - background-color: #f0f3ff; - width: 100%; -} - -BODY { - -moz-border-radius:5px; - -webkit-border-radius:5px; - width: 90ex; - margin: 2em auto; - padding: 0; - background-color: #ffffff; - color: #000000; - font-size: 110%; - font-family: DroidSerif, Georgia, serif; - } - -A:link { color: #5200A3; text-decoration: none } -A:visited { color: #5200A3; text-decoration: none } -A:hover { color: #5200A3; text-decoration: none; border-bottom:#5200A3 dashed 1px; } - -TABLE.vanilla { - width: 100%; - border-width: 0px; - /* I can't seem to specify cellspacing or cellpadding properly using CSS... */ -} - -DL { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - letter-spacing: -0.01em; - margin: 0; -} - -.vanilla .vanilla dl { font-size: 80%; } -.vanilla .vanilla dl dl { padding-left: 0; font-size: 95%; } - -TD.section1, TD.section2, TD.section3, TD.section4, TD.doc, DL { - padding: 0 30px 0 34px; -} - -TABLE.vanilla2 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - border-width: 0px; -} - -/* font is a little too small in MSIE */ -TT, PRE, CODE { - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - font-size: 90%; -} - -LI P { margin: 0pt } - -P { margin-top: 0; margin-bottom: 0.75em; } - -TD { - border-width: 0px; -} - -TABLE.narrow { - border-width: 0px; -} - -TD.s8 { height: 0; margin:0; padding: 0 } -TD.s15 { height: 20px; } - -SPAN.keyword { text-decoration: underline; } - -/* Resize the buttom image to match the text size */ -IMG.coll { width : 0.75em; height: 0.75em; margin-bottom: 0; margin-right: 0.5em } - -/* --------- Contents page ---------- */ - -DIV.node { - padding-left: 3em; -} - -DIV.cnode { - padding-left: 1.75em; -} - -SPAN.pkg { - position: absolute; - left: 50em; -} - -/* --------- Documentation elements ---------- */ - -TD FONT { font-weight: bold; letter-spacing: -0.02em; } - -TD.children { - padding-left: 25px; - } - -TD.synopsis { - padding: 2px; - background-color: #f0f0f0; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - } - -TD.decl { - padding: 4px 8px; - background-color: #FAFAFA; - border-bottom: #F2F2F2 solid 1px; - border-top: #FCFCFC solid 1px; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - vertical-align: top; - } - -TD.decl TD.decl { - font-size: 100%; - padding: 4px 0; - border: 0; -} - -TD.topdecl { - padding: 20px 30px 0.5ex 30px; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; -; - vertical-align: top; -} - -.vanilla .vanilla .vanilla .topdecl { - padding-left: 0; - padding-right: 0; -} - -.vanilla .vanilla .vanilla { - padding-left: 30px; -} - -.decl .vanilla { - padding-left: 0px !important; -} - -.body .vanilla .body { - padding-left: 0; - padding-right: 0; -} - -.body .vanilla .body .decl { - padding-left: 12px; -} - -.body .vanilla .body div .vanilla .decl { - padding-left: 12px; -} - -TABLE.declbar { - background-color: #f0f0f0; - border-spacing: 0px; - border-bottom:1px solid #d7d7df; - border-right:1px solid #d7d7df; - border-top:1px solid #f4f4f9; - border-left:1px solid #f4f4f9; - padding: 4px; - } - -TD.declname { - width: 100%; - padding-right: 4px; - } - -TD.declbut { - padding-left: 8px; - padding-right: 5px; - border-left-width: 1px; - border-left-color: #000099; - border-left-style: solid; - white-space: nowrap; - font-size: x-small; - } - -/* - arg is just like decl, except that wrapping is not allowed. It is - used for function and constructor arguments which have a text box - to the right, where if wrapping is allowed the text box squashes up - the declaration by wrapping it. -*/ -TD.arg { - padding: 2px 12px; - background-color: #f0f0f0; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - vertical-align: top; - white-space: nowrap; - } - -TD.recfield { padding-left: 20px } - -TD.doc { - padding-left: 38px; - font-size: 95%; - line-height: 1.66; - } - -TD.ndoc { - font-size: 95%; - line-height: 1.66; - padding: 2px 4px 2px 8px; - } - -TD.rdoc { - padding: 2px; - padding-left: 30px; - width: 100%; - font-size: 80%; - font-style: italic; - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - } - -TD.body { - padding: 0 30px; - } - -TD.pkg { - width: 100%; - padding-left: 30px -} - -TABLE.indexsearch TR.indexrow { - display: none; -} -TABLE.indexsearch TR.indexshow { - display: table-row; -} - -TD.indexentry { - vertical-align: top; - padding: 0 30px - } - -TD.indexannot { - vertical-align: top; - padding-left: 20px; - white-space: nowrap - } - -TD.indexlinks { - width: 100% - } - -/* ------- Section Headings ------- */ - -TD.section1, TD.section2, TD.section3, TD.section4, TD.section5 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; -} - -TD.section1 { - padding-top: 14px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 140% - } - -TD.section2 { - padding-top: 4px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 120% - } - -TD.section3 { - padding-top: 5px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 105% - } - -TD.section4 { - font-weight: bold; - padding-top: 12px; - padding-bottom: 4px; - letter-spacing: -0.02em; - font-size: 90% - } - -/* -------------- The title bar at the top of the page */ - -TD.infohead { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - font-weight: bold; - padding: 0 30px; - text-align: left; -} - -TD.infoval { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - padding: 0 30px; - text-align: left; -} - -TD.topbar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - background-color: #3465a4; - padding: 5px; - -moz-border-radius-topleft:5px; - -moz-border-radius-topright:5px; - -webkit-border-radius-topleft:5px; - -webkit-border-radius-topright:5px; -} - -TD.title { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - padding-left: 30px; - letter-spacing: -0.02em; - font-weight: bold; - width: 100% - } - -TD.topbut { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - padding-left: 5px; - padding-right: 5px; - border-left-width: 1px; - border-left-color: #ffffff; - border-left-style: solid; - letter-spacing: -0.02em; - font-weight: bold; - white-space: nowrap; - } - -TD.topbut A:link { - color: #ffffff - } - -TD.topbut A:visited { - color: #ffff00 - } - -TD.topbut A:hover { - background-color: #C9D3DE; - } - -TD.topbut:hover { - background-color: #C9D3DE; - } - -TD.modulebar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #141B24; - background-color: #C9D3DE; - padding: 5px; - border-top-width: 1px; - border-top-color: #ffffff; - border-top-style: solid; - -moz-border-radius-bottomleft:5px; - -moz-border-radius-bottomright:5px; - -webkit-border-radius-bottomleft:5px; - -webkit-border-radius-bottomright:5px; - - } - -/* --------- The page footer --------- */ - -TD.botbar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - -moz-border-radius:5px; - -webkit-border-radius:5px; - background-color: #3465a4; - color: #ffffff; - padding: 5px - } -TD.botbar A:link { - color: #ffffff; - text-decoration: underline - } -TD.botbar A:visited { - color: #ffff00 - } -TD.botbar A:hover { - background-color: #6060ff - } - -/* --------- Mini Synopsis for Frame View --------- */ - -.outer { - margin: 0 0; - padding: 0 0; -} - -.mini-synopsis { - padding: 0.25em 0.25em; -} - -.mini-synopsis H1 { font-size: 120%; } -.mini-synopsis H2 { font-size: 107%; } -.mini-synopsis H3 { font-size: 100%; } -.mini-synopsis H1, .mini-synopsis H2, .mini-synopsis H3 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - margin-top: 0.5em; - margin-bottom: 0.25em; - padding: 0 0; - font-weight: bold; letter-spacing: -0.02em; -} - -.mini-synopsis H1 { border-bottom: 1px solid #ccc; } - -.mini-topbar { - font-size: 120%; - background: #0077dd; - padding: 0.25em; -} - - diff --git a/static/docs/0.1.1/snap-core/haskell_icon.gif b/static/docs/0.1.1/snap-core/haskell_icon.gif deleted file mode 100644 index cb2a815..0000000 Binary files a/static/docs/0.1.1/snap-core/haskell_icon.gif and /dev/null differ diff --git a/static/docs/0.1.1/snap-core/index-frames.html b/static/docs/0.1.1/snap-core/index-frames.html deleted file mode 100644 index e044e74..0000000 --- a/static/docs/0.1.1/snap-core/index-frames.html +++ /dev/null @@ -1,43 +0,0 @@ - - -snap-core-0.1.1: Snap: A Haskell Web Framework (Core)

Data.CIByteString
Snap.Internal.Debug
Snap.Internal.Http.Types
Snap.Internal.Iteratee.Debug
Snap.Iteratee
Snap.Types
Snap.Util.FileServe
Snap.Util.GZip

diff --git a/static/docs/0.1.1/snap-core/index.html b/static/docs/0.1.1/snap-core/index.html deleted file mode 100644 index f4069a2..0000000 --- a/static/docs/0.1.1/snap-core/index.html +++ /dev/null @@ -1,300 +0,0 @@ - - -snap-core-0.1.1: Snap: A Haskell Web Framework (Core)
 snap-core-0.1.1: Snap: A Haskell Web Framework (Core)ContentsIndex
snap-core-0.1.1: Snap: A Haskell Web Framework (Core)

This is the first developer prerelease of the Snap framework. Snap is a -simple and fast web development framework and server written in Haskell. For -more information or to download the latest version, you can visit the Snap -project website at http://snapframework.com/. -

This library contains the core definitions and types for the Snap framework, -including: -

1. Primitive types and functions for HTTP (requests, responses, cookies, -post/query parameters, etc) -

2. Type aliases and helper functions for Iteratee I/O -

3. A monad for programming web handlers called "Snap", inspired by -happstack's (http://happstack.com/index.html), which allows: -

  • Stateful access to the HTTP request and response objects -
  • Monadic failure (i.e. MonadPlus/Alternative instances) for declining -to handle requests and chaining handlers together -
  • Early termination of the computation if you know early what you want -to return and want to prevent further monadic processing -

Quick start: The Snap monad and HTTP definitions are in Snap.Types, -some iteratee utilities are in Snap.Iteratee. -

Higher-level facilities for building web applications (like user/session -management, component interfaces, data modeling, etc.) are planned but not -yet implemented, so this release will mostly be of interest for those who: -

  • need a fast and minimal HTTP API at roughly the same level of abstraction -as Java servlets, or -
  • are interested in contributing to the Snap Framework project. -
Modules
show/hideData
Data.CIByteString
show/hideSnap
show/hideInternal
Snap.Internal.Debug
show/hideHttp
Snap.Internal.Http.Types
show/hideIteratee
Snap.Internal.Iteratee.Debug
Snap.Iteratee
Snap.Types
show/hideUtil
Snap.Util.FileServe
Snap.Util.GZip
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.1/snap-core/mini_Data-CIByteString.html b/static/docs/0.1.1/snap-core/mini_Data-CIByteString.html deleted file mode 100644 index 475b4ae..0000000 --- a/static/docs/0.1.1/snap-core/mini_Data-CIByteString.html +++ /dev/null @@ -1,35 +0,0 @@ - - -Data.CIByteString
Data.CIByteString
diff --git a/static/docs/0.1.1/snap-core/mini_Snap-Internal-Debug.html b/static/docs/0.1.1/snap-core/mini_Snap-Internal-Debug.html deleted file mode 100644 index 9f5123e..0000000 --- a/static/docs/0.1.1/snap-core/mini_Snap-Internal-Debug.html +++ /dev/null @@ -1,29 +0,0 @@ - - -Snap.Internal.Debug
Snap.Internal.Debug
diff --git a/static/docs/0.1.1/snap-core/mini_Snap-Internal-Http-Types.html b/static/docs/0.1.1/snap-core/mini_Snap-Internal-Http-Types.html deleted file mode 100644 index ce244b6..0000000 --- a/static/docs/0.1.1/snap-core/mini_Snap-Internal-Http-Types.html +++ /dev/null @@ -1,201 +0,0 @@ - - -Snap.Internal.Http.Types diff --git a/static/docs/0.1.1/snap-core/mini_Snap-Internal-Iteratee-Debug.html b/static/docs/0.1.1/snap-core/mini_Snap-Internal-Iteratee-Debug.html deleted file mode 100644 index c622c16..0000000 --- a/static/docs/0.1.1/snap-core/mini_Snap-Internal-Iteratee-Debug.html +++ /dev/null @@ -1,25 +0,0 @@ - - -Snap.Internal.Iteratee.Debug
Snap.Internal.Iteratee.Debug
diff --git a/static/docs/0.1.1/snap-core/mini_Snap-Iteratee.html b/static/docs/0.1.1/snap-core/mini_Snap-Iteratee.html deleted file mode 100644 index bf606a7..0000000 --- a/static/docs/0.1.1/snap-core/mini_Snap-Iteratee.html +++ /dev/null @@ -1,107 +0,0 @@ - - -Snap.Iteratee
Snap.Iteratee

Convenience aliases around types from Data.Iteratee -

type Stream
type IterV m
type Iteratee m
type Enumerator m a

Re-export types and functions from Data.Iteratee -

Helper functions -

Enumerators -

Conversion to/from WrappedByteString -

Iteratee utilities -

diff --git a/static/docs/0.1.1/snap-core/mini_Snap-Types.html b/static/docs/0.1.1/snap-core/mini_Snap-Types.html deleted file mode 100644 index c751abe..0000000 --- a/static/docs/0.1.1/snap-core/mini_Snap-Types.html +++ /dev/null @@ -1,379 +0,0 @@ - - -Snap.Types diff --git a/static/docs/0.1.1/snap-core/mini_Snap-Util-FileServe.html b/static/docs/0.1.1/snap-core/mini_Snap-Util-FileServe.html deleted file mode 100644 index 0ea73e5..0000000 --- a/static/docs/0.1.1/snap-core/mini_Snap-Util-FileServe.html +++ /dev/null @@ -1,51 +0,0 @@ - - -Snap.Util.FileServe diff --git a/static/docs/0.1.1/snap-core/mini_Snap-Util-GZip.html b/static/docs/0.1.1/snap-core/mini_Snap-Util-GZip.html deleted file mode 100644 index 93f3163..0000000 --- a/static/docs/0.1.1/snap-core/mini_Snap-Util-GZip.html +++ /dev/null @@ -1,29 +0,0 @@ - - -Snap.Util.GZip diff --git a/static/docs/0.1.1/snap-core/minus.gif b/static/docs/0.1.1/snap-core/minus.gif deleted file mode 100644 index 1deac2f..0000000 Binary files a/static/docs/0.1.1/snap-core/minus.gif and /dev/null differ diff --git a/static/docs/0.1.1/snap-core/plus.gif b/static/docs/0.1.1/snap-core/plus.gif deleted file mode 100644 index 2d15c14..0000000 Binary files a/static/docs/0.1.1/snap-core/plus.gif and /dev/null differ diff --git a/static/docs/0.1.1/snap-core/snap-core.haddock b/static/docs/0.1.1/snap-core/snap-core.haddock deleted file mode 100644 index 063dce3..0000000 Binary files a/static/docs/0.1.1/snap-core/snap-core.haddock and /dev/null differ diff --git a/static/docs/0.1.1/snap-core/src/Data-CIByteString.html b/static/docs/0.1.1/snap-core/src/Data-CIByteString.html deleted file mode 100644 index f98fa2e..0000000 --- a/static/docs/0.1.1/snap-core/src/Data-CIByteString.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - -src/Data/CIByteString.hs - - - -
{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE OverloadedStrings #-}
-
--- | "Data.CIByteString" is a module containing 'CIByteString', a wrapper for
--- 'ByteString' which provides case-insensitive (ASCII-wise) 'Ord' and 'Eq'
--- instances.
---
--- 'CIByteString' also has an 'IsString' instance, so if you use the
--- \"OverloadedStrings\" LANGUAGE pragma you can write case-insensitive string
--- literals, e.g.:
---
--- @
--- \> let a = \"Foo\" in
---   putStrLn $ (show $ unCI a) ++ \"==\\\"FoO\\\" is \" ++ show (a == \"FoO\")
--- \"Foo\"==\"FoO\" is True
--- @
-
-module Data.CIByteString
- ( CIByteString
- , toCI
- , unCI
- ) where
-
--- for IsString instance
-import           Data.ByteString.Char8 ()
-import           Data.ByteString (ByteString)
-import           Data.ByteString.Internal (c2w, w2c)
-import qualified Data.ByteString as S
-import           Data.Char
-import           Data.String
-
-
--- | A case-insensitive newtype wrapper for 'ByteString'
-data CIByteString = CIByteString { unCI        :: !ByteString
-                                 , _lowercased :: !ByteString }
-
-toCI :: ByteString -> CIByteString
-toCI s = CIByteString s t
-  where
-    t = lowercase s
-
-instance Show CIByteString where
-    show (CIByteString s _) = show s
-
-lowercase :: ByteString -> ByteString
-lowercase = S.map (c2w . toLower . w2c)
-
-instance Eq CIByteString where
-    (CIByteString _ a) == (CIByteString _ b) = a == b
-    (CIByteString _ a) /= (CIByteString _ b) = a /= b
-
-instance Ord CIByteString where
-    (CIByteString _ a) <= (CIByteString _ b) = a <= b
-
-instance IsString CIByteString where
-    fromString = toCI . fromString
-
- diff --git a/static/docs/0.1.1/snap-core/src/Snap-Internal-Debug.html b/static/docs/0.1.1/snap-core/src/Snap-Internal-Debug.html deleted file mode 100644 index c295589..0000000 --- a/static/docs/0.1.1/snap-core/src/Snap-Internal-Debug.html +++ /dev/null @@ -1,86 +0,0 @@ - - - - -src/Snap/Internal/Debug.hs - - - -
-- | An internal Snap module for (optionally) printing debugging
--- messages. Normally 'debug' does nothing, but you can pass \"-fdebug\" to
--- @cabal install@ to build a @snap-core@ which debugs to stderr.
---
--- /N.B./ this is an internal interface, please don't write external code that
--- depends on it.
-
-{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE CPP #-}
-
-module Snap.Internal.Debug where
-
-import           Control.Monad.Trans
-
-#ifdef DEBUG_TEST
-
-debug :: (MonadIO m) => String -> m ()
-debug !s = return $ s `seq` ()
-{-# INLINE debug #-}
-
-debugErrno :: (MonadIO m) => String -> m ()
-debugErrno !s = return $ s `seq` ()
-
-#elif defined(DEBUG)
-
-------------------------------------------------------------------------------
-import           Control.Concurrent
-import           Data.List
-import           Data.Maybe
-import           Foreign.C.Error
-import           System.IO
-import           System.IO.Unsafe
-import           Text.Printf
-------------------------------------------------------------------------------
-
-
-------------------------------------------------------------------------------
-_debugMVar :: MVar ()
-_debugMVar = unsafePerformIO $ newMVar ()
-
-
-------------------------------------------------------------------------------
-debug :: (MonadIO m) => String -> m ()
-debug s = liftIO $ withMVar _debugMVar $ \_ -> do
-              tid <- myThreadId
-              hPutStrLn stderr $ s' tid
-              hFlush stderr
-  where
-    chop x = let y = fromMaybe x $ stripPrefix "ThreadId " x
-             in printf "%8s" y
-
-    s' t   = "[" ++ chop (show t) ++ "] " ++ s
-
-{-# INLINE debug #-}
-
-
-------------------------------------------------------------------------------
-debugErrno :: (MonadIO m) => String -> m ()
-debugErrno loc = liftIO $ do
-    err <- getErrno
-    let ex = errnoToIOError loc err Nothing Nothing
-    debug $ show ex
-------------------------------------------------------------------------------
-
-#else
-
-------------------------------------------------------------------------------
-debug :: (MonadIO m) => String -> m ()
-debug _ = return ()
-{-# INLINE debug #-}
-
-debugErrno :: (MonadIO m) => String -> m ()
-debugErrno _ = return ()
-------------------------------------------------------------------------------
-
-#endif
-
- diff --git a/static/docs/0.1.1/snap-core/src/Snap-Internal-Http-Types.html b/static/docs/0.1.1/snap-core/src/Snap-Internal-Http-Types.html deleted file mode 100644 index 44d3120..0000000 --- a/static/docs/0.1.1/snap-core/src/Snap-Internal-Http-Types.html +++ /dev/null @@ -1,648 +0,0 @@ - - - - -src/Snap/Internal/Http/Types.hs - - - -
-- | An internal Snap module containing HTTP types.
---
--- /N.B./ this is an internal interface, please don't write user code that
--- depends on it. Most of these declarations (except for the
--- unsafe/encapsulation-breaking ones) are re-exported from "Snap.Types".
-
-{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE EmptyDataDecls #-}
-{-# LANGUAGE ForeignFunctionInterface #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RankNTypes #-}
-{-# LANGUAGE TypeSynonymInstances #-}
-
-module Snap.Internal.Http.Types where
-
-
-------------------------------------------------------------------------------
-import           Control.Applicative hiding (empty)
-import           Control.Monad (liftM, when)
-import qualified Data.Attoparsec as Atto
-import           Data.Attoparsec hiding (many, Result(..))
-import           Data.Bits
-import           Data.ByteString (ByteString)
-import           Data.ByteString.Internal (c2w,w2c)
-import qualified Data.ByteString.Nums.Careless.Hex as Cvt
-import qualified Data.ByteString as S
-import           Data.Char
-import           Data.DList (DList)
-import qualified Data.DList as DL
-import           Data.IORef
-import           Data.Map (Map)
-import qualified Data.Map as Map
-import           Data.Monoid
-import           Data.Serialize.Builder
-import           Data.Time.Clock
-import           Data.Time.Format
-import           Data.Word
-import           Foreign hiding (new)
-import           Foreign.C.String
-import           Foreign.C.Types
-import           Prelude hiding (take)
-import           System.Locale (defaultTimeLocale)
-
-------------------------------------------------------------------------------
-import           Data.CIByteString
-import qualified Snap.Iteratee as I
-
-
-------------------------------------------------------------------------------
-foreign import ccall unsafe "set_c_locale"
-        set_c_locale :: IO ()
-
-
-------------------------------------------------------------------------------
-foreign import ccall unsafe "c_parse_http_time"
-        c_parse_http_time :: CString -> IO CTime
-
-
-------------------------------------------------------------------------------
-foreign import ccall unsafe "c_format_http_time"
-        c_format_http_time :: CTime -> CString -> IO ()
-
-------------------------------------------------------------------------------
-type Enumerator a = I.Enumerator IO a
-
-------------------------------------------------------------------------------
--- | A type alias for a case-insensitive key-value mapping.
-type Headers = Map CIByteString [ByteString]
-
-
-------------------------------------------------------------------------------
--- | A typeclass for datatypes which contain HTTP headers.
-class HasHeaders a where
-
-    -- | Modify the datatype's headers.
-    updateHeaders :: (Headers -> Headers) -> a -> a
-
-    -- | Retrieve the headers from a datatype that has headers.
-    headers       :: a -> Headers
-
-
-------------------------------------------------------------------------------
--- | Adds a header key-value-pair to the 'HasHeaders' datatype. If a header with
--- the same name already exists, the new value is appended to the headers list.
-addHeader :: (HasHeaders a) => CIByteString -> ByteString -> a -> a
-addHeader k v = updateHeaders $ Map.insertWith' (++) k [v]
-
-
-------------------------------------------------------------------------------
--- | Sets a header key-value-pair in a 'HasHeaders' datatype. If a header with
--- the same name already exists, it is overwritten with the new value.
-setHeader :: (HasHeaders a) => CIByteString -> ByteString -> a -> a
-setHeader k v = updateHeaders $ Map.insert k [v]
-
-
-------------------------------------------------------------------------------
--- | Gets all of the values for a given header.
-getHeaders :: (HasHeaders a) => CIByteString -> a -> Maybe [ByteString]
-getHeaders k a = Map.lookup k $ headers a
-
-
-------------------------------------------------------------------------------
--- | Gets a header value out of a 'HasHeaders' datatype. If many headers came
--- in with the same name, they will be catenated together.
-getHeader :: (HasHeaders a) => CIByteString -> a -> Maybe ByteString
-getHeader k a = liftM (S.intercalate " ") (Map.lookup k $ headers a)
-
-
-------------------------------------------------------------------------------
--- | Enumerates the HTTP method values (see
--- <http://tools.ietf.org/html/rfc2068.html#section-5.1.1>).
-data Method  = GET | HEAD | POST | PUT | DELETE | TRACE | OPTIONS | CONNECT
-               deriving(Show,Read,Ord,Eq)
-
-
-------------------------------------------------------------------------------
-type HttpVersion = (Int,Int)
-
-
-------------------------------------------------------------------------------
--- | A datatype representing an HTTP cookie.
-data Cookie = Cookie {
-      -- | The name of the cookie.
-      cookieName    :: !ByteString
-
-      -- | The cookie's string value.
-    , cookieValue   :: !ByteString
-
-      -- | The cookie's expiration value, if it has one.
-    , cookieExpires :: !(Maybe UTCTime)
-
-      -- | The cookie's \"domain\" value, if it has one.
-    , cookieDomain  :: !(Maybe ByteString)
-
-      -- | The cookie path.
-    , cookiePath    :: !(Maybe ByteString)
-} deriving (Eq, Show)
-
-
-------------------------------------------------------------------------------
--- | A type alias for the HTTP parameters mapping. Each parameter
--- key maps to a list of ByteString values; if a parameter is specified
--- multiple times (e.g.: \"@GET /foo?param=bar1&param=bar2@\"), looking up
--- \"@param@\" in the mapping will give you @[\"bar1\", \"bar2\"]@.
-type Params = Map ByteString [ByteString]
-
-
-------------------------------------------------------------------------------
--- request type
-------------------------------------------------------------------------------
-
-data SomeEnumerator = SomeEnumerator (forall a . Enumerator a)
-
-
-------------------------------------------------------------------------------
--- | Contains all of the information about an incoming HTTP request.
-data Request = Request
-    { -- | The server name of the request, as it came in from the request's
-      -- @Host:@ header.
-      rqServerName     :: !ByteString
-
-      -- | Returns the port number the HTTP server is listening on.
-    , rqServerPort     :: !Int
-
-      -- | The remote IP address.
-    , rqRemoteAddr     :: !ByteString
-
-      -- | The remote TCP port number.
-    , rqRemotePort     :: !Int
-
-      -- | The local IP address for this request.
-    , rqLocalAddr      :: !ByteString
-
-      -- | Returns the port number the HTTP server is listening on.
-    , rqLocalPort      :: !Int
-
-      -- | Returns the HTTP server's idea of its local hostname.
-    , rqLocalHostname  :: !ByteString
-
-      -- | Returns @True@ if this is an @HTTPS@ session (currently always
-      -- @False@).
-    , rqIsSecure       :: !Bool
-    , rqHeaders        :: Headers
-    , rqBody           :: IORef SomeEnumerator
-
-      -- | Returns the @Content-Length@ of the HTTP request body.
-    , rqContentLength  :: !(Maybe Int)
-
-      -- | Returns the HTTP request method.
-    , rqMethod         :: !Method
-
-      -- | Returns the HTTP version used by the client.
-    , rqVersion        :: !HttpVersion
-
-      -- | Returns a list of the cookies that came in from the HTTP request
-      -- headers.
-    , rqCookies        :: [Cookie]
-
-
-      -- | We'll be doing web components (or \"snaplets\") for version 0.2. The
-      -- \"snaplet path\" refers to the place on the URL where your containing
-      -- snaplet is hung. The value of 'rqSnapletPath' is either @\"\"@ (at the
-      -- top-level context) or is a path beginning with a slash, but not ending
-      -- with one.
-      --
-      -- An identity is that:
-      --
-      -- > rqURI r == 'S.concat' [ rqSnapletPath r
-      -- >                       , rqContextPath r
-      -- >                       , rqPathInfo r ]
-      --
-      -- note that until we introduce snaplets in v0.2, 'rqSnapletPath' will be
-      -- \"\"
-    , rqSnapletPath    :: !ByteString
-
-      -- | Handlers can (/will be; --ed/) be hung on a @URI@ \"entry point\";
-      -- this is called the \"context path\". If a handler is hung on the
-      -- context path @\"\/foo\/\"@, and you request @\"\/foo\/bar\"@, the value
-      -- of 'rqPathInfo' will be @\"bar\"@.
-    , rqPathInfo       :: !ByteString
-
-      -- | The \"context path\" of the request; catenating 'rqContextPath', and
-      -- 'rqPathInfo' should get you back to the original 'rqURI'. The
-      -- 'rqContextPath' always begins and ends with a slash (@\"\/\"@)
-      -- character, and represents the path (relative to your
-      -- component\/snaplet) you took to get to your handler.
-    , rqContextPath    :: !ByteString
-
-      -- | Returns the @URI@ requested by the client.
-    , rqURI            :: !ByteString
-
-      -- | Returns the HTTP query string for this 'Request'.
-    , rqQueryString    :: !ByteString
-
-      -- | Returns the 'Params' mapping for this 'Request'. \"Parameters\" are
-      -- automatically decoded from the query string and @POST@ body and
-      -- entered into this mapping.
-    , rqParams         :: Params
-    }
-
-
-------------------------------------------------------------------------------
-instance Show Request where
-  show r = concat [ "Request <\n"
-                  , body
-                  , ">" ]
-    where
-      body = concat $ map (("    "++) . (++ "\n")) [
-                      sname
-                    , remote
-                    , local
-                    , beginheaders
-                    , hdrs
-                    , endheaders
-                    , contentlength
-                    , method
-                    , version
-                    , cookies
-                    , pathinfo
-                    , contextpath
-                    , snapletpath
-                    , uri
-                    , params
-                    ]
-
-      sname         = concat [ "server-name: ", toStr $ rqServerName r ]
-      remote        = concat [ "remote: "
-                             , toStr $ rqRemoteAddr r
-                             , ":"
-                             , show (rqRemotePort r)
-                             ]
-      local         = concat [ "local: "
-                             , toStr $ rqLocalAddr r
-                             , ":"
-                             , show $ rqServerPort r
-                             ]
-      beginheaders  = "Headers:\n      ========================================"
-      endheaders    = "  ========================================"
-      hdrs          = "      " ++ show (rqHeaders r)
-      contentlength = concat [ "content-length: "
-                             , show $ rqContentLength r
-                             ]
-      method        = concat [ "method: "
-                             , show $ rqMethod r
-                             ]
-      version       = concat [ "version: "
-                             , show $ rqVersion r
-                             ]
-      cookies       = concat [ "cookies:\n"
-                             , "      ========================================\n"
-                             , "      " ++ (show $ rqCookies r)
-                             , "\n      ========================================"
-                             ]
-      pathinfo      = concat [ "pathinfo: ", toStr $ rqPathInfo r ]
-      contextpath   = concat [ "contextpath: ", toStr $ rqContextPath r ]
-      snapletpath   = concat [ "snapletpath: ", toStr $ rqSnapletPath r ]
-      uri           = concat [ "URI: ", toStr $ rqURI r ]
-      params        = concat [ "params:\n"
-                             , "      ========================================\n"
-                             , "      " ++ (show $ rqParams r)
-                             , "\n      ========================================"
-                             ]
-
-
-------------------------------------------------------------------------------
-instance HasHeaders Request where
-    headers           = rqHeaders
-    updateHeaders f r = r { rqHeaders = f (rqHeaders r) }
-
-
-------------------------------------------------------------------------------
-instance HasHeaders Headers where
-    headers       = id
-    updateHeaders = id
-
-------------------------------------------------------------------------------
--- response type
-------------------------------------------------------------------------------
-
-data ResponseBody = Enum (forall a . Enumerator a) -- ^ output body is enumerator
-                  | SendFile FilePath              -- ^ output body is sendfile()
-
-
-------------------------------------------------------------------------------
-rspBodyMap :: (forall a . Enumerator a -> Enumerator a)
-           -> ResponseBody
-           -> ResponseBody
-rspBodyMap f b      = Enum $ f $ rspBodyToEnum b
-
-
-------------------------------------------------------------------------------
-rspBodyToEnum :: ResponseBody -> Enumerator a
-rspBodyToEnum (Enum e) = e
-rspBodyToEnum (SendFile fp) = I.enumFile fp
-
-
-------------------------------------------------------------------------------
--- | Represents an HTTP response.
-data Response = Response
-    { rspHeaders       :: Headers
-    , rspHttpVersion   :: !HttpVersion
-
-      -- | We will need to inspect the content length no matter what, and
-      --   looking up \"content-length\" in the headers and parsing the number
-      --   out of the text will be too expensive.
-    , rspContentLength :: !(Maybe Int)
-    , rspBody          :: ResponseBody
-
-      -- | Returns the HTTP status code.
-    , rspStatus        :: !Int
-
-      -- | Returns the HTTP status explanation string.
-    , rspStatusReason  :: !ByteString
-    }
-
-
-------------------------------------------------------------------------------
-instance Show Response where
-  show r = concat [ "Response <\n"
-                  , body
-                  , ">" ]
-    where
-      body = concat $ map (("    "++) . (++ "\n")) [
-                         hdrs
-                       , version
-                       , status
-                       , reason
-                       ]
-
-      hdrs    = concat [ "headers:\n"
-                       , "      ==============================\n      "
-                       , show $ rspHeaders r
-                       , "\n      ==============================" ]
-
-      version = concat [ "version: ", show $ rspHttpVersion r ]
-      status  = concat [ "status: ", show $ rspStatus r ]
-      reason  = concat [ "reason: ", toStr $ rspStatusReason r ]
-
-
-------------------------------------------------------------------------------
-instance HasHeaders Response where
-    headers = rspHeaders
-    updateHeaders f r = r { rspHeaders = f (rspHeaders r) }
-
-
-------------------------------------------------------------------------------
--- | Looks up the value(s) for the given named parameter. Parameters initially
--- come from the request's query string and any decoded POST body (if the
--- request's @Content-Type@ is @application\/x-www-form-urlencoded@). Parameter
--- values can be modified within handlers using "rqModifyParams".
-rqParam :: ByteString           -- ^ parameter name to look up
-        -> Request              -- ^ HTTP request
-        -> Maybe [ByteString]
-rqParam k rq = Map.lookup k $ rqParams rq
-{-# INLINE rqParam #-}
-
-
-------------------------------------------------------------------------------
--- | Modifies the parameters mapping (which is a @Map ByteString ByteString@) in
--- a 'Request' using the given function.
-rqModifyParams :: (Params -> Params) -> Request -> Request
-rqModifyParams f r = r { rqParams = p }
-  where
-    p = f $ rqParams r
-{-# INLINE rqModifyParams #-}
-
-
-------------------------------------------------------------------------------
--- | Writes a key-value pair to the parameters mapping within the given request.
-rqSetParam :: ByteString        -- ^ parameter name
-           -> [ByteString]      -- ^ parameter values
-           -> Request           -- ^ request
-           -> Request
-rqSetParam k v = rqModifyParams $ Map.insert k v
-{-# INLINE rqSetParam #-}
-
-------------------------------------------------------------------------------
--- responses
-------------------------------------------------------------------------------
-
--- | An empty 'Response'.
-emptyResponse       :: Response
-emptyResponse       = Response Map.empty (1,1) Nothing (Enum return) 200 "OK"
-
-
-------------------------------------------------------------------------------
--- | Sets an HTTP response body to the given 'Enumerator' value.
-setResponseBody     :: (forall a . Enumerator a)  -- ^ new response body
-                                                  -- enumerator
-                    -> Response                   -- ^ response to modify
-                    -> Response
-setResponseBody e r = r { rspBody = Enum e }
-{-# INLINE setResponseBody #-}
-
-
-------------------------------------------------------------------------------
--- | Sets the HTTP response status.
-setResponseStatus   :: Int        -- ^ HTTP response integer code
-                    -> ByteString -- ^ HTTP response explanation
-                    -> Response   -- ^ Response to be modified
-                    -> Response
-setResponseStatus s reason r = r { rspStatus=s, rspStatusReason=reason }
-{-# INLINE setResponseStatus #-}
-
-
-------------------------------------------------------------------------------
--- | Modifies a response body.
-modifyResponseBody  :: (forall a . Enumerator a -> Enumerator a)
-                    -> Response
-                    -> Response
-modifyResponseBody f r = r { rspBody = rspBodyMap f (rspBody r) }
-{-# INLINE modifyResponseBody #-}
-
-
-------------------------------------------------------------------------------
--- | Sets the @Content-Type@ in the 'Response' headers.
-setContentType      :: ByteString -> Response -> Response
-setContentType = setHeader "Content-Type"
-{-# INLINE setContentType #-}
-
-
-------------------------------------------------------------------------------
--- | Adds an HTTP 'Cookie' to the 'Response' headers.
-addCookie :: Cookie            -- ^ cookie value
-          -> Response          -- ^ response to modify
-          -> Response
-addCookie (Cookie k v mbExpTime mbDomain mbPath) = updateHeaders f
-  where
-    f       = Map.insertWith' (++) "Set-Cookie" [cookie]
-    cookie  = S.concat [k, "=", v, path, exptime, domain]
-    path    = maybe "" (S.append "; path=") mbPath
-    domain  = maybe "" (S.append "; domain=") mbDomain
-    exptime = maybe "" (S.append "; expires=" . fmt) mbExpTime
-    fmt     = fromStr . formatTime defaultTimeLocale "%a, %d-%b-%Y %H:%M:%S GMT"
-
-
-------------------------------------------------------------------------------
--- | A note here: if you want to set the @Content-Length@ for the response,
--- Snap forces you to do it with this function rather than by setting it in the
--- headers; the @Content-Length@ in the headers will be ignored.
---
--- The reason for this is that Snap needs to look up the value of
--- @Content-Length@ for each request, and looking the string value up in the
--- headers and parsing the number out of the text will be too expensive.
---
--- If you don't set a content length in your response, HTTP keep-alive will be
--- disabled for HTTP\/1.0 clients, forcing a @Connection: close@. For HTTP\/1.1
--- clients, Snap will switch to the chunked transfer encoding if
--- @Content-Length@ is not specified.
-setContentLength    :: Int -> Response -> Response
-setContentLength l r = r { rspContentLength = Just l }
-{-# INLINE setContentLength #-}
-
-
-------------------------------------------------------------------------------
--- | Removes any @Content-Length@ set in the 'Response'.
-clearContentLength :: Response -> Response
-clearContentLength r = r { rspContentLength = Nothing }
-{-# INLINE clearContentLength #-}
-
-
-------------------------------------------------------------------------------
--- HTTP dates
-
-{-
--- | Converts a 'ClockTime' into an HTTP timestamp.
-formatHttpTime :: UTCTime -> ByteString
-formatHttpTime = fromStr . formatTime defaultTimeLocale "%a, %d %b %Y %X GMT"
-
--- | Converts an HTTP timestamp into a 'UTCTime'.
-parseHttpTime :: ByteString -> Maybe UTCTime
-parseHttpTime s' =
-    parseTime defaultTimeLocale "%a, %d %b %Y %H:%M:%S GMT" s
-  where
-    s = toStr s'
--}
-
--- | Converts a 'CTime' into an HTTP timestamp.
-formatHttpTime :: CTime -> IO ByteString
-formatHttpTime t = allocaBytes 40 $ \ptr -> do
-    c_format_http_time t ptr
-    S.packCString ptr
-
-
-------------------------------------------------------------------------------
--- | Converts an HTTP timestamp into a 'CTime'.
-parseHttpTime :: ByteString -> IO CTime
-parseHttpTime s = S.useAsCString s $ \ptr ->
-    c_parse_http_time ptr
-
-
-------------------------------------------------------------------------------
--- URL ENCODING
-------------------------------------------------------------------------------
-
-parseToCompletion :: Parser a -> ByteString -> Maybe a
-parseToCompletion p s = toResult $ finish r
-  where
-    r = parse p s
-
-    toResult (Atto.Done _ c) = Just c
-    toResult _               = Nothing
-
-
-------------------------------------------------------------------------------
-pUrlEscaped :: Parser ByteString
-pUrlEscaped = do
-    sq <- nextChunk DL.empty
-    return $ S.concat $ DL.toList sq
-
-  where
-    nextChunk :: DList ByteString -> Parser (DList ByteString)
-    nextChunk s = (endOfInput *> pure s) <|> do
-        c <- anyWord8
-        case w2c c of
-          '+' -> plusSpace s
-          '%' -> percentEncoded s
-          _   -> unEncoded c s
-
-    percentEncoded :: DList ByteString -> Parser (DList ByteString)
-    percentEncoded l = do
-        hx <- take 2
-        when (S.length hx /= 2 ||
-               (not $ S.all (isHexDigit . w2c) hx)) $
-             fail "bad hex in url"
-          
-        let code = (Cvt.hex hx) :: Word8
-        nextChunk $ DL.snoc l (S.singleton code)
-
-    unEncoded :: Word8 -> DList ByteString -> Parser (DList ByteString)
-    unEncoded c l' = do
-        let l = DL.snoc l' (S.singleton c)
-        bs <- takeTill (flip elem (map c2w "%+"))
-        if S.null bs
-          then nextChunk l
-          else nextChunk $ DL.snoc l bs
-
-    plusSpace :: DList ByteString -> Parser (DList ByteString)
-    plusSpace l = nextChunk (DL.snoc l (S.singleton $ c2w ' '))
-
-
-------------------------------------------------------------------------------
--- | Decodes an URL-escaped string (see
--- <http://tools.ietf.org/html/rfc2396.html#section-2.4>)
-urlDecode :: ByteString -> Maybe ByteString
-urlDecode = parseToCompletion pUrlEscaped
-
-
-------------------------------------------------------------------------------
--- "...Only alphanumerics [0-9a-zA-Z], the special characters "$-_.+!*'(),"
--- [not including the quotes - ed], and reserved characters used for their
--- reserved purposes may be used unencoded within a URL."
-
--- | URL-escapes a string (see
--- <http://tools.ietf.org/html/rfc2396.html#section-2.4>)
-urlEncode :: ByteString -> ByteString
-urlEncode = toByteString . S.foldl' f empty
-  where
-    f b c =
-        if c == c2w ' '
-          then b `mappend` singleton (c2w '+')
-          else if isKosher c
-                 then b `mappend` singleton c
-                 else b `mappend` hexd c
-
-    isKosher w = any ($ c) [ isAlphaNum
-                           , flip elem ['$', '-', '.', '!', '*'
-                                       , '\'', '(', ')', ',' ]]
-      where
-        c = w2c w
-
-
-------------------------------------------------------------------------------
-hexd :: Word8 -> Builder
-hexd c = singleton (c2w '%') `mappend` singleton hi `mappend` singleton low
-  where
-    d   = c2w . intToDigit
-    low = d $ fromEnum $ c .&. 0xf
-    hi  = d $ fromEnum $ (c .&. 0xf0) `shift` (-4)
-
-
-------------------------------------------------------------------------------
-finish :: Atto.Result a -> Atto.Result a
-finish (Atto.Partial f) = flip feed "" $ f ""
-finish x                = x
-
-
-------------------------------------------------------------------------------
--- local definitions
-fromStr :: String -> ByteString
-fromStr = S.pack . map c2w
-{-# INLINE fromStr #-}
-
-------------------------------------------------------------------------------
--- private helper functions
-toStr :: ByteString -> String
-toStr = map w2c . S.unpack
-
-
- diff --git a/static/docs/0.1.1/snap-core/src/Snap-Internal-Iteratee-Debug.html b/static/docs/0.1.1/snap-core/src/Snap-Internal-Iteratee-Debug.html deleted file mode 100644 index 972fc9d..0000000 --- a/static/docs/0.1.1/snap-core/src/Snap-Internal-Iteratee-Debug.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - -src/Snap/Internal/Iteratee/Debug.hs - - - -
-- | An internal Snap module for debugging iteratees.
---
--- /N.B./ this is an internal interface, please don't write user code that
--- depends on it.
-
-{-# OPTIONS_GHC -fno-warn-orphans #-}
-{-# LANGUAGE FlexibleInstances #-}
-
-module Snap.Internal.Iteratee.Debug ( debugIteratee ) where
-
-------------------------------------------------------------------------------
-import           Data.Iteratee.WrappedByteString
-import           Data.Word (Word8)
-import           System.IO
-------------------------------------------------------------------------------
-import           Snap.Iteratee
-------------------------------------------------------------------------------
-
-
-------------------------------------------------------------------------------
-instance Show (WrappedByteString Word8) where
-    show (WrapBS s) = show s
-
-
-------------------------------------------------------------------------------
-debugIteratee :: Iteratee IO ()
-debugIteratee = IterateeG f
-  where
-    f c@(EOF _) = do
-        putStrLn $ "got chunk: " ++ show c
-        hFlush stdout
-        return (Done () c)
-
-    f c@(Chunk _) = do
-        putStrLn $ "got chunk: " ++ show c
-        hFlush stdout
-        return $ Cont debugIteratee Nothing
-
- diff --git a/static/docs/0.1.1/snap-core/src/Snap-Internal-Routing.html b/static/docs/0.1.1/snap-core/src/Snap-Internal-Routing.html deleted file mode 100644 index ab4539e..0000000 --- a/static/docs/0.1.1/snap-core/src/Snap-Internal-Routing.html +++ /dev/null @@ -1,195 +0,0 @@ - - - - -src/Snap/Internal/Routing.hs - - - -
module Snap.Internal.Routing where
-
-
-------------------------------------------------------------------------------
-import           Control.Applicative ((<|>))
-import           Data.ByteString (ByteString)
-import           Data.ByteString.Internal (c2w)
-import qualified Data.ByteString as B
-import           Data.Monoid
-import qualified Data.Map as Map
-
-------------------------------------------------------------------------------
-import           Snap.Internal.Http.Types
-import           Snap.Internal.Types
-
-
-------------------------------------------------------------------------------
-{-|
-
-The internal data type you use to build a routing tree.  Matching is
-done unambiguously.
-
-'Capture' and 'Dir' routes can have a "fallback" route:
-
-  - For 'Capture', the fallback is routed when there is nothing to capture
-  - For 'Dir', the fallback is routed when we can't find a route in its map
-
-Fallback routes are stacked: i.e. for a route like:
-
-> Dir [("foo", Capture "bar" (Action bar) NoRoute)] baz
-
-visiting the URI foo/ will result in the "bar" capture being empty and
-triggering its fallback. It's NoRoute, so we go to the nearest parent
-fallback and try that, which is the baz action.
-
--}
-data Route a = Action (Snap a)                        -- wraps a 'Snap' action
-             | Capture ByteString (Route a) (Route a) -- captures the dir in a param
-             | Dir (Map.Map ByteString (Route a)) (Route a)  -- match on a dir
-             | NoRoute
-
-
-------------------------------------------------------------------------------
-instance Monoid (Route a) where
-    mempty = NoRoute
-
-    -- Unions two routes, favoring the right-hand side
-    mappend NoRoute r = r
-
-    mappend l@(Action _) r = case r of
-      (Action _)        -> r
-      (Capture p r' fb) -> Capture p r' (mappend fb l)
-      (Dir _ _)         -> mappend (Dir Map.empty l) r
-      NoRoute           -> l
-
-    mappend l@(Capture p r' fb) r = case r of
-      (Action _)           -> Capture p r' (mappend fb r)
-      (Capture p' r'' fb')
-               | p == p'   -> Capture p (mappend r' r'') (mappend fb fb')
-               | otherwise -> r
-      (Dir rm fb')         -> Dir rm (mappend fb' l)
-      NoRoute              -> l
-
-    mappend l@(Dir rm fb) r = case r of
-      (Action _)      -> Dir rm (mappend fb r)
-      (Capture _ _ _) -> Dir rm (mappend fb r)
-      (Dir rm' fb')   -> Dir (Map.unionWith mappend rm rm') (mappend fb fb')
-      NoRoute         -> l
-
-
-------------------------------------------------------------------------------
--- | A web handler which, given a mapping from URL entry points to web
--- handlers, efficiently routes requests to the correct handler.
---
--- The URL entry points are given as relative paths, for example:
---
--- > route [ ("foo/bar/quux", fooBarQuux) ]
---
--- If the URI of the incoming request is
---
--- > /foo/bar/quux
---
--- or
---
--- > /foo/bar/quux/...anything...
---
--- then the request will be routed to \"@fooBarQuux@\", with 'rqContextPath'
--- set to \"@\/foo\/bar\/quux\/@\" and 'rqPathInfo' set to
--- \"@...anything...@\".
---
--- @FIXME@\/@TODO@: we need a version with and without the context path setting
--- behaviour; if the route is \"@article\/:id\/print@\", we probably want the
--- contextPath to be \"@\/article@\" instead of \"@\/article\/whatever\/print@\".
---
--- A path component within an URL entry point beginning with a colon (\"@:@\")
--- is treated as a /variable capture/; the corresponding path component within
--- the request URI will be entered into the 'rqParams' parameters mapping with
--- the given name. For instance, if the routes were:
---
--- > route [ ("foo/:bar/baz", fooBazHandler) ]
---
--- Then a request for \"@\/foo\/saskatchewan\/baz@\" would be routed to
--- @fooBazHandler@ with a mapping for:
---
--- > "bar" => "saskatchewan"
---
--- in its parameters table.
---
--- Longer paths are matched first, and specific routes are matched before
--- captures. That is, if given routes:
---
--- > [ ("a", h1), ("a/b", h2), ("a/:x", h3) ]
---
--- a request for \"@\/a\/b@\" will go to @h2@, \"@\/a\/s@\" for any /s/ will go
--- to @h3@, and \"@\/a@\" will go to @h1@.
---
--- The following example matches \"@\/article@\" to an article index,
--- \"@\/login@\" to a login, and \"@\/article\/...@\" to an article renderer.
---
--- > route [ ("article",     renderIndex)
--- >       , ("article/:id", renderArticle)
--- >       , ("login",       method POST doLogin) ]
---
-route :: [(ByteString, Snap a)] -> Snap a
-route rts = route' (return ()) rts' []
-  where
-    rts' = mconcat (map pRoute rts)
-
-
-------------------------------------------------------------------------------
--- | The 'routeLocal' function is the same as 'route', except it doesn't change
--- the request's context path. This is useful if you want to route to a
--- particular handler but you want that handler to receive the 'rqPathInfo' as
--- it is.
-routeLocal :: [(ByteString, Snap a)] -> Snap a
-routeLocal rts' = do
-    req    <- getRequest
-    let ctx = rqContextPath req
-    let p   = rqPathInfo req
-    let md  = modifyRequest $ \r -> r {rqContextPath=ctx, rqPathInfo=p}
-
-    route' md rts []   <|>   (md >> pass)
-
-  where
-    rts = mconcat (map pRoute rts')
-
-          
-------------------------------------------------------------------------------
-pRoute :: (ByteString, Snap a) -> Route a
-pRoute (r, a) = foldr f (Action a) hier
-  where
-    hier   = filter (not . B.null) $ B.splitWith (== (c2w '/')) r
-    f s rt = if B.head s == c2w ':'
-        then Capture (B.tail s) rt NoRoute
-        else Dir (Map.fromList [(s, rt)]) NoRoute
-
-
-------------------------------------------------------------------------------
-route' :: Snap ()               -- ^ an action to be run before any user
-                                -- handler
-       -> Route a               -- ^ currently active routing table
-       -> [Route a]             -- ^ list of fallback routing tables in case
-                                -- the current table fails
-       -> Snap a
-route' pre (Action action) _ = pre >> action
-
-route' pre (Capture param rt fb) fbs = do
-    cwd <- getRequest >>= return . B.takeWhile (/= (c2w '/')) . rqPathInfo
-    if B.null cwd
-      then route' pre fb fbs
-      else do localRequest (updateContextPath (B.length cwd) . (f cwd)) $
-                           route' pre rt (fb:fbs)
-  where
-    f v req = req { rqParams = Map.insertWith (++) param [v] (rqParams req) }
-
-route' pre (Dir rtm fb) fbs = do
-    cwd <- getRequest >>= return . B.takeWhile (/= (c2w '/')) . rqPathInfo
-    case Map.lookup cwd rtm of
-      Just rt -> do
-          localRequest (updateContextPath (B.length cwd)) $
-                       route' pre rt (fb:fbs)
-      Nothing -> route' pre fb fbs
-
-route' _ NoRoute       []   = pass
-route' pre NoRoute (fb:fbs) = route' pre fb fbs
-
- diff --git a/static/docs/0.1.1/snap-core/src/Snap-Internal-Types.html b/static/docs/0.1.1/snap-core/src/Snap-Internal-Types.html deleted file mode 100644 index 47a4af5..0000000 --- a/static/docs/0.1.1/snap-core/src/Snap-Internal-Types.html +++ /dev/null @@ -1,529 +0,0 @@ - - - - -src/Snap/Internal/Types.hs - - - -
{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE EmptyDataDecls #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RankNTypes #-}
-
-module Snap.Internal.Types where
-
-------------------------------------------------------------------------------
-import           Control.Applicative
-import           Control.Exception (throwIO, ErrorCall(..))
-import           Control.Monad.CatchIO
-import           Control.Monad.State.Strict
-import           Data.ByteString.Char8 (ByteString)
-import qualified Data.ByteString.Char8 as S
-import qualified Data.ByteString.Lazy.Char8 as L
-import           Data.IORef
-import qualified Data.Iteratee as Iter
-import           Data.Maybe
-import qualified Data.Text as T
-import qualified Data.Text.Encoding as T
-import qualified Data.Text.Lazy as LT
-import qualified Data.Text.Lazy.Encoding as LT
-
-import           Data.Typeable
-
-------------------------------------------------------------------------------
-import           Snap.Iteratee hiding (Enumerator)
-import           Snap.Internal.Http.Types
-
-
-------------------------------------------------------------------------------
--- The Snap Monad
-------------------------------------------------------------------------------
-
-{-|
-
-'Snap' is the 'Monad' that user web handlers run in. 'Snap' gives you:
-
-1. stateful access to fetch or modify an HTTP 'Request'
-
-2. stateful access to fetch or modify an HTTP 'Response'
-
-3. failure \/ 'Alternative' \/ 'MonadPlus' semantics: a 'Snap' handler can
-   choose not to handle a given request, using 'empty' or its synonym 'pass',
-   and you can try alternative handlers with the '<|>' operator:
-
-   > a :: Snap String
-   > a = pass
-   >
-   > b :: Snap String
-   > b = return "foo"
-   >
-   > c :: Snap String
-   > c = a <|> b             -- try running a, if it fails then try b
-
-4. convenience functions ('writeBS', 'writeLBS', 'writeText', 'writeLazyText',
-   'addToOutput') for writing output to the 'Response':
-
-   > a :: (forall a . Enumerator a) -> Snap ()
-   > a someEnumerator = do
-   >     writeBS "I'm a strict bytestring"
-   >     writeLBS "I'm a lazy bytestring"
-   >     addToOutput someEnumerator
-
-5. early termination: if you call 'finishWith':
-
-   > a :: Snap ()
-   > a = do
-   >   modifyResponse $ setResponseStatus 500 "Internal Server Error"
-   >   writeBS "500 error"
-   >   r <- getResponse
-   >   finishWith r
-
-   then any subsequent processing will be skipped and supplied 'Response' value
-   will be returned from 'runSnap' as-is.
-
-6. access to the 'IO' monad through a 'MonadIO' instance:
-
-   > a :: Snap ()
-   > a = liftIO fireTheMissiles
--}
-
-
-------------------------------------------------------------------------------
-newtype Snap a = Snap {
-      unSnap :: StateT SnapState (Iteratee IO) (Maybe (Either Response a))
-}
-
-
-------------------------------------------------------------------------------
-data SnapState = SnapState
-    { _snapRequest  :: Request
-    , _snapResponse :: Response }
-
-
-------------------------------------------------------------------------------
-instance Monad Snap where
-    (Snap m) >>= f =
-        Snap $ do
-            eth <- m
-            maybe (return Nothing)
-                  (either (return . Just . Left)
-                          (unSnap . f))
-                  eth
-
-    return = Snap . return . Just . Right
-    fail   = const $ Snap $ return Nothing
-
-
-------------------------------------------------------------------------------
-instance MonadIO Snap where
-    liftIO m = Snap $ liftM (Just . Right) $ liftIO m
-
-
-------------------------------------------------------------------------------
-instance MonadCatchIO Snap where
-    catch (Snap m) handler = Snap $ do
-        x <- try m
-        case x of
-          (Left e)  -> let (Snap z) = handler e in z
-          (Right y) -> return y
-
-    block (Snap m) = Snap $ block m
-    unblock (Snap m) = Snap $ unblock m
-
-
-------------------------------------------------------------------------------
-instance MonadPlus Snap where
-    mzero = Snap $ return Nothing
-
-    a `mplus` b =
-        Snap $ do
-            mb <- unSnap a
-            if isJust mb then return mb else unSnap b
-
-
-------------------------------------------------------------------------------
-instance Functor Snap where
-    fmap = liftM
-
-
-------------------------------------------------------------------------------
-instance Applicative Snap where
-    pure  = return
-    (<*>) = ap
-
-
-------------------------------------------------------------------------------
-instance Alternative Snap where
-    empty = mzero
-    (<|>) = mplus
-
-
-------------------------------------------------------------------------------
-liftIter :: Iteratee IO a -> Snap a
-liftIter i = Snap (lift i >>= return . Just . Right)
-
-
-------------------------------------------------------------------------------
--- | Sends the request body through an iteratee (data consumer) and
--- returns the result.
-runRequestBody :: Iteratee IO a -> Snap a
-runRequestBody iter = do
-    req  <- getRequest
-    senum <- liftIO $ readIORef $ rqBody req
-    let (SomeEnumerator enum) = senum
-
-    -- make sure the iteratee consumes all of the output
-    let iter' = iter >>= (\a -> Iter.skipToEof >> return a)
-
-    -- run the iteratee
-    result <- liftIter $ Iter.joinIM $ enum iter'
-
-    -- stuff a new dummy enumerator into the request, so you can only try to
-    -- read the request body from the socket once
-    liftIO $ writeIORef (rqBody req)
-                        (SomeEnumerator $ return . Iter.joinI . Iter.take 0 )
-
-    return result
-
-
-------------------------------------------------------------------------------
--- | Returns the request body as a bytestring.
-getRequestBody :: Snap L.ByteString
-getRequestBody = liftM fromWrap $ runRequestBody stream2stream
-{-# INLINE getRequestBody #-}
-
-
-------------------------------------------------------------------------------
--- | Detaches the request body's 'Enumerator' from the 'Request' and
--- returns it. You would want to use this if you needed to send the
--- HTTP request body (transformed or otherwise) through to the output
--- in O(1) space. (Examples: transcoding, \"echo\", etc)
--- 
--- Normally Snap is careful to ensure that the request body is fully
--- consumed after your web handler runs; this function is marked
--- \"unsafe\" because it breaks this guarantee and leaves the
--- responsibility up to you. If you don't fully consume the
--- 'Enumerator' you get here, the next HTTP request in the pipeline
--- (if any) will misparse. Be careful with exception handlers.
-unsafeDetachRequestBody :: Snap (Enumerator a)
-unsafeDetachRequestBody = do
-    req <- getRequest
-    let ioref = rqBody req
-    senum <- liftIO $ readIORef ioref
-    let (SomeEnumerator enum) = senum
-    liftIO $ writeIORef ioref
-               (SomeEnumerator $ return . Iter.joinI . Iter.take 0)
-    return enum
-
-
-------------------------------------------------------------------------------
--- | Short-circuits a 'Snap' monad action early, storing the given
--- 'Response' value in its state.
-finishWith :: Response -> Snap ()
-finishWith = Snap . return . Just . Left
-{-# INLINE finishWith #-}
-
-
-------------------------------------------------------------------------------
--- | Fails out of a 'Snap' monad action.  This is used to indicate
--- that you choose not to handle the given request within the given
--- handler.
-pass :: Snap a
-pass = empty
-
-
-------------------------------------------------------------------------------
--- | Runs a 'Snap' monad action only if the request's HTTP method matches
--- the given method.
-method :: Method -> Snap a -> Snap a
-method m action = do
-    req <- getRequest
-    unless (rqMethod req == m) pass
-    action
-{-# INLINE method #-}
-
-
-------------------------------------------------------------------------------
--- Appends n bytes of the path info to the context path with a
--- trailing slash.
-updateContextPath :: Int -> Request -> Request
-updateContextPath n req | n > 0     = req { rqContextPath = ctx
-                                          , rqPathInfo    = pinfo }
-                        | otherwise = req
-  where
-    ctx'  = S.take n (rqPathInfo req)
-    ctx   = S.concat [rqContextPath req, ctx', "/"]
-    pinfo = S.drop (n+1) (rqPathInfo req)
-
-
-------------------------------------------------------------------------------
--- Runs a 'Snap' monad action only if the 'rqPathInfo' matches the given
--- predicate.
-pathWith :: (ByteString -> ByteString -> Bool)
-         -> ByteString
-         -> Snap a
-         -> Snap a
-pathWith c p action = do
-    req <- getRequest
-    unless (c p (rqPathInfo req)) pass
-    localRequest (updateContextPath $ S.length p) action
-
-
-------------------------------------------------------------------------------
--- | Runs a 'Snap' monad action only when the 'rqPathInfo' of the request
--- starts with the given path. For example,
---
--- > dir "foo" handler
---
--- Will fail if 'rqPathInfo' is not \"@\/foo@\" or \"@\/foo\/...@\", and will
--- add @\"foo\/\"@ to the handler's local 'rqContextPath'.
-dir :: ByteString  -- ^ path component to match
-    -> Snap a      -- ^ handler to run
-    -> Snap a
-dir = pathWith f
-  where
-    f dr pinfo = dr == x
-      where
-        (x,_) = S.break (=='/') pinfo
-{-# INLINE dir #-}
-
-
-------------------------------------------------------------------------------
--- | Runs a 'Snap' monad action only for requests where 'rqPathInfo' is exactly
--- equal to the given string. If the path matches, locally sets 'rqContextPath'
--- to the old value of 'rqPathInfo', sets 'rqPathInfo'=\"\", and runs the given
--- handler.
-path :: ByteString  -- ^ path to match against
-     -> Snap a      -- ^ handler to run
-     -> Snap a
-path = pathWith (==)
-{-# INLINE path #-}
-
-
-------------------------------------------------------------------------------
--- | Runs a 'Snap' monad action only when 'rqPathInfo' is empty.
-ifTop :: Snap a -> Snap a
-ifTop = path ""
-{-# INLINE ifTop #-}
-
-
-------------------------------------------------------------------------------
--- | Local Snap version of 'get'.
-sget :: Snap SnapState
-sget = Snap $ liftM (Just . Right) get
-{-# INLINE sget #-}
-
-
-------------------------------------------------------------------------------
--- | Local Snap monad version of 'modify'.
-smodify :: (SnapState -> SnapState) -> Snap ()
-smodify f = Snap $ modify f >> return (Just $ Right ())
-{-# INLINE smodify #-}
-
-
-------------------------------------------------------------------------------
--- | Grabs the 'Request' object out of the 'Snap' monad.
-getRequest :: Snap Request
-getRequest = liftM _snapRequest sget
-{-# INLINE getRequest #-}
-
-
-------------------------------------------------------------------------------
--- | Grabs the 'Response' object out of the 'Snap' monad.
-getResponse :: Snap Response
-getResponse = liftM _snapResponse sget
-{-# INLINE getResponse #-}
-
-
-------------------------------------------------------------------------------
--- | Puts a new 'Response' object into the 'Snap' monad.
-putResponse :: Response -> Snap ()
-putResponse r = smodify $ \ss -> ss { _snapResponse = r }
-{-# INLINE putResponse #-}
-
-
-------------------------------------------------------------------------------
--- | Puts a new 'Request' object into the 'Snap' monad.
-putRequest :: Request -> Snap ()
-putRequest r = smodify $ \ss -> ss { _snapRequest = r }
-{-# INLINE putRequest #-}
-
-
-------------------------------------------------------------------------------
--- | Modifies the 'Request' object stored in a 'Snap' monad.
-modifyRequest :: (Request -> Request) -> Snap ()
-modifyRequest f = smodify $ \ss -> ss { _snapRequest = f $ _snapRequest ss }
-{-# INLINE modifyRequest #-}
-
-
-------------------------------------------------------------------------------
--- | Modifes the 'Response' object stored in a 'Snap' monad.
-modifyResponse :: (Response -> Response) -> Snap () 
-modifyResponse f = smodify $ \ss -> ss { _snapResponse = f $ _snapResponse ss }
-{-# INLINE modifyResponse #-}
-
-
-------------------------------------------------------------------------------
--- | Adds the output from the given enumerator to the 'Response'
--- stored in the 'Snap' monad state.
-addToOutput :: (forall a . Enumerator a)   -- ^ output to add
-            -> Snap ()
-addToOutput enum = modifyResponse $ modifyResponseBody (>. enum)
-
-
-------------------------------------------------------------------------------
--- | Adds the given strict 'ByteString' to the body of the 'Response' stored in
--- the 'Snap' monad state.
-writeBS :: ByteString -> Snap ()
-writeBS s = addToOutput $ enumBS s
-
-
-------------------------------------------------------------------------------
--- | Adds the given lazy 'L.ByteString' to the body of the 'Response' stored in
--- the 'Snap' monad state.
-writeLBS :: L.ByteString -> Snap ()
-writeLBS s = addToOutput $ enumLBS s
-
-
-------------------------------------------------------------------------------
--- | Adds the given strict 'T.Text' to the body of the 'Response' stored in the
--- 'Snap' monad state.
-writeText :: T.Text -> Snap ()
-writeText s = writeBS $ T.encodeUtf8 s
-
-
-------------------------------------------------------------------------------
--- | Adds the given lazy 'LT.Text' to the body of the 'Response' stored in the
--- 'Snap' monad state.
-writeLazyText :: LT.Text -> Snap ()
-writeLazyText s = writeLBS $ LT.encodeUtf8 s
-
-
-------------------------------------------------------------------------------
--- | Sets the output to be the contents of the specified file.
---
--- Calling 'sendFile' will overwrite any output queued to be sent in the
--- 'Response'. If the response body is not modified after the call to
--- 'sendFile', Snap will use the efficient @sendfile()@ system call on
--- platforms that support it.
---
--- If the response body is modified (using 'modifyResponseBody'), the file will
--- be read using @mmap()@.
-sendFile :: FilePath -> Snap ()
-sendFile f = modifyResponse $ \r -> r { rspBody = SendFile f }
-
-
-------------------------------------------------------------------------------
--- | Runs a 'Snap' action with a locally-modified 'Request' state
--- object. The 'Request' object in the Snap monad state after the call
--- to localRequest will be unchanged.
-localRequest :: (Request -> Request) -> Snap a -> Snap a
-localRequest f m = do
-    req <- getRequest
-
-    runAct req <|> (putRequest req >> pass)
-
-  where
-    runAct req = do
-        modifyRequest f
-        result <- m
-        putRequest req
-        return result
-{-# INLINE localRequest #-}
-
-
-------------------------------------------------------------------------------
--- | Fetches the 'Request' from state and hands it to the given action.
-withRequest :: (Request -> Snap a) -> Snap a
-withRequest = (getRequest >>=)
-{-# INLINE withRequest #-}
-
-
-------------------------------------------------------------------------------
--- | Fetches the 'Response' from state and hands it to the given action.
-withResponse :: (Response -> Snap a) -> Snap a
-withResponse = (getResponse >>=)
-{-# INLINE withResponse #-}
-
-
-------------------------------------------------------------------------------
--- | This exception is thrown if the handler you supply to 'runSnap' fails.
-data NoHandlerException = NoHandlerException
-   deriving (Eq, Typeable)
-
-
-------------------------------------------------------------------------------
-instance Show NoHandlerException where
-    show NoHandlerException = "No handler for request"
-
-
-------------------------------------------------------------------------------
-instance Exception NoHandlerException
-
-
-------------------------------------------------------------------------------
--- | Runs a 'Snap' monad action in the 'Iteratee IO' monad.
-runSnap :: Snap a -> Request -> Iteratee IO (Request,Response)
-runSnap (Snap m) req = do
-    (r, ss') <- runStateT m ss
-
-    e <- maybe (return $ Left fourohfour)
-               return
-               r
-
-    -- is this a case of early termination?
-    let resp = case e of 
-                 Left x  -> x
-                 Right _ -> _snapResponse ss'
-
-    return (_snapRequest ss', resp)
-
-  where
-    fourohfour = setContentLength 3 $
-                 setResponseStatus 404 "Not Found" $
-                 modifyResponseBody (>. enumBS "404") $
-                 emptyResponse
-
-    dresp = emptyResponse { rspHttpVersion = rqVersion req }
-
-    ss = SnapState req dresp
-{-# INLINE runSnap #-}
-
-
-------------------------------------------------------------------------------
-evalSnap :: Snap a -> Request -> Iteratee IO a
-evalSnap (Snap m) req = do
-    (r, _) <- runStateT m ss
-
-    e <- maybe (liftIO $ throwIO NoHandlerException)
-               return
-               r
-
-    -- is this a case of early termination?
-    case e of 
-      Left _  -> liftIO $ throwIO $ ErrorCall "no value"
-      Right x -> return x
-  where
-    dresp = emptyResponse { rspHttpVersion = rqVersion req }
-    ss = SnapState req dresp
-{-# INLINE evalSnap #-}
-
-
-
-------------------------------------------------------------------------------
--- | See 'rqParam'. Looks up a value for the given named parameter in the
--- 'Request'. If more than one value was entered for the given parameter name,
--- 'getParam' gloms the values together with:
---
--- @    'S.intercalate' \" \"@
---
-getParam :: ByteString          -- ^ parameter name to look up
-         -> Snap (Maybe ByteString)
-getParam k = do
-    rq <- getRequest
-    return $ liftM (S.intercalate " ") $ rqParam k rq
-
-
-
- diff --git a/static/docs/0.1.1/snap-core/src/Snap-Iteratee.html b/static/docs/0.1.1/snap-core/src/Snap-Iteratee.html deleted file mode 100644 index 0aecc98..0000000 --- a/static/docs/0.1.1/snap-core/src/Snap-Iteratee.html +++ /dev/null @@ -1,267 +0,0 @@ - - - - -src/Snap/Iteratee.hs - - - -
{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE TypeSynonymInstances #-}
-
--- | Snap Framework type aliases and utilities for iteratees. Note that as a
--- convenience, this module also exports everything from @Data.Iteratee@ in the
--- @iteratee@ library.
---
--- /WARNING/: Note that all of these types are scheduled to change in the
--- @darcs@ head version of the @iteratee@ library; John Lato et al. are working
--- on a much improved iteratee formulation.
-
-module Snap.Iteratee
-  ( -- * Convenience aliases around types from @Data.Iteratee@
-    Stream
-  , IterV
-  , Iteratee
-  , Enumerator
-
-    -- * Re-export types and functions from @Data.Iteratee@
-  , module Data.Iteratee
-
-    -- * Helper functions
-
-    -- ** Enumerators
-  , enumBS
-  , enumLBS
-  , enumFile
-
-    -- ** Conversion to/from 'WrappedByteString'
-  , fromWrap
-  , toWrap
-
-    -- ** Iteratee utilities
-  , takeExactly
-  , takeNoMoreThan
-  , countBytes
-  , bufferIteratee
-  ) where
-
-------------------------------------------------------------------------------
-import           Control.Exception (SomeException)
-import           Control.Monad
-import           Control.Monad.CatchIO
-import           Data.ByteString (ByteString)
-import qualified Data.ByteString as S
-import qualified Data.ByteString.Lazy as L
-import           Data.Iteratee
-import qualified Data.Iteratee.Base.StreamChunk as SC
-import           Data.Iteratee.WrappedByteString
-import           Data.Monoid (mappend)
-import           Data.Word (Word8)
-import           Prelude hiding (catch,drop)
-import           System.IO.Posix.MMap
-import qualified Data.DList as D
-------------------------------------------------------------------------------
-
-type Stream         = StreamG WrappedByteString Word8
-type IterV      m   = IterGV WrappedByteString Word8 m
-type Iteratee   m   = IterateeG WrappedByteString Word8 m
-type Enumerator m a = Iteratee m a -> m (Iteratee m a)
-
-
-------------------------------------------------------------------------------
-instance (Functor m, MonadCatchIO m) =>
-         MonadCatchIO (IterateeG s el m) where
-    --catch  :: Exception  e => m a -> (e -> m a) -> m a
-    catch m handler = IterateeG $ \str -> do
-        ee <- try $ runIter m str
-        case ee of 
-          (Left e)  -> runIter (handler e) str
-          (Right v) -> return v
-
-    --block :: m a -> m a        
-    block m = IterateeG $ \str -> block $ runIter m str
-    unblock m = IterateeG $ \str -> unblock $ runIter m str
-
-
-------------------------------------------------------------------------------
--- | Wraps an 'Iteratee', counting the number of bytes consumed by it.
-countBytes :: (Monad m) => Iteratee m a -> Iteratee m (a, Int)
-countBytes = go 0
-  where
-    go !n iter = IterateeG $ f n iter
-
-    f !n !iter ch@(Chunk ws) = do
-        iterv <- runIter iter ch
-        case iterv of
-          Done x rest -> let !n' = n + m - len rest
-                         in return $! Done (x, n') rest
-          Cont i err  -> return $ Cont ((go $! n + m) i) err
-      where
-        m = S.length $ unWrap ws
-
-        len (EOF _) = 0
-        len (Chunk s) = S.length $ unWrap s
-
-    f !n !iter stream = do
-        iterv <- runIter iter stream
-        case iterv of
-          Done x rest -> return $ Done (x, n) rest
-          Cont i err  -> return $ Cont (go n i) err
-
-
-------------------------------------------------------------------------------
--- | Buffers an iteratee.
---
--- Our enumerators produce a lot of little strings; rather than spending all
--- our time doing kernel context switches for 4-byte write() calls, we buffer
--- the iteratee to send 2KB at a time.
-bufferIteratee :: (Monad m) => Enumerator m a
-bufferIteratee = return . go (D.empty,0)
-  where
-    blocksize = 2048
-
-    --go :: (DList ByteString, Int) -> Iteratee m a -> Iteratee m a
-    go (!dl,!n) iter = IterateeG $! f (dl,n) iter
-
-    --f :: (DList ByteString, Int) -> Iteratee m a -> Stream -> m (IterV m a)
-    f _      !iter ch@(EOF (Just _)) = runIter iter ch
-    f (!dl,_) !iter ch@(EOF Nothing) = do
-        iterv <- runIter iter $ Chunk big
-        case iterv of
-          Done x rest     -> return $ Done x rest
-          Cont i (Just e) -> return $ Cont i (Just e)
-          Cont i Nothing  -> runIter i ch
-      where
-        big = toWrap $ L.fromChunks [S.concat $ D.toList dl]
-        
-    f (!dl,!n) iter (Chunk ws) =
-        if n' > blocksize
-           then do
-               iterv <- runIter iter (Chunk big)
-               case iterv of
-                  Done x rest     -> return $ Done x rest
-                  Cont i (Just e) -> return $ Cont i (Just e)
-                  Cont i Nothing  -> return $ Cont (go (D.empty,0) i) Nothing
-           else return $ Cont (go (dl',n') iter) Nothing
-      where
-        s   = S.concat $ L.toChunks $ fromWrap ws
-        m   = S.length s
-        n'  = n+m
-        dl' = D.snoc dl s
-        big = toWrap $ L.fromChunks [S.concat $ D.toList dl']
-        
-
-------------------------------------------------------------------------------
--- | Enumerates a strict bytestring.
-enumBS :: (Monad m) => ByteString -> Enumerator m a
-enumBS bs = enumPure1Chunk $ WrapBS bs
-{-# INLINE enumBS #-}
-
-
-------------------------------------------------------------------------------
--- | Enumerates a lazy bytestring.
-enumLBS :: (Monad m) => L.ByteString -> Enumerator m a
-enumLBS lbs iter = foldM k iter enums
-  where
-    enums = map (enumPure1Chunk . WrapBS) $ L.toChunks lbs
-    k i e = e i
-
-
-------------------------------------------------------------------------------
--- | Converts a lazy bytestring to a wrapped bytestring.
-toWrap :: L.ByteString -> WrappedByteString Word8
-toWrap = WrapBS . S.concat . L.toChunks
-{-# INLINE toWrap #-}
-
-
-------------------------------------------------------------------------------
--- | Converts a wrapped bytestring to a lazy bytestring.
-fromWrap :: WrappedByteString Word8 -> L.ByteString
-fromWrap = L.fromChunks . (:[]) . unWrap
-{-# INLINE fromWrap #-}
-
-
-------------------------------------------------------------------------------
--- | Reads n elements from a stream and applies the given iteratee to
--- the stream of the read elements. Reads exactly n elements, and if
--- the stream is short propagates an error.
-takeExactly :: (SC.StreamChunk s el, Monad m) =>
-               Int ->
-               EnumeratorN s el s el m a
-takeExactly 0 iter = return iter
-takeExactly n' iter =
-    if n' < 0
-      then takeExactly 0 iter
-      else IterateeG (step n')
-  where
-  step n chk@(Chunk str)
-    | SC.null str = return $ Cont (takeExactly n iter) Nothing
-    | SC.length str < n = liftM (flip Cont Nothing) inner
-      where inner = liftM (check (n - SC.length str)) (runIter iter chk)
-  step n (Chunk str) = done (Chunk s1) (Chunk s2)
-    where (s1, s2) = SC.splitAt n str
-  step _n (EOF (Just e))    = return $ Cont undefined (Just e)
-  step _n (EOF Nothing)     = return $ Cont undefined (Just (Err "short write"))
-  check n (Done x _)        = drop n >> return (return x)
-  check n (Cont x Nothing)  = takeExactly n x
-  check n (Cont _ (Just e)) = drop n >> throwErr e
-  done s1 s2 = liftM (flip Done s2) (runIter iter s1 >>= checkIfDone return)
-
-
-------------------------------------------------------------------------------
--- | Reads up to n elements from a stream and applies the given iteratee to the
--- stream of the read elements. If more than n elements are read, propagates an
--- error.
-takeNoMoreThan :: (SC.StreamChunk s el, Monad m) =>
-                  Int ->
-                  EnumeratorN s el s el m a
-takeNoMoreThan n' iter =
-    if n' < 0
-      then takeNoMoreThan 0 iter
-      else IterateeG (step n')
-  where
-    step n chk@(Chunk str)
-      | SC.null str = return $ Cont (takeNoMoreThan n iter) Nothing
-      | SC.length str < n = liftM (flip Cont Nothing) inner
-      | otherwise = done (Chunk s1) (Chunk s2)
-          where inner    = liftM (check (n - SC.length str)) (runIter iter chk)
-                (s1, s2) = SC.splitAt n str
-
-    step _n (EOF (Just e))    = return $ Cont undefined (Just e)
-    step _n chk@(EOF Nothing) = do
-        v  <- runIter iter chk
-
-        case v of
-          (Done x s)        -> return $ Done (return x) s
-          (Cont _ (Just e)) -> return $ Cont undefined (Just e)
-          (Cont _ Nothing)  -> return $ Cont (throwErr $ Err "premature EOF") Nothing
-
-    check _ v@(Done _ _)      = return $ liftI v
-    check n (Cont x Nothing)  = takeNoMoreThan n x
-    check _ (Cont _ (Just e)) = throwErr e
-
-    done _ (EOF _) = error "impossible"
-    done s1 s2@(Chunk s2') = do
-        v <- runIter iter s1
-        case v of
-          (Done x s')       -> return $ Done (return x) (s' `mappend` s2)
-          (Cont _ (Just e)) -> return $ Cont undefined (Just e)
-          (Cont i Nothing)  ->
-              if SC.null s2'
-                then return $ Cont (takeNoMoreThan 0 i) Nothing
-                else return $ Cont undefined (Just $ Err "too many bytes")
-
-
-------------------------------------------------------------------------------
-enumFile :: FilePath -> Iteratee IO a -> IO (Iteratee IO a)
-enumFile fp iter = do
-    es <- (try $
-           liftM WrapBS $
-           unsafeMMapFile fp) :: IO (Either SomeException (WrappedByteString Word8))
-    
-    case es of
-      (Left e)  -> return $ throwErr $ Err $ "IO error" ++ show e
-      (Right s) -> liftM liftI $ runIter iter $ Chunk s
-
- diff --git a/static/docs/0.1.1/snap-core/src/Snap-Types.html b/static/docs/0.1.1/snap-core/src/Snap-Types.html deleted file mode 100644 index 69d5c03..0000000 --- a/static/docs/0.1.1/snap-core/src/Snap-Types.html +++ /dev/null @@ -1,127 +0,0 @@ - - - - -src/Snap/Types.hs - - - -
{-|
-
-This module contains the core type definitions, class instances, and functions
-for HTTP as well as the 'Snap' monad, which is used for web handlers.
-
--}
-module Snap.Types
-  ( 
-    -- * The Snap Monad
-    Snap
-  , runSnap
-  , NoHandlerException(..)
-
-    -- ** Functions for control flow and early termination
-  , finishWith
-  , pass
-
-    -- ** Routing
-  , method
-  , path
-  , dir
-  , ifTop
-  , route
-  , routeLocal
-
-    -- ** Access to state
-  , getRequest
-  , getResponse
-  , putRequest
-  , putResponse
-  , modifyRequest
-  , modifyResponse
-  , localRequest
-  , withRequest
-  , withResponse
-
-    -- ** Grabbing request bodies
-  , runRequestBody
-  , getRequestBody
-  , unsafeDetachRequestBody
-    -- * HTTP Datatypes and Functions
-    -- $httpDoc
-    --
-  , Request
-  , Response
-  , Headers
-  , HasHeaders(..)
-  , Params
-  , Method(..)
-  , Cookie(..)
-  , HttpVersion
-
-    -- ** Headers
-  , addHeader
-  , setHeader
-  , getHeader
-
-    -- ** Requests
-  , rqServerName
-  , rqServerPort
-  , rqRemoteAddr
-  , rqRemotePort
-  , rqLocalAddr
-  , rqLocalHostname
-  , rqIsSecure
-  , rqContentLength
-  , rqMethod
-  , rqVersion
-  , rqCookies
-  , rqPathInfo
-  , rqContextPath
-  , rqURI
-  , rqQueryString
-  , rqParams
-  , rqParam
-  , getParam
-  , rqModifyParams
-  , rqSetParam
-
-    -- ** Responses
-  , emptyResponse
-  , setResponseStatus
-  , rspStatus
-  , rspStatusReason
-  , setContentType
-  , addCookie
-  , setContentLength
-  , clearContentLength
-
-    -- *** Response I/O
-  , setResponseBody
-  , modifyResponseBody
-  , addToOutput
-  , writeBS
-  , writeLazyText
-  , writeText
-  , writeLBS
-  , sendFile
-
-    -- * Iteratee
-  , Enumerator
-
-    -- * HTTP utilities
-  , formatHttpTime
-  , parseHttpTime 
-  , urlEncode
-  , urlDecode
-  ) where
-
-------------------------------------------------------------------------------
-import           Snap.Internal.Http.Types
-import           Snap.Internal.Routing
-import           Snap.Internal.Types
-------------------------------------------------------------------------------
-
--- $httpDoc
--- HTTP-related datatypes: 'Request', 'Response', 'Cookie', etc.
-
- diff --git a/static/docs/0.1.1/snap-core/src/Snap-Util-FileServe.html b/static/docs/0.1.1/snap-core/src/Snap-Util-FileServe.html deleted file mode 100644 index 38c9a3f..0000000 --- a/static/docs/0.1.1/snap-core/src/Snap-Util-FileServe.html +++ /dev/null @@ -1,273 +0,0 @@ - - - - -src/Snap/Util/FileServe.hs - - - -
{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
--- | Contains web handlers to serve files from a directory.
-module Snap.Util.FileServe
-(
-  getSafePath
-, fileServe
-, fileServe'
-, fileServeSingle
-, fileServeSingle'
-, defaultMimeTypes
-, MimeMap
-) where
-
-------------------------------------------------------------------------------
-import           Control.Monad
-import           Control.Monad.Trans
-import qualified Data.ByteString.Char8 as S
-import           Data.ByteString.Char8 (ByteString)
-import           Data.Map (Map)
-import qualified Data.Map as Map
-import           Data.Maybe (fromMaybe)
-import           System.Directory
-import           System.FilePath
-import           System.Posix.Files
-
-------------------------------------------------------------------------------
-import           Snap.Types
-
-
-------------------------------------------------------------------------------
--- | A type alias for MIME type 
-type MimeMap = Map FilePath ByteString
-
-
-------------------------------------------------------------------------------
--- | The default set of mime type mappings we use when serving files. Its
--- value:
---
--- > Map.fromList [
--- >   ( ".asc"     , "text/plain"                        ),
--- >   ( ".asf"     , "video/x-ms-asf"                    ),
--- >   ( ".asx"     , "video/x-ms-asf"                    ),
--- >   ( ".avi"     , "video/x-msvideo"                   ),
--- >   ( ".bz2"     , "application/x-bzip"                ),
--- >   ( ".c"       , "text/plain"                        ),
--- >   ( ".class"   , "application/octet-stream"          ),
--- >   ( ".conf"    , "text/plain"                        ),
--- >   ( ".cpp"     , "text/plain"                        ),
--- >   ( ".css"     , "text/css"                          ),
--- >   ( ".cxx"     , "text/plain"                        ),
--- >   ( ".dtd"     , "text/xml"                          ),
--- >   ( ".dvi"     , "application/x-dvi"                 ),
--- >   ( ".gif"     , "image/gif"                         ),
--- >   ( ".gz"      , "application/x-gzip"                ),
--- >   ( ".hs"      , "text/plain"                        ),
--- >   ( ".htm"     , "text/html"                         ),
--- >   ( ".html"    , "text/html"                         ),
--- >   ( ".jar"     , "application/x-java-archive"        ),
--- >   ( ".jpeg"    , "image/jpeg"                        ),
--- >   ( ".jpg"     , "image/jpeg"                        ),
--- >   ( ".js"      , "text/javascript"                   ),
--- >   ( ".log"     , "text/plain"                        ),
--- >   ( ".m3u"     , "audio/x-mpegurl"                   ),
--- >   ( ".mov"     , "video/quicktime"                   ),
--- >   ( ".mp3"     , "audio/mpeg"                        ),
--- >   ( ".mpeg"    , "video/mpeg"                        ),
--- >   ( ".mpg"     , "video/mpeg"                        ),
--- >   ( ".ogg"     , "application/ogg"                   ),
--- >   ( ".pac"     , "application/x-ns-proxy-autoconfig" ),
--- >   ( ".pdf"     , "application/pdf"                   ),
--- >   ( ".png"     , "image/png"                         ),
--- >   ( ".ps"      , "application/postscript"            ),
--- >   ( ".qt"      , "video/quicktime"                   ),
--- >   ( ".sig"     , "application/pgp-signature"         ),
--- >   ( ".spl"     , "application/futuresplash"          ),
--- >   ( ".swf"     , "application/x-shockwave-flash"     ),
--- >   ( ".tar"     , "application/x-tar"                 ),
--- >   ( ".tar.bz2" , "application/x-bzip-compressed-tar" ),
--- >   ( ".tar.gz"  , "application/x-tgz"                 ),
--- >   ( ".tbz"     , "application/x-bzip-compressed-tar" ),
--- >   ( ".text"    , "text/plain"                        ),
--- >   ( ".tgz"     , "application/x-tgz"                 ),
--- >   ( ".torrent" , "application/x-bittorrent"          ),
--- >   ( ".txt"     , "text/plain"                        ),
--- >   ( ".wav"     , "audio/x-wav"                       ),
--- >   ( ".wax"     , "audio/x-ms-wax"                    ),
--- >   ( ".wma"     , "audio/x-ms-wma"                    ),
--- >   ( ".wmv"     , "video/x-ms-wmv"                    ),
--- >   ( ".xbm"     , "image/x-xbitmap"                   ),
--- >   ( ".xml"     , "text/xml"                          ),
--- >   ( ".xpm"     , "image/x-xpixmap"                   ),
--- >   ( ".xwd"     , "image/x-xwindowdump"               ),
--- >   ( ".zip"     , "application/zip"                   ) ]
---
-defaultMimeTypes :: MimeMap
-defaultMimeTypes = Map.fromList [
-  ( ".asc"     , "text/plain"                        ),
-  ( ".asf"     , "video/x-ms-asf"                    ),
-  ( ".asx"     , "video/x-ms-asf"                    ),
-  ( ".avi"     , "video/x-msvideo"                   ),
-  ( ".bz2"     , "application/x-bzip"                ),
-  ( ".c"       , "text/plain"                        ),
-  ( ".class"   , "application/octet-stream"          ),
-  ( ".conf"    , "text/plain"                        ),
-  ( ".cpp"     , "text/plain"                        ),
-  ( ".css"     , "text/css"                          ),
-  ( ".cxx"     , "text/plain"                        ),
-  ( ".dtd"     , "text/xml"                          ),
-  ( ".dvi"     , "application/x-dvi"                 ),
-  ( ".gif"     , "image/gif"                         ),
-  ( ".gz"      , "application/x-gzip"                ),
-  ( ".hs"      , "text/plain"                        ),
-  ( ".htm"     , "text/html"                         ),
-  ( ".html"    , "text/html"                         ),
-  ( ".jar"     , "application/x-java-archive"        ),
-  ( ".jpeg"    , "image/jpeg"                        ),
-  ( ".jpg"     , "image/jpeg"                        ),
-  ( ".js"      , "text/javascript"                   ),
-  ( ".log"     , "text/plain"                        ),
-  ( ".m3u"     , "audio/x-mpegurl"                   ),
-  ( ".mov"     , "video/quicktime"                   ),
-  ( ".mp3"     , "audio/mpeg"                        ),
-  ( ".mpeg"    , "video/mpeg"                        ),
-  ( ".mpg"     , "video/mpeg"                        ),
-  ( ".ogg"     , "application/ogg"                   ),
-  ( ".pac"     , "application/x-ns-proxy-autoconfig" ),
-  ( ".pdf"     , "application/pdf"                   ),
-  ( ".png"     , "image/png"                         ),
-  ( ".ps"      , "application/postscript"            ),
-  ( ".qt"      , "video/quicktime"                   ),
-  ( ".sig"     , "application/pgp-signature"         ),
-  ( ".spl"     , "application/futuresplash"          ),
-  ( ".swf"     , "application/x-shockwave-flash"     ),
-  ( ".tar"     , "application/x-tar"                 ),
-  ( ".tar.bz2" , "application/x-bzip-compressed-tar" ),
-  ( ".tar.gz"  , "application/x-tgz"                 ),
-  ( ".tbz"     , "application/x-bzip-compressed-tar" ),
-  ( ".text"    , "text/plain"                        ),
-  ( ".tgz"     , "application/x-tgz"                 ),
-  ( ".torrent" , "application/x-bittorrent"          ),
-  ( ".ttf"     , "application/x-font-truetype"       ),
-  ( ".txt"     , "text/plain"                        ),
-  ( ".wav"     , "audio/x-wav"                       ),
-  ( ".wax"     , "audio/x-ms-wax"                    ),
-  ( ".wma"     , "audio/x-ms-wma"                    ),
-  ( ".wmv"     , "video/x-ms-wmv"                    ),
-  ( ".xbm"     , "image/x-xbitmap"                   ),
-  ( ".xml"     , "text/xml"                          ),
-  ( ".xpm"     , "image/x-xpixmap"                   ),
-  ( ".xwd"     , "image/x-xwindowdump"               ),
-  ( ".zip"     , "application/zip"                   ) ]
-
-------------------------------------------------------------------------------
--- | Gets a path from the 'Request' using 'rqPathInfo' and makes sure it is
--- safe to use for opening files.  A path is safe if it is a relative path
--- and has no ".." elements to escape the intended directory structure.
-getSafePath :: Snap FilePath
-getSafePath = do
-    req <- getRequest
-    let p = S.unpack $ rqPathInfo req
-
-    -- check that we don't have any sneaky .. paths
-    let dirs = splitDirectories p
-    when (elem ".." dirs) pass
-    return p
-
-
-------------------------------------------------------------------------------
--- | Serves files out of the given directory. The relative path given in
--- 'rqPathInfo' is searched for the given file, and the file is served with the
--- appropriate mime type if it is found. Absolute paths and \"@..@\" are prohibited
--- to prevent files from being served from outside the sandbox.
---
--- Uses 'defaultMimeTypes' to determine the @Content-Type@ based on the file's
--- extension.
-fileServe :: FilePath  -- ^ root directory
-          -> Snap ()
-fileServe = fileServe' defaultMimeTypes
-{-# INLINE fileServe #-}
-
-
-------------------------------------------------------------------------------
--- | Same as 'fileServe', with control over the MIME mapping used.
-fileServe' :: MimeMap           -- ^ MIME type mapping
-           -> FilePath          -- ^ root directory
-           -> Snap ()
-fileServe' mm root = do
-    sp <- getSafePath
-    let fp   = root </> sp
-
-    -- check that the file exists
-    liftIO (doesFileExist fp) >>= flip unless pass
-
-    let fn   = takeFileName fp
-    let mime = fileType mm fn
-    fileServeSingle' mime fp
-{-# INLINE fileServe' #-}
-
-
-------------------------------------------------------------------------------
--- | Serves a single file specified by a full or relative path.  The
--- path restrictions on fileServe don't apply to this function since
--- the path is not being supplied by the user.
-fileServeSingle :: FilePath          -- ^ path to file
-                -> Snap ()
-fileServeSingle fp =
-    fileServeSingle' (fileType defaultMimeTypes (takeFileName fp)) fp
-{-# INLINE fileServeSingle #-}
-
-
-------------------------------------------------------------------------------
--- | Same as 'fileServeSingle', with control over the MIME mapping used.
-fileServeSingle' :: ByteString        -- ^ MIME type mapping
-                 -> FilePath          -- ^ path to file
-                 -> Snap ()
-fileServeSingle' mime fp = do
-    req <- getRequest
-    
-    let mbH = getHeader "if-modified-since" req
-    mbIfModified <- liftIO $ case mbH of
-                               Nothing  -> return Nothing
-                               (Just s) -> liftM Just $ parseHttpTime s
-
-    -- check modification time and bug out early if the file is not modified.
-    filestat <- liftIO $ getFileStatus fp
-    let mt = modificationTime filestat
-    maybe (return ()) (chkModificationTime mt) mbIfModified
-
-    let sz = fromEnum $ fileSize filestat
-    lm <- liftIO $ formatHttpTime mt
-
-    modifyResponse $ setHeader "Last-Modified" lm
-                   . setContentType mime
-                   . setContentLength sz
-    sendFile fp
-
-  where
-    --------------------------------------------------------------------------
-    chkModificationTime mt lt = when (mt <= lt) notModified
-
-    --------------------------------------------------------------------------
-    notModified = finishWith $
-                  setResponseStatus 304 "Not Modified" emptyResponse
-
-
-------------------------------------------------------------------------------
-fileType :: MimeMap -> FilePath -> ByteString
-fileType mm f =
-    if null ext
-      then defaultMimeType
-      else fromMaybe (fileType mm (drop 1 ext))
-                     mbe
-
-  where
-    ext             = takeExtensions f
-    mbe             = Map.lookup ext mm
-
-
-------------------------------------------------------------------------------
-defaultMimeType :: ByteString
-defaultMimeType = "application/octet-stream"
-
- diff --git a/static/docs/0.1.1/snap-core/src/Snap-Util-GZip.html b/static/docs/0.1.1/snap-core/src/Snap-Util-GZip.html deleted file mode 100644 index 578c30d..0000000 --- a/static/docs/0.1.1/snap-core/src/Snap-Util-GZip.html +++ /dev/null @@ -1,339 +0,0 @@ - - - - -src/Snap/Util/GZip.hs - - - -
{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE ExistentialQuantification #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module Snap.Util.GZip
-( withCompression
-, withCompression' ) where
-
-import qualified Codec.Compression.GZip as GZip
-import qualified Codec.Compression.Zlib as Zlib
-import           Control.Concurrent
-import           Control.Applicative hiding (many)
-import           Control.Exception
-import           Control.Monad
-import           Control.Monad.Trans
-import           Data.Attoparsec.Char8 hiding (Done)
-import qualified Data.Attoparsec.Char8 as Atto
-import qualified Data.ByteString.Lazy.Char8 as L
-import           Data.ByteString.Char8 (ByteString)
-import           Data.Iteratee.WrappedByteString
-import           Data.Maybe
-import qualified Data.Set as Set
-import           Data.Set (Set)
-import           Data.Typeable
-import           Prelude hiding (catch, takeWhile)
-
-------------------------------------------------------------------------------
-import           Snap.Internal.Debug
-import           Snap.Iteratee hiding (Enumerator)
-import           Snap.Types
-
-
-------------------------------------------------------------------------------
--- | Runs a 'Snap' web handler with compression if available.
---
--- If the client has indicated support for @gzip@ or @compress@ in its
--- @Accept-Encoding@ header, and the @Content-Type@ in the response is one of
--- the following types:
---
---   * @application/x-javascript@
---
---   * @text/css@
---
---   * @text/html@
---
---   * @text/javascript@
---
---   * @text/plain@
---
---   * @text/xml@
---
---   * @application/x-font-truetype@
---
--- Then the given handler's output stream will be compressed,
--- @Content-Encoding@ will be set in the output headers, and the
--- @Content-Length@ will be cleared if it was set. (We can't process the stream
--- in O(1) space if the length is known beforehand.)
---
--- The wrapped handler will be run to completion, and then the 'Response'
--- that's contained within the 'Snap' monad state will be passed to
--- 'finishWith' to prevent further processing.
---
-withCompression :: Snap a   -- ^ the web handler to run
-                -> Snap ()
-withCompression = withCompression' compressibleMimeTypes
-
-
-------------------------------------------------------------------------------
--- | The same as 'withCompression', with control over which MIME types to
--- compress.
-withCompression' :: Set ByteString
-                    -- ^ set of compressible MIME types
-                 -> Snap a
-                    -- ^ the web handler to run
-                 -> Snap ()
-withCompression' mimeTable action = do
-    _    <- action
-    resp <- getResponse
-
-    -- If a content-encoding is already set, do nothing. This prevents
-    -- "withCompression $ withCompression m" from ruining your day.
-    if isJust $ getHeader "Content-Encoding" resp
-       then return ()
-       else do
-           let mbCt = getHeader "Content-Type" resp
-
-           debug $ "withCompression', content-type is " ++ show mbCt
-
-           case mbCt of
-             (Just ct) -> if Set.member ct mimeTable
-                             then chkAcceptEncoding
-                             else return ()
-             _         -> return ()
-
-
-    getResponse >>= finishWith
-
-  where
-    chkAcceptEncoding :: Snap ()
-    chkAcceptEncoding = do
-        req <- getRequest
-        debug $ "checking accept-encoding"
-        let mbAcc = getHeader "Accept-Encoding" req
-        debug $ "accept-encoding is " ++ show mbAcc
-        let s = fromMaybe "" mbAcc
-
-        types <- liftIO $ parseAcceptEncoding s
-
-        chooseType types
-
-
-    chooseType []               = return ()
-    chooseType ("gzip":_)       = gzipCompression
-    chooseType ("compress":_)   = compressCompression
-    chooseType ("x-gzip":_)     = gzipCompression
-    chooseType ("x-compress":_) = compressCompression
-    chooseType (_:xs)           = chooseType xs
-
-
-------------------------------------------------------------------------------
--- private following
-------------------------------------------------------------------------------
-
-
-------------------------------------------------------------------------------
-compressibleMimeTypes :: Set ByteString
-compressibleMimeTypes = Set.fromList [ "application/x-font-truetype"
-                                     , "application/x-javascript"
-                                     , "text/css"
-                                     , "text/html"
-                                     , "text/javascript"
-                                     , "text/plain"
-                                     , "text/xml" ]
-
-
-
-
-------------------------------------------------------------------------------
-gzipCompression :: Snap ()
-gzipCompression = modifyResponse f
-  where
-    f = setHeader "Content-Encoding" "gzip" .
-        clearContentLength .
-        modifyResponseBody gcompress
-
-
-------------------------------------------------------------------------------
-compressCompression :: Snap ()
-compressCompression = modifyResponse f
-  where
-    f = setHeader "Content-Encoding" "compress" .
-        clearContentLength .
-        modifyResponseBody ccompress
-
-
-------------------------------------------------------------------------------
-gcompress :: forall a . Enumerator a -> Enumerator a
-gcompress = compressEnumerator GZip.compress
-
-
-------------------------------------------------------------------------------
-ccompress :: forall a . Enumerator a -> Enumerator a
-ccompress = compressEnumerator Zlib.compress
-
-
-------------------------------------------------------------------------------
-compressEnumerator :: forall a .
-                      (L.ByteString -> L.ByteString)
-                   -> Enumerator a
-                   -> Enumerator a
-compressEnumerator compFunc enum iteratee = do
-    writeEnd <- newChan
-    readEnd  <- newChan
-    tid      <- forkIO $ threadProc readEnd writeEnd
-
-    enum (IterateeG $ f readEnd writeEnd tid iteratee)
-
-  where
-    --------------------------------------------------------------------------
-    streamFinished :: Stream -> Bool
-    streamFinished (EOF _)   = True
-    streamFinished (Chunk _) = False
-
-
-    --------------------------------------------------------------------------
-    consumeSomeOutput :: Chan Stream
-                      -> Iteratee IO a
-                      -> IO (Iteratee IO a)
-    consumeSomeOutput writeEnd iter = do
-        e <- isEmptyChan writeEnd
-        if e
-          then return iter
-          else do
-            ch <- readChan writeEnd
-
-            iter' <- liftM liftI $ runIter iter ch
-            if (streamFinished ch)
-               then return iter'
-               else consumeSomeOutput writeEnd iter'
-
-
-    --------------------------------------------------------------------------
-    consumeRest :: Chan Stream
-                -> Iteratee IO a
-                -> IO (IterV IO a)
-    consumeRest writeEnd iter = do
-        ch <- readChan writeEnd
-
-        iv <- runIter iter ch
-        if (streamFinished ch)
-           then return iv
-           else consumeRest writeEnd $ liftI iv
-
-
-    --------------------------------------------------------------------------
-    f readEnd writeEnd tid i (EOF Nothing) = do
-        writeChan readEnd Nothing
-        x <- consumeRest writeEnd i
-        killThread tid
-        return x
-
-    f _ _ tid i ch@(EOF (Just _)) = do
-        x <- runIter i ch
-        killThread tid
-        return x
-
-    f readEnd writeEnd tid i (Chunk s') = do
-        let s = unWrap s'
-        writeChan readEnd $ Just s
-        i' <- consumeSomeOutput writeEnd i
-        return $ Cont (IterateeG $ f readEnd writeEnd tid i') Nothing
-
-
-    --------------------------------------------------------------------------
-    threadProc :: Chan (Maybe ByteString)
-               -> Chan Stream
-               -> IO ()
-    threadProc readEnd writeEnd = do
-        stream <- getChanContents readEnd
-        let bs = L.fromChunks $ streamToChunks stream
-
-        let output = L.toChunks $ compFunc bs
-        let runIt = do
-            mapM_ (writeChan writeEnd . toChunk) output
-            writeChan writeEnd $ EOF Nothing
-
-        runIt `catch` \(e::SomeException) ->
-            writeChan writeEnd $ EOF (Just $ Err $ show e)
-
-
-    --------------------------------------------------------------------------
-    streamToChunks []            = []
-    streamToChunks (Nothing:_)   = []
-    streamToChunks ((Just x):xs) = x:(streamToChunks xs)
-
-
-    --------------------------------------------------------------------------
-    toChunk = Chunk . WrapBS
-
-
-------------------------------------------------------------------------------
-fullyParse :: ByteString -> Parser a -> Either String a
-fullyParse s p =
-    case r' of
-      (Fail _ _ e)    -> Left e
-      (Partial _)     -> Left "parse failed"
-      (Atto.Done _ x) -> Right x
-  where
-    r  = parse p s
-    r' = feed r ""
-
-
-------------------------------------------------------------------------------
--- We're not gonna bother with quality values; we'll do gzip or compress in
--- that order.
-acceptParser :: Parser [ByteString]
-acceptParser = do
-    xs <- option [] $ (:[]) <$> encoding
-    ys <- many (char ',' *> encoding)
-    endOfInput
-    return $ xs ++ ys
-  where
-    encoding = skipSpace *> c <* skipSpace
-
-    c = do
-        x <- coding
-        option () qvalue
-        return x
-
-    qvalue = do
-        skipSpace
-        char ';'
-        skipSpace
-        char 'q'
-        skipSpace
-        char '='
-        float
-        return ()
-
-    coding = string "*" <|> takeWhile isAlpha_ascii
-
-    float = takeWhile isDigit >>
-            option () (char '.' >> takeWhile isDigit >> pure ())
-
-
-------------------------------------------------------------------------------
-data BadAcceptEncodingException = BadAcceptEncodingException
-   deriving (Typeable)
-
-
-------------------------------------------------------------------------------
-instance Show BadAcceptEncodingException where
-    show BadAcceptEncodingException = "bad 'accept-encoding' header"
-
-
-------------------------------------------------------------------------------
-instance Exception BadAcceptEncodingException
-
-
-------------------------------------------------------------------------------
-parseAcceptEncoding :: ByteString -> IO [ByteString]
-parseAcceptEncoding s =
-    case r of
-      Left _ -> throwIO BadAcceptEncodingException
-      Right x -> return x
-  where
-    r = fullyParse s acceptParser
-
-
- diff --git a/static/docs/0.1.1/snap-core/src/hscolour.css b/static/docs/0.1.1/snap-core/src/hscolour.css deleted file mode 100644 index 150e4d0..0000000 --- a/static/docs/0.1.1/snap-core/src/hscolour.css +++ /dev/null @@ -1,15 +0,0 @@ -body { font-size: 90%; } - -pre, code, body { - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; -} - -.hs-keyglyph, .hs-layout {color: #5200A3;} -.hs-keyword {color: #3465a4; font-weight: bold;} -.hs-comment, .hs-comment a {color: #579; } -.hs-str, .hs-chr {color: #141B24;} -.hs-keyword, .hs-conid, .hs-varid, .hs-conop, .hs-varop, .hs-num, .hs-cpp, .hs-sel, .hs-definition {} diff --git a/static/docs/0.1.1/snap-server/Snap-Http-Server-Config.html b/static/docs/0.1.1/snap-server/Snap-Http-Server-Config.html deleted file mode 100644 index 52bc6c1..0000000 --- a/static/docs/0.1.1/snap-server/Snap-Http-Server-Config.html +++ /dev/null @@ -1,287 +0,0 @@ - - -Snap.Http.Server.Config
 snap-server-0.1.1: A fast, iteratee-based, epoll-enabled web server for the Snap FrameworkSource codeContentsIndex
Snap.Http.Server.Config
Documentation
data Config Source
Constructors
Config
localHostname :: !ByteString
bindAddress :: !ByteString
listenPort :: !Int
accessLog :: !(Maybe FilePath)
errorLog :: !(Maybe FilePath)
show/hide Instances
readConfigFromCmdLineArgsSource
:: Stringapplication description, e.g. - "Foo applet v0.2" -
-> IO Config
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.1/snap-server/Snap-Http-Server.html b/static/docs/0.1.1/snap-server/Snap-Http-Server.html deleted file mode 100644 index a99085f..0000000 --- a/static/docs/0.1.1/snap-server/Snap-Http-Server.html +++ /dev/null @@ -1,245 +0,0 @@ - - -Snap.Http.Server
 snap-server-0.1.1: A fast, iteratee-based, epoll-enabled web server for the Snap FrameworkSource codeContentsIndex
Snap.Http.Server
Description
The Snap HTTP server is a high performance, epoll-enabled, iteratee-based - web server library written in Haskell. Together with the snap-core library - upon which it depends, it provides a clean and efficient Haskell programming - interface to the HTTP protocol. -
Synopsis
httpServe :: ByteString -> Int -> ByteString -> Maybe FilePath -> Maybe FilePath -> Snap () -> IO ()
Documentation
httpServeSource
:: ByteStringbind address, or "*" for all -
-> Intport to bind to -
-> ByteStringlocal hostname (server name) -
-> Maybe FilePathpath to the (optional) access log -
-> Maybe FilePathpath to the (optional) error log -
-> Snap ()handler procedure -
-> IO ()
Starts serving HTTP requests on the given port using the given handler. - This function never returns; to shut down the HTTP server, kill the - controlling thread. -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.1/snap-server/System-FastLogger.html b/static/docs/0.1.1/snap-server/System-FastLogger.html deleted file mode 100644 index 9127025..0000000 --- a/static/docs/0.1.1/snap-server/System-FastLogger.html +++ /dev/null @@ -1,510 +0,0 @@ - - -System.FastLogger
 snap-server-0.1.1: A fast, iteratee-based, epoll-enabled web server for the Snap FrameworkSource codeContentsIndex
System.FastLogger
Synopsis
data Logger
timestampedLogEntry :: ByteString -> IO ByteString
combinedLogEntry :: ByteString -> Maybe ByteString -> ByteString -> Int -> Maybe Int -> Maybe ByteString -> ByteString -> IO ByteString
newLogger :: FilePath -> IO Logger
logMsg :: Logger -> ByteString -> IO ()
stopLogger :: Logger -> IO ()
Documentation
data Logger Source
Holds the state for a logger. -
timestampedLogEntry :: ByteString -> IO ByteStringSource
Prepares a log message with the time prepended. -
combinedLogEntrySource
:: ByteStringremote host -
-> Maybe ByteStringremote user -
-> ByteStringrequest line (up to you to ensure - there are no quotes in here) -
-> Intstatus code -
-> Maybe Intnum bytes sent -
-> Maybe ByteStringreferer (up to you to ensure - there are no quotes in here) -
-> ByteStringuser agent (up to you to ensure - there are no quotes in here) -
-> IO ByteString
Prepares a log message in "combined" format. -
newLogger :: FilePath -> IO LoggerSource
Creates a new logger, logging to the given file. If the file argument is - "-", then log to stdout; if it's "stderr" then we log to stderr, - otherwise we log to a regular file in append mode. The file is closed and - re-opened every 15 minutes to facilitate external log rotation. -
logMsg :: Logger -> ByteString -> IO ()Source
Sends out a log message verbatim with a newline appended. Note: - if you want a fancy log message you'll have to format it yourself - (or use combinedLogEntry). -
stopLogger :: Logger -> IO ()Source
Kills a logger thread, causing any unwritten contents to be - flushed out to disk -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.1/snap-server/doc-index.html b/static/docs/0.1.1/snap-server/doc-index.html deleted file mode 100644 index 7713ecc..0000000 --- a/static/docs/0.1.1/snap-server/doc-index.html +++ /dev/null @@ -1,168 +0,0 @@ - - -snap-server-0.1.1: A fast, iteratee-based, epoll-enabled web server for the Snap Framework (Index)
 snap-server-0.1.1: A fast, iteratee-based, epoll-enabled web server for the Snap FrameworkContentsIndex
accessLog
bindAddress
combinedLogEntry
Config
1 (Type/Class)
2 (Data Constructor)
errorLog
httpServe
listenPort
localHostname
Logger
logMsg
newLogger
readConfigFromCmdLineArgs
stopLogger
timestampedLogEntry
diff --git a/static/docs/0.1.1/snap-server/fonts/DroidSerif-Bold.eot b/static/docs/0.1.1/snap-server/fonts/DroidSerif-Bold.eot deleted file mode 100644 index 01b9e1f..0000000 Binary files a/static/docs/0.1.1/snap-server/fonts/DroidSerif-Bold.eot and /dev/null differ diff --git a/static/docs/0.1.1/snap-server/fonts/DroidSerif-Bold.svg b/static/docs/0.1.1/snap-server/fonts/DroidSerif-Bold.svg deleted file mode 100644 index 1f7f2d2..0000000 --- a/static/docs/0.1.1/snap-server/fonts/DroidSerif-Bold.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.1.1/snap-server/fonts/DroidSerif-Bold.ttf b/static/docs/0.1.1/snap-server/fonts/DroidSerif-Bold.ttf deleted file mode 100644 index da0ea11..0000000 Binary files a/static/docs/0.1.1/snap-server/fonts/DroidSerif-Bold.ttf and /dev/null differ diff --git a/static/docs/0.1.1/snap-server/fonts/DroidSerif-Bold.woff b/static/docs/0.1.1/snap-server/fonts/DroidSerif-Bold.woff deleted file mode 100644 index 91549cd..0000000 Binary files a/static/docs/0.1.1/snap-server/fonts/DroidSerif-Bold.woff and /dev/null differ diff --git a/static/docs/0.1.1/snap-server/fonts/DroidSerif-BoldItalic.eot b/static/docs/0.1.1/snap-server/fonts/DroidSerif-BoldItalic.eot deleted file mode 100644 index 47dd0a0..0000000 Binary files a/static/docs/0.1.1/snap-server/fonts/DroidSerif-BoldItalic.eot and /dev/null differ diff --git a/static/docs/0.1.1/snap-server/fonts/DroidSerif-BoldItalic.svg b/static/docs/0.1.1/snap-server/fonts/DroidSerif-BoldItalic.svg deleted file mode 100644 index 1a57dbb..0000000 --- a/static/docs/0.1.1/snap-server/fonts/DroidSerif-BoldItalic.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.1.1/snap-server/fonts/DroidSerif-BoldItalic.ttf b/static/docs/0.1.1/snap-server/fonts/DroidSerif-BoldItalic.ttf deleted file mode 100644 index 8be3fb4..0000000 Binary files a/static/docs/0.1.1/snap-server/fonts/DroidSerif-BoldItalic.ttf and /dev/null differ diff --git a/static/docs/0.1.1/snap-server/fonts/DroidSerif-BoldItalic.woff b/static/docs/0.1.1/snap-server/fonts/DroidSerif-BoldItalic.woff deleted file mode 100644 index 6d5fa3d..0000000 Binary files a/static/docs/0.1.1/snap-server/fonts/DroidSerif-BoldItalic.woff and /dev/null differ diff --git a/static/docs/0.1.1/snap-server/fonts/DroidSerif-Italic.eot b/static/docs/0.1.1/snap-server/fonts/DroidSerif-Italic.eot deleted file mode 100644 index 2d4850c..0000000 Binary files a/static/docs/0.1.1/snap-server/fonts/DroidSerif-Italic.eot and /dev/null differ diff --git a/static/docs/0.1.1/snap-server/fonts/DroidSerif-Italic.svg b/static/docs/0.1.1/snap-server/fonts/DroidSerif-Italic.svg deleted file mode 100644 index 356c374..0000000 --- a/static/docs/0.1.1/snap-server/fonts/DroidSerif-Italic.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.1.1/snap-server/fonts/DroidSerif-Italic.ttf b/static/docs/0.1.1/snap-server/fonts/DroidSerif-Italic.ttf deleted file mode 100644 index 3719dc2..0000000 Binary files a/static/docs/0.1.1/snap-server/fonts/DroidSerif-Italic.ttf and /dev/null differ diff --git a/static/docs/0.1.1/snap-server/fonts/DroidSerif-Italic.woff b/static/docs/0.1.1/snap-server/fonts/DroidSerif-Italic.woff deleted file mode 100644 index b64436f..0000000 Binary files a/static/docs/0.1.1/snap-server/fonts/DroidSerif-Italic.woff and /dev/null differ diff --git a/static/docs/0.1.1/snap-server/fonts/DroidSerif-Regular.eot b/static/docs/0.1.1/snap-server/fonts/DroidSerif-Regular.eot deleted file mode 100644 index 0d17523..0000000 Binary files a/static/docs/0.1.1/snap-server/fonts/DroidSerif-Regular.eot and /dev/null differ diff --git a/static/docs/0.1.1/snap-server/fonts/DroidSerif-Regular.svg b/static/docs/0.1.1/snap-server/fonts/DroidSerif-Regular.svg deleted file mode 100644 index b9b65fb..0000000 --- a/static/docs/0.1.1/snap-server/fonts/DroidSerif-Regular.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.1.1/snap-server/fonts/DroidSerif-Regular.ttf b/static/docs/0.1.1/snap-server/fonts/DroidSerif-Regular.ttf deleted file mode 100644 index 066dcaa..0000000 Binary files a/static/docs/0.1.1/snap-server/fonts/DroidSerif-Regular.ttf and /dev/null differ diff --git a/static/docs/0.1.1/snap-server/fonts/DroidSerif-Regular.woff b/static/docs/0.1.1/snap-server/fonts/DroidSerif-Regular.woff deleted file mode 100644 index cfd3d67..0000000 Binary files a/static/docs/0.1.1/snap-server/fonts/DroidSerif-Regular.woff and /dev/null differ diff --git a/static/docs/0.1.1/snap-server/frames.html b/static/docs/0.1.1/snap-server/frames.html deleted file mode 100644 index 9e904fc..0000000 --- a/static/docs/0.1.1/snap-server/frames.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/static/docs/0.1.1/snap-server/haddock-util.js b/static/docs/0.1.1/snap-server/haddock-util.js deleted file mode 100644 index 364081f..0000000 --- a/static/docs/0.1.1/snap-server/haddock-util.js +++ /dev/null @@ -1,139 +0,0 @@ -// Haddock JavaScript utilities -function toggle(button,id) -{ - var n = document.getElementById(id).style; - if (n.display == "none") - { - button.src = "minus.gif"; - n.display = "block"; - } - else - { - button.src = "plus.gif"; - n.display = "none"; - } -} - - -var max_results = 75; // 50 is not enough to search for map in the base libraries -var shown_range = null; -var last_search = null; - -function quick_search() -{ - perform_search(false); -} - -function full_search() -{ - perform_search(true); -} - - -function perform_search(full) -{ - var text = document.getElementById("searchbox").value.toLowerCase(); - if (text == last_search && !full) return; - last_search = text; - - var table = document.getElementById("indexlist"); - var status = document.getElementById("searchmsg"); - var children = table.firstChild.childNodes; - - // first figure out the first node with the prefix - var first = bisect(-1); - var last = (first == -1 ? -1 : bisect(1)); - - if (first == -1) - { - table.className = ""; - status.innerHTML = "No results found, displaying all"; - } - else if (first == 0 && last == children.length - 1) - { - table.className = ""; - status.innerHTML = ""; - } - else if (last - first >= max_results && !full) - { - table.className = ""; - status.innerHTML = "More than " + max_results + ", press Search to display"; - } - else - { - // decide what you need to clear/show - if (shown_range) - setclass(shown_range[0], shown_range[1], "indexrow"); - setclass(first, last, "indexshow"); - shown_range = [first, last]; - table.className = "indexsearch"; - status.innerHTML = ""; - } - - - function setclass(first, last, status) - { - for (var i = first; i <= last; i++) - { - children[i].className = status; - } - } - - - // do a binary search, treating 0 as ... - // return either -1 (no 0's found) or location of most far match - function bisect(dir) - { - var first = 0, finish = children.length - 1; - var mid, success = false; - - while (finish - first > 3) - { - mid = Math.floor((finish + first) / 2); - - var i = checkitem(mid); - if (i == 0) i = dir; - if (i == -1) - finish = mid; - else - first = mid; - } - var a = (dir == 1 ? first : finish); - var b = (dir == 1 ? finish : first); - for (var i = b; i != a - dir; i -= dir) - { - if (checkitem(i) == 0) return i; - } - return -1; - } - - - // from an index, decide what the result is - // 0 = match, -1 is lower, 1 is higher - function checkitem(i) - { - var s = getitem(i).toLowerCase().substr(0, text.length); - if (s == text) return 0; - else return (s > text ? -1 : 1); - } - - - // from an index, get its string - // this abstracts over alternates - function getitem(i) - { - for ( ; i >= 0; i--) - { - var s = children[i].firstChild.firstChild.data; - if (s.indexOf(' ') == -1) - return s; - } - return ""; // should never be reached - } -} - -function setSynopsis(filename) { - if (parent.window.synopsis) { - parent.window.synopsis.location = filename; - } -} diff --git a/static/docs/0.1.1/snap-server/haddock.css b/static/docs/0.1.1/snap-server/haddock.css deleted file mode 100644 index bbe9dac..0000000 --- a/static/docs/0.1.1/snap-server/haddock.css +++ /dev/null @@ -1,478 +0,0 @@ -/* -------- Global things --------- */ - -@font-face { - font-family: 'DroidSerif'; - src: url('fonts/DroidSerif-Regular.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Regular.woff') format('woff'), - url('fonts/DroidSerif-Regular.ttf') format('truetype'), - url('fonts/DroidSerif-Regular.svg#DroidSerif') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - font-style: italic; - src: url('fonts/DroidSerif-Italic.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Italic.woff') format('woff'), - url('fonts/DroidSerif-Italic.ttf') format('truetype'), - url('fonts/DroidSerif-Italic.svg#DroidSerif-Italic') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - font-weight: bold; - src: url('fonts/DroidSerif-Bold.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Bold.woff') format('woff'), - url('fonts/DroidSerif-Bold.ttf') format('truetype'), - url('fonts/DroidSerif-Bold.svg#DroidSerif-Bold') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - src: url('fonts/DroidSerif-BoldItalic.eot'); - font-weight: bold; - font-style: italic; - src: local('Droid Serif'), - url('fonts/DroidSerif-BoldItalic.woff') format('woff'), - url('fonts/DroidSerif-BoldItalic.ttf') format('truetype'), - url('fonts/DroidSerif-BoldItalic.svg#DroidSerif-BoldItalic') format('svg'); -} - - - -HTML { - background-color: #f0f3ff; - width: 100%; -} - -BODY { - -moz-border-radius:5px; - -webkit-border-radius:5px; - width: 90ex; - margin: 2em auto; - padding: 0; - background-color: #ffffff; - color: #000000; - font-size: 110%; - font-family: DroidSerif, Georgia, serif; - } - -A:link { color: #5200A3; text-decoration: none } -A:visited { color: #5200A3; text-decoration: none } -A:hover { color: #5200A3; text-decoration: none; border-bottom:#5200A3 dashed 1px; } - -TABLE.vanilla { - width: 100%; - border-width: 0px; - /* I can't seem to specify cellspacing or cellpadding properly using CSS... */ -} - -DL { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - letter-spacing: -0.01em; - margin: 0; -} - -.vanilla .vanilla dl { font-size: 80%; } -.vanilla .vanilla dl dl { padding-left: 0; font-size: 95%; } - -TD.section1, TD.section2, TD.section3, TD.section4, TD.doc, DL { - padding: 0 30px 0 34px; -} - -TABLE.vanilla2 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - border-width: 0px; -} - -/* font is a little too small in MSIE */ -TT, PRE, CODE { - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - font-size: 90%; -} - -LI P { margin: 0pt } - -P { margin-top: 0; margin-bottom: 0.75em; } - -TD { - border-width: 0px; -} - -TABLE.narrow { - border-width: 0px; -} - -TD.s8 { height: 0; margin:0; padding: 0 } -TD.s15 { height: 20px; } - -SPAN.keyword { text-decoration: underline; } - -/* Resize the buttom image to match the text size */ -IMG.coll { width : 0.75em; height: 0.75em; margin-bottom: 0; margin-right: 0.5em } - -/* --------- Contents page ---------- */ - -DIV.node { - padding-left: 3em; -} - -DIV.cnode { - padding-left: 1.75em; -} - -SPAN.pkg { - position: absolute; - left: 50em; -} - -/* --------- Documentation elements ---------- */ - -TD FONT { font-weight: bold; letter-spacing: -0.02em; } - -TD.children { - padding-left: 25px; - } - -TD.synopsis { - padding: 2px; - background-color: #f0f0f0; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - } - -TD.decl { - padding: 4px 8px; - background-color: #FAFAFA; - border-bottom: #F2F2F2 solid 1px; - border-top: #FCFCFC solid 1px; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - vertical-align: top; - } - -TD.decl TD.decl { - font-size: 100%; - padding: 4px 0; - border: 0; -} - -TD.topdecl { - padding: 20px 30px 0.5ex 30px; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; -; - vertical-align: top; -} - -.vanilla .vanilla .vanilla .topdecl { - padding-left: 0; - padding-right: 0; -} - -.vanilla .vanilla .vanilla { - padding-left: 30px; -} - -.decl .vanilla { - padding-left: 0px !important; -} - -.body .vanilla .body { - padding-left: 0; - padding-right: 0; -} - -.body .vanilla .body .decl { - padding-left: 12px; -} - -.body .vanilla .body div .vanilla .decl { - padding-left: 12px; -} - -TABLE.declbar { - background-color: #f0f0f0; - border-spacing: 0px; - border-bottom:1px solid #d7d7df; - border-right:1px solid #d7d7df; - border-top:1px solid #f4f4f9; - border-left:1px solid #f4f4f9; - padding: 4px; - } - -TD.declname { - width: 100%; - padding-right: 4px; - } - -TD.declbut { - padding-left: 8px; - padding-right: 5px; - border-left-width: 1px; - border-left-color: #000099; - border-left-style: solid; - white-space: nowrap; - font-size: x-small; - } - -/* - arg is just like decl, except that wrapping is not allowed. It is - used for function and constructor arguments which have a text box - to the right, where if wrapping is allowed the text box squashes up - the declaration by wrapping it. -*/ -TD.arg { - padding: 2px 12px; - background-color: #f0f0f0; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - vertical-align: top; - white-space: nowrap; - } - -TD.recfield { padding-left: 20px } - -TD.doc { - padding-left: 38px; - font-size: 95%; - line-height: 1.66; - } - -TD.ndoc { - font-size: 95%; - line-height: 1.66; - padding: 2px 4px 2px 8px; - } - -TD.rdoc { - padding: 2px; - padding-left: 30px; - width: 100%; - font-size: 80%; - font-style: italic; - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - } - -TD.body { - padding: 0 30px; - } - -TD.pkg { - width: 100%; - padding-left: 30px -} - -TABLE.indexsearch TR.indexrow { - display: none; -} -TABLE.indexsearch TR.indexshow { - display: table-row; -} - -TD.indexentry { - vertical-align: top; - padding: 0 30px - } - -TD.indexannot { - vertical-align: top; - padding-left: 20px; - white-space: nowrap - } - -TD.indexlinks { - width: 100% - } - -/* ------- Section Headings ------- */ - -TD.section1, TD.section2, TD.section3, TD.section4, TD.section5 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; -} - -TD.section1 { - padding-top: 14px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 140% - } - -TD.section2 { - padding-top: 4px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 120% - } - -TD.section3 { - padding-top: 5px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 105% - } - -TD.section4 { - font-weight: bold; - padding-top: 12px; - padding-bottom: 4px; - letter-spacing: -0.02em; - font-size: 90% - } - -/* -------------- The title bar at the top of the page */ - -TD.infohead { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - font-weight: bold; - padding: 0 30px; - text-align: left; -} - -TD.infoval { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - padding: 0 30px; - text-align: left; -} - -TD.topbar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - background-color: #3465a4; - padding: 5px; - -moz-border-radius-topleft:5px; - -moz-border-radius-topright:5px; - -webkit-border-radius-topleft:5px; - -webkit-border-radius-topright:5px; -} - -TD.title { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - padding-left: 30px; - letter-spacing: -0.02em; - font-weight: bold; - width: 100% - } - -TD.topbut { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - padding-left: 5px; - padding-right: 5px; - border-left-width: 1px; - border-left-color: #ffffff; - border-left-style: solid; - letter-spacing: -0.02em; - font-weight: bold; - white-space: nowrap; - } - -TD.topbut A:link { - color: #ffffff - } - -TD.topbut A:visited { - color: #ffff00 - } - -TD.topbut A:hover { - background-color: #C9D3DE; - } - -TD.topbut:hover { - background-color: #C9D3DE; - } - -TD.modulebar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #141B24; - background-color: #C9D3DE; - padding: 5px; - border-top-width: 1px; - border-top-color: #ffffff; - border-top-style: solid; - -moz-border-radius-bottomleft:5px; - -moz-border-radius-bottomright:5px; - -webkit-border-radius-bottomleft:5px; - -webkit-border-radius-bottomright:5px; - - } - -/* --------- The page footer --------- */ - -TD.botbar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - -moz-border-radius:5px; - -webkit-border-radius:5px; - background-color: #3465a4; - color: #ffffff; - padding: 5px - } -TD.botbar A:link { - color: #ffffff; - text-decoration: underline - } -TD.botbar A:visited { - color: #ffff00 - } -TD.botbar A:hover { - background-color: #6060ff - } - -/* --------- Mini Synopsis for Frame View --------- */ - -.outer { - margin: 0 0; - padding: 0 0; -} - -.mini-synopsis { - padding: 0.25em 0.25em; -} - -.mini-synopsis H1 { font-size: 120%; } -.mini-synopsis H2 { font-size: 107%; } -.mini-synopsis H3 { font-size: 100%; } -.mini-synopsis H1, .mini-synopsis H2, .mini-synopsis H3 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - margin-top: 0.5em; - margin-bottom: 0.25em; - padding: 0 0; - font-weight: bold; letter-spacing: -0.02em; -} - -.mini-synopsis H1 { border-bottom: 1px solid #ccc; } - -.mini-topbar { - font-size: 120%; - background: #0077dd; - padding: 0.25em; -} - - diff --git a/static/docs/0.1.1/snap-server/haskell_icon.gif b/static/docs/0.1.1/snap-server/haskell_icon.gif deleted file mode 100644 index cb2a815..0000000 Binary files a/static/docs/0.1.1/snap-server/haskell_icon.gif and /dev/null differ diff --git a/static/docs/0.1.1/snap-server/index-frames.html b/static/docs/0.1.1/snap-server/index-frames.html deleted file mode 100644 index 8fe09ab..0000000 --- a/static/docs/0.1.1/snap-server/index-frames.html +++ /dev/null @@ -1,28 +0,0 @@ - - -snap-server-0.1.1: A fast, iteratee-based, epoll-enabled web server for the Snap Framework

Snap.Http.Server
Snap.Http.Server.Config
System.FastLogger

diff --git a/static/docs/0.1.1/snap-server/index.html b/static/docs/0.1.1/snap-server/index.html deleted file mode 100644 index 6dddea2..0000000 --- a/static/docs/0.1.1/snap-server/index.html +++ /dev/null @@ -1,178 +0,0 @@ - - -snap-server-0.1.1: A fast, iteratee-based, epoll-enabled web server for the Snap Framework
 snap-server-0.1.1: A fast, iteratee-based, epoll-enabled web server for the Snap FrameworkContentsIndex
snap-server-0.1.1: A fast, iteratee-based, epoll-enabled web server for the Snap Framework

This is the first developer prerelease of the Snap framework. Snap is a -simple and fast web development framework and server written in Haskell. For -more information or to download the latest version, you can visit the Snap -project website at http://snapframework.com/. -

The Snap HTTP server is a high performance, epoll-enabled, iteratee-based web -server library written in Haskell. Together with the snap-core library upon -which it depends, it provides a clean and efficient Haskell programming -interface to the HTTP protocol. -

Higher-level facilities for building web applications (like user/session -management, component interfaces, data modeling, etc.) are planned but not -yet implemented, so this release will mostly be of interest for those who: -

  • need a fast and minimal HTTP API at roughly the same level of abstraction -as Java servlets, or -
  • are interested in contributing to the Snap Framework project. -
Modules
show/hideSnap
show/hideHttp
show/hideSnap.Http.Server
Snap.Http.Server.Config
show/hideSystem
System.FastLogger
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.1/snap-server/mini_Snap-Http-Server-Config.html b/static/docs/0.1.1/snap-server/mini_Snap-Http-Server-Config.html deleted file mode 100644 index c4ec20a..0000000 --- a/static/docs/0.1.1/snap-server/mini_Snap-Http-Server-Config.html +++ /dev/null @@ -1,31 +0,0 @@ - - -Snap.Http.Server.Config
Snap.Http.Server.Config
diff --git a/static/docs/0.1.1/snap-server/mini_Snap-Http-Server.html b/static/docs/0.1.1/snap-server/mini_Snap-Http-Server.html deleted file mode 100644 index 3841177..0000000 --- a/static/docs/0.1.1/snap-server/mini_Snap-Http-Server.html +++ /dev/null @@ -1,25 +0,0 @@ - - -Snap.Http.Server
Snap.Http.Server
diff --git a/static/docs/0.1.1/snap-server/mini_System-FastLogger.html b/static/docs/0.1.1/snap-server/mini_System-FastLogger.html deleted file mode 100644 index 891c97c..0000000 --- a/static/docs/0.1.1/snap-server/mini_System-FastLogger.html +++ /dev/null @@ -1,47 +0,0 @@ - - -System.FastLogger diff --git a/static/docs/0.1.1/snap-server/minus.gif b/static/docs/0.1.1/snap-server/minus.gif deleted file mode 100644 index 1deac2f..0000000 Binary files a/static/docs/0.1.1/snap-server/minus.gif and /dev/null differ diff --git a/static/docs/0.1.1/snap-server/plus.gif b/static/docs/0.1.1/snap-server/plus.gif deleted file mode 100644 index 2d15c14..0000000 Binary files a/static/docs/0.1.1/snap-server/plus.gif and /dev/null differ diff --git a/static/docs/0.1.1/snap-server/snap-server.haddock b/static/docs/0.1.1/snap-server/snap-server.haddock deleted file mode 100644 index 6d91b59..0000000 Binary files a/static/docs/0.1.1/snap-server/snap-server.haddock and /dev/null differ diff --git a/static/docs/0.1.1/snap-server/src/Snap-Http-Server-Config.html b/static/docs/0.1.1/snap-server/src/Snap-Http-Server-Config.html deleted file mode 100644 index 5c11ecf..0000000 --- a/static/docs/0.1.1/snap-server/src/Snap-Http-Server-Config.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - -src/Snap/Http/Server/Config.hs - - - -
{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# OPTIONS_GHC -fno-warn-orphans #-}
-
-module Snap.Http.Server.Config
-  ( Config(..)
-  , readConfigFromCmdLineArgs
-  ) where
-
-import           Data.ByteString (ByteString)
-import qualified Data.ByteString as B
-import           Data.ByteString.Internal (c2w)
-import           Data.ByteString.Char8 ()
-import           Data.Maybe
-import           Data.Monoid
-import           System.Console.GetOpt
-import           System.Environment
-import           System.Exit
-import           System.IO
-
-data Config = Config
-    { localHostname :: !ByteString
-    , bindAddress   :: !ByteString
-    , listenPort    :: !Int
-    , accessLog     :: !(Maybe FilePath)
-    , errorLog      :: !(Maybe FilePath)
-    } deriving (Show)
-
-
-data Flag = Flag
-    { flagLocalHost   :: Maybe String
-    , flagBindAddress :: Maybe String
-    , flagPort        :: Maybe Int
-    , flagAccessLog   :: Maybe String
-    , flagErrorLog    :: Maybe String
-    , flagUsage       :: Bool
-    }
-
-instance Monoid Flag where
-    mempty = Flag Nothing Nothing Nothing Nothing Nothing False
-
-    (Flag a1 b1 c1 d1 e1 f1) `mappend` (Flag a2 b2 c2 d2 e2 f2) =
-        Flag (getLast $ Last a1 `mappend` Last a2)
-             (getLast $ Last b1 `mappend` Last b2)
-             (getLast $ Last c1 `mappend` Last c2)
-             (getLast $ Last d1 `mappend` Last d2)
-             (getLast $ Last e1 `mappend` Last e2)
-             (f1 || f2)
-
-flagLH :: String -> Flag
-flagLH s = mempty { flagLocalHost = Just s }
-
-flagBA :: String -> Flag
-flagBA s = mempty { flagBindAddress = Just s }
-
-flagPt :: String -> Flag
-flagPt p = mempty { flagPort = Just (read p) }
-
-flagAL :: String -> Flag
-flagAL s = mempty { flagAccessLog = Just s }
-
-flagEL :: String -> Flag
-flagEL s = mempty { flagErrorLog = Just s }
-
-flagHelp :: Flag
-flagHelp = mempty { flagUsage = True }
-
-fromStr :: String -> ByteString
-fromStr = B.pack . map c2w
-
-flags2config :: Flag -> Config
-flags2config (Flag a b c d e _) =
-    Config (maybe "localhost" fromStr a)
-           (maybe "*" fromStr b)
-           (fromMaybe 8888 c)
-           d
-           e
-
-
-options :: [OptDescr Flag]
-options =
-    [ Option "l" ["localHostname"]
-                 (ReqArg flagLH "STR")
-                 "local hostname, default 'localhost'"
-    , Option "p" ["listenPort"]
-                 (ReqArg flagPt "NUM")
-                 "port to listen on, default 8888"
-    , Option "b" ["bindAddress"]
-                 (ReqArg flagBA "STR")
-                 "address to bind to, default '*'"
-    , Option "a" ["accessLog"]
-                 (ReqArg flagAL "STR")
-                 "access log in the 'combined' format, optional"
-    , Option "e" ["errorLog"]
-                 (ReqArg flagEL "STR")
-                 "error log, optional"
-    , Option "h" ["help"]
-                 (NoArg flagHelp)
-                 "display this usage statement" ]
-
-
-readConfigFromCmdLineArgs :: String     -- ^ application description, e.g.
-                                        --   \"Foo applet v0.2\"
-                          -> IO Config
-readConfigFromCmdLineArgs appName = do
-    argv     <- getArgs
-    progName <- getProgName
-
-    case getOpt Permute options argv of
-      (f,_,[]  ) -> withFlags progName f
-      (_,_,errs) -> bombout progName errs
-  where
-    bombout progName errs = do
-        let hdr = appName ++ "\n\nUsage: " ++ progName ++ " [OPTIONS]"
-        let msg = concat errs ++ usageInfo hdr options
-        hPutStrLn stderr msg
-        exitFailure
-
-    withFlags progName fs = do
-        let f = mconcat fs
-        if flagUsage f
-           then bombout progName []
-           else return $ flags2config f
-
- diff --git a/static/docs/0.1.1/snap-server/src/Snap-Http-Server.html b/static/docs/0.1.1/snap-server/src/Snap-Http-Server.html deleted file mode 100644 index dbe6ebb..0000000 --- a/static/docs/0.1.1/snap-server/src/Snap-Http-Server.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - -src/Snap/Http/Server.hs - - - -
-- | The Snap HTTP server is a high performance, epoll-enabled, iteratee-based
--- web server library written in Haskell. Together with the @snap-core@ library
--- upon which it depends, it provides a clean and efficient Haskell programming
--- interface to the HTTP protocol.
-module Snap.Http.Server
-(
-  httpServe
-) where
-
-import           Data.ByteString (ByteString)
-import           Snap.Types
-import qualified Snap.Internal.Http.Server as Int
-
-
--- | Starts serving HTTP requests on the given port using the given handler.
--- This function never returns; to shut down the HTTP server, kill the
--- controlling thread.
-httpServe :: ByteString      -- ^ bind address, or \"*\" for all
-          -> Int             -- ^ port to bind to
-          -> ByteString      -- ^ local hostname (server name)
-          -> Maybe FilePath  -- ^ path to the (optional) access log
-          -> Maybe FilePath  -- ^ path to the (optional) error log
-          -> Snap ()         -- ^ handler procedure
-          -> IO ()
-httpServe bindAddress bindPort localHostname alog elog handler =
-    Int.httpServe bindAddress bindPort localHostname alog elog handler'
-  where
-    handler' = runSnap handler
-
- diff --git a/static/docs/0.1.1/snap-server/src/Snap-Internal-Http-Parser.html b/static/docs/0.1.1/snap-server/src/Snap-Internal-Http-Parser.html deleted file mode 100644 index a50a1de..0000000 --- a/static/docs/0.1.1/snap-server/src/Snap-Internal-Http-Parser.html +++ /dev/null @@ -1,450 +0,0 @@ - - - - -src/Snap/Internal/Http/Parser.hs - - - -
{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RankNTypes #-}
-
-module Snap.Internal.Http.Parser
-  ( IRequest(..)
-  , parseRequest
-  , readChunkedTransferEncoding
-  , parserToIteratee
-  , parseCookie
-  , parseUrlEncoded
-  , writeChunkedTransferEncoding
-  , strictize
-  ) where
-
-
-------------------------------------------------------------------------------
-import           Control.Applicative
-import           Control.Arrow (first, second)
-import           Control.Monad (liftM)
-import           Control.Monad.Trans
-import           Data.Attoparsec hiding (many, Result(..))
-import           Data.Attoparsec.Iteratee
-import           Data.Bits
-import           Data.ByteString (ByteString)
-import qualified Data.ByteString as S
-import           Data.ByteString.Internal (c2w, w2c)
-import qualified Data.ByteString.Lazy as L
-import qualified Data.ByteString.Nums.Careless.Hex as Cvt
-import           Data.Char
-import           Data.CIByteString
-import           Data.List (foldl')
-import           Data.Int
-import           Data.Map (Map)
-import qualified Data.Map as Map
-import           Data.Maybe (catMaybes, fromMaybe)
-import           Data.Time.Format (parseTime)
-import qualified Data.Vector.Unboxed as Vec
-import           Data.Vector.Unboxed (Vector)
-import           Data.Word (Word8, Word64)
-import           Prelude hiding (take, takeWhile)
-import           System.Locale (defaultTimeLocale)
-------------------------------------------------------------------------------
-import           Snap.Internal.Http.Types hiding (Enumerator)
-import           Snap.Iteratee hiding (take, foldl')
-
-
-
-------------------------------------------------------------------------------
--- | an internal version of the headers part of an HTTP request
-data IRequest = IRequest
-    { iMethod :: Method
-    , iRequestUri :: ByteString
-    , iHttpVersion :: (Int,Int)
-    , iRequestHeaders :: [(ByteString, ByteString)]
-    }
-
-instance Show IRequest where
-    show (IRequest m u v r) =
-        concat [ show m
-               , " "
-               , show u
-               , " "
-               , show v
-               , " "
-               , show r ]
-
-------------------------------------------------------------------------------
-parseRequest :: (Monad m) => Iteratee m (Maybe IRequest)
-parseRequest = parserToIteratee pRequest
-
-
-readChunkedTransferEncoding :: (Monad m) => Enumerator m a
-readChunkedTransferEncoding iter = do
-      i <- chunkParserToEnumerator (parserToIteratee pGetTransferChunk)
-                                   iter
-
-      return i 
-
-
-toHex :: Int64 -> ByteString
-toHex !i' = S.reverse s
-  where
-    !i     = abs i'
-    (!s,_) = S.unfoldrN 16 f (fromIntegral i)
-
-    f :: Word64 -> Maybe (Word8, Word64)
-    f d = if d == 0
-            then Nothing
-            else Just (ch, theRest)
-
-      where
-        low4    = fromIntegral $ d .&. 0xf
-        ch      = if low4 >= 10
-                    then c2w 'a' + low4 - 10
-                    else c2w '0' + low4
-        theRest = (d .&. (complement 0xf)) `shiftR` 4
-
-
--- | Given an iteratee, produces a new one that wraps chunks sent to it with a
--- chunked transfer-encoding. Example usage:
---
--- > > (writeChunkedTransferEncoding
--- >     (enumLBS (L.fromChunks ["foo","bar","quux"]))
--- >     stream2stream) >>=
--- >     run >>=
--- >     return . fromWrap
--- >
--- > Chunk "3\r\nfoo\r\n3\r\nbar\r\n4\r\nquux\r\n0\r\n\r\n" Empty
---
-writeChunkedTransferEncoding :: (Monad m) => Enumerator m a -> Enumerator m a
-writeChunkedTransferEncoding enum it = do
-    i <- wrap it
-    enum i
-
-  where
-    wrap iter = return $ IterateeG $ \s ->
-        case s of
-          (EOF Nothing) -> do
-              v <- runIter iter (Chunk $ toWrap "0\r\n\r\n")
-              i <- checkIfDone return v
-              runIter i (EOF Nothing)
-          (EOF e) -> return $ Cont undefined e
-          (Chunk x') -> do
-              let x = S.concat $ L.toChunks $ fromWrap x'
-              let n = S.length x
-              let o = L.fromChunks [ toHex (toEnum n)
-                                   , "\r\n"
-                                   , x
-                                   , "\r\n" ]
-              v <- runIter iter (Chunk $ toWrap o)
-              i <- checkIfDone wrap v
-              return $ Cont i Nothing
-
-
-chunkParserToEnumerator :: (Monad m) =>
-                           Iteratee m (Maybe ByteString)
-                        -> Iteratee m a
-                        -> m (Iteratee m a)
-chunkParserToEnumerator getChunk client = return $ do
-    mbB <- getChunk
-    maybe (finishIt client) (sendBS client) mbB
-
-  where
-    sendBS iter s = do
-        v <- lift $ runIter iter (Chunk $ toWrap $ L.fromChunks [s])
-
-        case v of
-          (Done _ (EOF (Just e))) -> throwErr e
-
-          (Done x _) -> return x
-
-          (Cont _ (Just e)) -> throwErr e
-
-          (Cont k Nothing) -> joinIM $
-                              chunkParserToEnumerator getChunk k
-
-    finishIt iter = do
-        e <- lift $ sendEof iter
-
-        case e of
-          Left x  -> throwErr x
-          Right x -> return x
-
-    sendEof iter = do
-        v <- runIter iter (EOF Nothing)
-
-        return $ case v of
-          (Done _ (EOF (Just e))) -> Left e
-          (Done x _)              -> Right x
-          (Cont _ (Just e))       -> Left e
-          (Cont _ _)              -> Left $ Err $ "divergent iteratee"
-
-
-------------------------------------------------------------------------------
--- parse functions
-------------------------------------------------------------------------------
-
--- theft alert: many of these routines adapted from Johan Tibell's hyena
--- package
-
--- | Parsers for different tokens in an HTTP request.
-sp, digit, letter :: Parser Word8
-sp       = word8 $ c2w ' '
-digit    = satisfy (isDigit . w2c)
-letter   = satisfy (isAlpha . w2c)
-
-untilEOL :: Parser ByteString
-untilEOL = takeWhile notend
-  where
-    notend d = let c = w2c d in not $ c == '\r' || c == '\n'
-
-crlf :: Parser ByteString
-crlf = string "\r\n"
-
--- | Parser for zero or more spaces.
-spaces :: Parser [Word8]
-spaces = many sp
-
-pSpaces :: Parser ByteString
-pSpaces = takeWhile (isSpace . w2c)
-
--- | Parser for the internal request data type.
-pRequest :: Parser (Maybe IRequest)
-pRequest = (Just <$> pRequest') <|> (endOfInput *> pure Nothing)
-
-pRequest' :: Parser IRequest
-pRequest' = IRequest
-               <$> (option "" crlf *> pMethod)  <* sp
-               <*> pUri                         <* sp
-               <*> pVersion                     <* crlf
-               <*> pHeaders                     <* crlf
-
-  -- note: the optional crlf is at the beginning because some older browsers
-  -- send an extra crlf after a POST body
-
-
--- | Parser for the request method.
-pMethod :: Parser Method
-pMethod =     (OPTIONS <$ string "OPTIONS")
-          <|> (GET     <$ string "GET")
-          <|> (HEAD    <$ string "HEAD")
-          <|> word8 (c2w 'P') *> ((POST <$ string "OST") <|>
-                                  (PUT  <$ string "UT"))
-          <|> (DELETE  <$ string "DELETE")
-          <|> (TRACE   <$ string "TRACE")
-          <|> (CONNECT <$ string "CONNECT")
-
--- | Parser for the request URI.
-pUri :: Parser ByteString
-pUri = takeWhile (not . isSpace . w2c)
-
--- | Parser for the request's HTTP protocol version.
-pVersion :: Parser (Int, Int)
-pVersion = string "HTTP/" *>
-           liftA2 (,) (digit' <* word8 (c2w '.')) digit'
-    where
-      digit' = fmap (digitToInt . w2c) digit
-
-fieldChars :: Parser ByteString
-fieldChars = takeWhile isFieldChar
-  where
-    isFieldChar c = (Vec.!) fieldCharTable (fromEnum c)
-
-fieldCharTable :: Vector Bool
-fieldCharTable = Vec.generate 256 f
-  where
-    f d = let c=toEnum d in (isDigit c) || (isAlpha c) || c == '-' || c == '_'
-
-
--- | Parser for request headers.
-pHeaders :: Parser [(ByteString, ByteString)]
-pHeaders = many header
-  where
-    header = {-# SCC "pHeaders/header" #-}
-             liftA2 (,)
-                 fieldName
-                 (word8 (c2w ':') *> spaces *> contents)
-
-    fieldName = {-# SCC "pHeaders/fieldName" #-}
-                liftA2 S.cons letter fieldChars
-
-    contents = {-# SCC "pHeaders/contents" #-}
-               liftA2 S.append
-                   (untilEOL <* crlf)
-                   (continuation <|> pure S.empty)
-
-    isLeadingWS w = {-# SCC "pHeaders/isLeadingWS" #-}
-                    elem w wstab
-
-    wstab = map c2w " \t"
-
-    leadingWhiteSpace = {-# SCC "pHeaders/leadingWhiteSpace" #-}
-                        takeWhile1 isLeadingWS
-
-    continuation = {-# SCC "pHeaders/continuation" #-}
-                   liftA2 S.cons
-                          (leadingWhiteSpace *> pure (c2w ' '))
-                          contents
-
-
-pGetTransferChunk :: Parser (Maybe ByteString)
-pGetTransferChunk = do
-    !hex <- liftM fromHex $ (takeWhile (isHexDigit . w2c))
-    takeTill ((== '\r') . w2c)
-    crlf
-    if hex <= 0
-      then return Nothing
-      else do
-          x <- take hex
-          crlf
-          return $ Just x
-  where
-    fromHex :: ByteString -> Int
-    fromHex s = Cvt.hex (L.fromChunks [s])
-
-
-------------------------------------------------------------------------------
--- COOKIE PARSING
-------------------------------------------------------------------------------
-
--- these definitions try to mirror RFC-2068 (the HTTP/1.1 spec) and RFC-2109
--- (cookie spec): please point out any errors!
-
-{-# INLINE matchAll #-}
-matchAll :: [ Char -> Bool ] -> Char -> Bool
-matchAll x c = and $ map ($ c) x
-
-{-# INLINE isToken #-}
-isToken :: Char -> Bool
-isToken c = (Vec.!) tokenTable (fromEnum c)
-  where
-    tokenTable :: Vector Bool
-    tokenTable = Vec.generate 256 (f . toEnum)
-
-    f = matchAll [ isAscii
-                 , not . isControl
-                 , not . isSpace 
-                 , not . flip elem [ '(', ')', '<', '>', '@', ',', ';'
-                                   , ':', '\\', '\"', '/', '[', ']'
-                                   , '?', '=', '{', '}' ]
-                 ]
-
-{-# INLINE isRFCText #-}
-isRFCText :: Char -> Bool
-isRFCText = not . isControl
-
-pToken :: Parser ByteString
-pToken = takeWhile (isToken . w2c)
-
-
-pQuotedString :: Parser ByteString
-pQuotedString = q *> quotedText <* q
-  where
-    quotedText = (S.concat . reverse) <$> f []
-
-    f soFar = do
-        t <- takeWhile qdtext
-
-        let soFar' = t:soFar
-
-        -- RFC says that backslash only escapes for <">
-        choice [ string "\\\"" *> f ("\"" : soFar')
-               , pure soFar' ]
-
-
-    q = word8 $ c2w '\"'
-
-    qdtext = matchAll [ isRFCText, (/= '\"'), (/= '\\') ] . w2c
-    
-
-pCookie :: Parser Cookie
-pCookie = do
-    -- grab kvps and turn to strict bytestrings
-    kvps <- pAvPairs
-
-    -- kvps guaranteed non-null due to grammar. First avpair specifies
-    -- name=value mapping.
-    let ((nm,val):attrs') = kvps
-    let attrs             = map (first toCI) attrs'
-
-    -- and we'll gather the rest of the fields with helper functions.
-    return $ foldl' field (nullCookie nm val) attrs
-
-
-  where
-    nullCookie nm val = Cookie nm val Nothing Nothing Nothing
-
-    fieldFuncs :: [ (CIByteString, Cookie -> ByteString -> Cookie) ]
-    fieldFuncs = [ ("domain", domain)
-                 , ("expires", expires)
-                 , ("path", path) ]
-
-    domain c d     = c { cookieDomain  = Just d }
-    path c p       = c { cookiePath    = Just p }
-    expires c e    = c { cookieExpires = parseExpires e }
-    parseExpires e = parseTime defaultTimeLocale
-                               "%a, %d-%b-%Y %H:%M:%S GMT"
-                               (map w2c $ S.unpack e)
-
-    field c (k,v) = fromMaybe c (flip ($ c) v <$> lookup k fieldFuncs)
-
-
--- unhelpfully, the spec mentions "old-style" cookies that don't have quotes
--- around the value. wonderful.
-pWord :: Parser ByteString
-pWord = pQuotedString <|> (takeWhile ((/= ';') . w2c))
-
-pAvPairs :: Parser [(ByteString, ByteString)]
-pAvPairs = do
-    a <- pAvPair
-    b <- many (pSpaces *> char ';' *> pSpaces *> pAvPair)
-
-    return $ a:b
-
-pAvPair :: Parser (ByteString, ByteString)
-pAvPair = do
-    key <- pToken <* pSpaces
-    val <- option "" $ char '=' *> pSpaces *> pWord
-
-    return (key,val)
-
-parseCookie :: ByteString -> Maybe Cookie
-parseCookie = parseToCompletion pCookie
-
-------------------------------------------------------------------------------
--- MULTIPART/FORMDATA
-------------------------------------------------------------------------------
-
-parseUrlEncoded :: ByteString -> Map ByteString [ByteString]
-parseUrlEncoded s = foldl' (\m (k,v) -> Map.insertWith' (++) k [v] m)
-                           Map.empty
-                           decoded
-  where
-    breakApart = (second (S.drop 1)) . S.break (== (c2w '=')) 
-
-    parts :: [(ByteString,ByteString)]
-    parts = map breakApart $ S.split (c2w '&') s
-
-    urldecode = parseToCompletion pUrlEscaped
-
-    decodeOne (a,b) = do
-        a' <- urldecode a
-        b' <- urldecode b
-        return (a',b')
-
-    decoded = catMaybes $ map decodeOne parts
-
-
-------------------------------------------------------------------------------
--- utility functions
-------------------------------------------------------------------------------
-
-strictize :: L.ByteString -> ByteString
-strictize         = S.concat . L.toChunks
-
-------------------------------------------------------------------------------
-char :: Char -> Parser Word8
-char = word8 . c2w
-
-
- diff --git a/static/docs/0.1.1/snap-server/src/Snap-Internal-Http-Server-Date.html b/static/docs/0.1.1/snap-server/src/Snap-Internal-Http-Server-Date.html deleted file mode 100644 index 40a5e91..0000000 --- a/static/docs/0.1.1/snap-server/src/Snap-Internal-Http-Server-Date.html +++ /dev/null @@ -1,125 +0,0 @@ - - - - -src/Snap/Internal/Http/Server/Date.hs - - - -
{-# LANGUAGE BangPatterns #-}
-
-module Snap.Internal.Http.Server.Date
-( getDateString
-, getLogDateString
-, getCurrentDateTime) where
-
-import           Control.Concurrent
-import           Control.Exception
-import           Control.Monad
-import           Data.ByteString (ByteString)
-import           Data.ByteString.Internal (c2w)
-import qualified Data.ByteString as B
-import           Data.IORef
-import           Data.Time.Clock
-import           Data.Time.LocalTime
-import           Data.Time.Format
-import           System.IO.Unsafe
-import           System.Locale
-
-
--- Here comes a dirty hack. We don't want to be wasting context switches
--- building date strings, so we're only going to compute one every two
--- seconds. (Approximate timestamps to within a couple of seconds are OK here,
--- and we'll reduce overhead.)
---
--- Note that we also don't want to wake up a potentially sleeping CPU by just
--- running the computation on a timer. We'll allow client traffic to trigger
--- the process.
-
-data DateState = DateState {
-      _cachedDateString :: !(IORef ByteString)
-    , _cachedLogString  :: !(IORef ByteString)
-    , _cachedDate       :: !(IORef UTCTime)
-    , _valueIsOld       :: !(IORef Bool)
-    , _morePlease       :: !(MVar ())
-    , _dataAvailable    :: !(MVar ())
-    , _dateThread       :: !(MVar ThreadId)
-    }
-
-dateState :: DateState
-dateState = unsafePerformIO $ do
-    (s1,s2,date) <- fetchTime
-    bs1 <- newIORef s1
-    bs2 <- newIORef s2
-    dt  <- newIORef date
-    ov  <- newIORef False
-    th  <- newEmptyMVar
-    mp  <- newMVar ()
-    da  <- newMVar ()
-
-    let d = DateState bs1 bs2 dt ov mp da th
-
-    t  <- forkIO $ dateThread d
-    putMVar th t
-
-    return d
-
-
-fetchTime :: IO (ByteString,ByteString,UTCTime)
-fetchTime = do
-     now <- getCurrentTime
-     zt  <- liftM zonedTimeToLocalTime getZonedTime
-     return (t1 now, t2 zt, now)
-  where
-    t1 now = B.pack $ map c2w $
-             formatTime defaultTimeLocale "%a, %d %b %Y %H:%M:%S GMT" now
-    t2 now = B.pack $ map c2w $
-             formatTime defaultTimeLocale "%d/%b/%Y:%H:%M:%S %z" now
-
-dateThread :: DateState -> IO ()
-dateThread ds@(DateState dateString logString time valueIsOld morePlease
-                         dataAvailable _) = do
-    -- a lot of effort to make sure we don't deadlock
-    takeMVar morePlease
-
-    (s1,s2,now) <- fetchTime
-    atomicModifyIORef dateString $ const (s1,())
-    atomicModifyIORef logString $ const (s2,())
-    atomicModifyIORef time $ const (now,())
-
-    writeIORef valueIsOld False
-    tryPutMVar dataAvailable ()
-
-    threadDelay 2000000
-
-    takeMVar dataAvailable
-    writeIORef valueIsOld True
-
-    dateThread ds
-
-ensureFreshDate :: IO ()
-ensureFreshDate = block $ do
-    old <- readIORef $ _valueIsOld dateState
-    when old $ do
-        tryPutMVar (_morePlease dateState) ()
-        readMVar $ _dataAvailable dateState
-
-getDateString :: IO ByteString
-getDateString = block $ do
-    ensureFreshDate
-    readIORef $ _cachedDateString dateState
-
-
-getLogDateString :: IO ByteString
-getLogDateString = block $ do
-    ensureFreshDate
-    readIORef $ _cachedLogString dateState
-
-
-getCurrentDateTime :: IO UTCTime
-getCurrentDateTime = block $ do
-    ensureFreshDate
-    readIORef $ _cachedDate dateState
-
-
- diff --git a/static/docs/0.1.1/snap-server/src/Snap-Internal-Http-Server-LibevBackend.html b/static/docs/0.1.1/snap-server/src/Snap-Internal-Http-Server-LibevBackend.html deleted file mode 100644 index 8348ccf..0000000 --- a/static/docs/0.1.1/snap-server/src/Snap-Internal-Http-Server-LibevBackend.html +++ /dev/null @@ -1,643 +0,0 @@ - - - - -dist/build/Snap/Internal/Http/Server/LibevBackend.hs - - - -
{-# LINE 1 "src/Snap/Internal/Http/Server/LibevBackend.hsc" #-}
-{-# LANGUAGE BangPatterns #-}
-{-# LINE 2 "src/Snap/Internal/Http/Server/LibevBackend.hsc" #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE ForeignFunctionInterface #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RankNTypes #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module Snap.Internal.Http.Server.LibevBackend
-( Backend
-, BackendTerminatedException
-, Connection
-, TimeoutException
-, debug
-, bindIt
-, new
-, stop
-, withConnection
-, sendFile
-, getReadEnd
-, getWriteEnd
-, getRemoteAddr
-, getRemotePort
-, getLocalAddr
-, getLocalPort
-) where
-
----------------------------
--- TODO: document module --
----------------------------
-
-------------------------------------------------------------------------------
-import           Control.Concurrent
-import           Control.Exception
-import           Control.Monad
-import           Control.Monad.Trans
-import           Data.ByteString (ByteString)
-import           Data.ByteString.Internal (c2w, w2c)
-import qualified Data.ByteString.Unsafe as B
-import qualified Data.ByteString as B
-import           Data.IORef
-import           Data.Iteratee.WrappedByteString
-import           Data.Set (Set)
-import qualified Data.Set as Set
-import           Data.Typeable
-import           Foreign hiding (new)
-import           Foreign.C.Error
-import           Foreign.C.Types
-import           GHC.Conc (forkOnIO)
-import           Network.Libev
-import           Network.Socket
-import qualified Network.Socket.SendFile as SF
-import           Prelude hiding (catch)
-import           System.Timeout
-------------------------------------------------------------------------------
-import           Snap.Iteratee
-import           Snap.Internal.Debug
-
-
-data Backend = Backend
-    { _acceptSocket      :: Socket
-    , _acceptFd          :: CInt
-    , _connectionQueue   :: Chan CInt
-    , _evLoop            :: EvLoopPtr
-    , _acceptIOCallback  :: FunPtr IoCallback
-    , _acceptIOObj       :: EvIoPtr
-
-      -- FIXME: we don't need _loopThread
-    , _loopThread        :: MVar ThreadId
-    , _mutexCallbacks    :: (FunPtr MutexCallback, FunPtr MutexCallback)
-    , _loopLock          :: MVar ()
-    , _asyncCb           :: FunPtr AsyncCallback
-    , _asyncObj          :: EvAsyncPtr
-    , _killCb           :: FunPtr AsyncCallback
-    , _killObj          :: EvAsyncPtr
-    , _connectionThreads :: MVar (Set ThreadId)
-    , _backendCPU        :: Int
-    }
-
-
-data Connection = Connection
-    { _backend        :: Backend
-    , _socket         :: Socket
-    , _socketFd       :: CInt
-    , _remoteAddr     :: ByteString
-    , _remotePort     :: Int
-    , _localAddr      :: ByteString
-    , _localPort      :: Int
-    , _readAvailable  :: MVar ()
-    , _writeAvailable :: MVar ()
-    , _timerObj       :: EvTimerPtr
-    , _timerCallback  :: FunPtr TimerCallback
-    , _openingTime    :: CDouble
-    , _lastActivity   :: IORef CDouble
-    , _connIOObj      :: EvIoPtr
-    , _connIOCallback :: FunPtr IoCallback
-    , _connThread     :: MVar ThreadId
-    }
-
-
-sendFile :: Connection -> FilePath -> IO ()
-sendFile c fp = do
-    withMVar lock $ \_ -> evIoStop loop io
-    SF.sendFile s fp
-    withMVar lock $ \_ -> do
-      tryPutMVar (_readAvailable c) ()
-      tryPutMVar (_writeAvailable c) ()
-      evIoStart loop io
-      evAsyncSend loop asy
-
-  where
-    s    = _socket c
-    io   = _connIOObj c
-    b    = _backend c
-    loop = _evLoop b
-    lock = _loopLock b
-    asy  = _asyncObj b
-
-
-bindIt :: ByteString         -- ^ bind address, or \"*\" for all
-       -> Int                -- ^ port to bind to
-       -> IO (Socket,CInt)
-bindIt bindAddress bindPort = do
-    sock <- socket AF_INET Stream 0
-    addr <- getHostAddr bindPort bindAddress
-    setSocketOption sock ReuseAddr 1
-    bindSocket sock addr
-    listen sock bindPort
-    let sockFd = fdSocket sock
-    c_setnonblocking sockFd
-    return (sock, sockFd)
-
-
-new :: (Socket,CInt)   -- ^ value you got from bindIt
-    -> Int             -- ^ cpu
-    -> IO Backend
-new (sock,sockFd) cpu = do
-    connq <- newChan
-
-    -- We'll try kqueue on OSX even though the libev docs complain that it's
-    -- "broken", in the hope that it works as expected for sockets
-    f  <- evRecommendedBackends
-    lp <- evLoopNew $ toEnum . fromEnum $ f .|. evbackend_kqueue
-
-
-    -- we'll be working multithreaded so we need to set up locking for the C
-    -- event loop struct
-    (mc1,mc2,looplock) <- setupLockingForLoop lp
-
-    -- setup async callbacks -- these allow us to wake up the main loop
-    -- (normally blocked in c-land) from other threads
-    asyncObj <- mkEvAsync
-    asyncCB  <- mkAsyncCallback $ \_ _ _ -> do
-                            debug "async wakeup"
-                            return ()
-
-    killObj <- mkEvAsync
-    killCB  <- mkAsyncCallback $ \_ _ _ -> do
-                            debug "async kill wakeup"
-                            evUnloop lp 2
-                            return ()
-
-    evAsyncInit asyncObj asyncCB
-    evAsyncStart lp asyncObj
-    evAsyncInit killObj killCB
-    evAsyncStart lp killObj
-
-    -- setup the accept callback; this watches for read readiness on the listen
-    -- port
-    accCB <- mkIoCallback $ acceptCallback sockFd connq
-    accIO <- mkEvIo
-    evIoInit accIO accCB sockFd ev_read
-    evIoStart lp accIO
-
-    -- an MVar for the loop thread, and one to keep track of the set of active
-    -- threads
-    threadMVar <- newEmptyMVar
-    threadSetMVar <- newMVar Set.empty
-
-    let b = Backend sock
-                    sockFd
-                    connq
-                    lp
-                    accCB
-                    accIO
-                    threadMVar
-                    (mc1,mc2)
-                    looplock
-                    asyncCB
-                    asyncObj
-                    killCB
-                    killObj
-                    threadSetMVar
-                    cpu
-
-    tid <- forkOnIO cpu $ loopThread b
-    putMVar threadMVar tid
-
-    debug $ "Backend.new: loop spawned"
-    return b
-
-
--- | Run evLoop in a thread
-loopThread :: Backend -> IO ()
-loopThread backend = do
-    debug $ "starting loop"
-    (ignoreException go) `finally` cleanup
-    debug $ "loop finished"
-  where
-    cleanup = do
-        debug $ "loopThread: cleaning up"
-        ignoreException $ freeBackend backend
-    lock    = _loopLock backend
-    loop    = _evLoop backend
-    go      = takeMVar lock >> block (evLoop loop 0)
-
-
-acceptCallback :: CInt -> Chan CInt -> IoCallback
-acceptCallback accFd chan _loopPtr _ioPtr _ = do
-    r <- c_accept accFd
-
-    case r of
-      -- this (EWOULDBLOCK) shouldn't happen (we just got told it was ready!),
-      -- if it does (maybe the request got picked up by another thread) we'll
-      -- just bail out
-      -2 -> return ()
-      -1 -> debugErrno "Backend.acceptCallback:c_accept()"
-      fd -> writeChan chan fd
-
-
-ioCallback :: MVar () -> MVar () -> IoCallback
-ioCallback ra wa _loopPtr _ioPtr event = do
-    -- send notifications to the worker thread
-    when isRead  $ tryPutMVar ra () >> return ()
-    when isWrite $ tryPutMVar wa () >> return ()
-
-  where
-    isRead  = (event .&. ev_read) /= 0
-    isWrite = (event .&. ev_write) /= 0
-
-
-seconds :: Int -> Int
-seconds n = n * ((10::Int)^(6::Int))
-
-
-stop :: Backend -> IO ()
-stop b = ignoreException $ do
-    debug $ "Backend.stop"
-
-    -- FIXME: what are we gonna do here?
-    --
-    -- 1. take the loop lock
-    -- 2. shut down the accept() callback
-    -- 3. stuff a poison pill (a bunch of -1 values should do) down the
-    --    connection queue so that withConnection knows to throw an exception
-    --    back up to its caller
-    -- 4. release the loop lock
-    -- 5. wait until all of the threads have finished, or until 10 seconds have
-    --    elapsed, whichever comes first
-    -- 6. take the loop lock
-    -- 7. call evUnloop and wake up the loop using evAsyncSend
-    -- 8. release the loop lock, the main loop thread should then free/clean
-    --    everything up (threads, connections, io objects, callbacks, etc)
-
-    withMVar lock $ \_ -> do
-        evIoStop loop acceptObj
-        replicateM_ 10 $ writeChan connQ (-1)
-
-    debug $ "Backend.stop: waiting at most 10 seconds for connection threads to die"
-    waitForThreads b $ seconds 10
-    debug $ "Backend.stop: all threads dead, unlooping"
-
-    withMVar lock $ \_ -> do
-        -- FIXME: hlibev should export EVUNLOOP_ALL
-        evUnloop loop 2
-        evAsyncSend loop killObj
-
-    debug $ "unloop sent"
-
-
-  where
-    loop           = _evLoop b
-    acceptObj      = _acceptIOObj b
-    killObj        = _killObj b
-    lock           = _loopLock b
-    connQ          = _connectionQueue b
-
-
-
-waitForThreads :: Backend -> Int -> IO ()
-waitForThreads backend t = timeout t wait >> return ()
-  where
-    threadSet = _connectionThreads backend
-    wait = do
-        threads <- readMVar threadSet
-        if (Set.null threads)
-          then return ()
-          else threadDelay (seconds 1) >> wait
-
-
-
-getAddr :: SockAddr -> IO (ByteString, Int)
-getAddr addr =
-    case addr of
-      SockAddrInet p ha -> do
-          s <- liftM (B.pack . map c2w) (inet_ntoa ha)
-          return (s, fromIntegral p)
-
-      a -> throwIO $ AddressNotSupportedException (show a)
-
-
--- | throw a timeout exception to the handling thread -- it'll clean up
--- everything
-timerCallback :: MVar ThreadId -> TimerCallback
-timerCallback tmv _ _ _ = do
-    tid <- readMVar tmv
-    throwTo tid TimeoutException
-
-
-freeConnection :: Connection -> IO ()
-freeConnection conn = ignoreException $ do
-    withMVar loopLock $ \_ -> block $ do
-        -- close socket (twice to get proper linger behaviour)
-        c_close fd
-        c_close fd
-
-        -- stop and free timer object
-        evTimerStop loop timerObj
-        freeEvTimer timerObj
-        freeTimerCallback timerCb
-
-        -- stop and free i/o object
-        evIoStop loop ioObj
-        freeEvIo ioObj
-        freeIoCallback ioCb
-
-        -- remove the thread id from the backend set
-        tid <- readMVar threadMVar
-        modifyMVar_ tsetMVar $ return . Set.delete tid
-
-        -- wake up the event loop so it can be apprised of the changes
-        evAsyncSend loop asyncObj
-
-  where
-    backend    = _backend conn
-    tsetMVar   = _connectionThreads backend
-    loop       = _evLoop backend
-    loopLock   = _loopLock backend
-    asyncObj   = _asyncObj backend
-
-    fd         = _socketFd conn
-    threadMVar = _connThread conn
-    ioObj      = _connIOObj conn
-    ioCb       = _connIOCallback conn
-    timerObj   = _timerObj conn
-    timerCb    = _timerCallback conn
-
-
-ignoreException :: IO () -> IO ()
-ignoreException = handle (\(_::SomeException) -> return ())
-
-
-freeBackend :: Backend -> IO ()
-freeBackend backend = ignoreException $ block $ do
-    -- note: we only get here after an unloop
-
-    withMVar tsetMVar $ \set -> do
-        mapM_ killThread $ Set.toList set
-
-    debug $ "Backend.freeBackend: wait at most 2 seconds for threads to die"
-    waitForThreads backend $ seconds 2
-
-    debug $ "Backend.freeBackend: all threads dead"
-
-    debug $ "Backend.freeBackend: destroying resources"
-    freeEvIo acceptObj
-    freeIoCallback acceptCb
-    c_close fd
-
-    evAsyncStop loop asyncObj
-    freeEvAsync asyncObj
-    freeAsyncCallback asyncCb
-
-    evAsyncStop loop killObj
-    freeEvAsync killObj
-    freeAsyncCallback killCb
-
-    freeMutexCallback mcb1
-    freeMutexCallback mcb2
-
-    evLoopDestroy loop
-    debug $ "Backend.freeBackend: resources destroyed"
-
-  where
-    fd          = _acceptFd backend
-    acceptObj   = _acceptIOObj backend
-    acceptCb    = _acceptIOCallback backend
-    tsetMVar    = _connectionThreads backend
-    asyncObj    = _asyncObj backend
-    asyncCb     = _asyncCb backend
-    killObj     = _killObj backend
-    killCb      = _killCb backend
-    (mcb1,mcb2) = _mutexCallbacks backend
-    loop        = _evLoop backend
-
-
--- | Note: proc gets run in the background
-withConnection :: Backend -> Int -> (Connection -> IO ()) -> IO ()
-withConnection backend cpu proc = go
-  where
-    threadProc conn = ignoreException (proc conn) `finally` freeConnection conn
-
-    go = do
-        fd   <- readChan $ _connectionQueue backend
-
-        -- if fd < 0 throw an exception here (because this only happens if stop
-        -- is called)
-        when (fd < 0) $ throwIO BackendTerminatedException
-
-        sock <- mkSocket fd AF_INET Stream 0 Connected
-        peerName <- getPeerName sock
-        sockName <- getSocketName sock
-
-        -- set_linger fd
-        c_setnonblocking fd
-
-        (remoteAddr, remotePort) <- getAddr peerName
-        (localAddr, localPort) <- getAddr sockName
-
-        let lp = _evLoop backend
-
-        now        <- evNow lp
-        lastActRef <- newIORef now
-
-        -- makes sense to assume the socket is read/write available when
-        -- opened; worst-case is we get EWOULDBLOCK
-        ra    <- newMVar ()
-        wa    <- newMVar ()
-
-        tmr   <- mkEvTimer
-        thrmv <- newEmptyMVar
-        tcb   <- mkTimerCallback $ timerCallback thrmv
-        evTimerInit tmr tcb 20 0
-
-        evio <- mkEvIo
-        iocb <- mkIoCallback $ ioCallback ra wa
-        evIoInit evio iocb fd (ev_read .|. ev_write)
-
-        -- take ev_loop lock, start timer and io watchers
-        withMVar (_loopLock backend) $ \_ -> do
-             evTimerStart lp tmr
-             evIoStart lp evio
-
-             -- wakeup the loop thread so that these new watchers get
-             -- registered next time through the loop
-             evAsyncSend lp $ _asyncObj backend
-
-        let conn = Connection backend
-                              sock
-                              fd
-                              remoteAddr
-                              remotePort
-                              localAddr
-                              localPort
-                              ra
-                              wa
-                              tmr
-                              tcb
-                              now
-                              lastActRef
-                              evio
-                              iocb
-                              thrmv
-
-
-        tid <- forkOnIO cpu $ threadProc conn
-
-        modifyMVar_ (_connectionThreads backend) $ ins tid
-        putMVar thrmv tid
-
-      where
-        ins !thr !s = let !r = Set.insert thr s in return (r `seq` r)
-
-
-data BackendTerminatedException = BackendTerminatedException
-   deriving (Typeable)
-
-instance Show BackendTerminatedException where
-    show BackendTerminatedException = "Backend terminated"
-
-instance Exception BackendTerminatedException
-
-
-
-data AddressNotSupportedException = AddressNotSupportedException String
-   deriving (Typeable)
-
-instance Show AddressNotSupportedException where
-    show (AddressNotSupportedException x) = "Address not supported: " ++ x
-
-instance Exception AddressNotSupportedException
-
-
-getRemoteAddr :: Connection -> ByteString
-getRemoteAddr = _remoteAddr
-
-getRemotePort :: Connection -> Int
-getRemotePort = _remotePort
-
-getLocalAddr :: Connection -> ByteString
-getLocalAddr = _localAddr
-
-getLocalPort :: Connection -> Int
-getLocalPort = _localPort
-
-------------------------------------------------------------------------------
-
--- fixme: new function name
-getHostAddr :: Int
-            -> ByteString
-            -> IO SockAddr
-getHostAddr p s = do
-    h <- if s == "*"
-          then return iNADDR_ANY
-          else inet_addr (map w2c . B.unpack $ s)
-
-    return $ SockAddrInet (fromIntegral p) h
-
-
-
-bLOCKSIZE :: Int
-bLOCKSIZE = 8192
-
-
-data TimeoutException = TimeoutException
-   deriving (Typeable)
-
-instance Show TimeoutException where
-    show _ = "timeout"
-
-instance Exception TimeoutException
-
-
-recvData :: Connection -> Int -> IO ByteString
-recvData conn n = do
-    dbg "entered"
-    allocaBytes n $ \cstr -> do
-    sz <- throwErrnoIfMinus1RetryMayBlock
-              "recvData"
-              (c_read fd cstr (toEnum n))
-              waitForLock
-
-    dbg $ "sz returned " ++ show sz
-
-    if sz == 0
-      then return ""
-      else B.packCStringLen ((castPtr cstr),(fromEnum sz))
-
-  where
-    dbg s = debug $ "Backend.recvData(" ++ show (_socketFd conn) ++ "): " ++ s
-
-    fd          = _socketFd conn
-    lock        = _readAvailable conn
-    waitForLock = do
-        dbg "waitForLock"
-        takeMVar lock
-
-
-sendData :: Connection -> ByteString -> IO ()
-sendData conn bs = do
-    let len = B.length bs
-    dbg $ "entered w/ " ++ show len ++ " bytes"
-    written <- B.unsafeUseAsCString bs $ \cstr ->
-        throwErrnoIfMinus1RetryMayBlock
-                   "sendData"
-                   (c_write fd cstr (toEnum len))
-                   waitForLock
-
-    dbg $ "wrote " ++ show written ++ " bytes"
-
-    let n = fromEnum written
-    if n < len
-       then sendData conn $ B.drop n bs
-       else return ()
-
-  where
-    dbg s = debug $ "Backend.sendData(" ++ show (_socketFd conn) ++ "): " ++ s
-    fd          = _socketFd conn
-    lock        = _writeAvailable conn
-    waitForLock = takeMVar lock
-
-
-getReadEnd :: Connection -> Enumerator IO a
-getReadEnd = enumerate
-
-
-getWriteEnd :: Connection -> Iteratee IO ()
-getWriteEnd = writeOut
-
-
-enumerate :: (MonadIO m) => Connection -> Enumerator m a
-enumerate = loop
-  where
-    loop conn f = do
-        s <- liftIO $ recvData conn bLOCKSIZE
-        sendOne conn f s
-
-    sendOne conn f s = do
-        v <- runIter f (if B.null s
-                         then EOF Nothing
-                         else Chunk $ WrapBS s)
-        case v of
-          r@(Done _ _)      -> return $ liftI r
-          (Cont k Nothing)  -> loop conn k
-          (Cont _ (Just e)) -> return $ throwErr e
-
-
-writeOut :: (MonadIO m) => Connection -> Iteratee m ()
-writeOut conn = IterateeG out
-  where
-    out c@(EOF _)   = return $ Done () c
-
-    out (Chunk s) = do
-        let x = unWrap s
-
-        ee <- liftIO $ ((try $ sendData conn x)
-                            :: IO (Either SomeException ()))
-
-        case ee of
-          (Left e)  -> return $ Done () (EOF $ Just $ Err $ show e)
-          (Right _) -> return $ Cont (writeOut conn) Nothing
-
-
- diff --git a/static/docs/0.1.1/snap-server/src/Snap-Internal-Http-Server.html b/static/docs/0.1.1/snap-server/src/Snap-Internal-Http-Server.html deleted file mode 100644 index e51b977..0000000 --- a/static/docs/0.1.1/snap-server/src/Snap-Internal-Http-Server.html +++ /dev/null @@ -1,633 +0,0 @@ - - - - -src/Snap/Internal/Http/Server.hs - - - -
{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE CPP #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module Snap.Internal.Http.Server where
-
-------------------------------------------------------------------------------
-import           Control.Arrow (first, second)
-import           Control.Monad.State.Strict
-import           Control.Concurrent.MVar
-import           Control.Exception
-import           Data.Char
-import           Data.CIByteString
-import           Data.ByteString (ByteString)
-import qualified Data.ByteString as S
-import qualified Data.ByteString.Lazy as L
-import           Data.ByteString.Internal (c2w, w2c)
-import qualified Data.ByteString.Nums.Careless.Int as Cvt
-import           Data.IORef
-import           Data.List (foldl')
-import qualified Data.Map as Map
-import           Data.Maybe (fromJust, catMaybes, fromMaybe)
-import           Data.Monoid
-import           GHC.Conc
-import           Prelude hiding (catch, show, Show)
-import qualified Prelude
-import           System.Posix.Files hiding (setFileSize)
-import           Text.Show.ByteString hiding (runPut)
-------------------------------------------------------------------------------
-import           System.FastLogger
-import           Snap.Internal.Http.Types hiding (Enumerator)
-import           Snap.Internal.Http.Parser
-import           Snap.Iteratee hiding (foldl', head, take)
-import qualified Snap.Iteratee as I
-
-#ifdef LIBEV
-import qualified Snap.Internal.Http.Server.LibevBackend as Backend
-import           Snap.Internal.Http.Server.LibevBackend (debug)
-#else
-import qualified Snap.Internal.Http.Server.SimpleBackend as Backend
-import           Snap.Internal.Http.Server.SimpleBackend (debug)
-#endif
-
-import           Snap.Internal.Http.Server.Date
-
-------------------------------------------------------------------------------
--- | The handler has to return the request object because we have to clear the
--- HTTP request body before we send the response. If the handler consumes the
--- request body, it is responsible for setting @rqBody=return@ in the returned
--- request (otherwise we will mess up reading the input stream).
---
--- Note that we won't be bothering end users with this -- the details will be
--- hidden inside the Snap monad
-type ServerHandler = Request -> Iteratee IO (Request,Response)
-
-type ServerMonad = StateT ServerState (Iteratee IO)
-
-data ServerState = ServerState
-    { _forceConnectionClose  :: Bool
-    , _localHostname         :: ByteString
-    , _localAddress          :: ByteString
-    , _localPort             :: Int
-    , _remoteAddr            :: ByteString
-    , _remotePort            :: Int
-    , _logAccess             :: Request -> Response -> IO ()
-    , _logError              :: ByteString -> IO ()
-    }
-
-
-------------------------------------------------------------------------------
-runServerMonad :: ByteString                     -- ^ local host name
-               -> ByteString                     -- ^ local ip address
-               -> Int                            -- ^ local port
-               -> ByteString                     -- ^ remote ip address
-               -> Int                            -- ^ remote port
-               -> (Request -> Response -> IO ()) -- ^ access log function
-               -> (ByteString -> IO ())          -- ^ error log function
-               -> ServerMonad a                  -- ^ monadic action to run
-               -> Iteratee IO a
-runServerMonad lh lip lp rip rp la le m = evalStateT m st
-  where
-    st = ServerState False lh lip lp rip rp la le
-
-
-
-------------------------------------------------------------------------------
--- input/output
-
-
-------------------------------------------------------------------------------
-httpServe :: ByteString         -- ^ bind address, or \"*\" for all
-          -> Int                -- ^ port to bind to
-          -> ByteString         -- ^ local hostname (server name)
-          -> Maybe FilePath     -- ^ path to the access log
-          -> Maybe FilePath     -- ^ path to the error log
-          -> ServerHandler      -- ^ handler procedure
-          -> IO ()
-httpServe bindAddress bindPort localHostname alogPath elogPath handler =
-    withLoggers alogPath elogPath
-                (\(alog, elog) -> spawnAll alog elog)
-
-  where
-    spawnAll alog elog = do
-        let n = numCapabilities
-        bracket (spawn n)
-                (\xs -> do
-                     logE elog "Server.httpServe: SHUTDOWN"
-                     mapM_ (Backend.stop . fst) xs
-                     logE elog "Server.httpServe: BACKEND STOPPED")
-                (runAll alog elog)
-
-
-    runAll alog elog xs = do
-        mapM_ f $ xs `zip` [0..]
-        mapM_ (takeMVar . snd) xs
-      where
-        f ((backend,mvar),cpu) =
-            forkOnIO cpu $ do
-                labelMe $ map w2c $ S.unpack $
-                          S.concat ["accThread ", l2s $ show cpu]
-                (try $ (goooo alog elog backend cpu)) :: IO (Either SomeException ())
-                putMVar mvar ()
-
-    goooo alog elog backend cpu =
-        let loop = go alog elog backend cpu >> loop
-        in loop
-
-    maybeSpawnLogger = maybe (return Nothing) $ (liftM Just) . newLogger
-
-    withLoggers afp efp =
-        bracket (do alog <- maybeSpawnLogger afp
-                    elog <- maybeSpawnLogger efp
-                    return (alog, elog))
-                (\(alog, elog) -> do
-                    threadDelay 1000000
-                    maybe (return ()) stopLogger alog
-                    maybe (return ()) stopLogger elog)
-
-    labelMe :: String -> IO ()
-    labelMe s = do
-        tid <- myThreadId
-        labelThread tid s
-
-    spawn n = do
-        sock <- Backend.bindIt bindAddress bindPort
-        backends <- mapM (Backend.new sock) $ [0..(n-1)]
-        mvars <- replicateM n newEmptyMVar
-
-        return (backends `zip` mvars)
-
-
-    runOne alog elog backend cpu = Backend.withConnection backend cpu $ \conn -> do
-        debug "Server.httpServe.runOne: entered"
-        let readEnd = Backend.getReadEnd conn
-        writeEnd <- I.bufferIteratee $ Backend.getWriteEnd conn
-
-        let raddr = Backend.getRemoteAddr conn
-        let rport = Backend.getRemotePort conn
-        let laddr = Backend.getLocalAddr conn
-        let lport = Backend.getLocalPort conn
-
-        runHTTP localHostname laddr lport raddr rport
-                alog elog readEnd writeEnd (Backend.sendFile conn)
-                handler
-
-        debug "Server.httpServe.runHTTP: finished"
-
-
-    go alog elog backend cpu = runOne alog elog backend cpu
-        `catches`
-        [ Handler $ \(_ :: Backend.TimeoutException) -> return ()
-
-        , Handler $ \(e :: AsyncException) -> do
-              logE elog $
-                   S.concat [ "Server.httpServe.go: got async exception, "
-                            , "terminating:\n", bshow e ]
-              throwIO e
-
-        , Handler $ \(e :: Backend.BackendTerminatedException) -> do
-              logE elog $ "Server.httpServe.go: got backend terminated, waiting for cleanup"
-              throwIO e
-
-        , Handler $ \(e :: IOException) -> do
-              logE elog $ S.concat [ "Server.httpServe.go: got io exception: "
-                                   , bshow e ]
-
-        , Handler $ \(e :: SomeException) -> do
-              logE elog $ S.concat [
-                        "Server.httpServe.go: got someexception: "
-                       , bshow e ]
-              return () ]
-
-------------------------------------------------------------------------------
-debugE :: (MonadIO m) => ByteString -> m ()
-debugE s = debug $ "Server: " ++ (map w2c $ S.unpack s)
-
-
-------------------------------------------------------------------------------
-logE :: Maybe Logger -> ByteString -> IO ()
-logE elog = maybe debugE (\l s -> debugE s >> logE' l s) elog
-
-logE' :: Logger -> ByteString -> IO ()
-logE' logger s = (timestampedLogEntry s) >>= logMsg logger
-
-
-bshow :: (Prelude.Show a) => a -> ByteString
-bshow = toBS . Prelude.show
-
-------------------------------------------------------------------------------
-logA ::Maybe Logger -> Request -> Response -> IO ()
-logA alog = maybe (\_ _ -> return ()) logA' alog
-
-logA' :: Logger -> Request -> Response -> IO ()
-logA' logger req rsp = do
-    let hdrs      = rqHeaders req
-    let host      = rqRemoteAddr req
-    let user      = Nothing -- TODO we don't do authentication yet
-    let (v, v')   = rqVersion req
-    let ver       = S.concat [ "HTTP/", bshow v, ".", bshow v' ]
-    let method    = toBS $ Prelude.show (rqMethod req)
-    let reql      = S.intercalate " " [ method, rqURI req, ver ]
-    let status    = rspStatus rsp
-    let cl        = rspContentLength rsp
-    let referer   = maybe Nothing (Just . head) $ Map.lookup "referer" hdrs
-    let userAgent = maybe "-" head $ Map.lookup "user-agent" hdrs
-
-    msg <- combinedLogEntry host user reql status cl referer userAgent
-    logMsg logger msg
-
-
-------------------------------------------------------------------------------
-runHTTP :: ByteString           -- ^ local host name
-        -> ByteString           -- ^ local ip address
-        -> Int                  -- ^ local port
-        -> ByteString           -- ^ remote ip address
-        -> Int                  -- ^ remote port
-        -> Maybe Logger         -- ^ access logger
-        -> Maybe Logger         -- ^ error logger
-        -> Enumerator IO ()     -- ^ read end of socket
-        -> Iteratee IO ()       -- ^ write end of socket
-        -> (FilePath -> IO ())  -- ^ sendfile end
-        -> ServerHandler        -- ^ handler procedure
-        -> IO ()
-runHTTP lh lip lp rip rp alog elog readEnd writeEnd onSendFile handler =
-    go `catches` [ Handler $ \(e :: AsyncException) -> do
-                       throwIO e
-
-                 , Handler $ \(_ :: Backend.TimeoutException) -> return ()
-
-                 , Handler $ \(e :: SomeException) ->
-                             logE elog $ toBS $ Prelude.show e ]
-
-  where
-    go = do
-        let iter = runServerMonad lh lip lp rip rp (logA alog) (logE elog) $
-                                  httpSession writeEnd onSendFile handler
-        readEnd iter >>= run
-
-
-------------------------------------------------------------------------------
-sERVER_HEADER :: [ByteString]
-sERVER_HEADER = ["Snap/0.pre-1"]
-
-
-------------------------------------------------------------------------------
-logAccess :: Request -> Response -> ServerMonad ()
-logAccess req rsp = gets _logAccess >>= (\l -> liftIO $ l req rsp)
-
-------------------------------------------------------------------------------
-logError :: ByteString -> ServerMonad ()
-logError s = gets _logError >>= (\l -> liftIO $ l s)
-
-------------------------------------------------------------------------------
--- | Runs an HTTP session.
-httpSession :: Iteratee IO ()       -- ^ write end of socket
-            -> (FilePath -> IO ())  -- ^ sendfile continuation
-            -> ServerHandler        -- ^ handler procedure
-            -> ServerMonad ()
-httpSession writeEnd onSendFile handler = do
-    liftIO $ debug "Server.httpSession: entered"
-    mreq       <- receiveRequest
-
-    case mreq of
-      (Just req) -> do
-          (req',rspOrig) <- lift $ handler req
-          let rspTmp = rspOrig { rspHttpVersion = rqVersion req }
-          checkConnectionClose (rspHttpVersion rspTmp) (rspHeaders rspTmp)
-
-          cc <- gets _forceConnectionClose
-          let rsp = if cc
-                      then (setHeader "Connection" "close" rspTmp)
-                      else rspTmp
-
-
-          liftIO $ debug "Server.httpSession: handled, skipping request body"
-          srqEnum <- liftIO $ readIORef $ rqBody req'
-          let (SomeEnumerator rqEnum) = srqEnum
-          lift $ joinIM $ rqEnum skipToEof
-          liftIO $ debug "Server.httpSession: request body skipped, sending response"
-
-          date <- liftIO getDateString
-          let ins = (Map.insert "Date" [date] . Map.insert "Server" sERVER_HEADER)
-          let rsp' = updateHeaders ins rsp
-          (bytesSent,_) <- sendResponse rsp' writeEnd onSendFile
-
-          maybe (logAccess req rsp')
-                (\_ -> logAccess req $ setContentLength bytesSent rsp')
-                (rspContentLength rsp')
-
-          if cc
-             then return ()
-             else httpSession writeEnd onSendFile handler
-
-      Nothing -> return ()
-
-------------------------------------------------------------------------------
-receiveRequest :: ServerMonad (Maybe Request)
-receiveRequest = do
-    mreq <- lift parseRequest
-
-    case mreq of
-      (Just ireq) -> do
-          req' <- toRequest ireq
-          setEnumerator req'
-          req  <- parseForm req'
-          checkConnectionClose (rqVersion req) (rqHeaders req)
-          return $ Just req
-
-      Nothing     -> return Nothing
-
-
-  where
-    -- check: did the client specify "transfer-encoding: chunked"? then we have
-    -- to honor that.
-    --
-    -- otherwise: check content-length header. if set: only take N bytes from
-    -- the read end of the socket
-    --
-    -- if no content-length and no chunked encoding, enumerate the entire
-    -- socket and close afterwards
-    setEnumerator :: Request -> ServerMonad ()
-    setEnumerator req =
-        if isChunked
-          then liftIO $ writeIORef (rqBody req)
-                                   (SomeEnumerator readChunkedTransferEncoding)
-          else maybe noContentLength hasContentLength mbCL
-
-      where
-        isChunked = maybe False
-                          ((== ["chunked"]) . map toCI)
-                          (Map.lookup "transfer-encoding" hdrs)
-
-        hasContentLength :: Int -> ServerMonad ()
-        hasContentLength l = do
-            liftIO $ writeIORef (rqBody req)
-                         (SomeEnumerator e)
-          where
-            e :: Enumerator IO a
-            e = return . joinI . I.take l
-
-        noContentLength :: ServerMonad ()
-        noContentLength =
-            liftIO $ writeIORef (rqBody req)
-                (SomeEnumerator $ return . joinI . I.take 0 )
-
-
-        hdrs = rqHeaders req
-        mbCL = Map.lookup "content-length" hdrs >>= return . Cvt.int . head
-
-
-    parseForm :: Request -> ServerMonad Request
-    parseForm req = if doIt then getIt else return req
-      where
-        doIt = mbCT == Just "application/x-www-form-urlencoded"
-        mbCT = liftM head $ Map.lookup "content-type" (rqHeaders req)
-
-        maximumPOSTBodySize :: Int
-        maximumPOSTBodySize = 10*1024*1024
-
-        getIt :: ServerMonad Request
-        getIt = do
-            senum <- liftIO $ readIORef $ rqBody req
-            let (SomeEnumerator enum) = senum
-            let i = joinI $ takeNoMoreThan maximumPOSTBodySize stream2stream
-            iter <- liftIO $ enum i
-            body <- lift iter
-            let newParams = parseUrlEncoded $ strictize $ fromWrap body
-            liftIO $ writeIORef (rqBody req)
-                         (SomeEnumerator $ return . I.joinI . I.take 0)
-            return $ req { rqParams = rqParams req `mappend` newParams }
-
-
-    toRequest (IRequest method uri version kvps) = do
-        localAddr     <- gets _localAddress
-        localPort     <- gets _localPort
-        remoteAddr    <- gets _remoteAddr
-        remotePort    <- gets _remotePort
-        localHostname <- gets _localHostname
-
-        let (serverName, serverPort) = fromMaybe
-                                         (localHostname, localPort)
-                                         (liftM (parseHost . head)
-                                                (Map.lookup "host" hdrs))
-
-        -- will override in "setEnumerator"
-        enum <- liftIO $ newIORef $ SomeEnumerator return
-
-
-        return $ Request serverName
-                         serverPort
-                         remoteAddr
-                         remotePort
-                         localAddr
-                         localPort
-                         localHostname
-                         isSecure
-                         hdrs
-                         enum
-                         mbContentLength
-                         method
-                         version
-                         cookies
-                         snapletPath
-                         pathInfo
-                         contextPath
-                         uri
-                         queryString
-                         params
-
-      where
-        snapletPath = ""        -- TODO: snaplets in v0.2
-
-        dropLeadingSlash s = maybe s f mbS
-          where
-            f (a,s') = if a == c2w '/' then s' else s
-            mbS = S.uncons s
-
-        isSecure        = False
-
-        hdrs            = toHeaders kvps
-
-        mbContentLength = liftM (Cvt.int . head) $
-                          Map.lookup "content-length" hdrs
-
-        cookies         = maybe []
-                                (catMaybes . map parseCookie)
-                                (Map.lookup "set-cookie" hdrs)
-
-        contextPath     = "/"
-
-        parseHost h = (a, Cvt.int (S.drop 1 b))
-          where
-            (a,b) = S.break (== (c2w ':')) h
-
-        params          = parseUrlEncoded queryString
-
-        (pathInfo, queryString) = first dropLeadingSlash . second (S.drop 1) $
-                                  S.break (== (c2w '?')) uri
-
-
-------------------------------------------------------------------------------
--- Response must be well-formed here
-sendResponse :: Response
-             -> Iteratee IO a
-             -> (FilePath -> IO a)
-             -> ServerMonad (Int,a)
-sendResponse rsp' writeEnd onSendFile = do
-    rsp <- fixupResponse rsp'
-    let !headerString = mkHeaderString rsp
-
-    (!x,!bs) <- case (rspBody rsp) of
-                  (Enum e)     -> liftIO $ whenEnum headerString e
-                  (SendFile f) -> liftIO $ whenSendFile headerString rsp f
-
-    return $! (bs,x)
-
-  where
-    whenEnum hs e = do
-        let enum = enumBS hs >. e
-        let hl = S.length hs
-        (x,bs) <- liftIO $ enum (countBytes writeEnd) >>= run
-
-        return (x, bs-hl)
-
-    whenSendFile hs r f = do
-        -- guaranteed to have a content length here.
-        enumBS hs writeEnd >>= run
-
-        let !cl = fromJust $ rspContentLength r
-        x <- onSendFile f
-        return (x, cl)
-
-    (major,minor) = rspHttpVersion rsp'
-
-
-    fmtHdrs hdrs =
-        {-# SCC "fmtHdrs" #-}
-        concat xs
-      where
-        xs = map f $ Map.toList hdrs
-
-        f (k, ys) = map (g k) ys
-
-        g k y = S.concat [ unCI k, ": ", y, "\r\n" ]
-
-
-    noCL :: Response -> ServerMonad Response
-    noCL r =
-        {-# SCC "noCL" #-}
-        do
-            -- are we in HTTP/1.1?
-            let sendChunked = (rspHttpVersion r) == (1,1)
-            if sendChunked
-              then do
-                  let r' = setHeader "Transfer-Encoding" "chunked" r
-                  let e  = writeChunkedTransferEncoding $ rspBodyToEnum $ rspBody r
-                  return $ r' { rspBody = Enum e }
-
-              else do
-                  -- HTTP/1.0 and no content-length? We'll have to close the
-                  -- socket.
-                  modify $! \s -> s { _forceConnectionClose = True }
-                  return $ setHeader "Connection" "close" r
-
-
-    hasCL :: Int -> Response -> ServerMonad Response
-    hasCL cl r =
-        {-# SCC "hasCL" #-}
-        do
-            -- set the content-length header
-            let r' = setHeader "Content-Length" (l2s $ show cl) r
-            let b = case (rspBody r') of
-                      (Enum e)     -> Enum (i e)
-                      (SendFile f) -> SendFile f
-
-            return $ r' { rspBody = b }
-
-      where
-        i :: Enumerator IO a -> Enumerator IO a
-        i enum iter = enum (joinI $ takeExactly cl iter)
-
-
-    setFileSize :: FilePath -> Response -> ServerMonad Response
-    setFileSize fp r =
-        {-# SCC "setFileSize" #-}
-        do
-            fs <- liftM fromEnum $ liftIO $ getFileSize fp
-            return $ r { rspContentLength = Just fs }
-
-
-    fixupResponse :: Response -> ServerMonad Response
-    fixupResponse r =
-        {-# SCC "fixupResponse" #-}
-        do
-            let r' = updateHeaders (Map.delete "Content-Length") r
-            r'' <- case (rspBody r') of
-                     (Enum _)     -> return r'
-                     (SendFile f) -> setFileSize f r'
-            case (rspContentLength r'') of
-              Nothing   -> noCL r''
-              (Just sz) -> hasCL sz r''
-
-
-    bsshow = l2s . show
-
-
-    mkHeaderString :: Response -> ByteString
-    mkHeaderString r =
-        {-# SCC "mkHeaderString" #-}
-        S.concat $ concat [hl, hdr, eol]
-      where
-        hl = [ "HTTP/"
-             , bsshow major
-             , "."
-             , bsshow minor
-             , " "
-             , bsshow $ rspStatus r
-             , " "
-             , rspStatusReason r
-             , "\r\n" ]
-
-        hdr = fmtHdrs $ headers r
-
-        eol = ["\r\n"]
-
-
-------------------------------------------------------------------------------
-checkConnectionClose :: (Int, Int) -> Headers -> ServerMonad ()
-checkConnectionClose ver hdrs =
-    -- For HTTP/1.1:
-    --   if there is an explicit Connection: close, close the socket.
-    -- For HTTP/1.0:
-    --   if there is no explicit Connection: Keep-Alive, close the socket.
-    if (ver == (1,1) && l == Just ["close"]) ||
-       (ver == (1,0) && l /= Just ["Keep-Alive"])
-       then modify $ \s -> s { _forceConnectionClose = True }
-       else return ()
-  where
-    l  = liftM (map tl) $ Map.lookup "Connection" hdrs
-    tl = S.map (c2w . toLower . w2c)
-
-
-------------------------------------------------------------------------------
--- FIXME: whitespace-trim the values here.
-toHeaders :: [(ByteString,ByteString)] -> Headers
-toHeaders kvps = foldl' f Map.empty kvps'
-  where
-    kvps'     = map (first toCI . second (:[])) kvps
-    f m (k,v) = Map.insertWith' (flip (++)) k v m
-
-
-------------------------------------------------------------------------------
-getFileSize :: FilePath -> IO FileOffset
-getFileSize fp = liftM fileSize $ getFileStatus fp
-
-
-l2s :: L.ByteString -> S.ByteString
-l2s = S.concat . L.toChunks
-
-
-toBS :: String -> ByteString
-toBS = S.pack . map c2w
-
- diff --git a/static/docs/0.1.1/snap-server/src/System-FastLogger.html b/static/docs/0.1.1/snap-server/src/System-FastLogger.html deleted file mode 100644 index 0a9d919..0000000 --- a/static/docs/0.1.1/snap-server/src/System-FastLogger.html +++ /dev/null @@ -1,211 +0,0 @@ - - - - -src/System/FastLogger.hs - - - -
{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module System.FastLogger 
-( Logger
-, timestampedLogEntry
-, combinedLogEntry
-, newLogger
-, logMsg
-, stopLogger
-) where
-
-import           Control.Concurrent
-import           Control.Exception
-import           Control.Monad
-import           Data.ByteString.Char8 (ByteString)
-import qualified Data.ByteString.Char8 as S
-import qualified Data.ByteString.Lazy.Char8 as L
-import           Data.ByteString.Internal (c2w)
-import           Data.DList (DList)
-import qualified Data.DList as D
-import           Data.IORef
-import           Data.Maybe
-import           Data.Serialize.Put
-import           Data.Time.Clock
-import           Prelude hiding (catch, show)
-import qualified Prelude
-import           System.IO
-import           Text.Show.ByteString hiding (runPut)
-
-import           Snap.Internal.Http.Server.Date
-
-
--- | Holds the state for a logger.
-data Logger = Logger
-    { _queuedMessages :: !(IORef (DList ByteString))
-    , _dataWaiting    :: !(MVar ())
-    , _loggerPath     :: !(FilePath)
-    , _loggingThread  :: !(MVar ThreadId) }
-
-
--- | Creates a new logger, logging to the given file. If the file argument is
--- \"-\", then log to stdout; if it's \"stderr\" then we log to stderr,
--- otherwise we log to a regular file in append mode. The file is closed and
--- re-opened every 15 minutes to facilitate external log rotation.
-newLogger :: FilePath -> IO Logger
-newLogger fp = do
-    q  <- newIORef D.empty
-    dw <- newEmptyMVar
-    th <- newEmptyMVar
-
-    let lg = Logger q dw fp th
-
-    tid <- forkIO $ loggingThread lg
-    putMVar th tid
-
-    return lg
-
--- | Prepares a log message with the time prepended.
-timestampedLogEntry :: ByteString -> IO ByteString
-timestampedLogEntry msg = do
-    timeStr <- getLogDateString
-
-    return $ runPut $ do
-        putWord8 $ c2w '['
-        putByteString timeStr
-        putByteString "] "
-        putByteString msg
-
-
--- | Prepares a log message in \"combined\" format.
-combinedLogEntry :: ByteString        -- ^ remote host
-                 -> Maybe ByteString  -- ^ remote user
-                 -> ByteString        -- ^ request line (up to you to ensure
-                                      --   there are no quotes in here)
-                 -> Int               -- ^ status code
-                 -> Maybe Int         -- ^ num bytes sent
-                 -> Maybe ByteString  -- ^ referer (up to you to ensure
-                                      --   there are no quotes in here)
-                 -> ByteString        -- ^ user agent (up to you to ensure
-                                      --   there are no quotes in here)
-                 -> IO ByteString
-combinedLogEntry host mbUser req status mbNumBytes mbReferer userAgent = do
-    let user = fromMaybe "-" mbUser
-    let numBytes = maybe "-" (\s -> strict $ show s) mbNumBytes
-    let referer = maybe "-" (\s -> S.concat ["\"", s, "\""]) mbReferer
-
-    timeStr <- getLogDateString
-
-    let p = [ host
-            , " - "
-            , user
-            , " ["
-            , timeStr
-            , "] \""
-            , req
-            , "\" "
-            , strict $ show status
-            , " "
-            , numBytes
-            , " "
-            , referer
-            , " \""
-            , userAgent
-            , "\"" ]
-
-    return $ S.concat p
-
-
-  where
-    strict = S.concat . L.toChunks
-
-
--- | Sends out a log message verbatim with a newline appended. Note:
--- if you want a fancy log message you'll have to format it yourself
--- (or use 'combinedLogEntry').
-logMsg :: Logger -> ByteString -> IO ()
-logMsg lg s = do
-    let s' = S.snoc s '\n'
-    atomicModifyIORef (_queuedMessages lg) $ \d -> (D.snoc d s',())
-    tryPutMVar (_dataWaiting lg) () >> return ()
-
-
-loggingThread :: Logger -> IO ()
-loggingThread (Logger queue notifier filePath _) = do
-    initialize >>= go
-
-  where
-    openIt = if filePath == "-"
-               then return stdout
-               else if filePath == "stderr"
-                      then return stderr
-                      else openFile filePath AppendMode
-
-    closeIt h = if filePath == "-" || filePath == "stderr"
-                  then return ()
-                  else hClose h
-
-    go (href, lastOpened) =
-        (loop (href, lastOpened))
-          `catches`
-          [ Handler $ \(_::AsyncException) -> killit (href, lastOpened)
-          , Handler $ \(e::SomeException)  -> do
-                hPutStrLn stderr $ "logger got exception: " ++ Prelude.show e
-                threadDelay 20000000
-                go (href, lastOpened) ]
-
-
-    initialize = do
-        lh   <- openIt
-        href <- newIORef lh
-        t    <- getCurrentTime
-        tref <- newIORef t
-        return (href, tref)
-
-
-    killit (href, lastOpened) = do
-        flushIt (href, lastOpened)
-        h <- readIORef href
-        closeIt h
-
-
-    flushIt (href, lastOpened) = do
-        dl <- atomicModifyIORef queue $ \x -> (D.empty,x)
-
-        let msgs = D.toList dl
-        let s = L.fromChunks msgs
-        h <- readIORef href
-        L.hPut h s
-        hFlush h
-
-        -- close the file every 15 minutes (for log rotation)
-        t <- getCurrentTime
-        old <- readIORef lastOpened
-
-        if diffUTCTime t old > 900
-          then do
-              closeIt h
-              openIt >>= writeIORef href
-              writeIORef lastOpened t
-          else return ()
-
-
-    loop (href, lastOpened) = do
-        -- wait on the notification mvar
-        _ <- takeMVar notifier
-
-        -- grab the queued messages and write them out
-        flushIt (href, lastOpened)
-
-        -- at least five seconds between log dumps
-        threadDelay 5000000
-
-        loop (href, lastOpened)
-
-
--- | Kills a logger thread, causing any unwritten contents to be
--- flushed out to disk
-stopLogger :: Logger -> IO ()
-stopLogger lg = withMVar (_loggingThread lg) killThread
-
- diff --git a/static/docs/0.1.1/snap-server/src/hscolour.css b/static/docs/0.1.1/snap-server/src/hscolour.css deleted file mode 100644 index 150e4d0..0000000 --- a/static/docs/0.1.1/snap-server/src/hscolour.css +++ /dev/null @@ -1,15 +0,0 @@ -body { font-size: 90%; } - -pre, code, body { - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; -} - -.hs-keyglyph, .hs-layout {color: #5200A3;} -.hs-keyword {color: #3465a4; font-weight: bold;} -.hs-comment, .hs-comment a {color: #579; } -.hs-str, .hs-chr {color: #141B24;} -.hs-keyword, .hs-conid, .hs-varid, .hs-conop, .hs-varop, .hs-num, .hs-cpp, .hs-sel, .hs-definition {} diff --git a/static/docs/0.1.2/heist/Text-Templating-Heist-Splices-Apply.html b/static/docs/0.1.2/heist/Text-Templating-Heist-Splices-Apply.html deleted file mode 100644 index f794d47..0000000 --- a/static/docs/0.1.2/heist/Text-Templating-Heist-Splices-Apply.html +++ /dev/null @@ -1,225 +0,0 @@ - - -Text.Templating.Heist.Splices.Apply
 heist-0.1.1: An xhtml templating systemSource codeContentsIndex
Text.Templating.Heist.Splices.Apply
Synopsis
applyTag :: ByteString
applyAttr :: ByteString
applyImpl :: Monad m => Splice m
Documentation
applyTag :: ByteStringSource
Default name for the apply splice. -
applyAttr :: ByteStringSource
Default attribute name for the apply tag. -
applyImpl :: Monad m => Splice mSource
Implementation of the apply splice. -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.2/heist/Text-Templating-Heist-Splices-Bind.html b/static/docs/0.1.2/heist/Text-Templating-Heist-Splices-Bind.html deleted file mode 100644 index 888055c..0000000 --- a/static/docs/0.1.2/heist/Text-Templating-Heist-Splices-Bind.html +++ /dev/null @@ -1,225 +0,0 @@ - - -Text.Templating.Heist.Splices.Bind
 heist-0.1.1: An xhtml templating systemSource codeContentsIndex
Text.Templating.Heist.Splices.Bind
Synopsis
bindTag :: ByteString
bindAttr :: ByteString
bindImpl :: Monad m => Splice m
Documentation
bindTag :: ByteStringSource
Default name for the bind splice. -
bindAttr :: ByteStringSource
Default attribute name for the bind tag. -
bindImpl :: Monad m => Splice mSource
Implementation of the bind splice. -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.2/heist/Text-Templating-Heist-Splices-Ignore.html b/static/docs/0.1.2/heist/Text-Templating-Heist-Splices-Ignore.html deleted file mode 100644 index 4adaff9..0000000 --- a/static/docs/0.1.2/heist/Text-Templating-Heist-Splices-Ignore.html +++ /dev/null @@ -1,183 +0,0 @@ - - -Text.Templating.Heist.Splices.Ignore
 heist-0.1.1: An xhtml templating systemSource codeContentsIndex
Text.Templating.Heist.Splices.Ignore
Synopsis
ignoreTag :: ByteString
ignoreImpl :: Monad m => Splice m
Documentation
ignoreTag :: ByteStringSource
Default name for the ignore splice. -
ignoreImpl :: Monad m => Splice mSource
The ignore tag and everything it surrounds disappears in the - rendered output. -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.2/heist/Text-Templating-Heist-Splices-Markdown.html b/static/docs/0.1.2/heist/Text-Templating-Heist-Splices-Markdown.html deleted file mode 100644 index e1b4826..0000000 --- a/static/docs/0.1.2/heist/Text-Templating-Heist-Splices-Markdown.html +++ /dev/null @@ -1,592 +0,0 @@ - - -Text.Templating.Heist.Splices.Markdown
 heist-0.1.1: An xhtml templating systemSource codeContentsIndex
Text.Templating.Heist.Splices.Markdown
Synopsis
data PandocMissingException = PandocMissingException
data MarkdownException = MarkdownException ByteString
markdownTag :: ByteString
markdownSplice :: MonadIO m => Splice m
pandoc :: FilePath -> FilePath -> IO ByteString
pandocBS :: FilePath -> ByteString -> IO ByteString
readProcessWithExitCode' :: FilePath -> [String] -> ByteString -> IO (ExitCode, ByteString, ByteString)
Documentation
data PandocMissingException Source
Constructors
PandocMissingException
show/hide Instances
data MarkdownException Source
Constructors
MarkdownException ByteString
show/hide Instances
markdownTag :: ByteStringSource
Default name for the markdown splice. -
markdownSplice :: MonadIO m => Splice mSource
Implementation of the markdown splice. -
pandoc :: FilePath -> FilePath -> IO ByteStringSource
pandocBS :: FilePath -> ByteString -> IO ByteStringSource
readProcessWithExitCode'Source
:: FilePathcommand to run -
-> [String]any arguments -
-> ByteStringstandard input -
-> IO (ExitCode, ByteString, ByteString)exitcode, stdout, stderr -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.2/heist/Text-Templating-Heist-Splices-Static.html b/static/docs/0.1.2/heist/Text-Templating-Heist-Splices-Static.html deleted file mode 100644 index d53c06a..0000000 --- a/static/docs/0.1.2/heist/Text-Templating-Heist-Splices-Static.html +++ /dev/null @@ -1,253 +0,0 @@ - - -Text.Templating.Heist.Splices.Static
 heist-0.1.1: An xhtml templating systemSource codeContentsIndex
Text.Templating.Heist.Splices.Static
Synopsis
data StaticTagState
bindStaticTag :: MonadIO m => TemplateState m -> IO (TemplateState m, StaticTagState)
clearStaticTagCache :: StaticTagState -> IO ()
Documentation
data StaticTagState Source
State for storing static tag information -
bindStaticTag :: MonadIO m => TemplateState m -> IO (TemplateState m, StaticTagState)Source
Modifies a TemplateState to include a static tag. -
clearStaticTagCache :: StaticTagState -> IO ()Source
Clears the static tag state. -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.2/heist/Text-Templating-Heist-Splices.html b/static/docs/0.1.2/heist/Text-Templating-Heist-Splices.html deleted file mode 100644 index 33180ea..0000000 --- a/static/docs/0.1.2/heist/Text-Templating-Heist-Splices.html +++ /dev/null @@ -1,132 +0,0 @@ - - -Text.Templating.Heist.Splices
 heist-0.1.1: An xhtml templating systemSource codeContentsIndex
Text.Templating.Heist.Splices
Documentation
module Text.Templating.Heist.Splices.Apply
module Text.Templating.Heist.Splices.Bind
module Text.Templating.Heist.Splices.Ignore
module Text.Templating.Heist.Splices.Markdown
module Text.Templating.Heist.Splices.Static
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.2/heist/Text-Templating-Heist.html b/static/docs/0.1.2/heist/Text-Templating-Heist.html deleted file mode 100644 index 90b1afc..0000000 --- a/static/docs/0.1.2/heist/Text-Templating-Heist.html +++ /dev/null @@ -1,2303 +0,0 @@ - - -Text.Templating.Heist
 heist-0.1.1: An xhtml templating systemSource codeContentsIndex
Text.Templating.Heist
Contents
Types -
Functions and declarations on TemplateState values -
Hook functions -
TemplateMonad functions -
Functions for running splices and templates -
Misc functions -
Description

This module contains the core definitions for the Heist template system. -

The Heist template system is based on XML/xhtml. It allows you to build - custom XML-based markup languages. With Heist you can define your own - domain-specific XML tags implemented with Haskell and use them in your - templates. -

The most important concept in Heist is the Splice. Splices can be thought - of as functions that transform a node into a list of nodes. Heist then - substitutes the resulting list of nodes into your template in place of the - input node. Splice is implemented as a type synonym type Splice m = - TemplateMonad m [Node], and TemplateMonad has a function getParamNode - that lets you get the input node. -

Suppose you have a place on your page where you want to display a link with - the text "Logout username" if the user is currently logged in or a link to - the login page if no user is logged in. Assume you have a function - getUser :: MyAppMonad (Maybe ByteString) that gets the current user. - You can implement this functionality with a Splice as follows: -

- import Text.XML.Expat.Tree
-
- link :: ByteString -> ByteString -> Node
- link target text = X.Element "a" [("href", target)] [X.Text text]
- 
- loginLink :: Node
- loginLink = link "/login" "Login"
- 
- logoutLink :: ByteString -> Node
- logoutLink user = link "/logout" (B.append "Logout " user)
- 
- loginLogoutSplice :: Splice MyAppMonad
- loginLogoutSplice = do
-     user <- lift getUser
-     return $ [maybe loginLink logoutLink user]
-
-

Next, you need to bind that splice to an XML tag. Heist stores information - about splices and templates in the TemplateState data structure. The - following code demonstrates how this splice would be used. -

 mySplices = [ ("loginLogout", loginLogoutSplice) ]
- 
- main = do
-     ets <- loadTemplates "templates" $
-            foldr (uncurry bindSplice) emptyTemplateState mySplices
-     let ts = either error id ets
-     t <- runMyAppMonad $ renderTemplate ts "index"
-     print $ maybe "Page not found" id t
-

Here we build up our TemplateState by starting with emptyTemplateState and - applying bindSplice for all the splices we want to add. Then we pass this - to loadTemplates our final TemplateState wrapped in an Either to handle - errors. Then we use this TemplateState to render our templates. -

Synopsis
type Node = Node ByteString ByteString
type Splice m = TemplateMonad m Template
type Template = [Node]
data TemplateMonad m a
data TemplateState m
addTemplate :: Monad m => ByteString -> Template -> TemplateState m -> TemplateState m
emptyTemplateState :: MonadIO m => TemplateState m
bindSplice :: Monad m => ByteString -> Splice m -> TemplateState m -> TemplateState m
lookupSplice :: Monad m => ByteString -> TemplateState m -> Maybe (Splice m)
setTemplates :: Monad m => TemplateMap -> TemplateState m -> TemplateState m
loadTemplates :: Monad m => FilePath -> TemplateState m -> IO (Either String (TemplateState m))
addOnLoadHook :: Monad m => (Template -> IO Template) -> TemplateState m -> TemplateState m
addPreRunHook :: Monad m => (Template -> m Template) -> TemplateState m -> TemplateState m
addPostRunHook :: Monad m => (Template -> m Template) -> TemplateState m -> TemplateState m
stopRecursion :: Monad m => TemplateMonad m ()
getParamNode :: Monad m => TemplateMonad m Node
runNodeList :: Monad m => [Node] -> Splice m
getContext :: Monad m => TemplateMonad m TPath
runTemplate :: Monad m => TemplateState m -> ByteString -> m (Maybe [Node])
evalTemplate :: Monad m => ByteString -> TemplateMonad m (Maybe [Node])
callTemplate :: Monad m => ByteString -> [(ByteString, ByteString)] -> TemplateMonad m (Maybe Template)
renderTemplate :: Monad m => TemplateState m -> ByteString -> m (Maybe ByteString)
bindStrings :: Monad m => [(ByteString, ByteString)] -> TemplateState m -> TemplateState m
runSplice :: Monad m => TemplateState m -> Node -> Splice m -> m [Node]
runRawTemplate :: Monad m => TemplateState m -> Template -> m [Node]
getDoc :: String -> IO (Either String Template)
bindStaticTag :: MonadIO m => TemplateState m -> IO (TemplateState m, StaticTagState)
heistExpatOptions :: ParserOptions ByteString ByteString
htmlEntityLookupTable :: Map ByteString ByteString
Types -
type Node = Node ByteString ByteStringSource
Heist templates are XML documents. The hexpat library is polymorphic over - the type of strings, so here we define a Node alias to fix the string - types of the tag names and tag bodies to ByteString. -
type Splice m = TemplateMonad m TemplateSource
A Splice is a TemplateMonad computation that returns [Node]. -
type Template = [Node]Source
A Template is a forest of XML nodes. -
data TemplateMonad m a Source
TemplateMonad is a monad transformer that gives you access to the Node - being processed (using the MonadReader instance) as well as holding the - TemplateState that contains splice and template mappings (accessible - using the MonadState instance. -
show/hide Instances
data TemplateState m Source

Holds all the state information needed for template processing: -

  • a collection of named templates. If you use the <apply - template="foo"> tag to include another template by name, "foo" - is looked up in here. -
  • the mapping from tag names to Splices. -
  • a flag to control whether we will recurse during splice processing. -

We'll illustrate the recursion flag with a small example template: -

 <foo>
-   <bar>
-     ...
-   </bar>
- </foo>
-

Assume that "foo" is bound to a splice procedure. Running the foo - splice will result in a list of nodes L; if the recursion flag is on we - will recursively scan L for splices, otherwise L will be included in the - output verbatim. -

show/hide Instances
Functions and declarations on TemplateState values -
addTemplate :: Monad m => ByteString -> Template -> TemplateState m -> TemplateState mSource
Adds a template to the template state. -
emptyTemplateState :: MonadIO m => TemplateState mSource
An empty template state, with Heist's default splices (<bind> and - <apply>) mapped. -
bindSpliceSource
:: Monad m
=> ByteStringtag name -
-> Splice msplice action -
-> TemplateState msource state -
-> TemplateState m
Bind a new splice declaration to a tag name within a TemplateState. -
lookupSplice :: Monad m => ByteString -> TemplateState m -> Maybe (Splice m)Source
Convenience function for looking up a splice. -
setTemplates :: Monad m => TemplateMap -> TemplateState m -> TemplateState mSource
Sets the templateMap in a TemplateState. -
loadTemplates :: Monad m => FilePath -> TemplateState m -> IO (Either String (TemplateState m))Source
Traverses the specified directory structure and builds a - TemplateState by loading all the files with a .tpl extension. -
Hook functions -

Heist hooks allow you to modify templates when they are loaded and before - and after they are run. Every time you call one of the addAbcHook - functions the hook is added to onto the processing pipeline. The hooks - processes the template in the order that they were added to the - TemplateState. -

The pre-run and post-run hooks are run before and after every template is - run/rendered. You should be careful what code you put in these hooks - because it can significantly affect the performance of your site. -

addOnLoadHook :: Monad m => (Template -> IO Template) -> TemplateState m -> TemplateState mSource
Adds an on-load hook to a TemplateState. -
addPreRunHook :: Monad m => (Template -> m Template) -> TemplateState m -> TemplateState mSource
Adds a pre-run hook to a TemplateState. -
addPostRunHook :: Monad m => (Template -> m Template) -> TemplateState m -> TemplateState mSource
Adds a post-run hook to a TemplateState. -
TemplateMonad functions -
stopRecursion :: Monad m => TemplateMonad m ()Source
Stops the recursive processing of splices. -
getParamNode :: Monad m => TemplateMonad m NodeSource
Gets the node currently being processed. -
runNodeList :: Monad m => [Node] -> Splice mSource
Performs splice processing on a list of nodes. -
getContext :: Monad m => TemplateMonad m TPathSource
Gets the current context -
Functions for running splices and templates -
runTemplate :: Monad m => TemplateState m -> ByteString -> m (Maybe [Node])Source
Looks up a template name in the supplied TemplateState and runs - it in the underlying monad. -
evalTemplate :: Monad m => ByteString -> TemplateMonad m (Maybe [Node])Source
Looks up a template name evaluates it. Same as runTemplate except it - runs in TemplateMonad instead of m. -
callTemplateSource
:: Monad m
=> ByteStringThe name of the template -
-> [(ByteString, ByteString)]Association list of - (name,value) parameter pairs -
-> TemplateMonad m (Maybe Template)
Renders a template with the specified parameters. This is the function - to use when you want to call a template and pass in parameters from code. -
renderTemplate :: Monad m => TemplateState m -> ByteString -> m (Maybe ByteString)Source
Renders a template from the specified TemplateState. -
bindStrings :: Monad m => [(ByteString, ByteString)] -> TemplateState m -> TemplateState mSource
Binds a list of constant string splices -
Misc functions -
runSpliceSource
:: Monad m
=> TemplateState mThe initial template state -
-> NodeThe splice's input node -
-> Splice mThe splice -
-> m [Node]
Runs a splice in the underlying monad. Splices require two - parameters, the template state, and an input node. -
runRawTemplate :: Monad m => TemplateState m -> Template -> m [Node]Source
Runs a template in the underlying monad. Similar to runSplice - except that templates don't require a Node as a parameter. -
getDoc :: String -> IO (Either String Template)Source
Reads an XML document from disk. -
bindStaticTag :: MonadIO m => TemplateState m -> IO (TemplateState m, StaticTagState)Source
Modifies a TemplateState to include a static tag. -
heistExpatOptions :: ParserOptions ByteString ByteStringSource
htmlEntityLookupTable :: Map ByteString ByteStringSource
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.2/heist/doc-index.html b/static/docs/0.1.2/heist/doc-index.html deleted file mode 100644 index 2253f89..0000000 --- a/static/docs/0.1.2/heist/doc-index.html +++ /dev/null @@ -1,438 +0,0 @@ - - -heist-0.1.1: An xhtml templating system (Index)
 heist-0.1.1: An xhtml templating systemContentsIndex
addOnLoadHook
addPostRunHook
addPreRunHook
addTemplate
applyAttr
applyImpl
applyTag
bindAttr
bindImpl
bindSplice
bindStaticTag
bindStrings
bindTag
callTemplate
clearStaticTagCache
emptyTemplateState
evalTemplate
getContext
getDoc
getParamNode
heistExpatOptions
htmlEntityLookupTable
ignoreImpl
ignoreTag
loadTemplates
lookupSplice
MarkdownException
1 (Type/Class)
2 (Data Constructor)
markdownSplice
markdownTag
Node
pandoc
pandocBS
PandocMissingException
1 (Type/Class)
2 (Data Constructor)
readProcessWithExitCode'
renderTemplate
runNodeList
runRawTemplate
runSplice
runTemplate
setTemplates
Splice
StaticTagState
stopRecursion
Template
TemplateMonad
TemplateState
diff --git a/static/docs/0.1.2/heist/fonts/DroidSerif-Bold.eot b/static/docs/0.1.2/heist/fonts/DroidSerif-Bold.eot deleted file mode 100644 index 01b9e1f..0000000 Binary files a/static/docs/0.1.2/heist/fonts/DroidSerif-Bold.eot and /dev/null differ diff --git a/static/docs/0.1.2/heist/fonts/DroidSerif-Bold.svg b/static/docs/0.1.2/heist/fonts/DroidSerif-Bold.svg deleted file mode 100644 index 1f7f2d2..0000000 --- a/static/docs/0.1.2/heist/fonts/DroidSerif-Bold.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.1.2/heist/fonts/DroidSerif-Bold.ttf b/static/docs/0.1.2/heist/fonts/DroidSerif-Bold.ttf deleted file mode 100644 index da0ea11..0000000 Binary files a/static/docs/0.1.2/heist/fonts/DroidSerif-Bold.ttf and /dev/null differ diff --git a/static/docs/0.1.2/heist/fonts/DroidSerif-Bold.woff b/static/docs/0.1.2/heist/fonts/DroidSerif-Bold.woff deleted file mode 100644 index 91549cd..0000000 Binary files a/static/docs/0.1.2/heist/fonts/DroidSerif-Bold.woff and /dev/null differ diff --git a/static/docs/0.1.2/heist/fonts/DroidSerif-BoldItalic.eot b/static/docs/0.1.2/heist/fonts/DroidSerif-BoldItalic.eot deleted file mode 100644 index 47dd0a0..0000000 Binary files a/static/docs/0.1.2/heist/fonts/DroidSerif-BoldItalic.eot and /dev/null differ diff --git a/static/docs/0.1.2/heist/fonts/DroidSerif-BoldItalic.svg b/static/docs/0.1.2/heist/fonts/DroidSerif-BoldItalic.svg deleted file mode 100644 index 1a57dbb..0000000 --- a/static/docs/0.1.2/heist/fonts/DroidSerif-BoldItalic.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.1.2/heist/fonts/DroidSerif-BoldItalic.ttf b/static/docs/0.1.2/heist/fonts/DroidSerif-BoldItalic.ttf deleted file mode 100644 index 8be3fb4..0000000 Binary files a/static/docs/0.1.2/heist/fonts/DroidSerif-BoldItalic.ttf and /dev/null differ diff --git a/static/docs/0.1.2/heist/fonts/DroidSerif-BoldItalic.woff b/static/docs/0.1.2/heist/fonts/DroidSerif-BoldItalic.woff deleted file mode 100644 index 6d5fa3d..0000000 Binary files a/static/docs/0.1.2/heist/fonts/DroidSerif-BoldItalic.woff and /dev/null differ diff --git a/static/docs/0.1.2/heist/fonts/DroidSerif-Italic.eot b/static/docs/0.1.2/heist/fonts/DroidSerif-Italic.eot deleted file mode 100644 index 2d4850c..0000000 Binary files a/static/docs/0.1.2/heist/fonts/DroidSerif-Italic.eot and /dev/null differ diff --git a/static/docs/0.1.2/heist/fonts/DroidSerif-Italic.svg b/static/docs/0.1.2/heist/fonts/DroidSerif-Italic.svg deleted file mode 100644 index 356c374..0000000 --- a/static/docs/0.1.2/heist/fonts/DroidSerif-Italic.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.1.2/heist/fonts/DroidSerif-Italic.ttf b/static/docs/0.1.2/heist/fonts/DroidSerif-Italic.ttf deleted file mode 100644 index 3719dc2..0000000 Binary files a/static/docs/0.1.2/heist/fonts/DroidSerif-Italic.ttf and /dev/null differ diff --git a/static/docs/0.1.2/heist/fonts/DroidSerif-Italic.woff b/static/docs/0.1.2/heist/fonts/DroidSerif-Italic.woff deleted file mode 100644 index b64436f..0000000 Binary files a/static/docs/0.1.2/heist/fonts/DroidSerif-Italic.woff and /dev/null differ diff --git a/static/docs/0.1.2/heist/fonts/DroidSerif-Regular.eot b/static/docs/0.1.2/heist/fonts/DroidSerif-Regular.eot deleted file mode 100644 index 0d17523..0000000 Binary files a/static/docs/0.1.2/heist/fonts/DroidSerif-Regular.eot and /dev/null differ diff --git a/static/docs/0.1.2/heist/fonts/DroidSerif-Regular.svg b/static/docs/0.1.2/heist/fonts/DroidSerif-Regular.svg deleted file mode 100644 index b9b65fb..0000000 --- a/static/docs/0.1.2/heist/fonts/DroidSerif-Regular.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.1.2/heist/fonts/DroidSerif-Regular.ttf b/static/docs/0.1.2/heist/fonts/DroidSerif-Regular.ttf deleted file mode 100644 index 066dcaa..0000000 Binary files a/static/docs/0.1.2/heist/fonts/DroidSerif-Regular.ttf and /dev/null differ diff --git a/static/docs/0.1.2/heist/fonts/DroidSerif-Regular.woff b/static/docs/0.1.2/heist/fonts/DroidSerif-Regular.woff deleted file mode 100644 index cfd3d67..0000000 Binary files a/static/docs/0.1.2/heist/fonts/DroidSerif-Regular.woff and /dev/null differ diff --git a/static/docs/0.1.2/heist/frames.html b/static/docs/0.1.2/heist/frames.html deleted file mode 100644 index 9e904fc..0000000 --- a/static/docs/0.1.2/heist/frames.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/static/docs/0.1.2/heist/haddock-util.js b/static/docs/0.1.2/heist/haddock-util.js deleted file mode 100644 index 364081f..0000000 --- a/static/docs/0.1.2/heist/haddock-util.js +++ /dev/null @@ -1,139 +0,0 @@ -// Haddock JavaScript utilities -function toggle(button,id) -{ - var n = document.getElementById(id).style; - if (n.display == "none") - { - button.src = "minus.gif"; - n.display = "block"; - } - else - { - button.src = "plus.gif"; - n.display = "none"; - } -} - - -var max_results = 75; // 50 is not enough to search for map in the base libraries -var shown_range = null; -var last_search = null; - -function quick_search() -{ - perform_search(false); -} - -function full_search() -{ - perform_search(true); -} - - -function perform_search(full) -{ - var text = document.getElementById("searchbox").value.toLowerCase(); - if (text == last_search && !full) return; - last_search = text; - - var table = document.getElementById("indexlist"); - var status = document.getElementById("searchmsg"); - var children = table.firstChild.childNodes; - - // first figure out the first node with the prefix - var first = bisect(-1); - var last = (first == -1 ? -1 : bisect(1)); - - if (first == -1) - { - table.className = ""; - status.innerHTML = "No results found, displaying all"; - } - else if (first == 0 && last == children.length - 1) - { - table.className = ""; - status.innerHTML = ""; - } - else if (last - first >= max_results && !full) - { - table.className = ""; - status.innerHTML = "More than " + max_results + ", press Search to display"; - } - else - { - // decide what you need to clear/show - if (shown_range) - setclass(shown_range[0], shown_range[1], "indexrow"); - setclass(first, last, "indexshow"); - shown_range = [first, last]; - table.className = "indexsearch"; - status.innerHTML = ""; - } - - - function setclass(first, last, status) - { - for (var i = first; i <= last; i++) - { - children[i].className = status; - } - } - - - // do a binary search, treating 0 as ... - // return either -1 (no 0's found) or location of most far match - function bisect(dir) - { - var first = 0, finish = children.length - 1; - var mid, success = false; - - while (finish - first > 3) - { - mid = Math.floor((finish + first) / 2); - - var i = checkitem(mid); - if (i == 0) i = dir; - if (i == -1) - finish = mid; - else - first = mid; - } - var a = (dir == 1 ? first : finish); - var b = (dir == 1 ? finish : first); - for (var i = b; i != a - dir; i -= dir) - { - if (checkitem(i) == 0) return i; - } - return -1; - } - - - // from an index, decide what the result is - // 0 = match, -1 is lower, 1 is higher - function checkitem(i) - { - var s = getitem(i).toLowerCase().substr(0, text.length); - if (s == text) return 0; - else return (s > text ? -1 : 1); - } - - - // from an index, get its string - // this abstracts over alternates - function getitem(i) - { - for ( ; i >= 0; i--) - { - var s = children[i].firstChild.firstChild.data; - if (s.indexOf(' ') == -1) - return s; - } - return ""; // should never be reached - } -} - -function setSynopsis(filename) { - if (parent.window.synopsis) { - parent.window.synopsis.location = filename; - } -} diff --git a/static/docs/0.1.2/heist/haddock.css b/static/docs/0.1.2/heist/haddock.css deleted file mode 100644 index fe050fe..0000000 --- a/static/docs/0.1.2/heist/haddock.css +++ /dev/null @@ -1,478 +0,0 @@ -/* -------- Global things --------- */ - -@font-face { - font-family: 'DroidSerif'; - src: url('fonts/DroidSerif-Regular.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Regular.woff') format('woff'), - url('fonts/DroidSerif-Regular.ttf') format('truetype'), - url('fonts/DroidSerif-Regular.svg#DroidSerif') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - font-style: italic; - src: url('fonts/DroidSerif-Italic.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Italic.woff') format('woff'), - url('fonts/DroidSerif-Italic.ttf') format('truetype'), - url('fonts/DroidSerif-Italic.svg#DroidSerif-Italic') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - font-weight: bold; - src: url('fonts/DroidSerif-Bold.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Bold.woff') format('woff'), - url('fonts/DroidSerif-Bold.ttf') format('truetype'), - url('fonts/DroidSerif-Bold.svg#DroidSerif-Bold') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - src: url('fonts/DroidSerif-BoldItalic.eot'); - font-weight: bold; - font-style: italic; - src: local('Droid Serif'), - url('fonts/DroidSerif-BoldItalic.woff') format('woff'), - url('fonts/DroidSerif-BoldItalic.ttf') format('truetype'), - url('fonts/DroidSerif-BoldItalic.svg#DroidSerif-BoldItalic') format('svg'); -} - - - -HTML { - background-color: #f0f3ff; - width: 100%; -} - -BODY { - -moz-border-radius:5px; - -webkit-border-radius:5px; - width: 50em; - margin: 2em auto; - padding: 0; - background-color: #ffffff; - color: #000000; - font-size: 110%; - font-family: DroidSerif, Georgia, serif; - } - -A:link { color: #5200A3; text-decoration: none } -A:visited { color: #5200A3; text-decoration: none } -A:hover { color: #5200A3; text-decoration: none; border-bottom:#5200A3 dashed 1px; } - -TABLE.vanilla { - width: 100%; - border-width: 0px; - /* I can't seem to specify cellspacing or cellpadding properly using CSS... */ -} - -DL { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - letter-spacing: -0.01em; - margin: 0; -} - -.vanilla .vanilla dl { font-size: 80%; } -.vanilla .vanilla dl dl { padding-left: 0; font-size: 95%; } - -TD.section1, TD.section2, TD.section3, TD.section4, TD.doc, DL { - padding: 0 30px 0 34px; -} - -TABLE.vanilla2 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - border-width: 0px; -} - -/* font is a little too small in MSIE */ -TT, PRE, CODE { - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - font-size: 90%; -} - -LI P { margin: 0pt } - -P { margin-top: 0; margin-bottom: 0.75em; } - -TD { - border-width: 0px; -} - -TABLE.narrow { - border-width: 0px; -} - -TD.s8 { height: 0; margin:0; padding: 0 } -TD.s15 { height: 20px; } - -SPAN.keyword { text-decoration: underline; } - -/* Resize the buttom image to match the text size */ -IMG.coll { width : 0.75em; height: 0.75em; margin-bottom: 0; margin-right: 0.5em } - -/* --------- Contents page ---------- */ - -DIV.node { - padding-left: 3em; -} - -DIV.cnode { - padding-left: 1.75em; -} - -SPAN.pkg { - position: absolute; - left: 50em; -} - -/* --------- Documentation elements ---------- */ - -TD FONT { font-weight: bold; letter-spacing: -0.02em; } - -TD.children { - padding-left: 25px; - } - -TD.synopsis { - padding: 2px; - background-color: #f0f0f0; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - } - -TD.decl { - padding: 4px 8px; - background-color: #FAFAFA; - border-bottom: #F2F2F2 solid 1px; - border-top: #FCFCFC solid 1px; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - vertical-align: top; - } - -TD.decl TD.decl { - font-size: 100%; - padding: 4px 0; - border: 0; -} - -TD.topdecl { - padding: 20px 30px 0.5ex 30px; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; -; - vertical-align: top; -} - -.vanilla .vanilla .vanilla .topdecl { - padding-left: 0; - padding-right: 0; -} - -.vanilla .vanilla .vanilla { - padding-left: 30px; -} - -.decl .vanilla { - padding-left: 0px !important; -} - -.body .vanilla .body { - padding-left: 0; - padding-right: 0; -} - -.body .vanilla .body .decl { - padding-left: 12px; -} - -.body .vanilla .body div .vanilla .decl { - padding-left: 12px; -} - -TABLE.declbar { - background-color: #f0f0f0; - border-spacing: 0px; - border-bottom:1px solid #d7d7df; - border-right:1px solid #d7d7df; - border-top:1px solid #f4f4f9; - border-left:1px solid #f4f4f9; - padding: 4px; - } - -TD.declname { - width: 100%; - padding-right: 4px; - } - -TD.declbut { - padding-left: 8px; - padding-right: 5px; - border-left-width: 1px; - border-left-color: #000099; - border-left-style: solid; - white-space: nowrap; - font-size: x-small; - } - -/* - arg is just like decl, except that wrapping is not allowed. It is - used for function and constructor arguments which have a text box - to the right, where if wrapping is allowed the text box squashes up - the declaration by wrapping it. -*/ -TD.arg { - padding: 2px 12px; - background-color: #f0f0f0; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - vertical-align: top; - white-space: nowrap; - } - -TD.recfield { padding-left: 20px } - -TD.doc { - padding-left: 38px; - font-size: 95%; - line-height: 1.66; - } - -TD.ndoc { - font-size: 95%; - line-height: 1.66; - padding: 2px 4px 2px 8px; - } - -TD.rdoc { - padding: 2px; - padding-left: 30px; - width: 100%; - font-size: 80%; - font-style: italic; - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - } - -TD.body { - padding: 0 30px; - } - -TD.pkg { - width: 100%; - padding-left: 30px -} - -TABLE.indexsearch TR.indexrow { - display: none; -} -TABLE.indexsearch TR.indexshow { - display: table-row; -} - -TD.indexentry { - vertical-align: top; - padding: 0 30px - } - -TD.indexannot { - vertical-align: top; - padding-left: 20px; - white-space: nowrap - } - -TD.indexlinks { - width: 100% - } - -/* ------- Section Headings ------- */ - -TD.section1, TD.section2, TD.section3, TD.section4, TD.section5 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; -} - -TD.section1 { - padding-top: 14px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 140% - } - -TD.section2 { - padding-top: 4px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 120% - } - -TD.section3 { - padding-top: 5px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 105% - } - -TD.section4 { - font-weight: bold; - padding-top: 12px; - padding-bottom: 4px; - letter-spacing: -0.02em; - font-size: 90% - } - -/* -------------- The title bar at the top of the page */ - -TD.infohead { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - font-weight: bold; - padding: 0 30px; - text-align: left; -} - -TD.infoval { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - padding: 0 30px; - text-align: left; -} - -TD.topbar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - background-color: #3465a4; - padding: 5px; - -moz-border-radius-topleft:5px; - -moz-border-radius-topright:5px; - -webkit-border-radius-topleft:5px; - -webkit-border-radius-topright:5px; -} - -TD.title { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - padding-left: 30px; - letter-spacing: -0.02em; - font-weight: bold; - width: 100% - } - -TD.topbut { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - padding-left: 5px; - padding-right: 5px; - border-left-width: 1px; - border-left-color: #ffffff; - border-left-style: solid; - letter-spacing: -0.02em; - font-weight: bold; - white-space: nowrap; - } - -TD.topbut A:link { - color: #ffffff - } - -TD.topbut A:visited { - color: #ffff00 - } - -TD.topbut A:hover { - background-color: #C9D3DE; - } - -TD.topbut:hover { - background-color: #C9D3DE; - } - -TD.modulebar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #141B24; - background-color: #C9D3DE; - padding: 5px; - border-top-width: 1px; - border-top-color: #ffffff; - border-top-style: solid; - -moz-border-radius-bottomleft:5px; - -moz-border-radius-bottomright:5px; - -webkit-border-radius-bottomleft:5px; - -webkit-border-radius-bottomright:5px; - - } - -/* --------- The page footer --------- */ - -TD.botbar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - -moz-border-radius:5px; - -webkit-border-radius:5px; - background-color: #3465a4; - color: #ffffff; - padding: 5px - } -TD.botbar A:link { - color: #ffffff; - text-decoration: underline - } -TD.botbar A:visited { - color: #ffff00 - } -TD.botbar A:hover { - background-color: #6060ff - } - -/* --------- Mini Synopsis for Frame View --------- */ - -.outer { - margin: 0 0; - padding: 0 0; -} - -.mini-synopsis { - padding: 0.25em 0.25em; -} - -.mini-synopsis H1 { font-size: 120%; } -.mini-synopsis H2 { font-size: 107%; } -.mini-synopsis H3 { font-size: 100%; } -.mini-synopsis H1, .mini-synopsis H2, .mini-synopsis H3 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - margin-top: 0.5em; - margin-bottom: 0.25em; - padding: 0 0; - font-weight: bold; letter-spacing: -0.02em; -} - -.mini-synopsis H1 { border-bottom: 1px solid #ccc; } - -.mini-topbar { - font-size: 120%; - background: #0077dd; - padding: 0.25em; -} - - diff --git a/static/docs/0.1.2/heist/haskell_icon.gif b/static/docs/0.1.2/heist/haskell_icon.gif deleted file mode 100644 index cb2a815..0000000 Binary files a/static/docs/0.1.2/heist/haskell_icon.gif and /dev/null differ diff --git a/static/docs/0.1.2/heist/heist.haddock b/static/docs/0.1.2/heist/heist.haddock deleted file mode 100644 index 30d6ef2..0000000 Binary files a/static/docs/0.1.2/heist/heist.haddock and /dev/null differ diff --git a/static/docs/0.1.2/heist/index-frames.html b/static/docs/0.1.2/heist/index-frames.html deleted file mode 100644 index a285836..0000000 --- a/static/docs/0.1.2/heist/index-frames.html +++ /dev/null @@ -1,40 +0,0 @@ - - -heist-0.1.1: An xhtml templating system

Text.Templating.Heist
Text.Templating.Heist.Splices
Text.Templating.Heist.Splices.Apply
Text.Templating.Heist.Splices.Bind
Text.Templating.Heist.Splices.Ignore
Text.Templating.Heist.Splices.Markdown
Text.Templating.Heist.Splices.Static

diff --git a/static/docs/0.1.2/heist/index.html b/static/docs/0.1.2/heist/index.html deleted file mode 100644 index f58c200..0000000 --- a/static/docs/0.1.2/heist/index.html +++ /dev/null @@ -1,181 +0,0 @@ - - -heist-0.1.1: An xhtml templating system
 heist-0.1.1: An xhtml templating systemContentsIndex
heist-0.1.1: An xhtml templating system
An xhtml templating system -
Modules
show/hideText
show/hideTemplating
show/hideText.Templating.Heist
show/hideText.Templating.Heist.Splices
Text.Templating.Heist.Splices.Apply
Text.Templating.Heist.Splices.Bind
Text.Templating.Heist.Splices.Ignore
Text.Templating.Heist.Splices.Markdown
Text.Templating.Heist.Splices.Static
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.2/heist/mini_Text-Templating-Heist-Splices-Apply.html b/static/docs/0.1.2/heist/mini_Text-Templating-Heist-Splices-Apply.html deleted file mode 100644 index b3a2987..0000000 --- a/static/docs/0.1.2/heist/mini_Text-Templating-Heist-Splices-Apply.html +++ /dev/null @@ -1,33 +0,0 @@ - - -Text.Templating.Heist.Splices.Apply
Text.Templating.Heist.Splices.Apply
diff --git a/static/docs/0.1.2/heist/mini_Text-Templating-Heist-Splices-Bind.html b/static/docs/0.1.2/heist/mini_Text-Templating-Heist-Splices-Bind.html deleted file mode 100644 index 347bf97..0000000 --- a/static/docs/0.1.2/heist/mini_Text-Templating-Heist-Splices-Bind.html +++ /dev/null @@ -1,33 +0,0 @@ - - -Text.Templating.Heist.Splices.Bind
Text.Templating.Heist.Splices.Bind
diff --git a/static/docs/0.1.2/heist/mini_Text-Templating-Heist-Splices-Ignore.html b/static/docs/0.1.2/heist/mini_Text-Templating-Heist-Splices-Ignore.html deleted file mode 100644 index cf11fd3..0000000 --- a/static/docs/0.1.2/heist/mini_Text-Templating-Heist-Splices-Ignore.html +++ /dev/null @@ -1,29 +0,0 @@ - - -Text.Templating.Heist.Splices.Ignore
Text.Templating.Heist.Splices.Ignore
diff --git a/static/docs/0.1.2/heist/mini_Text-Templating-Heist-Splices-Markdown.html b/static/docs/0.1.2/heist/mini_Text-Templating-Heist-Splices-Markdown.html deleted file mode 100644 index 70738c6..0000000 --- a/static/docs/0.1.2/heist/mini_Text-Templating-Heist-Splices-Markdown.html +++ /dev/null @@ -1,53 +0,0 @@ - - -Text.Templating.Heist.Splices.Markdown diff --git a/static/docs/0.1.2/heist/mini_Text-Templating-Heist-Splices-Static.html b/static/docs/0.1.2/heist/mini_Text-Templating-Heist-Splices-Static.html deleted file mode 100644 index 482ea55..0000000 --- a/static/docs/0.1.2/heist/mini_Text-Templating-Heist-Splices-Static.html +++ /dev/null @@ -1,35 +0,0 @@ - - -Text.Templating.Heist.Splices.Static
Text.Templating.Heist.Splices.Static
diff --git a/static/docs/0.1.2/heist/mini_Text-Templating-Heist-Splices.html b/static/docs/0.1.2/heist/mini_Text-Templating-Heist-Splices.html deleted file mode 100644 index f3e9a96..0000000 --- a/static/docs/0.1.2/heist/mini_Text-Templating-Heist-Splices.html +++ /dev/null @@ -1,21 +0,0 @@ - - -Text.Templating.Heist.Splices
Text.Templating.Heist.Splices
diff --git a/static/docs/0.1.2/heist/mini_Text-Templating-Heist.html b/static/docs/0.1.2/heist/mini_Text-Templating-Heist.html deleted file mode 100644 index d0342ea..0000000 --- a/static/docs/0.1.2/heist/mini_Text-Templating-Heist.html +++ /dev/null @@ -1,165 +0,0 @@ - - -Text.Templating.Heist
Text.Templating.Heist

Types -

type Node
type Splice m
type Template
data TemplateMonad m a

Functions and declarations on TemplateState values -

Hook functions -

TemplateMonad functions -

Functions for running splices and templates -

Misc functions -

diff --git a/static/docs/0.1.2/heist/minus.gif b/static/docs/0.1.2/heist/minus.gif deleted file mode 100644 index 1deac2f..0000000 Binary files a/static/docs/0.1.2/heist/minus.gif and /dev/null differ diff --git a/static/docs/0.1.2/heist/plus.gif b/static/docs/0.1.2/heist/plus.gif deleted file mode 100644 index 2d15c14..0000000 Binary files a/static/docs/0.1.2/heist/plus.gif and /dev/null differ diff --git a/static/docs/0.1.2/heist/src/Text-Templating-Heist-Constants.html b/static/docs/0.1.2/heist/src/Text-Templating-Heist-Constants.html deleted file mode 100644 index 1f8683a..0000000 --- a/static/docs/0.1.2/heist/src/Text-Templating-Heist-Constants.html +++ /dev/null @@ -1,265 +0,0 @@ - - - - -src/Text/Templating/Heist/Constants.hs - - - -
{-# LANGUAGE OverloadedStrings #-}
-module Text.Templating.Heist.Constants where
-
-import           Data.ByteString.Char8 (ByteString)
-import qualified Data.Map as Map
-import           Data.Map (Map)
-
-htmlEntityLookupTable :: Map ByteString ByteString
-htmlEntityLookupTable = Map.fromList [
-                         ("acute"      , "\xc2\xb4")
-                       , ("cedil"      , "\xc2\xb8")
-                       , ("circ"       , "\xcb\x86")
-                       , ("macr"       , "\xc2\xaf")
-                       , ("middot"     , "\xc2\xb7")
-                       , ("tilde"      , "\xcb\x9c")
-                       , ("uml"        , "\xc2\xa8")
-                       , ("Aacute"     , "\xc3\x81")
-                       , ("aacute"     , "\xc3\xa1")
-                       , ("Acirc"      , "\xc3\x82")
-                       , ("acirc"      , "\xc3\xa2")
-                       , ("AElig"      , "\xc3\x86")
-                       , ("aelig"      , "\xc3\xa6")
-                       , ("Agrave"     , "\xc3\x80")
-                       , ("agrave"     , "\xc3\xa0")
-                       , ("Aring"      , "\xc3\x85")
-                       , ("aring"      , "\xc3\xa5")
-                       , ("Atilde"     , "\xc3\x83")
-                       , ("atilde"     , "\xc3\xa3")
-                       , ("Auml"       , "\xc3\x84")
-                       , ("auml"       , "\xc3\xa4")
-                       , ("Ccedil"     , "\xc3\x87")
-                       , ("ccedil"     , "\xc3\xa7")
-                       , ("Eacute"     , "\xc3\x89")
-                       , ("eacute"     , "\xc3\xa9")
-                       , ("Ecirc"      , "\xc3\x8a")
-                       , ("ecirc"      , "\xc3\xaa")
-                       , ("Egrave"     , "\xc3\x88")
-                       , ("egrave"     , "\xc3\xa8")
-                       , ("ETH"        , "\xc3\x90")
-                       , ("eth"        , "\xc3\xb0")
-                       , ("Euml"       , "\xc3\x8b")
-                       , ("euml"       , "\xc3\xab")
-                       , ("Iacute"     , "\xc3\x8d")
-                       , ("iacute"     , "\xc3\xad")
-                       , ("Icirc"      , "\xc3\x8e")
-                       , ("icirc"      , "\xc3\xae")
-                       , ("Igrave"     , "\xc3\x8c")
-                       , ("igrave"     , "\xc3\xac")
-                       , ("Iuml"       , "\xc3\x8f")
-                       , ("iuml"       , "\xc3\xaf")
-                       , ("Ntilde"     , "\xc3\x91")
-                       , ("ntilde"     , "\xc3\xb1")
-                       , ("Oacute"     , "\xc3\x93")
-                       , ("oacute"     , "\xc3\xb3")
-                       , ("Ocirc"      , "\xc3\x94")
-                       , ("ocirc"      , "\xc3\xb4")
-                       , ("OElig"      , "\xc5\x92")
-                       , ("oelig"      , "\xc5\x93")
-                       , ("Ograve"     , "\xc3\x92")
-                       , ("ograve"     , "\xc3\xb2")
-                       , ("Oslash"     , "\xc3\x98")
-                       , ("oslash"     , "\xc3\xb8")
-                       , ("Otilde"     , "\xc3\x95")
-                       , ("otilde"     , "\xc3\xb5")
-                       , ("Ouml"       , "\xc3\x96")
-                       , ("ouml"       , "\xc3\xb6")
-                       , ("Scaron"     , "\xc5\xa0")
-                       , ("scaron"     , "\xc5\xa1")
-                       , ("szlig"      , "\xc3\x9f")
-                       , ("THORN"      , "\xc3\x9e")
-                       , ("thorn"      , "\xc3\xbe")
-                       , ("Uacute"     , "\xc3\x9a")
-                       , ("uacute"     , "\xc3\xba")
-                       , ("Ucirc"      , "\xc3\x9b")
-                       , ("ucirc"      , "\xc3\xbb")
-                       , ("Ugrave"     , "\xc3\x99")
-                       , ("ugrave"     , "\xc3\xb9")
-                       , ("Uuml"       , "\xc3\x9c")
-                       , ("uuml"       , "\xc3\xbc")
-                       , ("Yacute"     , "\xc3\x9d")
-                       , ("yacute"     , "\xc3\xbd")
-                       , ("yuml"       , "\xc3\xbf")
-                       , ("Yuml"       , "\xc5\xb8")
-                       , ("cent"       , "\xc2\xa2")
-                       , ("curren"     , "\xc2\xa4")
-                       , ("euro"       , "\xe2\x82\xac")
-                       , ("pound"      , "\xc2\xa3")
-                       , ("yen"        , "\xc2\xa5")
-                       , ("brvbar"     , "\xc2\xa6")
-                       , ("bull"       , "\xe2\x80\xa2")
-                       , ("copy"       , "\xc2\xa9")
-                       , ("dagger"     , "\xe2\x80\xa0")
-                       , ("Dagger"     , "\xe2\x80\xa1")
-                       , ("frasl"      , "\xe2\x81\x84")
-                       , ("hellip"     , "\xe2\x80\xa6")
-                       , ("iexcl"      , "\xc2\xa1")
-                       , ("image"      , "\xe2\x84\x91")
-                       , ("iquest"     , "\xc2\xbf")
-                       , ("mdash"      , "\xe2\x80\x94")
-                       , ("ndash"      , "\xe2\x80\x93")
-                       , ("not"        , "\xc2\xac")
-                       , ("oline"      , "\xe2\x80\xbe")
-                       , ("ordf"       , "\xc2\xaa")
-                       , ("ordm"       , "\xc2\xba")
-                       , ("para"       , "\xc2\xb6")
-                       , ("permil"     , "\xe2\x80\xb0")
-                       , ("prime"      , "\xe2\x80\xb2")
-                       , ("Prime"      , "\xe2\x80\xb3")
-                       , ("real"       , "\xe2\x84\x9c")
-                       , ("reg"        , "\xc2\xae")
-                       , ("sect"       , "\xc2\xa7")
-                       , ("shy"        , "\173")
-                       , ("sup1"       , "\xc2\xb9")
-                       , ("trade"      , "\xe2\x84\xa2")
-                       , ("weierp"     , "\xe2\x84\x98")
-                       , ("bdquo"      , "\xe2\x80\x9e")
-                       , ("laquo"      , "\xc2\xab")
-                       , ("ldquo"      , "\xe2\x80\x9c")
-                       , ("lsaquo"     , "\xe2\x80\xb9")
-                       , ("lsquo"      , "\xe2\x80\x98")
-                       , ("raquo"      , "\xc2\xbb")
-                       , ("rdquo"      , "\xe2\x80\x9d")
-                       , ("rsaquo"     , "\xe2\x80\xba")
-                       , ("rsquo"      , "\xe2\x80\x99")
-                       , ("sbquo"      , "\xe2\x80\x9a")
-                       , ("emsp"       , "\xe2\x80\x83")
-                       , ("ensp"       , "\xe2\x80\x82")
-                       , ("nbsp"       , "\x20")
-                       , ("thinsp"     , "\xe2\x80\x89")
-                       , ("zwj"        , "\xe2\x80\x8d")
-                       , ("zwnj"       , "\xe2\x80\x8c")
-                       , ("deg"        , "\xc2\xb0")
-                       , ("divide"     , "\xc3\xb7")
-                       , ("frac12"     , "\xc2\xbd")
-                       , ("frac14"     , "\xc2\xbc")
-                       , ("frac34"     , "\xc2\xbe")
-                       , ("ge"         , "\xe2\x89\xa5")
-                       , ("le"         , "\xe2\x89\xa4")
-                       , ("minus"      , "\xe2\x88\x92")
-                       , ("sup2"       , "\xc2\xb2")
-                       , ("sup3"       , "\xc2\xb3")
-                       , ("times"      , "\xc3\x97")
-                       , ("alefsym"    , "\xe2\x84\xb5")
-                       , ("and"        , "\xe2\x88\xa7")
-                       , ("ang"        , "\xe2\x88\xa0")
-                       , ("asymp"      , "\xe2\x89\x88")
-                       , ("cap"        , "\xe2\x88\xa9")
-                       , ("cong"       , "\xe2\x89\x85")
-                       , ("cup"        , "\xe2\x88\xaa")
-                       , ("empty"      , "\xe2\x88\x85")
-                       , ("equiv"      , "\xe2\x89\xa1")
-                       , ("exist"      , "\xe2\x88\x83")
-                       , ("fnof"       , "\xc6\x92")
-                       , ("forall"     , "\xe2\x88\x80")
-                       , ("infin"      , "\xe2\x88\x9e")
-                       , ("int"        , "\xe2\x88\xab")
-                       , ("isin"       , "\xe2\x88\x88")
-                       , ("lang"       , "\xe3\x80\x88")
-                       , ("lceil"      , "\xe2\x8c\x88")
-                       , ("lfloor"     , "\xe2\x8c\x8a")
-                       , ("lowast"     , "\xe2\x88\x97")
-                       , ("micro"      , "\xc2\xb5")
-                       , ("nabla"      , "\xe2\x88\x87")
-                       , ("ne"         , "\xe2\x89\xa0")
-                       , ("ni"         , "\xe2\x88\x8b")
-                       , ("notin"      , "\xe2\x88\x89")
-                       , ("nsub"       , "\xe2\x8a\x84")
-                       , ("oplus"      , "\xe2\x8a\x95")
-                       , ("or"         , "\xe2\x88\xa8")
-                       , ("otimes"     , "\xe2\x8a\x97")
-                       , ("part"       , "\xe2\x88\x82")
-                       , ("perp"       , "\xe2\x8a\xa5")
-                       , ("plusmn"     , "\xc2\xb1")
-                       , ("prod"       , "\xe2\x88\x8f")
-                       , ("prop"       , "\xe2\x88\x9d")
-                       , ("radic"      , "\xe2\x88\x9a")
-                       , ("rang"       , "\xe3\x80\x89")
-                       , ("rceil"      , "\xe2\x8c\x89")
-                       , ("rfloor"     , "\xe2\x8c\x8b")
-                       , ("sdot"       , "\xe2\x8b\x85")
-                       , ("sim"        , "\xe2\x88\xbc")
-                       , ("sub"        , "\xe2\x8a\x82")
-                       , ("sube"       , "\xe2\x8a\x86")
-                       , ("sum"        , "\xe2\x88\x91")
-                       , ("sup"        , "\xe2\x8a\x83")
-                       , ("supe"       , "\xe2\x8a\x87")
-                       , ("there4"     , "\xe2\x88\xb4")
-                       , ("Alpha"      , "\xce\x91")
-                       , ("alpha"      , "\xce\xb1")
-                       , ("Beta"       , "\xce\x92")
-                       , ("beta"       , "\xce\xb2")
-                       , ("Chi"        , "\xce\xa7")
-                       , ("chi"        , "\xcf\x87")
-                       , ("Delta"      , "\xce\x94")
-                       , ("delta"      , "\xce\xb4")
-                       , ("Epsilon"    , "\xce\x95")
-                       , ("epsilon"    , "\xce\xb5")
-                       , ("Eta"        , "\xce\x97")
-                       , ("eta"        , "\xce\xb7")
-                       , ("Gamma"      , "\xce\x93")
-                       , ("gamma"      , "\xce\xb3")
-                       , ("Iota"       , "\xce\x99")
-                       , ("iota"       , "\xce\xb9")
-                       , ("Kappa"      , "\xce\x9a")
-                       , ("kappa"      , "\xce\xba")
-                       , ("Lambda"     , "\xce\x9b")
-                       , ("lambda"     , "\xce\xbb")
-                       , ("Mu"         , "\xce\x9c")
-                       , ("mu"         , "\xce\xbc")
-                       , ("Nu"         , "\xce\x9d")
-                       , ("nu"         , "\xce\xbd")
-                       , ("Omega"      , "\xce\xa9")
-                       , ("omega"      , "\xcf\x89")
-                       , ("Omicron"    , "\xce\x9f")
-                       , ("omicron"    , "\xce\xbf")
-                       , ("Phi"        , "\xce\xa6")
-                       , ("phi"        , "\xcf\x86")
-                       , ("Pi"         , "\xce\xa0")
-                       , ("pi"         , "\xcf\x80")
-                       , ("piv"        , "\xcf\x96")
-                       , ("Psi"        , "\xce\xa8")
-                       , ("psi"        , "\xcf\x88")
-                       , ("Rho"        , "\xce\xa1")
-                       , ("rho"        , "\xcf\x81")
-                       , ("Sigma"      , "\xce\xa3")
-                       , ("sigma"      , "\xcf\x83")
-                       , ("sigmaf"     , "\xcf\x82")
-                       , ("Tau"        , "\xce\xa4")
-                       , ("tau"        , "\xcf\x84")
-                       , ("Theta"      , "\xce\x98")
-                       , ("theta"      , "\xce\xb8")
-                       , ("thetasym"   , "\xcf\x91")
-                       , ("upsih"      , "\xcf\x92")
-                       , ("Upsilon"    , "\xce\xa5")
-                       , ("upsilon"    , "\xcf\x85")
-                       , ("Xi"         , "\xce\x9e")
-                       , ("xi"         , "\xce\xbe")
-                       , ("Zeta"       , "\xce\x96")
-                       , ("zeta"       , "\xce\xb6")
-                       , ("crarr"      , "\xe2\x86\xb5")
-                       , ("darr"       , "\xe2\x86\x93")
-                       , ("dArr"       , "\xe2\x87\x93")
-                       , ("harr"       , "\xe2\x86\x94")
-                       , ("hArr"       , "\xe2\x87\x94")
-                       , ("larr"       , "\xe2\x86\x90")
-                       , ("lArr"       , "\xe2\x87\x90")
-                       , ("rarr"       , "\xe2\x86\x92")
-                       , ("rArr"       , "\xe2\x87\x92")
-                       , ("uarr"       , "\xe2\x86\x91")
-                       , ("uArr"       , "\xe2\x87\x91")
-                       , ("clubs"      , "\xe2\x99\xa3")
-                       , ("diams"      , "\xe2\x99\xa6")
-                       , ("hearts"     , "\xe2\x99\xa5")
-                       , ("spades"     , "\xe2\x99\xa0")
-                       , ("loz"        , "\xe2\x97\x8a") ]
-
- diff --git a/static/docs/0.1.2/heist/src/Text-Templating-Heist-Internal.html b/static/docs/0.1.2/heist/src/Text-Templating-Heist-Internal.html deleted file mode 100644 index fa22e13..0000000 --- a/static/docs/0.1.2/heist/src/Text-Templating-Heist-Internal.html +++ /dev/null @@ -1,503 +0,0 @@ - - - - -src/Text/Templating/Heist/Internal.hs - - - -
{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-
-module Text.Templating.Heist.Internal where
-
-------------------------------------------------------------------------------
-import           Control.Exception (SomeException)
-import           Control.Monad.CatchIO
-import           Control.Monad.RWS.Strict
-import           Data.ByteString.Char8 (ByteString)
-import qualified Data.ByteString.Char8 as B
-import qualified Data.ByteString.Lazy as L
-import           Data.Either
-import qualified Data.Foldable as F
-import           Data.List
-import qualified Data.Map as Map
-import           Data.Map (Map)
-import           Prelude hiding (catch)
-import           System.Directory.Tree hiding (name)
-import           Text.XML.Expat.Format
-import qualified Text.XML.Expat.Tree as X
-
-------------------------------------------------------------------------------
-import           Text.Templating.Heist.Constants
-
-------------------------------------------------------------------------------
--- Types
-------------------------------------------------------------------------------
-
--- | Heist templates are XML documents. The hexpat library is polymorphic over
--- the type of strings, so here we define a 'Node' alias to fix the string
--- types of the tag names and tag bodies to 'ByteString'.
-type Node = X.Node ByteString ByteString
-
-
-------------------------------------------------------------------------------
--- | A 'Template' is a forest of XML nodes.
-type Template = [Node]
-
-
-------------------------------------------------------------------------------
--- | Reversed list of directories
-type TPath = [ByteString]
-
-
-------------------------------------------------------------------------------
-type TemplateMap = Map TPath Template
-
-
-------------------------------------------------------------------------------
--- | Holds all the state information needed for template processing:
---
---     * a collection of named templates. If you use the @\<apply
---       template=\"foo\"\>@ tag to include another template by name, @\"foo\"@
---       is looked up in here.
---
---     * the mapping from tag names to 'Splice's.
---
---     * a flag to control whether we will recurse during splice processing.
---
--- We'll illustrate the recursion flag with a small example template:
---
---   > <foo>
---   >   <bar>
---   >     ...
---   >   </bar>
---   > </foo>
---
--- Assume that @\"foo\"@ is bound to a splice procedure. Running the @foo@
--- splice will result in a list of nodes @L@; if the recursion flag is on we
--- will recursively scan @L@ for splices, otherwise @L@ will be included in the
--- output verbatim.
-data TemplateState m = TemplateState {
-    -- | A mapping of splice names to splice actions
-      _spliceMap      :: SpliceMap m
-    -- | A mapping of template names to templates
-    , _templateMap    :: TemplateMap
-    -- | A flag to control splice recursion
-    , _recurse        :: Bool
-    , _curContext     :: TPath
-    , _recursionDepth :: Int
-    , _onLoadHook     :: Template -> IO Template
-    , _preRunHook     :: Template -> m Template
-    , _postRunHook    :: Template -> m Template
-}
-
-
-------------------------------------------------------------------------------
-instance Eq (TemplateState m) where
-    a == b = (_recurse a == _recurse b) &&
-             (_templateMap a == _templateMap b) &&
-             (_curContext a == _curContext b)
-
-
-------------------------------------------------------------------------------
--- | 'TemplateMonad' is a monad transformer that gives you access to the 'Node'
---   being processed (using the 'MonadReader' instance) as well as holding the
---   'TemplateState' that contains splice and template mappings (accessible
---   using the 'MonadState' instance.
-newtype TemplateMonad m a = TemplateMonad (RWST Node () (TemplateState m) m a)
-  deriving ( Monad
-           , MonadIO
-           , MonadCatchIO
-           , MonadReader Node
-           , MonadState (TemplateState m) )
-
-
-------------------------------------------------------------------------------
-instance (Monad m) => Monoid (TemplateState m) where
-    mempty = TemplateState Map.empty Map.empty True [] 0
-                           return return return
-
-    (TemplateState s1 t1 r1 _ d1 o1 b1 a1) `mappend`
-        (TemplateState s2 t2 r2 c2 d2 o2 b2 a2) =
-        TemplateState s t r c2 d (o1 >=> o2) (b1 >=> b2) (a1 >=> a2)
-      where
-        s = s1 `mappend` s2
-        t = t1 `mappend` t2
-        r = r1 && r2
-        d = max d1 d2
-
-
-------------------------------------------------------------------------------
-instance MonadTrans TemplateMonad where
-  lift = TemplateMonad . lift
-
-------------------------------------------------------------------------------
--- | A Splice is a TemplateMonad computation that returns [Node].
-type Splice m = TemplateMonad m Template
-
-
-------------------------------------------------------------------------------
--- | SpliceMap associates a name and a Splice.
-type SpliceMap m = Map ByteString (Splice m)
-
-
-------------------------------------------------------------------------------
--- TemplateState functions
-------------------------------------------------------------------------------
-
-
-------------------------------------------------------------------------------
--- | Adds an on-load hook to a `TemplateState`.
-addOnLoadHook :: (Monad m) =>
-                 (Template -> IO Template)
-              -> TemplateState m
-              -> TemplateState m
-addOnLoadHook hook ts = ts { _onLoadHook = _onLoadHook ts >=> hook }
-
-
-------------------------------------------------------------------------------
--- | Adds a pre-run hook to a `TemplateState`.
-addPreRunHook :: (Monad m) =>
-                 (Template -> m Template)
-              -> TemplateState m
-              -> TemplateState m
-addPreRunHook hook ts = ts { _preRunHook = _preRunHook ts >=> hook }
-
-
-------------------------------------------------------------------------------
--- | Adds a post-run hook to a `TemplateState`.
-addPostRunHook :: (Monad m) =>
-                  (Template -> m Template)
-               -> TemplateState m
-               -> TemplateState m
-addPostRunHook hook ts = ts { _postRunHook = _postRunHook ts >=> hook }
-
-
-------------------------------------------------------------------------------
--- | Bind a new splice declaration to a tag name within a 'TemplateState'.
-bindSplice :: Monad m =>
-              ByteString        -- ^ tag name
-           -> Splice m          -- ^ splice action
-           -> TemplateState m   -- ^ source state
-           -> TemplateState m
-bindSplice n v ts = ts {_spliceMap = Map.insert n v (_spliceMap ts)}
-
-
-------------------------------------------------------------------------------
--- | Convenience function for looking up a splice.
-lookupSplice :: Monad m =>
-                ByteString
-             -> TemplateState m
-             -> Maybe (Splice m)
-lookupSplice nm ts = Map.lookup nm $ _spliceMap ts
-
-
-------------------------------------------------------------------------------
--- | Converts a path into an array of the elements in reverse order.
-splitPaths :: ByteString -> TPath
-splitPaths = reverse . B.split '/'
-
-
-------------------------------------------------------------------------------
--- | Does a single template lookup without cascading up.
-singleLookup :: TemplateMap
-             -> TPath
-             -> ByteString
-             -> Maybe (Template, TPath)
-singleLookup tm path name = fmap (\a -> (a,path)) $ Map.lookup (name:path) tm
-
-
-------------------------------------------------------------------------------
--- | Searches for a template by looking in the full path then backing up into each
--- of the parent directories until the template is found.
-traversePath :: TemplateMap
-             -> TPath
-             -> ByteString
-             -> Maybe (Template, TPath)
-traversePath tm [] name = fmap (\a -> (a,[])) (Map.lookup [name] tm)
-traversePath tm path name =
-    singleLookup tm path name `mplus`
-    traversePath tm (tail path) name
-
-
-------------------------------------------------------------------------------
--- | Convenience function for looking up a template.
-lookupTemplate :: Monad m =>
-                  ByteString
-               -> TemplateState m
-               -> Maybe (Template, TPath)
-lookupTemplate nameStr ts = 
-    f (_templateMap ts) path name
-  where (name:p) = case splitPaths nameStr of
-                       [] -> [""]
-                       ps -> ps
-        path = p ++ (_curContext ts)
-        f = if '/' `B.elem` nameStr
-                then singleLookup
-                else traversePath
-
-
-------------------------------------------------------------------------------
--- | Sets the templateMap in a TemplateState.
-setTemplates :: Monad m => TemplateMap -> TemplateState m -> TemplateState m
-setTemplates m ts = ts { _templateMap = m }
-
-
-------------------------------------------------------------------------------
--- | Adds a template to the template state.
-insertTemplate :: Monad m =>
-               TPath
-            -> Template
-            -> TemplateState m
-            -> TemplateState m
-insertTemplate p t st =
-    setTemplates (Map.insert p t (_templateMap st)) st
-
-
-------------------------------------------------------------------------------
--- | Adds a template to the template state.
-addTemplate :: Monad m =>
-               ByteString
-            -> Template
-            -> TemplateState m
-            -> TemplateState m
-addTemplate n t st = insertTemplate (splitPaths n) t st
-
-
-------------------------------------------------------------------------------
--- | Gets the node currently being processed.
-getParamNode :: Monad m => TemplateMonad m Node
-getParamNode = ask
-
-
-------------------------------------------------------------------------------
--- | Stops the recursive processing of splices.
-stopRecursion :: Monad m => TemplateMonad m ()
-stopRecursion = modify (\st -> st { _recurse = False })
-
-
-------------------------------------------------------------------------------
--- | Sets the current context
-setContext :: Monad m => TPath -> TemplateMonad m ()
-setContext c = modify (\st -> st { _curContext = c })
-
-
-------------------------------------------------------------------------------
--- | Gets the current context
-getContext :: Monad m => TemplateMonad m TPath
-getContext = gets _curContext
-  
-
-------------------------------------------------------------------------------
--- | Performs splice processing on a list of nodes.
-runNodeList :: Monad m => [Node] -> Splice m
-runNodeList nodes = liftM concat $ sequence (map runNode nodes)
-
-
-------------------------------------------------------------------------------
--- | Performs splice processing on a single node.
-runNode :: Monad m => Node -> Splice m
-runNode n@(X.Text _)          = return [n]
-runNode n@(X.Element nm _ ch) = do
-    s <- liftM (lookupSplice nm) get
-    maybe runChildren (recurseSplice n) s
-
-  where
-    runChildren = do
-        newKids <- runNodeList ch
-        return [X.modifyChildren (const newKids) n]
-
-
-------------------------------------------------------------------------------
--- | The maximum recursion depth.  (Used to prevent infinite loops.)
-mAX_RECURSION_DEPTH :: Int
-mAX_RECURSION_DEPTH = 20
-
-
-------------------------------------------------------------------------------
--- | Checks the recursion flag and recurses accordingly.  Does not recurse
--- deeper than mAX_RECURSION_DEPTH to avoid infinite loops.
-recurseSplice :: Monad m => Node -> Splice m -> Splice m
-recurseSplice node splice = do
-    result <- local (const node) splice
-    ts' <- get
-    if _recurse ts' && _recursionDepth ts' < mAX_RECURSION_DEPTH
-        then do modify (\st -> st { _recursionDepth = _recursionDepth st + 1 })
-                res <- runNodeList result
-                put ts'
-                return res
-        else return result
-
-
-------------------------------------------------------------------------------
--- | Runs a splice in the underlying monad.  Splices require two
--- parameters, the template state, and an input node.
-runSplice :: Monad m =>
-             TemplateState m -- ^ The initial template state
-          -> Node            -- ^ The splice's input node
-          -> Splice m        -- ^ The splice
-          -> m [Node]
-runSplice ts node (TemplateMonad splice) = do
-    (result,_,_) <- runRWST splice node ts
-    return result
-
-
-------------------------------------------------------------------------------
--- | Runs a template in the underlying monad.  Similar to runSplice
--- except that templates don't require a Node as a parameter.
-runRawTemplate :: Monad m => TemplateState m -> Template -> m [Node]
-runRawTemplate ts template =
-    _preRunHook ts template >>=
-    runSplice ts (X.Text "") . runNodeList >>=
-    _postRunHook ts
-
-
-------------------------------------------------------------------------------
--- | Looks up a template name in the supplied 'TemplateState' and runs
--- it in the underlying monad.
-runTemplate :: Monad m
-            => TemplateState m
-            -> ByteString
-            -> m (Maybe [Node])
-runTemplate ts name =
-    maybe (return Nothing)
-          (\(t,ctx) ->
-              return . Just =<<
-              runRawTemplate (ts {_curContext = ctx}) t)
-          (lookupTemplate name ts)
-
-
-------------------------------------------------------------------------------
--- | Looks up a template name evaluates it.  Same as runTemplate except it
--- runs in TemplateMonad instead of m.
-evalTemplate :: Monad m
-            => ByteString
-            -> TemplateMonad m (Maybe [Node])
-evalTemplate name = do
-    ts <- get
-    lift $ runTemplate ts name
-
-
-------------------------------------------------------------------------------
--- | Binds a list of constant string splices
-bindStrings :: Monad m
-            => [(ByteString, ByteString)]
-            -> TemplateState m
-            -> TemplateState m
-bindStrings pairs ts = foldr add ts pairs
-  where
-    add (n,v) = bindSplice n (return [X.Text v])
-
-
-------------------------------------------------------------------------------
--- | Renders a template with the specified parameters.  This is the function
--- to use when you want to "call" a template and pass in parameters from code.
-callTemplate :: Monad m
-             => ByteString                 -- ^ The name of the template
-             -> [(ByteString, ByteString)] -- ^ Association list of
-                                           -- (name,value) parameter pairs
-             -> TemplateMonad m (Maybe Template)
-callTemplate name params = do
-    modify $ bindStrings params
-    evalTemplate name
-
-
-------------------------------------------------------------------------------
--- | Renders a template from the specified TemplateState.
-renderTemplate :: Monad m
-               => TemplateState m
-               -> ByteString
-               -> m (Maybe ByteString)
-renderTemplate ts name = do
-    ns <- runTemplate ts name
-    return $ (Just . formatList') =<< ns
-
-
-------------------------------------------------------------------------------
-heistExpatOptions :: X.ParserOptions ByteString ByteString
-heistExpatOptions =
-    X.defaultParserOptions {
-           X.parserEncoding = Just X.UTF8
-         , X.entityDecoder  = Just (\k -> Map.lookup k htmlEntityLookupTable)
-         }
-
-------------------------------------------------------------------------------
--- Template loading
-------------------------------------------------------------------------------
-
--- | Reads an XML document from disk.
-getDoc :: String -> IO (Either String Template)
-getDoc f = do
-    bs <- catch (liftM Right $ B.readFile f)
-                (\(e::SomeException) -> return $ Left $ show e)
-    let wrap b = "<snap:root>\n" `B.append` b `B.append` "\n</snap:root>"
-    return $ (mapRight X.getChildren .
-              mapLeft genErrorMsg .
-              X.parse' heistExpatOptions . wrap) =<< bs
-  where
-    genErrorMsg (X.XMLParseError str loc) = f ++ " " ++ locMsg loc ++ ": " ++ translate str
-    locMsg (X.XMLParseLocation line col _ _) =
-        "(line " ++ show (line-1) ++ ", col " ++ show col ++ ")"
-    translate "junk after document element" = "document must have a single root element"
-    translate s = s
-
-------------------------------------------------------------------------------
-mapLeft :: (a -> b) -> Either a c -> Either b c
-mapLeft g = either (Left . g) Right
-mapRight :: (b -> c) -> Either a b -> Either a c
-mapRight g = either Left (Right . g)
-
-
-------------------------------------------------------------------------------
--- | Loads a template with the specified path and filename.  The
--- template is only loaded if it has a ".tpl" extension.
-loadTemplate :: String -> String -> IO [Either String (TPath, Template)] --TemplateMap
-loadTemplate path fname
-    | ".tpl" `isSuffixOf` fname = do
-        c <- getDoc fname
-        return [fmap (\t -> (splitPaths $ B.pack tName, t)) c]
-    | otherwise = return []
-  where tName = drop ((length path)+1) $
-                take ((length fname) - 4) fname
-
-
-------------------------------------------------------------------------------
--- | Traverses the specified directory structure and builds a
--- TemplateState by loading all the files with a ".tpl" extension.
-loadTemplates :: Monad m => FilePath -> TemplateState m -> IO (Either String (TemplateState m))
-loadTemplates dir ts = do
-    d <- readDirectoryWith (loadTemplate dir) dir
-    let tlist = F.fold (free d)
-        errs = lefts tlist
-    case errs of
-        [] -> liftM Right $ foldM loadHook ts $ rights tlist
-        _  -> return $ Left $ unlines errs
-
-
-------------------------------------------------------------------------------
--- | Runs the onLoad hook on the template and returns the `TemplateState`
--- with the result inserted.
-loadHook :: Monad m => TemplateState m -> (TPath, Template) -> IO (TemplateState m)
-loadHook ts (tp, t) = do
-    t' <- _onLoadHook ts t
-    return $ insertTemplate tp t' ts
-
-
-------------------------------------------------------------------------------
--- These are here until we can get them into hexpat.
-------------------------------------------------------------------------------
-
-formatList :: (X.GenericXMLString tag, X.GenericXMLString text) =>
-              [X.Node tag text]
-           -> L.ByteString
-formatList nodes = foldl L.append L.empty $ map formatNode nodes
-
-formatList' :: (X.GenericXMLString tag, X.GenericXMLString text) =>
-               [X.Node tag text]
-            -> B.ByteString
-formatList' = B.concat . L.toChunks . formatList
-
-
- diff --git a/static/docs/0.1.2/heist/src/Text-Templating-Heist-Splices-Apply.html b/static/docs/0.1.2/heist/src/Text-Templating-Heist-Splices-Apply.html deleted file mode 100644 index 83efe53..0000000 --- a/static/docs/0.1.2/heist/src/Text-Templating-Heist-Splices-Apply.html +++ /dev/null @@ -1,57 +0,0 @@ - - - - -src/Text/Templating/Heist/Splices/Apply.hs - - - -
{-# LANGUAGE OverloadedStrings #-}
-
-module Text.Templating.Heist.Splices.Apply where
-
-------------------------------------------------------------------------------
-import           Control.Monad.RWS.Strict
-import           Data.ByteString.Char8 (ByteString)
-import qualified Data.ByteString.Char8 as B
-import qualified Text.XML.Expat.Tree as X
-
-------------------------------------------------------------------------------
-import           Text.Templating.Heist.Internal
-
-------------------------------------------------------------------------------
--- | Default name for the apply splice.
-applyTag :: ByteString
-applyTag = "apply"
-
-
-------------------------------------------------------------------------------
--- | Default attribute name for the apply tag.
-applyAttr :: ByteString
-applyAttr = "template"
-
-
-------------------------------------------------------------------------------
--- | Implementation of the apply splice.
-applyImpl :: Monad m => Splice m
-applyImpl = do
-    node <- getParamNode
-    case X.getAttribute node applyAttr of
-        Nothing   -> return [] -- TODO: error handling
-        Just attr -> do 
-            st <- get
-            processedChildren <- runNodeList $ X.getChildren node
-            modify (bindSplice "content" $ return processedChildren)
-            maybe (return []) -- TODO: error handling
-                  (\(t,ctx) -> do setContext ctx
-                                  result <- runNodeList t
-                                  put st
-                                  return result)
-                  (lookupTemplate attr (st {_curContext = nextCtx attr st}))
-  where nextCtx name st
-            | B.isPrefixOf "/" name = []
-            | otherwise             = _curContext st
-
-
-
- diff --git a/static/docs/0.1.2/heist/src/Text-Templating-Heist-Splices-Bind.html b/static/docs/0.1.2/heist/src/Text-Templating-Heist-Splices-Bind.html deleted file mode 100644 index 27c602f..0000000 --- a/static/docs/0.1.2/heist/src/Text-Templating-Heist-Splices-Bind.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - -src/Text/Templating/Heist/Splices/Bind.hs - - - -
{-# LANGUAGE OverloadedStrings #-}
-
-module Text.Templating.Heist.Splices.Bind where
-
-------------------------------------------------------------------------------
-import           Control.Monad.RWS.Strict
-import           Data.ByteString.Char8 (ByteString)
-import qualified Text.XML.Expat.Tree as X
-
-------------------------------------------------------------------------------
-import           Text.Templating.Heist.Internal
-
--- | Default name for the bind splice.
-bindTag :: ByteString
-bindTag = "bind"
-
-
-------------------------------------------------------------------------------
--- | Default attribute name for the bind tag.
-bindAttr :: ByteString
-bindAttr = "tag"
-
-
-------------------------------------------------------------------------------
--- | Implementation of the bind splice.
-bindImpl :: Monad m => Splice m
-bindImpl = do
-    node <- getParamNode
-    maybe (return ())
-          (add node)
-          (X.getAttribute node bindAttr)
-    return []
-
-  where
-    add node nm = modify $ bindSplice nm (return $ X.getChildren node)
-
-
-
- diff --git a/static/docs/0.1.2/heist/src/Text-Templating-Heist-Splices-Ignore.html b/static/docs/0.1.2/heist/src/Text-Templating-Heist-Splices-Ignore.html deleted file mode 100644 index 94cfc79..0000000 --- a/static/docs/0.1.2/heist/src/Text-Templating-Heist-Splices-Ignore.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - -src/Text/Templating/Heist/Splices/Ignore.hs - - - -
{-# LANGUAGE OverloadedStrings #-}
-
-module Text.Templating.Heist.Splices.Ignore where
-
-------------------------------------------------------------------------------
-import           Data.ByteString.Char8 (ByteString)
-
-------------------------------------------------------------------------------
-import           Text.Templating.Heist.Internal
-
-
-------------------------------------------------------------------------------
--- | Default name for the ignore splice.
-ignoreTag :: ByteString
-ignoreTag = "ignore"
-
-
-------------------------------------------------------------------------------
--- | The ignore tag and everything it surrounds disappears in the
--- rendered output.
-ignoreImpl :: Monad m => Splice m
-ignoreImpl = return []
-
-
-
- diff --git a/static/docs/0.1.2/heist/src/Text-Templating-Heist-Splices-Markdown.html b/static/docs/0.1.2/heist/src/Text-Templating-Heist-Splices-Markdown.html deleted file mode 100644 index 56cc561..0000000 --- a/static/docs/0.1.2/heist/src/Text-Templating-Heist-Splices-Markdown.html +++ /dev/null @@ -1,160 +0,0 @@ - - - - -src/Text/Templating/Heist/Splices/Markdown.hs - - - -
{-# LANGUAGE OverloadedStrings, DeriveDataTypeable #-}
-
-module Text.Templating.Heist.Splices.Markdown where
-
-import           Data.ByteString (ByteString)
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Char8 as BC
-import           Data.Maybe
-import           Control.Concurrent
-import           Control.Exception (evaluate, throwIO)
-import           Control.Monad
-import           Control.Monad.CatchIO
-import           Control.Monad.Trans
-import           Data.Typeable
-import           Prelude hiding (catch)
-import           System.Directory
-import           System.Exit
-import           System.IO
-import           System.Process
-import           Text.Templating.Heist.Internal
-import           Text.XML.Expat.Tree hiding (Node)
-
-
-data PandocMissingException = PandocMissingException
-   deriving (Typeable)
-
-instance Show PandocMissingException where
-    show PandocMissingException =
-        "Cannot find the \"pandoc\" executable; is it on your $PATH?"
-
-instance Exception PandocMissingException
-
-
-data MarkdownException = MarkdownException ByteString
-   deriving (Typeable)
-
-instance Show MarkdownException where
-    show (MarkdownException e) =
-        "Markdown error: pandoc replied:\n\n" ++ BC.unpack e
-
-instance Exception MarkdownException
-
-
-------------------------------------------------------------------------------
--- | Default name for the markdown splice.
-markdownTag :: ByteString
-markdownTag = "markdown"
-
-------------------------------------------------------------------------------
--- | Implementation of the markdown splice.
-markdownSplice :: MonadIO m => Splice m
-markdownSplice = do
-    pdMD <- liftIO $ findExecutable "pandoc"
-
-    when (isNothing pdMD) $ liftIO $ throwIO PandocMissingException
-
-    tree <- getParamNode
-    markup <- liftIO $
-        case getAttribute tree "file" of
-            Just f  -> pandoc (fromJust pdMD) $ BC.unpack f
-            Nothing -> pandocBS (fromJust pdMD) $ textContent tree
-
-    let ee = parse' heistExpatOptions markup
-    case ee of
-      (Left e) -> throw $ MarkdownException
-                        $ BC.pack ("Error parsing markdown output: " ++ show e)
-      (Right n) -> return [n]
-
-
-pandoc :: FilePath -> FilePath -> IO ByteString
-pandoc pandocPath inputFile = do
-    (ex, sout, serr) <- readProcessWithExitCode' pandocPath args ""
-
-    when (isFail ex) $ throw $ MarkdownException serr
-    return $ BC.concat [ "<div class=\"markdown\">\n"
-                       , sout
-                       , "\n</div>" ]
-
-  where
-    isFail ExitSuccess = False
-    isFail _           = True
-
-    -- FIXME: hardcoded path
-    args = [ "-S", "--no-wrap", "templates/"++inputFile ]
-
-
-pandocBS :: FilePath -> ByteString -> IO ByteString
-pandocBS pandocPath s = do
-    -- using the crummy string functions for convenience here
-    (ex, sout, serr) <- readProcessWithExitCode' pandocPath args s
-
-    when (isFail ex) $ throw $ MarkdownException serr
-    return $ BC.concat [ "<div class=\"markdown\">\n"
-                       , sout
-                       , "\n</div>" ]
-
-  where
-    isFail ExitSuccess = False
-    isFail _           = True
-    args = [ "-S", "--no-wrap" ]
-
-
--- a version of readProcessWithExitCode that does I/O properly
-readProcessWithExitCode'
-    :: FilePath                 -- ^ command to run
-    -> [String]                 -- ^ any arguments
-    -> ByteString               -- ^ standard input
-    -> IO (ExitCode,ByteString,ByteString) -- ^ exitcode, stdout, stderr
-readProcessWithExitCode' cmd args input = do
-    (Just inh, Just outh, Just errh, pid) <-
-        createProcess (proc cmd args){ std_in  = CreatePipe,
-                                       std_out = CreatePipe,
-                                       std_err = CreatePipe }
-    outMVar <- newEmptyMVar
-
-    outM <- newEmptyMVar
-    errM <- newEmptyMVar
-
-    -- fork off a thread to start consuming stdout
-    forkIO $ do
-        out <- B.hGetContents outh
-        putMVar outM out
-        putMVar outMVar ()
-
-    -- fork off a thread to start consuming stderr
-    forkIO $ do
-        err  <- B.hGetContents errh
-        putMVar errM err
-        putMVar outMVar ()
-
-    -- now write and flush any input
-    when (not (B.null input)) $ do B.hPutStr inh input; hFlush inh
-    hClose inh -- done with stdin
-
-    -- wait on the output
-    takeMVar outMVar
-    takeMVar outMVar
-    hClose outh
-
-    -- wait on the process
-    ex <- waitForProcess pid
-
-    out <- readMVar outM
-    err <- readMVar errM
-
-    return (ex, out, err)
-
-
-
-
-
- diff --git a/static/docs/0.1.2/heist/src/Text-Templating-Heist-Splices-Static.html b/static/docs/0.1.2/heist/src/Text-Templating-Heist-Splices-Static.html deleted file mode 100644 index 734781d..0000000 --- a/static/docs/0.1.2/heist/src/Text-Templating-Heist-Splices-Static.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - -src/Text/Templating/Heist/Splices/Static.hs - - - -
{-# LANGUAGE OverloadedStrings #-}
-
-module Text.Templating.Heist.Splices.Static 
-  ( StaticTagState
-  , bindStaticTag
-  , clearStaticTagCache
-  ) where
-
-------------------------------------------------------------------------------
-import           Control.Concurrent
-import           Control.Monad
-import           Control.Monad.Trans
-import           Data.ByteString.Char8 (ByteString)
-import qualified Data.ByteString.Char8 as B
-import           Data.IORef
-import qualified Data.Map as Map
-import           Data.Map (Map)
-import           Data.Maybe
-import qualified Data.Set as Set
-import           System.Random
-import           Text.XML.Expat.Cursor
-import           Text.XML.Expat.Tree hiding (Node)
-
-
-------------------------------------------------------------------------------
-import           Text.Templating.Heist.Internal
-
-
-------------------------------------------------------------------------------
--- | State for storing static tag information
-newtype StaticTagState = STS (MVar (Map ByteString Template))
-
-
-------------------------------------------------------------------------------
--- | Clears the static tag state.
-clearStaticTagCache :: StaticTagState -> IO ()
-clearStaticTagCache (STS staticMVar) =
-    modifyMVar_ staticMVar (const $ return Map.empty)
-
-
-------------------------------------------------------------------------------
--- | The "static" splice ensures that its contents are evaluated once and then
--- cached.  The cached contents are returned every time the splice is
--- referenced.
-staticImpl :: (MonadIO m)
-           => StaticTagState
-           -> TemplateMonad m Template
-staticImpl (STS mv) = do
-    tree <- getParamNode
-    let i = fromJust $ getAttribute tree "id"
-
-    mp <- liftIO $ readMVar mv
-
-    (mp',ns) <- do
-                   let mbn = Map.lookup i mp
-                   case mbn of
-                       Nothing -> do
-                           nodes' <- runNodeList $ getChildren tree
-                           return $! (Map.insert i nodes' mp, nodes')
-                       (Just n) -> do
-                           stopRecursion
-                           return $! (mp,n)
-
-    liftIO $ modifyMVar_ mv (const $ return mp')
-
-    return ns
-
-
-------------------------------------------------------------------------------
--- | Modifies a TemplateState to include a "static" tag.
-bindStaticTag :: MonadIO m
-              => TemplateState m
-              -> IO (TemplateState m, StaticTagState)
-bindStaticTag ts = do
-    sr <- newIORef $ Set.empty
-    mv <- liftM STS $ newMVar Map.empty
-
-    return $ (addOnLoadHook (assignIds sr) $
-                bindSplice "static" (staticImpl mv) ts,
-              mv)
-
-  where
-    generateId :: IO Int
-    generateId = getStdRandom random
-
-    assignIds setref = mapM f
-        where
-          f node = g $ fromTree node
-
-          getId = do
-              i  <- liftM (B.pack . show) generateId
-              st <- readIORef setref
-              if Set.member i st
-                then getId
-                else do
-                    writeIORef setref $ Set.insert i st
-                    return i
-
-          g curs = do
-              let node = current curs
-              curs' <- if getName node == "static"
-                         then do
-                             i <- getId
-                             return $ modifyContent (setAttribute "id" i) curs
-                         else return curs
-              let mbc = nextDF curs'
-              maybe (return $ toTree curs') g mbc
-
-
-
-
-
- diff --git a/static/docs/0.1.2/heist/src/Text-Templating-Heist-Splices.html b/static/docs/0.1.2/heist/src/Text-Templating-Heist-Splices.html deleted file mode 100644 index 9919a2e..0000000 --- a/static/docs/0.1.2/heist/src/Text-Templating-Heist-Splices.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - -src/Text/Templating/Heist/Splices.hs - - - -
module Text.Templating.Heist.Splices
-  ( module Text.Templating.Heist.Splices.Apply
-  , module Text.Templating.Heist.Splices.Bind
-  , module Text.Templating.Heist.Splices.Ignore
-  , module Text.Templating.Heist.Splices.Markdown
-  , module Text.Templating.Heist.Splices.Static
-  ) where
-
-import Text.Templating.Heist.Splices.Apply
-import Text.Templating.Heist.Splices.Bind
-import Text.Templating.Heist.Splices.Ignore
-import Text.Templating.Heist.Splices.Markdown
-import Text.Templating.Heist.Splices.Static
-
-
- diff --git a/static/docs/0.1.2/heist/src/Text-Templating-Heist.html b/static/docs/0.1.2/heist/src/Text-Templating-Heist.html deleted file mode 100644 index e38d59b..0000000 --- a/static/docs/0.1.2/heist/src/Text-Templating-Heist.html +++ /dev/null @@ -1,166 +0,0 @@ - - - - -src/Text/Templating/Heist.hs - - - -
{-# LANGUAGE OverloadedStrings, GeneralizedNewtypeDeriving #-}
-
-{-|
-
-  This module contains the core definitions for the Heist template system.
-
-  The Heist template system is based on XML\/xhtml.  It allows you to build
-  custom XML-based markup languages.  With Heist you can define your own
-  domain-specific XML tags implemented with Haskell and use them in your
-  templates.  
-
-  The most important concept in Heist is the 'Splice'.  Splices can be thought
-  of as functions that transform a node into a list of nodes.  Heist then
-  substitutes the resulting list of nodes into your template in place of the
-  input node.  'Splice' is implemented as a type synonym @type Splice m =
-  TemplateMonad m [Node]@, and 'TemplateMonad' has a function 'getParamNode'
-  that lets you get the input node.
-
-  Suppose you have a place on your page where you want to display a link with
-  the text \"Logout username\" if the user is currently logged in or a link to
-  the login page if no user is logged in.  Assume you have a function
-  @getUser :: MyAppMonad (Maybe ByteString)@ that gets the current user.
-  You can implement this functionality with a 'Splice' as follows:
-
-  >
-  > import Text.XML.Expat.Tree
-  >
-  > link :: ByteString -> ByteString -> Node
-  > link target text = X.Element "a" [("href", target)] [X.Text text]
-  > 
-  > loginLink :: Node
-  > loginLink = link "/login" "Login"
-  > 
-  > logoutLink :: ByteString -> Node
-  > logoutLink user = link "/logout" (B.append "Logout " user)
-  > 
-  > loginLogoutSplice :: Splice MyAppMonad
-  > loginLogoutSplice = do
-  >     user <- lift getUser
-  >     return $ [maybe loginLink logoutLink user]
-  >
-
-  Next, you need to bind that splice to an XML tag.  Heist stores information
-  about splices and templates in the 'TemplateState' data structure.  The
-  following code demonstrates how this splice would be used.
-
-  > mySplices = [ ("loginLogout", loginLogoutSplice) ]
-  > 
-  > main = do
-  >     ets <- loadTemplates "templates" $
-  >            foldr (uncurry bindSplice) emptyTemplateState mySplices
-  >     let ts = either error id ets
-  >     t <- runMyAppMonad $ renderTemplate ts "index"
-  >     print $ maybe "Page not found" id t
-
-  Here we build up our 'TemplateState' by starting with emptyTemplateState and
-  applying bindSplice for all the splices we want to add.  Then we pass this
-  to loadTemplates our final 'TemplateState' wrapped in an Either to handle
-  errors.  Then we use this 'TemplateState' to render our templates.
-
--}
-
-module Text.Templating.Heist
-  (
-    -- * Types
-    Node
-  , Splice
-  , Template
-  , TemplateMonad
-  , TemplateState
-
-    -- * Functions and declarations on TemplateState values
-  , addTemplate
-  , emptyTemplateState
-  , bindSplice
-  , lookupSplice
-  , setTemplates
-  , loadTemplates
-
-    -- * Hook functions
-    -- $hookDoc
-  , addOnLoadHook
-  , addPreRunHook
-  , addPostRunHook
-
-    -- * TemplateMonad functions
-  , stopRecursion
-  , getParamNode
-  , runNodeList
-  , getContext
-
-    -- * Functions for running splices and templates
-  , runTemplate
-  , evalTemplate
-  , callTemplate
-  , renderTemplate
-  , bindStrings
-
-    -- * Misc functions
-  , runSplice
-  , runRawTemplate
-  , getDoc
-  , bindStaticTag
-
-  , heistExpatOptions
-  , module Text.Templating.Heist.Constants
-  ) where
-
-import           Control.Monad.Trans
-import qualified Data.Map as Map
-import           Text.Templating.Heist.Internal
-import           Text.Templating.Heist.Constants
-import           Text.Templating.Heist.Splices
-
-
-------------------------------------------------------------------------------
--- | The default set of built-in splices.
-defaultSpliceMap :: MonadIO m => SpliceMap m
-defaultSpliceMap = Map.fromList
-    [(applyTag, applyImpl)
-    ,(bindTag, bindImpl)
-    ,(ignoreTag, ignoreImpl)
-    ,(markdownTag, markdownSplice)
-    ]
-
-
-------------------------------------------------------------------------------
--- | An empty template state, with Heist's default splices (@\<bind\>@ and
--- @\<apply\>@) mapped.
-emptyTemplateState :: MonadIO m => TemplateState m
-emptyTemplateState = TemplateState defaultSpliceMap Map.empty True [] 0
-                                   return return return
-
-
-------------------------------------------------------------------------------
--- | Reloads the templates from disk and renders the specified
--- template.  (Old convenience code.)
---renderTemplate' :: FilePath -> ByteString -> IO (Maybe ByteString)
---renderTemplate' baseDir name = do
---    etm <- loadTemplates baseDir emptyTemplateState
---    let ts = either (const emptyTemplateState) id etm
---    ns <- runTemplate ts name
---    return $ (Just . formatList') =<< ns
-
-
--- $hookDoc
--- Heist hooks allow you to modify templates when they are loaded and before
--- and after they are run.  Every time you call one of the addAbcHook
--- functions the hook is added to onto the processing pipeline.  The hooks
--- processes the template in the order that they were added to the
--- TemplateState.
---
--- The pre-run and post-run hooks are run before and after every template is
--- run/rendered.  You should be careful what code you put in these hooks
--- because it can significantly affect the performance of your site.
-
-
- diff --git a/static/docs/0.1.2/heist/src/hscolour.css b/static/docs/0.1.2/heist/src/hscolour.css deleted file mode 100644 index 150e4d0..0000000 --- a/static/docs/0.1.2/heist/src/hscolour.css +++ /dev/null @@ -1,15 +0,0 @@ -body { font-size: 90%; } - -pre, code, body { - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; -} - -.hs-keyglyph, .hs-layout {color: #5200A3;} -.hs-keyword {color: #3465a4; font-weight: bold;} -.hs-comment, .hs-comment a {color: #579; } -.hs-str, .hs-chr {color: #141B24;} -.hs-keyword, .hs-conid, .hs-varid, .hs-conop, .hs-varop, .hs-num, .hs-cpp, .hs-sel, .hs-definition {} diff --git a/static/docs/0.1.2/snap-core/Data-CIByteString.html b/static/docs/0.1.2/snap-core/Data-CIByteString.html deleted file mode 100644 index 01d3740..0000000 --- a/static/docs/0.1.2/snap-core/Data-CIByteString.html +++ /dev/null @@ -1,324 +0,0 @@ - - -Data.CIByteString
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Data.CIByteString
Description

Data.CIByteString is a module containing CIByteString, a wrapper for - ByteString which provides case-insensitive (ASCII-wise) Ord and Eq - instances. -

CIByteString also has an IsString instance, so if you use the - "OverloadedStrings" LANGUAGE pragma you can write case-insensitive string - literals, e.g.: -

- > let a = "Foo" in
-   putStrLn $ (show $ unCI a) ++ "==\"FoO\" is " ++ show (a == "FoO")
- "Foo"=="FoO" is True
-
Synopsis
data CIByteString
toCI :: ByteString -> CIByteString
unCI :: CIByteString -> ByteString
Documentation
data CIByteString Source
A case-insensitive newtype wrapper for ByteString -
show/hide Instances
toCI :: ByteString -> CIByteStringSource
unCI :: CIByteString -> ByteStringSource
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.2/snap-core/Snap-Internal-Debug.html b/static/docs/0.1.2/snap-core/Snap-Internal-Debug.html deleted file mode 100644 index a8a987b..0000000 --- a/static/docs/0.1.2/snap-core/Snap-Internal-Debug.html +++ /dev/null @@ -1,169 +0,0 @@ - - -Snap.Internal.Debug
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Snap.Internal.Debug
Description

An internal Snap module for (optionally) printing debugging - messages. Normally debug does nothing, but you can pass "-fdebug" to - cabal install to build a snap-core which debugs to stderr. -

N.B. this is an internal interface, please don't write external code that - depends on it. -

Documentation
debug :: MonadIO m => String -> m ()Source
debugErrno :: MonadIO m => String -> m ()Source
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.2/snap-core/Snap-Internal-Http-Types.html b/static/docs/0.1.2/snap-core/Snap-Internal-Http-Types.html deleted file mode 100644 index 74db005..0000000 --- a/static/docs/0.1.2/snap-core/Snap-Internal-Http-Types.html +++ /dev/null @@ -1,3854 +0,0 @@ - - -Snap.Internal.Http.Types
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Snap.Internal.Http.Types
Description

An internal Snap module containing HTTP types. -

N.B. this is an internal interface, please don't write user code that - depends on it. Most of these declarations (except for the - unsafe/encapsulation-breaking ones) are re-exported from Snap.Types. -

Synopsis
set_c_locale :: IO ()
c_parse_http_time :: CString -> IO CTime
c_format_http_time :: CTime -> CString -> IO ()
type Enumerator a = Enumerator IO a
type Headers = Map CIByteString [ByteString]
class HasHeaders a where
updateHeaders :: (Headers -> Headers) -> a -> a
headers :: a -> Headers
addHeader :: HasHeaders a => CIByteString -> ByteString -> a -> a
setHeader :: HasHeaders a => CIByteString -> ByteString -> a -> a
getHeaders :: HasHeaders a => CIByteString -> a -> Maybe [ByteString]
getHeader :: HasHeaders a => CIByteString -> a -> Maybe ByteString
data Method
= GET
| HEAD
| POST
| PUT
| DELETE
| TRACE
| OPTIONS
| CONNECT
type HttpVersion = (Int, Int)
data Cookie = Cookie {
cookieName :: !ByteString
cookieValue :: !ByteString
cookieExpires :: !(Maybe UTCTime)
cookieDomain :: !(Maybe ByteString)
cookiePath :: !(Maybe ByteString)
}
type Params = Map ByteString [ByteString]
data SomeEnumerator = SomeEnumerator (forall a. Enumerator a)
data Request = Request {
rqServerName :: !ByteString
rqServerPort :: !Int
rqRemoteAddr :: !ByteString
rqRemotePort :: !Int
rqLocalAddr :: !ByteString
rqLocalPort :: !Int
rqLocalHostname :: !ByteString
rqIsSecure :: !Bool
rqHeaders :: Headers
rqBody :: IORef SomeEnumerator
rqContentLength :: !(Maybe Int)
rqMethod :: !Method
rqVersion :: !HttpVersion
rqCookies :: [Cookie]
rqSnapletPath :: !ByteString
rqPathInfo :: !ByteString
rqContextPath :: !ByteString
rqURI :: !ByteString
rqQueryString :: !ByteString
rqParams :: Params
}
data ResponseBody
= Enum (forall a. Enumerator a)
| SendFile FilePath
rspBodyMap :: (forall a. Enumerator a -> Enumerator a) -> ResponseBody -> ResponseBody
rspBodyToEnum :: ResponseBody -> Enumerator a
data Response = Response {
rspHeaders :: Headers
rspHttpVersion :: !HttpVersion
rspContentLength :: !(Maybe Int)
rspBody :: ResponseBody
rspStatus :: !Int
rspStatusReason :: !ByteString
}
rqParam :: ByteString -> Request -> Maybe [ByteString]
rqModifyParams :: (Params -> Params) -> Request -> Request
rqSetParam :: ByteString -> [ByteString] -> Request -> Request
emptyResponse :: Response
setResponseBody :: (forall a. Enumerator a) -> Response -> Response
setResponseStatus :: Int -> ByteString -> Response -> Response
modifyResponseBody :: (forall a. Enumerator a -> Enumerator a) -> Response -> Response
setContentType :: ByteString -> Response -> Response
addCookie :: Cookie -> Response -> Response
setContentLength :: Int -> Response -> Response
clearContentLength :: Response -> Response
formatHttpTime :: CTime -> IO ByteString
parseHttpTime :: ByteString -> IO CTime
parseToCompletion :: Parser a -> ByteString -> Maybe a
pUrlEscaped :: Parser ByteString
urlDecode :: ByteString -> Maybe ByteString
urlEncode :: ByteString -> ByteString
hexd :: Word8 -> Builder
finish :: Result a -> Result a
fromStr :: String -> ByteString
toStr :: ByteString -> String
Documentation
set_c_locale :: IO ()Source
c_parse_http_time :: CString -> IO CTimeSource
c_format_http_time :: CTime -> CString -> IO ()Source
type Enumerator a = Enumerator IO aSource
type Headers = Map CIByteString [ByteString]Source
A type alias for a case-insensitive key-value mapping. -
class HasHeaders a whereSource
A typeclass for datatypes which contain HTTP headers. -
Methods
updateHeaders :: (Headers -> Headers) -> a -> aSource
Modify the datatype's headers. -
headers :: a -> HeadersSource
Retrieve the headers from a datatype that has headers. -
show/hide Instances
addHeader :: HasHeaders a => CIByteString -> ByteString -> a -> aSource
Adds a header key-value-pair to the HasHeaders datatype. If a header with - the same name already exists, the new value is appended to the headers list. -
setHeader :: HasHeaders a => CIByteString -> ByteString -> a -> aSource
Sets a header key-value-pair in a HasHeaders datatype. If a header with - the same name already exists, it is overwritten with the new value. -
getHeaders :: HasHeaders a => CIByteString -> a -> Maybe [ByteString]Source
Gets all of the values for a given header. -
getHeader :: HasHeaders a => CIByteString -> a -> Maybe ByteStringSource
Gets a header value out of a HasHeaders datatype. If many headers came - in with the same name, they will be catenated together. -
data Method Source
Enumerates the HTTP method values (see - http://tools.ietf.org/html/rfc2068.html#section-5.1.1). -
Constructors
GET
HEAD
POST
PUT
DELETE
TRACE
OPTIONS
CONNECT
show/hide Instances
type HttpVersion = (Int, Int)Source
data Cookie Source
A datatype representing an HTTP cookie. -
Constructors
Cookie
cookieName :: !ByteStringThe name of the cookie. -
cookieValue :: !ByteStringThe cookie's string value. -
cookieExpires :: !(Maybe UTCTime)The cookie's expiration value, if it has one. -
cookieDomain :: !(Maybe ByteString)The cookie's "domain" value, if it has one. -
cookiePath :: !(Maybe ByteString)The cookie path. -
show/hide Instances
type Params = Map ByteString [ByteString]Source
A type alias for the HTTP parameters mapping. Each parameter - key maps to a list of ByteString values; if a parameter is specified - multiple times (e.g.: "GET /foo?param=bar1&param=bar2"), looking up - "param" in the mapping will give you ["bar1", "bar2"]. -
data SomeEnumerator Source
Constructors
SomeEnumerator (forall a. Enumerator a)
data Request Source
Contains all of the information about an incoming HTTP request. -
Constructors
Request
rqServerName :: !ByteStringThe server name of the request, as it came in from the request's - Host: header. -
rqServerPort :: !IntReturns the port number the HTTP server is listening on. -
rqRemoteAddr :: !ByteStringThe remote IP address. -
rqRemotePort :: !IntThe remote TCP port number. -
rqLocalAddr :: !ByteStringThe local IP address for this request. -
rqLocalPort :: !IntReturns the port number the HTTP server is listening on. -
rqLocalHostname :: !ByteStringReturns the HTTP server's idea of its local hostname. -
rqIsSecure :: !BoolReturns True if this is an HTTPS session (currently always - False). -
rqHeaders :: Headers
rqBody :: IORef SomeEnumerator
rqContentLength :: !(Maybe Int)Returns the Content-Length of the HTTP request body. -
rqMethod :: !MethodReturns the HTTP request method. -
rqVersion :: !HttpVersionReturns the HTTP version used by the client. -
rqCookies :: [Cookie]Returns a list of the cookies that came in from the HTTP request - headers. -
rqSnapletPath :: !ByteString

We'll be doing web components (or "snaplets") for version 0.2. The - "snaplet path" refers to the place on the URL where your containing - snaplet is hung. The value of rqSnapletPath is either "" (at the - top-level context) or is a path beginning with a slash, but not ending - with one. -

An identity is that: -

 rqURI r == 'S.concat' [ rqSnapletPath r
-                       , rqContextPath r
-                       , rqPathInfo r ]
-

note that until we introduce snaplets in v0.2, rqSnapletPath will be - "" -

rqPathInfo :: !ByteStringHandlers can (will be; --ed) be hung on a URI "entry point"; - this is called the "context path". If a handler is hung on the - context path "/foo/", and you request "/foo/bar", the value - of rqPathInfo will be "bar". -
rqContextPath :: !ByteStringThe "context path" of the request; catenating rqContextPath, and - rqPathInfo should get you back to the original rqURI. The - rqContextPath always begins and ends with a slash ("/") - character, and represents the path (relative to your - component/snaplet) you took to get to your handler. -
rqURI :: !ByteStringReturns the URI requested by the client. -
rqQueryString :: !ByteStringReturns the HTTP query string for this Request. -
rqParams :: ParamsReturns the Params mapping for this Request. "Parameters" are - automatically decoded from the query string and POST body and - entered into this mapping. -
show/hide Instances
data ResponseBody Source
Constructors
Enum (forall a. Enumerator a)output body is enumerator -
SendFile FilePathoutput body is sendfile() -
rspBodyMap :: (forall a. Enumerator a -> Enumerator a) -> ResponseBody -> ResponseBodySource
rspBodyToEnum :: ResponseBody -> Enumerator aSource
data Response Source
Represents an HTTP response. -
Constructors
Response
rspHeaders :: Headers
rspHttpVersion :: !HttpVersion
rspContentLength :: !(Maybe Int)We will need to inspect the content length no matter what, and - looking up "content-length" in the headers and parsing the number - out of the text will be too expensive. -
rspBody :: ResponseBody
rspStatus :: !IntReturns the HTTP status code. -
rspStatusReason :: !ByteStringReturns the HTTP status explanation string. -
show/hide Instances
rqParamSource
:: ByteStringparameter name to look up -
-> RequestHTTP request -
-> Maybe [ByteString]
Looks up the value(s) for the given named parameter. Parameters initially - come from the request's query string and any decoded POST body (if the - request's Content-Type is application/x-www-form-urlencoded). Parameter - values can be modified within handlers using rqModifyParams. -
rqModifyParams :: (Params -> Params) -> Request -> RequestSource
Modifies the parameters mapping (which is a Map ByteString ByteString) in - a Request using the given function. -
rqSetParamSource
:: ByteStringparameter name -
-> [ByteString]parameter values -
-> Requestrequest -
-> Request
Writes a key-value pair to the parameters mapping within the given request. -
emptyResponse :: ResponseSource
An empty Response. -
setResponseBodySource
:: forall a. Enumerator anew response body - enumerator -
-> Responseresponse to modify -
-> Response
Sets an HTTP response body to the given Enumerator value. -
setResponseStatusSource
:: IntHTTP response integer code -
-> ByteStringHTTP response explanation -
-> ResponseResponse to be modified -
-> Response
Sets the HTTP response status. -
modifyResponseBody :: (forall a. Enumerator a -> Enumerator a) -> Response -> ResponseSource
Modifies a response body. -
setContentType :: ByteString -> Response -> ResponseSource
Sets the Content-Type in the Response headers. -
addCookieSource
:: Cookiecookie value -
-> Responseresponse to modify -
-> Response
Adds an HTTP Cookie to the Response headers. -
setContentLength :: Int -> Response -> ResponseSource

A note here: if you want to set the Content-Length for the response, - Snap forces you to do it with this function rather than by setting it in the - headers; the Content-Length in the headers will be ignored. -

The reason for this is that Snap needs to look up the value of - Content-Length for each request, and looking the string value up in the - headers and parsing the number out of the text will be too expensive. -

If you don't set a content length in your response, HTTP keep-alive will be - disabled for HTTP/1.0 clients, forcing a Connection: close. For HTTP/1.1 - clients, Snap will switch to the chunked transfer encoding if - Content-Length is not specified. -

clearContentLength :: Response -> ResponseSource
Removes any Content-Length set in the Response. -
formatHttpTime :: CTime -> IO ByteStringSource
Converts a CTime into an HTTP timestamp. -
parseHttpTime :: ByteString -> IO CTimeSource
Converts an HTTP timestamp into a CTime. -
parseToCompletion :: Parser a -> ByteString -> Maybe aSource
pUrlEscaped :: Parser ByteStringSource
urlDecode :: ByteString -> Maybe ByteStringSource
Decodes an URL-escaped string (see - http://tools.ietf.org/html/rfc2396.html#section-2.4) -
urlEncode :: ByteString -> ByteStringSource
URL-escapes a string (see - http://tools.ietf.org/html/rfc2396.html#section-2.4) -
hexd :: Word8 -> BuilderSource
finish :: Result a -> Result aSource
fromStr :: String -> ByteStringSource
toStr :: ByteString -> StringSource
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.2/snap-core/Snap-Internal-Iteratee-Debug.html b/static/docs/0.1.2/snap-core/Snap-Internal-Iteratee-Debug.html deleted file mode 100644 index 16cce1a..0000000 --- a/static/docs/0.1.2/snap-core/Snap-Internal-Iteratee-Debug.html +++ /dev/null @@ -1,129 +0,0 @@ - - -Snap.Internal.Iteratee.Debug
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Snap.Internal.Iteratee.Debug
Description

An internal Snap module for debugging iteratees. -

N.B. this is an internal interface, please don't write user code that - depends on it. -

Documentation
debugIteratee :: Iteratee IO ()Source
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.2/snap-core/Snap-Iteratee.html b/static/docs/0.1.2/snap-core/Snap-Iteratee.html deleted file mode 100644 index eaae3d4..0000000 --- a/static/docs/0.1.2/snap-core/Snap-Iteratee.html +++ /dev/null @@ -1,971 +0,0 @@ - - -Snap.Iteratee
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Snap.Iteratee
Contents
Convenience aliases around types from Data.Iteratee -
Re-export types and functions from Data.Iteratee -
Helper functions -
Enumerators -
Conversion to/from WrappedByteString -
Iteratee utilities -
Description

Snap Framework type aliases and utilities for iteratees. Note that as a - convenience, this module also exports everything from Data.Iteratee in the - iteratee library. -

WARNING: Note that all of these types are scheduled to change in the - darcs head version of the iteratee library; John Lato et al. are working - on a much improved iteratee formulation. -

Synopsis
type Stream = StreamG WrappedByteString Word8
type IterV m = IterGV WrappedByteString Word8 m
type Iteratee m = IterateeG WrappedByteString Word8 m
type Enumerator m a = Iteratee m a -> m (Iteratee m a)
module Data.Iteratee
enumBS :: Monad m => ByteString -> Enumerator m a
enumLBS :: Monad m => ByteString -> Enumerator m a
enumFile :: FilePath -> Iteratee IO a -> IO (Iteratee IO a)
fromWrap :: WrappedByteString Word8 -> ByteString
toWrap :: ByteString -> WrappedByteString Word8
takeExactly :: (StreamChunk s el, Monad m) => Int -> EnumeratorN s el s el m a
takeNoMoreThan :: (StreamChunk s el, Monad m) => Int -> EnumeratorN s el s el m a
countBytes :: Monad m => Iteratee m a -> Iteratee m (a, Int)
bufferIteratee :: Monad m => Enumerator m a
Convenience aliases around types from Data.Iteratee -
type Stream = StreamG WrappedByteString Word8Source
type IterV m = IterGV WrappedByteString Word8 mSource
type Iteratee m = IterateeG WrappedByteString Word8 mSource
type Enumerator m a = Iteratee m a -> m (Iteratee m a)Source
Re-export types and functions from Data.Iteratee -
module Data.Iteratee
Helper functions -
Enumerators -
enumBS :: Monad m => ByteString -> Enumerator m aSource
Enumerates a strict bytestring. -
enumLBS :: Monad m => ByteString -> Enumerator m aSource
Enumerates a lazy bytestring. -
enumFile :: FilePath -> Iteratee IO a -> IO (Iteratee IO a)Source
Conversion to/from WrappedByteString -
fromWrap :: WrappedByteString Word8 -> ByteStringSource
Converts a wrapped bytestring to a lazy bytestring. -
toWrap :: ByteString -> WrappedByteString Word8Source
Converts a lazy bytestring to a wrapped bytestring. -
Iteratee utilities -
takeExactly :: (StreamChunk s el, Monad m) => Int -> EnumeratorN s el s el m aSource
Reads n elements from a stream and applies the given iteratee to - the stream of the read elements. Reads exactly n elements, and if - the stream is short propagates an error. -
takeNoMoreThan :: (StreamChunk s el, Monad m) => Int -> EnumeratorN s el s el m aSource
Reads up to n elements from a stream and applies the given iteratee to the - stream of the read elements. If more than n elements are read, propagates an - error. -
countBytes :: Monad m => Iteratee m a -> Iteratee m (a, Int)Source
Wraps an Iteratee, counting the number of bytes consumed by it. -
bufferIteratee :: Monad m => Enumerator m aSource

Buffers an iteratee. -

Our enumerators produce a lot of little strings; rather than spending all - our time doing kernel context switches for 4-byte write() calls, we buffer - the iteratee to send 2KB at a time. -

Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.2/snap-core/Snap-Types.html b/static/docs/0.1.2/snap-core/Snap-Types.html deleted file mode 100644 index d0241b8..0000000 --- a/static/docs/0.1.2/snap-core/Snap-Types.html +++ /dev/null @@ -1,5874 +0,0 @@ - - -Snap.Types
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Snap.Types
Contents
The Snap Monad -
Functions for control flow and early termination -
Routing -
Access to state -
Grabbing request bodies -
HTTP Datatypes and Functions -
Headers -
Requests -
Responses -
Response I/O -
Iteratee -
HTTP utilities -
Description
This module contains the core type definitions, class instances, and functions -for HTTP as well as the Snap monad, which is used for web handlers. -
Synopsis
data Snap a
runSnap :: Snap a -> Request -> Iteratee IO (Request, Response)
data NoHandlerException = NoHandlerException
finishWith :: Response -> Snap ()
pass :: Snap a
method :: Method -> Snap a -> Snap a
path :: ByteString -> Snap a -> Snap a
dir :: ByteString -> Snap a -> Snap a
ifTop :: Snap a -> Snap a
route :: [(ByteString, Snap a)] -> Snap a
routeLocal :: [(ByteString, Snap a)] -> Snap a
getRequest :: Snap Request
getResponse :: Snap Response
putRequest :: Request -> Snap ()
putResponse :: Response -> Snap ()
modifyRequest :: (Request -> Request) -> Snap ()
modifyResponse :: (Response -> Response) -> Snap ()
localRequest :: (Request -> Request) -> Snap a -> Snap a
withRequest :: (Request -> Snap a) -> Snap a
withResponse :: (Response -> Snap a) -> Snap a
runRequestBody :: Iteratee IO a -> Snap a
getRequestBody :: Snap ByteString
unsafeDetachRequestBody :: Snap (Enumerator a)
data Request
data Response
type Headers = Map CIByteString [ByteString]
class HasHeaders a where
updateHeaders :: (Headers -> Headers) -> a -> a
headers :: a -> Headers
type Params = Map ByteString [ByteString]
data Method
= GET
| HEAD
| POST
| PUT
| DELETE
| TRACE
| OPTIONS
| CONNECT
data Cookie = Cookie {
cookieName :: !ByteString
cookieValue :: !ByteString
cookieExpires :: !(Maybe UTCTime)
cookieDomain :: !(Maybe ByteString)
cookiePath :: !(Maybe ByteString)
}
type HttpVersion = (Int, Int)
addHeader :: HasHeaders a => CIByteString -> ByteString -> a -> a
setHeader :: HasHeaders a => CIByteString -> ByteString -> a -> a
getHeader :: HasHeaders a => CIByteString -> a -> Maybe ByteString
rqServerName :: Request -> ByteString
rqServerPort :: Request -> Int
rqRemoteAddr :: Request -> ByteString
rqRemotePort :: Request -> Int
rqLocalAddr :: Request -> ByteString
rqLocalHostname :: Request -> ByteString
rqIsSecure :: Request -> Bool
rqContentLength :: Request -> Maybe Int
rqMethod :: Request -> Method
rqVersion :: Request -> HttpVersion
rqCookies :: Request -> [Cookie]
rqPathInfo :: Request -> ByteString
rqContextPath :: Request -> ByteString
rqURI :: Request -> ByteString
rqQueryString :: Request -> ByteString
rqParams :: Request -> Params
rqParam :: ByteString -> Request -> Maybe [ByteString]
getParam :: ByteString -> Snap (Maybe ByteString)
rqModifyParams :: (Params -> Params) -> Request -> Request
rqSetParam :: ByteString -> [ByteString] -> Request -> Request
emptyResponse :: Response
setResponseStatus :: Int -> ByteString -> Response -> Response
rspStatus :: Response -> Int
rspStatusReason :: Response -> ByteString
setContentType :: ByteString -> Response -> Response
addCookie :: Cookie -> Response -> Response
setContentLength :: Int -> Response -> Response
clearContentLength :: Response -> Response
setResponseBody :: (forall a. Enumerator a) -> Response -> Response
modifyResponseBody :: (forall a. Enumerator a -> Enumerator a) -> Response -> Response
addToOutput :: (forall a. Enumerator a) -> Snap ()
writeBS :: ByteString -> Snap ()
writeLazyText :: Text -> Snap ()
writeText :: Text -> Snap ()
writeLBS :: ByteString -> Snap ()
sendFile :: FilePath -> Snap ()
type Enumerator a = Enumerator IO a
formatHttpTime :: CTime -> IO ByteString
parseHttpTime :: ByteString -> IO CTime
urlEncode :: ByteString -> ByteString
urlDecode :: ByteString -> Maybe ByteString
The Snap Monad -
data Snap a Source

Snap is the Monad that user web handlers run in. Snap gives you: -

1. stateful access to fetch or modify an HTTP Request -

2. stateful access to fetch or modify an HTTP Response -

3. failure / Alternative / MonadPlus semantics: a Snap handler can - choose not to handle a given request, using empty or its synonym pass, - and you can try alternative handlers with the <|> operator: -

 a :: Snap String
- a = pass
-
- b :: Snap String
- b = return "foo"
-
- c :: Snap String
- c = a <|> b             -- try running a, if it fails then try b
-

4. convenience functions (writeBS, writeLBS, writeText, writeLazyText, - addToOutput) for writing output to the Response: -

 a :: (forall a . Enumerator a) -> Snap ()
- a someEnumerator = do
-     writeBS "I'm a strict bytestring"
-     writeLBS "I'm a lazy bytestring"
-     addToOutput someEnumerator
-

5. early termination: if you call finishWith: -

 a :: Snap ()
- a = do
-   modifyResponse $ setResponseStatus 500 "Internal Server Error"
-   writeBS "500 error"
-   r <- getResponse
-   finishWith r
-

then any subsequent processing will be skipped and supplied Response value - will be returned from runSnap as-is. -

6. access to the IO monad through a MonadIO instance: -

 a :: Snap ()
- a = liftIO fireTheMissiles
-
show/hide Instances
runSnap :: Snap a -> Request -> Iteratee IO (Request, Response)Source
Runs a Snap monad action in the 'Iteratee IO' monad. -
data NoHandlerException Source
This exception is thrown if the handler you supply to runSnap fails. -
Constructors
NoHandlerException
show/hide Instances
Functions for control flow and early termination -
finishWith :: Response -> Snap ()Source
Short-circuits a Snap monad action early, storing the given - Response value in its state. -
pass :: Snap aSource
Fails out of a Snap monad action. This is used to indicate - that you choose not to handle the given request within the given - handler. -
Routing -
method :: Method -> Snap a -> Snap aSource
Runs a Snap monad action only if the request's HTTP method matches - the given method. -
pathSource
:: ByteStringpath to match against -
-> Snap ahandler to run -
-> Snap a
Runs a Snap monad action only for requests where rqPathInfo is exactly - equal to the given string. If the path matches, locally sets rqContextPath - to the old value of rqPathInfo, sets rqPathInfo="", and runs the given - handler. -
dirSource
:: ByteStringpath component to match -
-> Snap ahandler to run -
-> Snap a

Runs a Snap monad action only when the rqPathInfo of the request - starts with the given path. For example, -

 dir "foo" handler
-

Will fail if rqPathInfo is not "/foo" or "/foo/...", and will - add "foo/" to the handler's local rqContextPath. -

ifTop :: Snap a -> Snap aSource
Runs a Snap monad action only when rqPathInfo is empty. -
route :: [(ByteString, Snap a)] -> Snap aSource

A web handler which, given a mapping from URL entry points to web - handlers, efficiently routes requests to the correct handler. -

The URL entry points are given as relative paths, for example: -

 route [ ("foo/bar/quux", fooBarQuux) ]
-

If the URI of the incoming request is -

 /foo/bar/quux
-

or -

 /foo/bar/quux/...anything...
-

then the request will be routed to "fooBarQuux", with rqContextPath - set to "/foo/bar/quux/" and rqPathInfo set to - "...anything...". -

FIXME/TODO: we need a version with and without the context path setting - behaviour; if the route is "article/:id/print", we probably want the - contextPath to be "/article" instead of "/article/whatever/print". -

A path component within an URL entry point beginning with a colon (":") - is treated as a variable capture; the corresponding path component within - the request URI will be entered into the rqParams parameters mapping with - the given name. For instance, if the routes were: -

 route [ ("foo/:bar/baz", fooBazHandler) ]
-

Then a request for "/foo/saskatchewan/baz" would be routed to - fooBazHandler with a mapping for: -

 "bar" => "saskatchewan"
-

in its parameters table. -

Longer paths are matched first, and specific routes are matched before - captures. That is, if given routes: -

 [ ("a", h1), ("a/b", h2), ("a/:x", h3) ]
-

a request for "/a/b" will go to h2, "/a/s" for any s will go - to h3, and "/a" will go to h1. -

The following example matches "/article" to an article index, - "/login" to a login, and "/article/..." to an article renderer. -

 route [ ("article",     renderIndex)
-       , ("article/:id", renderArticle)
-       , ("login",       method POST doLogin) ]
-
routeLocal :: [(ByteString, Snap a)] -> Snap aSource
The routeLocal function is the same as route, except it doesn't change - the request's context path. This is useful if you want to route to a - particular handler but you want that handler to receive the rqPathInfo as - it is. -
Access to state -
getRequest :: Snap RequestSource
Grabs the Request object out of the Snap monad. -
getResponse :: Snap ResponseSource
Grabs the Response object out of the Snap monad. -
putRequest :: Request -> Snap ()Source
Puts a new Request object into the Snap monad. -
putResponse :: Response -> Snap ()Source
Puts a new Response object into the Snap monad. -
modifyRequest :: (Request -> Request) -> Snap ()Source
Modifies the Request object stored in a Snap monad. -
modifyResponse :: (Response -> Response) -> Snap ()Source
Modifes the Response object stored in a Snap monad. -
localRequest :: (Request -> Request) -> Snap a -> Snap aSource
Runs a Snap action with a locally-modified Request state - object. The Request object in the Snap monad state after the call - to localRequest will be unchanged. -
withRequest :: (Request -> Snap a) -> Snap aSource
Fetches the Request from state and hands it to the given action. -
withResponse :: (Response -> Snap a) -> Snap aSource
Fetches the Response from state and hands it to the given action. -
Grabbing request bodies -
runRequestBody :: Iteratee IO a -> Snap aSource
Sends the request body through an iteratee (data consumer) and - returns the result. -
getRequestBody :: Snap ByteStringSource
Returns the request body as a bytestring. -
unsafeDetachRequestBody :: Snap (Enumerator a)Source

Detaches the request body's Enumerator from the Request and - returns it. You would want to use this if you needed to send the - HTTP request body (transformed or otherwise) through to the output - in O(1) space. (Examples: transcoding, "echo", etc) -

Normally Snap is careful to ensure that the request body is fully - consumed after your web handler runs; this function is marked - "unsafe" because it breaks this guarantee and leaves the - responsibility up to you. If you don't fully consume the - Enumerator you get here, the next HTTP request in the pipeline - (if any) will misparse. Be careful with exception handlers. -

HTTP Datatypes and Functions -
HTTP-related datatypes: Request, Response, Cookie, etc. -
data Request Source
Contains all of the information about an incoming HTTP request. -
show/hide Instances
data Response Source
Represents an HTTP response. -
show/hide Instances
type Headers = Map CIByteString [ByteString]Source
A type alias for a case-insensitive key-value mapping. -
class HasHeaders a whereSource
A typeclass for datatypes which contain HTTP headers. -
Methods
updateHeaders :: (Headers -> Headers) -> a -> aSource
Modify the datatype's headers. -
headers :: a -> HeadersSource
Retrieve the headers from a datatype that has headers. -
show/hide Instances
type Params = Map ByteString [ByteString]Source
A type alias for the HTTP parameters mapping. Each parameter - key maps to a list of ByteString values; if a parameter is specified - multiple times (e.g.: "GET /foo?param=bar1&param=bar2"), looking up - "param" in the mapping will give you ["bar1", "bar2"]. -
data Method Source
Enumerates the HTTP method values (see - http://tools.ietf.org/html/rfc2068.html#section-5.1.1). -
Constructors
GET
HEAD
POST
PUT
DELETE
TRACE
OPTIONS
CONNECT
show/hide Instances
data Cookie Source
A datatype representing an HTTP cookie. -
Constructors
Cookie
cookieName :: !ByteStringThe name of the cookie. -
cookieValue :: !ByteStringThe cookie's string value. -
cookieExpires :: !(Maybe UTCTime)The cookie's expiration value, if it has one. -
cookieDomain :: !(Maybe ByteString)The cookie's "domain" value, if it has one. -
cookiePath :: !(Maybe ByteString)The cookie path. -
show/hide Instances
type HttpVersion = (Int, Int)Source
Headers -
addHeader :: HasHeaders a => CIByteString -> ByteString -> a -> aSource
Adds a header key-value-pair to the HasHeaders datatype. If a header with - the same name already exists, the new value is appended to the headers list. -
setHeader :: HasHeaders a => CIByteString -> ByteString -> a -> aSource
Sets a header key-value-pair in a HasHeaders datatype. If a header with - the same name already exists, it is overwritten with the new value. -
getHeader :: HasHeaders a => CIByteString -> a -> Maybe ByteStringSource
Gets a header value out of a HasHeaders datatype. If many headers came - in with the same name, they will be catenated together. -
Requests -
rqServerName :: Request -> ByteStringSource
The server name of the request, as it came in from the request's - Host: header. -
rqServerPort :: Request -> IntSource
Returns the port number the HTTP server is listening on. -
rqRemoteAddr :: Request -> ByteStringSource
The remote IP address. -
rqRemotePort :: Request -> IntSource
The remote TCP port number. -
rqLocalAddr :: Request -> ByteStringSource
The local IP address for this request. -
rqLocalHostname :: Request -> ByteStringSource
Returns the HTTP server's idea of its local hostname. -
rqIsSecure :: Request -> BoolSource
Returns True if this is an HTTPS session (currently always - False). -
rqContentLength :: Request -> Maybe IntSource
Returns the Content-Length of the HTTP request body. -
rqMethod :: Request -> MethodSource
Returns the HTTP request method. -
rqVersion :: Request -> HttpVersionSource
Returns the HTTP version used by the client. -
rqCookies :: Request -> [Cookie]Source
Returns a list of the cookies that came in from the HTTP request - headers. -
rqPathInfo :: Request -> ByteStringSource
Handlers can (will be; --ed) be hung on a URI "entry point"; - this is called the "context path". If a handler is hung on the - context path "/foo/", and you request "/foo/bar", the value - of rqPathInfo will be "bar". -
rqContextPath :: Request -> ByteStringSource
The "context path" of the request; catenating rqContextPath, and - rqPathInfo should get you back to the original rqURI. The - rqContextPath always begins and ends with a slash ("/") - character, and represents the path (relative to your - component/snaplet) you took to get to your handler. -
rqURI :: Request -> ByteStringSource
Returns the URI requested by the client. -
rqQueryString :: Request -> ByteStringSource
Returns the HTTP query string for this Request. -
rqParams :: Request -> ParamsSource
Returns the Params mapping for this Request. "Parameters" are - automatically decoded from the query string and POST body and - entered into this mapping. -
rqParamSource
:: ByteStringparameter name to look up -
-> RequestHTTP request -
-> Maybe [ByteString]
Looks up the value(s) for the given named parameter. Parameters initially - come from the request's query string and any decoded POST body (if the - request's Content-Type is application/x-www-form-urlencoded). Parameter - values can be modified within handlers using rqModifyParams. -
getParamSource
:: ByteStringparameter name to look up -
-> Snap (Maybe ByteString)

See rqParam. Looks up a value for the given named parameter in the - Request. If more than one value was entered for the given parameter name, - getParam gloms the values together with: -

    intercalate " "
rqModifyParams :: (Params -> Params) -> Request -> RequestSource
Modifies the parameters mapping (which is a Map ByteString ByteString) in - a Request using the given function. -
rqSetParamSource
:: ByteStringparameter name -
-> [ByteString]parameter values -
-> Requestrequest -
-> Request
Writes a key-value pair to the parameters mapping within the given request. -
Responses -
emptyResponse :: ResponseSource
An empty Response. -
setResponseStatusSource
:: IntHTTP response integer code -
-> ByteStringHTTP response explanation -
-> ResponseResponse to be modified -
-> Response
Sets the HTTP response status. -
rspStatus :: Response -> IntSource
Returns the HTTP status code. -
rspStatusReason :: Response -> ByteStringSource
Returns the HTTP status explanation string. -
setContentType :: ByteString -> Response -> ResponseSource
Sets the Content-Type in the Response headers. -
addCookieSource
:: Cookiecookie value -
-> Responseresponse to modify -
-> Response
Adds an HTTP Cookie to the Response headers. -
setContentLength :: Int -> Response -> ResponseSource

A note here: if you want to set the Content-Length for the response, - Snap forces you to do it with this function rather than by setting it in the - headers; the Content-Length in the headers will be ignored. -

The reason for this is that Snap needs to look up the value of - Content-Length for each request, and looking the string value up in the - headers and parsing the number out of the text will be too expensive. -

If you don't set a content length in your response, HTTP keep-alive will be - disabled for HTTP/1.0 clients, forcing a Connection: close. For HTTP/1.1 - clients, Snap will switch to the chunked transfer encoding if - Content-Length is not specified. -

clearContentLength :: Response -> ResponseSource
Removes any Content-Length set in the Response. -
Response I/O -
setResponseBodySource
:: forall a. Enumerator anew response body - enumerator -
-> Responseresponse to modify -
-> Response
Sets an HTTP response body to the given Enumerator value. -
modifyResponseBody :: (forall a. Enumerator a -> Enumerator a) -> Response -> ResponseSource
Modifies a response body. -
addToOutputSource
:: forall a. Enumerator aoutput to add -
-> Snap ()
Adds the output from the given enumerator to the Response - stored in the Snap monad state. -
writeBS :: ByteString -> Snap ()Source
Adds the given strict ByteString to the body of the Response stored in - the Snap monad state. -
writeLazyText :: Text -> Snap ()Source
Adds the given lazy Text to the body of the Response stored in the - Snap monad state. -
writeText :: Text -> Snap ()Source
Adds the given strict Text to the body of the Response stored in the - Snap monad state. -
writeLBS :: ByteString -> Snap ()Source
Adds the given lazy ByteString to the body of the Response stored in - the Snap monad state. -
sendFile :: FilePath -> Snap ()Source

Sets the output to be the contents of the specified file. -

Calling sendFile will overwrite any output queued to be sent in the - Response. If the response body is not modified after the call to - sendFile, Snap will use the efficient sendfile() system call on - platforms that support it. -

If the response body is modified (using modifyResponseBody), the file will - be read using mmap(). -

Iteratee -
type Enumerator a = Enumerator IO aSource
HTTP utilities -
formatHttpTime :: CTime -> IO ByteStringSource
Converts a CTime into an HTTP timestamp. -
parseHttpTime :: ByteString -> IO CTimeSource
Converts an HTTP timestamp into a CTime. -
urlEncode :: ByteString -> ByteStringSource
URL-escapes a string (see - http://tools.ietf.org/html/rfc2396.html#section-2.4) -
urlDecode :: ByteString -> Maybe ByteStringSource
Decodes an URL-escaped string (see - http://tools.ietf.org/html/rfc2396.html#section-2.4) -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.2/snap-core/Snap-Util-FileServe.html b/static/docs/0.1.2/snap-core/Snap-Util-FileServe.html deleted file mode 100644 index 3448069..0000000 --- a/static/docs/0.1.2/snap-core/Snap-Util-FileServe.html +++ /dev/null @@ -1,651 +0,0 @@ - - -Snap.Util.FileServe
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Snap.Util.FileServe
Description
Contains web handlers to serve files from a directory. -
Synopsis
getSafePath :: Snap FilePath
fileServe :: FilePath -> Snap ()
fileServe' :: MimeMap -> FilePath -> Snap ()
fileServeSingle :: FilePath -> Snap ()
fileServeSingle' :: ByteString -> FilePath -> Snap ()
defaultMimeTypes :: MimeMap
type MimeMap = Map FilePath ByteString
Documentation
getSafePath :: Snap FilePathSource
Gets a path from the Request using rqPathInfo and makes sure it is - safe to use for opening files. A path is safe if it is a relative path - and has no .. elements to escape the intended directory structure. -
fileServeSource
:: FilePathroot directory -
-> Snap ()

Serves files out of the given directory. The relative path given in - rqPathInfo is searched for the given file, and the file is served with the - appropriate mime type if it is found. Absolute paths and ".." are prohibited - to prevent files from being served from outside the sandbox. -

Uses defaultMimeTypes to determine the Content-Type based on the file's - extension. -

fileServe'Source
:: MimeMapMIME type mapping -
-> FilePathroot directory -
-> Snap ()
Same as fileServe, with control over the MIME mapping used. -
fileServeSingleSource
:: FilePathpath to file -
-> Snap ()
Serves a single file specified by a full or relative path. The - path restrictions on fileServe don't apply to this function since - the path is not being supplied by the user. -
fileServeSingle'Source
:: ByteStringMIME type mapping -
-> FilePathpath to file -
-> Snap ()
Same as fileServeSingle, with control over the MIME mapping used. -
defaultMimeTypes :: MimeMapSource

The default set of mime type mappings we use when serving files. Its - value: -

 Map.fromList [
-   ( ".asc"     , "text/plain"                        ),
-   ( ".asf"     , "video/x-ms-asf"                    ),
-   ( ".asx"     , "video/x-ms-asf"                    ),
-   ( ".avi"     , "video/x-msvideo"                   ),
-   ( ".bz2"     , "application/x-bzip"                ),
-   ( ".c"       , "text/plain"                        ),
-   ( ".class"   , "application/octet-stream"          ),
-   ( ".conf"    , "text/plain"                        ),
-   ( ".cpp"     , "text/plain"                        ),
-   ( ".css"     , "text/css"                          ),
-   ( ".cxx"     , "text/plain"                        ),
-   ( ".dtd"     , "text/xml"                          ),
-   ( ".dvi"     , "application/x-dvi"                 ),
-   ( ".gif"     , "image/gif"                         ),
-   ( ".gz"      , "application/x-gzip"                ),
-   ( ".hs"      , "text/plain"                        ),
-   ( ".htm"     , "text/html"                         ),
-   ( ".html"    , "text/html"                         ),
-   ( ".jar"     , "application/x-java-archive"        ),
-   ( ".jpeg"    , "image/jpeg"                        ),
-   ( ".jpg"     , "image/jpeg"                        ),
-   ( ".js"      , "text/javascript"                   ),
-   ( ".log"     , "text/plain"                        ),
-   ( ".m3u"     , "audio/x-mpegurl"                   ),
-   ( ".mov"     , "video/quicktime"                   ),
-   ( ".mp3"     , "audio/mpeg"                        ),
-   ( ".mpeg"    , "video/mpeg"                        ),
-   ( ".mpg"     , "video/mpeg"                        ),
-   ( ".ogg"     , "application/ogg"                   ),
-   ( ".pac"     , "application/x-ns-proxy-autoconfig" ),
-   ( ".pdf"     , "application/pdf"                   ),
-   ( ".png"     , "image/png"                         ),
-   ( ".ps"      , "application/postscript"            ),
-   ( ".qt"      , "video/quicktime"                   ),
-   ( ".sig"     , "application/pgp-signature"         ),
-   ( ".spl"     , "application/futuresplash"          ),
-   ( ".swf"     , "application/x-shockwave-flash"     ),
-   ( ".tar"     , "application/x-tar"                 ),
-   ( ".tar.bz2" , "application/x-bzip-compressed-tar" ),
-   ( ".tar.gz"  , "application/x-tgz"                 ),
-   ( ".tbz"     , "application/x-bzip-compressed-tar" ),
-   ( ".text"    , "text/plain"                        ),
-   ( ".tgz"     , "application/x-tgz"                 ),
-   ( ".torrent" , "application/x-bittorrent"          ),
-   ( ".txt"     , "text/plain"                        ),
-   ( ".wav"     , "audio/x-wav"                       ),
-   ( ".wax"     , "audio/x-ms-wax"                    ),
-   ( ".wma"     , "audio/x-ms-wma"                    ),
-   ( ".wmv"     , "video/x-ms-wmv"                    ),
-   ( ".xbm"     , "image/x-xbitmap"                   ),
-   ( ".xml"     , "text/xml"                          ),
-   ( ".xpm"     , "image/x-xpixmap"                   ),
-   ( ".xwd"     , "image/x-xwindowdump"               ),
-   ( ".zip"     , "application/zip"                   ) ]
-
type MimeMap = Map FilePath ByteStringSource
A type alias for MIME type -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.2/snap-core/Snap-Util-GZip.html b/static/docs/0.1.2/snap-core/Snap-Util-GZip.html deleted file mode 100644 index 5c3ec4c..0000000 --- a/static/docs/0.1.2/snap-core/Snap-Util-GZip.html +++ /dev/null @@ -1,328 +0,0 @@ - - -Snap.Util.GZip
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Snap.Util.GZip
Synopsis
withCompression :: Snap a -> Snap ()
withCompression' :: Set ByteString -> Snap a -> Snap ()
Documentation
withCompressionSource
:: Snap athe web handler to run -
-> Snap ()

Runs a Snap web handler with compression if available. -

If the client has indicated support for gzip or compress in its - Accept-Encoding header, and the Content-Type in the response is one of - the following types: -

  • application/x-javascript
  • text/css
  • text/html
  • text/javascript
  • text/plain
  • text/xml
  • application/x-font-truetype

Then the given handler's output stream will be compressed, - Content-Encoding will be set in the output headers, and the - Content-Length will be cleared if it was set. (We can't process the stream - in O(1) space if the length is known beforehand.) -

The wrapped handler will be run to completion, and then the Response - that's contained within the Snap monad state will be passed to - finishWith to prevent further processing. -

withCompression'Source
:: Set ByteStringset of compressible MIME types -
-> Snap athe web handler to run -
-> Snap ()
The same as withCompression, with control over which MIME types to - compress. -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.2/snap-core/doc-index-62.html b/static/docs/0.1.2/snap-core/doc-index-62.html deleted file mode 100644 index d664bd4..0000000 --- a/static/docs/0.1.2/snap-core/doc-index-62.html +++ /dev/null @@ -1,144 +0,0 @@ - - -snap-core-0.1.2: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (>)
>.
diff --git a/static/docs/0.1.2/snap-core/doc-index-A.html b/static/docs/0.1.2/snap-core/doc-index-A.html deleted file mode 100644 index e1379e1..0000000 --- a/static/docs/0.1.2/snap-core/doc-index-A.html +++ /dev/null @@ -1,166 +0,0 @@ - - -snap-core-0.1.2: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (A)
addCookie
addHeader
addToOutput
diff --git a/static/docs/0.1.2/snap-core/doc-index-B.html b/static/docs/0.1.2/snap-core/doc-index-B.html deleted file mode 100644 index bd1f89b..0000000 --- a/static/docs/0.1.2/snap-core/doc-index-B.html +++ /dev/null @@ -1,152 +0,0 @@ - - -snap-core-0.1.2: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (B)
break
bufferIteratee
diff --git a/static/docs/0.1.2/snap-core/doc-index-C.html b/static/docs/0.1.2/snap-core/doc-index-C.html deleted file mode 100644 index 1d8ea5e..0000000 --- a/static/docs/0.1.2/snap-core/doc-index-C.html +++ /dev/null @@ -1,294 +0,0 @@ - - -snap-core-0.1.2: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (C)
checkErr
checkIfDone
Chunk
CIByteString
clearContentLength
CONNECT
Cont
convStream
Cookie
1 (Type/Class)
2 (Data Constructor)
cookieDomain
cookieExpires
cookieName
cookiePath
cookieValue
countBytes
c_format_http_time
c_parse_http_time
diff --git a/static/docs/0.1.2/snap-core/doc-index-D.html b/static/docs/0.1.2/snap-core/doc-index-D.html deleted file mode 100644 index bf26815..0000000 --- a/static/docs/0.1.2/snap-core/doc-index-D.html +++ /dev/null @@ -1,206 +0,0 @@ - - -snap-core-0.1.2: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (D)
debug
debugErrno
debugIteratee
defaultMimeTypes
DELETE
dir
Done
drop
dropWhile
diff --git a/static/docs/0.1.2/snap-core/doc-index-E.html b/static/docs/0.1.2/snap-core/doc-index-E.html deleted file mode 100644 index fea5529..0000000 --- a/static/docs/0.1.2/snap-core/doc-index-E.html +++ /dev/null @@ -1,292 +0,0 @@ - - -snap-core-0.1.2: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (E)
emptyResponse
Endian
endianRead2
endianRead3
endianRead4
Enum
enumBS
enumEof
Enumerator
1 (Type/Class)
2 (Type/Class)
EnumeratorGM
EnumeratorGMM
EnumeratorN
enumErr
enumFile
enumLBS
enumPair
enumPure1Chunk
enumPureNChunk
EOF
Err
ErrMsg
diff --git a/static/docs/0.1.2/snap-core/doc-index-F.html b/static/docs/0.1.2/snap-core/doc-index-F.html deleted file mode 100644 index 2fb81ef..0000000 --- a/static/docs/0.1.2/snap-core/doc-index-F.html +++ /dev/null @@ -1,254 +0,0 @@ - - -snap-core-0.1.2: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (F)
fileDriver
fileDriverRandom
FileOffset
fileServe
fileServe'
fileServeSingle
fileServeSingle'
filter
finish
finishWith
foldl
foldl'
foldl1
formatHttpTime
fromStr
fromWrap
diff --git a/static/docs/0.1.2/snap-core/doc-index-G.html b/static/docs/0.1.2/snap-core/doc-index-G.html deleted file mode 100644 index 7ccb2fa..0000000 --- a/static/docs/0.1.2/snap-core/doc-index-G.html +++ /dev/null @@ -1,206 +0,0 @@ - - -snap-core-0.1.2: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (G)
GET
getHeader
getHeaders
getParam
getRequest
getRequestBody
getResponse
getSafePath
diff --git a/static/docs/0.1.2/snap-core/doc-index-H.html b/static/docs/0.1.2/snap-core/doc-index-H.html deleted file mode 100644 index 641832b..0000000 --- a/static/docs/0.1.2/snap-core/doc-index-H.html +++ /dev/null @@ -1,208 +0,0 @@ - - -snap-core-0.1.2: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (H)
HasHeaders
HEAD
head
Headers
headers
heads
hexd
HttpVersion
diff --git a/static/docs/0.1.2/snap-core/doc-index-I.html b/static/docs/0.1.2/snap-core/doc-index-I.html deleted file mode 100644 index 10647c2..0000000 --- a/static/docs/0.1.2/snap-core/doc-index-I.html +++ /dev/null @@ -1,196 +0,0 @@ - - -snap-core-0.1.2: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (I)
identity
ifTop
isFinished
Iteratee
IterateeG
1 (Data Constructor)
2 (Type/Class)
IterGV
IterV
diff --git a/static/docs/0.1.2/snap-core/doc-index-J.html b/static/docs/0.1.2/snap-core/doc-index-J.html deleted file mode 100644 index 2085237..0000000 --- a/static/docs/0.1.2/snap-core/doc-index-J.html +++ /dev/null @@ -1,150 +0,0 @@ - - -snap-core-0.1.2: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (J)
joinI
joinIM
diff --git a/static/docs/0.1.2/snap-core/doc-index-L.html b/static/docs/0.1.2/snap-core/doc-index-L.html deleted file mode 100644 index 5467108..0000000 --- a/static/docs/0.1.2/snap-core/doc-index-L.html +++ /dev/null @@ -1,188 +0,0 @@ - - -snap-core-0.1.2: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (L)
length
liftI
liftInner
localRequest
LooseMap
looseMap
looseMapStream
LSB
diff --git a/static/docs/0.1.2/snap-core/doc-index-M.html b/static/docs/0.1.2/snap-core/doc-index-M.html deleted file mode 100644 index 41ccc42..0000000 --- a/static/docs/0.1.2/snap-core/doc-index-M.html +++ /dev/null @@ -1,202 +0,0 @@ - - -snap-core-0.1.2: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (M)
mapStream
Method
method
MimeMap
modifyRequest
modifyResponse
modifyResponseBody
MSB
diff --git a/static/docs/0.1.2/snap-core/doc-index-N.html b/static/docs/0.1.2/snap-core/doc-index-N.html deleted file mode 100644 index 049a2e8..0000000 --- a/static/docs/0.1.2/snap-core/doc-index-N.html +++ /dev/null @@ -1,158 +0,0 @@ - - -snap-core-0.1.2: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (N)
NoHandlerException
1 (Type/Class)
2 (Data Constructor)
diff --git a/static/docs/0.1.2/snap-core/doc-index-O.html b/static/docs/0.1.2/snap-core/doc-index-O.html deleted file mode 100644 index 546811c..0000000 --- a/static/docs/0.1.2/snap-core/doc-index-O.html +++ /dev/null @@ -1,148 +0,0 @@ - - -snap-core-0.1.2: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (O)
OPTIONS
diff --git a/static/docs/0.1.2/snap-core/doc-index-P.html b/static/docs/0.1.2/snap-core/doc-index-P.html deleted file mode 100644 index fbfd2c5..0000000 --- a/static/docs/0.1.2/snap-core/doc-index-P.html +++ /dev/null @@ -1,238 +0,0 @@ - - -snap-core-0.1.2: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (P)
Params
parseHttpTime
parseToCompletion
pass
path
peek
POST
product
pUrlEscaped
PUT
putRequest
putResponse
diff --git a/static/docs/0.1.2/snap-core/doc-index-R.html b/static/docs/0.1.2/snap-core/doc-index-R.html deleted file mode 100644 index c4f915c..0000000 --- a/static/docs/0.1.2/snap-core/doc-index-R.html +++ /dev/null @@ -1,530 +0,0 @@ - - -snap-core-0.1.2: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (R)
Request
1 (Type/Class)
2 (Data Constructor)
Response
1 (Type/Class)
2 (Data Constructor)
ResponseBody
rigidMapStream
route
routeLocal
rqBody
rqContentLength
rqContextPath
rqCookies
rqHeaders
rqIsSecure
rqLocalAddr
rqLocalHostname
rqLocalPort
rqMethod
rqModifyParams
rqParam
rqParams
rqPathInfo
rqQueryString
rqRemoteAddr
rqRemotePort
rqServerName
rqServerPort
rqSetParam
rqSnapletPath
rqURI
rqVersion
rspBody
rspBodyMap
rspBodyToEnum
rspContentLength
rspHeaders
rspHttpVersion
rspStatus
rspStatusReason
run
runIter
runRequestBody
runSnap
diff --git a/static/docs/0.1.2/snap-core/doc-index-S.html b/static/docs/0.1.2/snap-core/doc-index-S.html deleted file mode 100644 index 8e6bbc7..0000000 --- a/static/docs/0.1.2/snap-core/doc-index-S.html +++ /dev/null @@ -1,296 +0,0 @@ - - -snap-core-0.1.2: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (S)
Seek
seek
SendFile
sendFile
setContentLength
setContentType
setEOF
setHeader
setResponseBody
setResponseStatus
set_c_locale
skipToEof
Snap
SomeEnumerator
1 (Type/Class)
2 (Data Constructor)
Stream
stream2list
stream2stream
StreamG
sum
diff --git a/static/docs/0.1.2/snap-core/doc-index-T.html b/static/docs/0.1.2/snap-core/doc-index-T.html deleted file mode 100644 index c392b1d..0000000 --- a/static/docs/0.1.2/snap-core/doc-index-T.html +++ /dev/null @@ -1,206 +0,0 @@ - - -snap-core-0.1.2: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (T)
take
takeExactly
takeNoMoreThan
takeR
throwErr
toCI
toStr
toWrap
TRACE
diff --git a/static/docs/0.1.2/snap-core/doc-index-U.html b/static/docs/0.1.2/snap-core/doc-index-U.html deleted file mode 100644 index 1d0ee9c..0000000 --- a/static/docs/0.1.2/snap-core/doc-index-U.html +++ /dev/null @@ -1,184 +0,0 @@ - - -snap-core-0.1.2: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (U)
unCI
unsafeDetachRequestBody
updateHeaders
urlDecode
urlEncode
diff --git a/static/docs/0.1.2/snap-core/doc-index-W.html b/static/docs/0.1.2/snap-core/doc-index-W.html deleted file mode 100644 index 3f6c26d..0000000 --- a/static/docs/0.1.2/snap-core/doc-index-W.html +++ /dev/null @@ -1,202 +0,0 @@ - - -snap-core-0.1.2: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (W)
withCompression
withCompression'
withRequest
withResponse
writeBS
writeLazyText
writeLBS
writeText
diff --git a/static/docs/0.1.2/snap-core/doc-index.html b/static/docs/0.1.2/snap-core/doc-index.html deleted file mode 100644 index d7d0df0..0000000 --- a/static/docs/0.1.2/snap-core/doc-index.html +++ /dev/null @@ -1,134 +0,0 @@ - - -snap-core-0.1.2: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)ContentsIndex
Index
ABCDEFGHIJLMNOPRSTUW>
diff --git a/static/docs/0.1.2/snap-core/fonts/DroidSerif-Bold.eot b/static/docs/0.1.2/snap-core/fonts/DroidSerif-Bold.eot deleted file mode 100644 index 01b9e1f..0000000 Binary files a/static/docs/0.1.2/snap-core/fonts/DroidSerif-Bold.eot and /dev/null differ diff --git a/static/docs/0.1.2/snap-core/fonts/DroidSerif-Bold.svg b/static/docs/0.1.2/snap-core/fonts/DroidSerif-Bold.svg deleted file mode 100644 index 1f7f2d2..0000000 --- a/static/docs/0.1.2/snap-core/fonts/DroidSerif-Bold.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.1.2/snap-core/fonts/DroidSerif-Bold.ttf b/static/docs/0.1.2/snap-core/fonts/DroidSerif-Bold.ttf deleted file mode 100644 index da0ea11..0000000 Binary files a/static/docs/0.1.2/snap-core/fonts/DroidSerif-Bold.ttf and /dev/null differ diff --git a/static/docs/0.1.2/snap-core/fonts/DroidSerif-Bold.woff b/static/docs/0.1.2/snap-core/fonts/DroidSerif-Bold.woff deleted file mode 100644 index 91549cd..0000000 Binary files a/static/docs/0.1.2/snap-core/fonts/DroidSerif-Bold.woff and /dev/null differ diff --git a/static/docs/0.1.2/snap-core/fonts/DroidSerif-BoldItalic.eot b/static/docs/0.1.2/snap-core/fonts/DroidSerif-BoldItalic.eot deleted file mode 100644 index 47dd0a0..0000000 Binary files a/static/docs/0.1.2/snap-core/fonts/DroidSerif-BoldItalic.eot and /dev/null differ diff --git a/static/docs/0.1.2/snap-core/fonts/DroidSerif-BoldItalic.svg b/static/docs/0.1.2/snap-core/fonts/DroidSerif-BoldItalic.svg deleted file mode 100644 index 1a57dbb..0000000 --- a/static/docs/0.1.2/snap-core/fonts/DroidSerif-BoldItalic.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.1.2/snap-core/fonts/DroidSerif-BoldItalic.ttf b/static/docs/0.1.2/snap-core/fonts/DroidSerif-BoldItalic.ttf deleted file mode 100644 index 8be3fb4..0000000 Binary files a/static/docs/0.1.2/snap-core/fonts/DroidSerif-BoldItalic.ttf and /dev/null differ diff --git a/static/docs/0.1.2/snap-core/fonts/DroidSerif-BoldItalic.woff b/static/docs/0.1.2/snap-core/fonts/DroidSerif-BoldItalic.woff deleted file mode 100644 index 6d5fa3d..0000000 Binary files a/static/docs/0.1.2/snap-core/fonts/DroidSerif-BoldItalic.woff and /dev/null differ diff --git a/static/docs/0.1.2/snap-core/fonts/DroidSerif-Italic.eot b/static/docs/0.1.2/snap-core/fonts/DroidSerif-Italic.eot deleted file mode 100644 index 2d4850c..0000000 Binary files a/static/docs/0.1.2/snap-core/fonts/DroidSerif-Italic.eot and /dev/null differ diff --git a/static/docs/0.1.2/snap-core/fonts/DroidSerif-Italic.svg b/static/docs/0.1.2/snap-core/fonts/DroidSerif-Italic.svg deleted file mode 100644 index 356c374..0000000 --- a/static/docs/0.1.2/snap-core/fonts/DroidSerif-Italic.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.1.2/snap-core/fonts/DroidSerif-Italic.ttf b/static/docs/0.1.2/snap-core/fonts/DroidSerif-Italic.ttf deleted file mode 100644 index 3719dc2..0000000 Binary files a/static/docs/0.1.2/snap-core/fonts/DroidSerif-Italic.ttf and /dev/null differ diff --git a/static/docs/0.1.2/snap-core/fonts/DroidSerif-Italic.woff b/static/docs/0.1.2/snap-core/fonts/DroidSerif-Italic.woff deleted file mode 100644 index b64436f..0000000 Binary files a/static/docs/0.1.2/snap-core/fonts/DroidSerif-Italic.woff and /dev/null differ diff --git a/static/docs/0.1.2/snap-core/fonts/DroidSerif-Regular.eot b/static/docs/0.1.2/snap-core/fonts/DroidSerif-Regular.eot deleted file mode 100644 index 0d17523..0000000 Binary files a/static/docs/0.1.2/snap-core/fonts/DroidSerif-Regular.eot and /dev/null differ diff --git a/static/docs/0.1.2/snap-core/fonts/DroidSerif-Regular.svg b/static/docs/0.1.2/snap-core/fonts/DroidSerif-Regular.svg deleted file mode 100644 index b9b65fb..0000000 --- a/static/docs/0.1.2/snap-core/fonts/DroidSerif-Regular.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.1.2/snap-core/fonts/DroidSerif-Regular.ttf b/static/docs/0.1.2/snap-core/fonts/DroidSerif-Regular.ttf deleted file mode 100644 index 066dcaa..0000000 Binary files a/static/docs/0.1.2/snap-core/fonts/DroidSerif-Regular.ttf and /dev/null differ diff --git a/static/docs/0.1.2/snap-core/fonts/DroidSerif-Regular.woff b/static/docs/0.1.2/snap-core/fonts/DroidSerif-Regular.woff deleted file mode 100644 index cfd3d67..0000000 Binary files a/static/docs/0.1.2/snap-core/fonts/DroidSerif-Regular.woff and /dev/null differ diff --git a/static/docs/0.1.2/snap-core/frames.html b/static/docs/0.1.2/snap-core/frames.html deleted file mode 100644 index 9e904fc..0000000 --- a/static/docs/0.1.2/snap-core/frames.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/static/docs/0.1.2/snap-core/haddock-util.js b/static/docs/0.1.2/snap-core/haddock-util.js deleted file mode 100644 index 364081f..0000000 --- a/static/docs/0.1.2/snap-core/haddock-util.js +++ /dev/null @@ -1,139 +0,0 @@ -// Haddock JavaScript utilities -function toggle(button,id) -{ - var n = document.getElementById(id).style; - if (n.display == "none") - { - button.src = "minus.gif"; - n.display = "block"; - } - else - { - button.src = "plus.gif"; - n.display = "none"; - } -} - - -var max_results = 75; // 50 is not enough to search for map in the base libraries -var shown_range = null; -var last_search = null; - -function quick_search() -{ - perform_search(false); -} - -function full_search() -{ - perform_search(true); -} - - -function perform_search(full) -{ - var text = document.getElementById("searchbox").value.toLowerCase(); - if (text == last_search && !full) return; - last_search = text; - - var table = document.getElementById("indexlist"); - var status = document.getElementById("searchmsg"); - var children = table.firstChild.childNodes; - - // first figure out the first node with the prefix - var first = bisect(-1); - var last = (first == -1 ? -1 : bisect(1)); - - if (first == -1) - { - table.className = ""; - status.innerHTML = "No results found, displaying all"; - } - else if (first == 0 && last == children.length - 1) - { - table.className = ""; - status.innerHTML = ""; - } - else if (last - first >= max_results && !full) - { - table.className = ""; - status.innerHTML = "More than " + max_results + ", press Search to display"; - } - else - { - // decide what you need to clear/show - if (shown_range) - setclass(shown_range[0], shown_range[1], "indexrow"); - setclass(first, last, "indexshow"); - shown_range = [first, last]; - table.className = "indexsearch"; - status.innerHTML = ""; - } - - - function setclass(first, last, status) - { - for (var i = first; i <= last; i++) - { - children[i].className = status; - } - } - - - // do a binary search, treating 0 as ... - // return either -1 (no 0's found) or location of most far match - function bisect(dir) - { - var first = 0, finish = children.length - 1; - var mid, success = false; - - while (finish - first > 3) - { - mid = Math.floor((finish + first) / 2); - - var i = checkitem(mid); - if (i == 0) i = dir; - if (i == -1) - finish = mid; - else - first = mid; - } - var a = (dir == 1 ? first : finish); - var b = (dir == 1 ? finish : first); - for (var i = b; i != a - dir; i -= dir) - { - if (checkitem(i) == 0) return i; - } - return -1; - } - - - // from an index, decide what the result is - // 0 = match, -1 is lower, 1 is higher - function checkitem(i) - { - var s = getitem(i).toLowerCase().substr(0, text.length); - if (s == text) return 0; - else return (s > text ? -1 : 1); - } - - - // from an index, get its string - // this abstracts over alternates - function getitem(i) - { - for ( ; i >= 0; i--) - { - var s = children[i].firstChild.firstChild.data; - if (s.indexOf(' ') == -1) - return s; - } - return ""; // should never be reached - } -} - -function setSynopsis(filename) { - if (parent.window.synopsis) { - parent.window.synopsis.location = filename; - } -} diff --git a/static/docs/0.1.2/snap-core/haddock.css b/static/docs/0.1.2/snap-core/haddock.css deleted file mode 100644 index fe050fe..0000000 --- a/static/docs/0.1.2/snap-core/haddock.css +++ /dev/null @@ -1,478 +0,0 @@ -/* -------- Global things --------- */ - -@font-face { - font-family: 'DroidSerif'; - src: url('fonts/DroidSerif-Regular.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Regular.woff') format('woff'), - url('fonts/DroidSerif-Regular.ttf') format('truetype'), - url('fonts/DroidSerif-Regular.svg#DroidSerif') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - font-style: italic; - src: url('fonts/DroidSerif-Italic.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Italic.woff') format('woff'), - url('fonts/DroidSerif-Italic.ttf') format('truetype'), - url('fonts/DroidSerif-Italic.svg#DroidSerif-Italic') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - font-weight: bold; - src: url('fonts/DroidSerif-Bold.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Bold.woff') format('woff'), - url('fonts/DroidSerif-Bold.ttf') format('truetype'), - url('fonts/DroidSerif-Bold.svg#DroidSerif-Bold') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - src: url('fonts/DroidSerif-BoldItalic.eot'); - font-weight: bold; - font-style: italic; - src: local('Droid Serif'), - url('fonts/DroidSerif-BoldItalic.woff') format('woff'), - url('fonts/DroidSerif-BoldItalic.ttf') format('truetype'), - url('fonts/DroidSerif-BoldItalic.svg#DroidSerif-BoldItalic') format('svg'); -} - - - -HTML { - background-color: #f0f3ff; - width: 100%; -} - -BODY { - -moz-border-radius:5px; - -webkit-border-radius:5px; - width: 50em; - margin: 2em auto; - padding: 0; - background-color: #ffffff; - color: #000000; - font-size: 110%; - font-family: DroidSerif, Georgia, serif; - } - -A:link { color: #5200A3; text-decoration: none } -A:visited { color: #5200A3; text-decoration: none } -A:hover { color: #5200A3; text-decoration: none; border-bottom:#5200A3 dashed 1px; } - -TABLE.vanilla { - width: 100%; - border-width: 0px; - /* I can't seem to specify cellspacing or cellpadding properly using CSS... */ -} - -DL { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - letter-spacing: -0.01em; - margin: 0; -} - -.vanilla .vanilla dl { font-size: 80%; } -.vanilla .vanilla dl dl { padding-left: 0; font-size: 95%; } - -TD.section1, TD.section2, TD.section3, TD.section4, TD.doc, DL { - padding: 0 30px 0 34px; -} - -TABLE.vanilla2 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - border-width: 0px; -} - -/* font is a little too small in MSIE */ -TT, PRE, CODE { - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - font-size: 90%; -} - -LI P { margin: 0pt } - -P { margin-top: 0; margin-bottom: 0.75em; } - -TD { - border-width: 0px; -} - -TABLE.narrow { - border-width: 0px; -} - -TD.s8 { height: 0; margin:0; padding: 0 } -TD.s15 { height: 20px; } - -SPAN.keyword { text-decoration: underline; } - -/* Resize the buttom image to match the text size */ -IMG.coll { width : 0.75em; height: 0.75em; margin-bottom: 0; margin-right: 0.5em } - -/* --------- Contents page ---------- */ - -DIV.node { - padding-left: 3em; -} - -DIV.cnode { - padding-left: 1.75em; -} - -SPAN.pkg { - position: absolute; - left: 50em; -} - -/* --------- Documentation elements ---------- */ - -TD FONT { font-weight: bold; letter-spacing: -0.02em; } - -TD.children { - padding-left: 25px; - } - -TD.synopsis { - padding: 2px; - background-color: #f0f0f0; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - } - -TD.decl { - padding: 4px 8px; - background-color: #FAFAFA; - border-bottom: #F2F2F2 solid 1px; - border-top: #FCFCFC solid 1px; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - vertical-align: top; - } - -TD.decl TD.decl { - font-size: 100%; - padding: 4px 0; - border: 0; -} - -TD.topdecl { - padding: 20px 30px 0.5ex 30px; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; -; - vertical-align: top; -} - -.vanilla .vanilla .vanilla .topdecl { - padding-left: 0; - padding-right: 0; -} - -.vanilla .vanilla .vanilla { - padding-left: 30px; -} - -.decl .vanilla { - padding-left: 0px !important; -} - -.body .vanilla .body { - padding-left: 0; - padding-right: 0; -} - -.body .vanilla .body .decl { - padding-left: 12px; -} - -.body .vanilla .body div .vanilla .decl { - padding-left: 12px; -} - -TABLE.declbar { - background-color: #f0f0f0; - border-spacing: 0px; - border-bottom:1px solid #d7d7df; - border-right:1px solid #d7d7df; - border-top:1px solid #f4f4f9; - border-left:1px solid #f4f4f9; - padding: 4px; - } - -TD.declname { - width: 100%; - padding-right: 4px; - } - -TD.declbut { - padding-left: 8px; - padding-right: 5px; - border-left-width: 1px; - border-left-color: #000099; - border-left-style: solid; - white-space: nowrap; - font-size: x-small; - } - -/* - arg is just like decl, except that wrapping is not allowed. It is - used for function and constructor arguments which have a text box - to the right, where if wrapping is allowed the text box squashes up - the declaration by wrapping it. -*/ -TD.arg { - padding: 2px 12px; - background-color: #f0f0f0; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - vertical-align: top; - white-space: nowrap; - } - -TD.recfield { padding-left: 20px } - -TD.doc { - padding-left: 38px; - font-size: 95%; - line-height: 1.66; - } - -TD.ndoc { - font-size: 95%; - line-height: 1.66; - padding: 2px 4px 2px 8px; - } - -TD.rdoc { - padding: 2px; - padding-left: 30px; - width: 100%; - font-size: 80%; - font-style: italic; - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - } - -TD.body { - padding: 0 30px; - } - -TD.pkg { - width: 100%; - padding-left: 30px -} - -TABLE.indexsearch TR.indexrow { - display: none; -} -TABLE.indexsearch TR.indexshow { - display: table-row; -} - -TD.indexentry { - vertical-align: top; - padding: 0 30px - } - -TD.indexannot { - vertical-align: top; - padding-left: 20px; - white-space: nowrap - } - -TD.indexlinks { - width: 100% - } - -/* ------- Section Headings ------- */ - -TD.section1, TD.section2, TD.section3, TD.section4, TD.section5 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; -} - -TD.section1 { - padding-top: 14px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 140% - } - -TD.section2 { - padding-top: 4px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 120% - } - -TD.section3 { - padding-top: 5px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 105% - } - -TD.section4 { - font-weight: bold; - padding-top: 12px; - padding-bottom: 4px; - letter-spacing: -0.02em; - font-size: 90% - } - -/* -------------- The title bar at the top of the page */ - -TD.infohead { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - font-weight: bold; - padding: 0 30px; - text-align: left; -} - -TD.infoval { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - padding: 0 30px; - text-align: left; -} - -TD.topbar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - background-color: #3465a4; - padding: 5px; - -moz-border-radius-topleft:5px; - -moz-border-radius-topright:5px; - -webkit-border-radius-topleft:5px; - -webkit-border-radius-topright:5px; -} - -TD.title { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - padding-left: 30px; - letter-spacing: -0.02em; - font-weight: bold; - width: 100% - } - -TD.topbut { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - padding-left: 5px; - padding-right: 5px; - border-left-width: 1px; - border-left-color: #ffffff; - border-left-style: solid; - letter-spacing: -0.02em; - font-weight: bold; - white-space: nowrap; - } - -TD.topbut A:link { - color: #ffffff - } - -TD.topbut A:visited { - color: #ffff00 - } - -TD.topbut A:hover { - background-color: #C9D3DE; - } - -TD.topbut:hover { - background-color: #C9D3DE; - } - -TD.modulebar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #141B24; - background-color: #C9D3DE; - padding: 5px; - border-top-width: 1px; - border-top-color: #ffffff; - border-top-style: solid; - -moz-border-radius-bottomleft:5px; - -moz-border-radius-bottomright:5px; - -webkit-border-radius-bottomleft:5px; - -webkit-border-radius-bottomright:5px; - - } - -/* --------- The page footer --------- */ - -TD.botbar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - -moz-border-radius:5px; - -webkit-border-radius:5px; - background-color: #3465a4; - color: #ffffff; - padding: 5px - } -TD.botbar A:link { - color: #ffffff; - text-decoration: underline - } -TD.botbar A:visited { - color: #ffff00 - } -TD.botbar A:hover { - background-color: #6060ff - } - -/* --------- Mini Synopsis for Frame View --------- */ - -.outer { - margin: 0 0; - padding: 0 0; -} - -.mini-synopsis { - padding: 0.25em 0.25em; -} - -.mini-synopsis H1 { font-size: 120%; } -.mini-synopsis H2 { font-size: 107%; } -.mini-synopsis H3 { font-size: 100%; } -.mini-synopsis H1, .mini-synopsis H2, .mini-synopsis H3 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - margin-top: 0.5em; - margin-bottom: 0.25em; - padding: 0 0; - font-weight: bold; letter-spacing: -0.02em; -} - -.mini-synopsis H1 { border-bottom: 1px solid #ccc; } - -.mini-topbar { - font-size: 120%; - background: #0077dd; - padding: 0.25em; -} - - diff --git a/static/docs/0.1.2/snap-core/haskell_icon.gif b/static/docs/0.1.2/snap-core/haskell_icon.gif deleted file mode 100644 index cb2a815..0000000 Binary files a/static/docs/0.1.2/snap-core/haskell_icon.gif and /dev/null differ diff --git a/static/docs/0.1.2/snap-core/index-frames.html b/static/docs/0.1.2/snap-core/index-frames.html deleted file mode 100644 index 52b3ed2..0000000 --- a/static/docs/0.1.2/snap-core/index-frames.html +++ /dev/null @@ -1,43 +0,0 @@ - - -snap-core-0.1.2: Snap: A Haskell Web Framework (Core)

Data.CIByteString
Snap.Internal.Debug
Snap.Internal.Http.Types
Snap.Internal.Iteratee.Debug
Snap.Iteratee
Snap.Types
Snap.Util.FileServe
Snap.Util.GZip

diff --git a/static/docs/0.1.2/snap-core/index.html b/static/docs/0.1.2/snap-core/index.html deleted file mode 100644 index 13e4c32..0000000 --- a/static/docs/0.1.2/snap-core/index.html +++ /dev/null @@ -1,300 +0,0 @@ - - -snap-core-0.1.2: Snap: A Haskell Web Framework (Core)
 snap-core-0.1.2: Snap: A Haskell Web Framework (Core)ContentsIndex
snap-core-0.1.2: Snap: A Haskell Web Framework (Core)

This is the first developer prerelease of the Snap framework. Snap is a -simple and fast web development framework and server written in Haskell. For -more information or to download the latest version, you can visit the Snap -project website at http://snapframework.com/. -

This library contains the core definitions and types for the Snap framework, -including: -

1. Primitive types and functions for HTTP (requests, responses, cookies, -post/query parameters, etc) -

2. Type aliases and helper functions for Iteratee I/O -

3. A monad for programming web handlers called "Snap", inspired by -happstack's (http://happstack.com/index.html), which allows: -

  • Stateful access to the HTTP request and response objects -
  • Monadic failure (i.e. MonadPlus/Alternative instances) for declining -to handle requests and chaining handlers together -
  • Early termination of the computation if you know early what you want -to return and want to prevent further monadic processing -

Quick start: The Snap monad and HTTP definitions are in Snap.Types, -some iteratee utilities are in Snap.Iteratee. -

Higher-level facilities for building web applications (like user/session -management, component interfaces, data modeling, etc.) are planned but not -yet implemented, so this release will mostly be of interest for those who: -

  • need a fast and minimal HTTP API at roughly the same level of abstraction -as Java servlets, or -
  • are interested in contributing to the Snap Framework project. -
Modules
show/hideData
Data.CIByteString
show/hideSnap
show/hideInternal
Snap.Internal.Debug
show/hideHttp
Snap.Internal.Http.Types
show/hideIteratee
Snap.Internal.Iteratee.Debug
Snap.Iteratee
Snap.Types
show/hideUtil
Snap.Util.FileServe
Snap.Util.GZip
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.2/snap-core/mini_Data-CIByteString.html b/static/docs/0.1.2/snap-core/mini_Data-CIByteString.html deleted file mode 100644 index 475b4ae..0000000 --- a/static/docs/0.1.2/snap-core/mini_Data-CIByteString.html +++ /dev/null @@ -1,35 +0,0 @@ - - -Data.CIByteString
Data.CIByteString
diff --git a/static/docs/0.1.2/snap-core/mini_Snap-Internal-Debug.html b/static/docs/0.1.2/snap-core/mini_Snap-Internal-Debug.html deleted file mode 100644 index 9f5123e..0000000 --- a/static/docs/0.1.2/snap-core/mini_Snap-Internal-Debug.html +++ /dev/null @@ -1,29 +0,0 @@ - - -Snap.Internal.Debug
Snap.Internal.Debug
diff --git a/static/docs/0.1.2/snap-core/mini_Snap-Internal-Http-Types.html b/static/docs/0.1.2/snap-core/mini_Snap-Internal-Http-Types.html deleted file mode 100644 index ce244b6..0000000 --- a/static/docs/0.1.2/snap-core/mini_Snap-Internal-Http-Types.html +++ /dev/null @@ -1,201 +0,0 @@ - - -Snap.Internal.Http.Types diff --git a/static/docs/0.1.2/snap-core/mini_Snap-Internal-Iteratee-Debug.html b/static/docs/0.1.2/snap-core/mini_Snap-Internal-Iteratee-Debug.html deleted file mode 100644 index c622c16..0000000 --- a/static/docs/0.1.2/snap-core/mini_Snap-Internal-Iteratee-Debug.html +++ /dev/null @@ -1,25 +0,0 @@ - - -Snap.Internal.Iteratee.Debug
Snap.Internal.Iteratee.Debug
diff --git a/static/docs/0.1.2/snap-core/mini_Snap-Iteratee.html b/static/docs/0.1.2/snap-core/mini_Snap-Iteratee.html deleted file mode 100644 index bf606a7..0000000 --- a/static/docs/0.1.2/snap-core/mini_Snap-Iteratee.html +++ /dev/null @@ -1,107 +0,0 @@ - - -Snap.Iteratee
Snap.Iteratee

Convenience aliases around types from Data.Iteratee -

type Stream
type IterV m
type Iteratee m
type Enumerator m a

Re-export types and functions from Data.Iteratee -

Helper functions -

Enumerators -

Conversion to/from WrappedByteString -

Iteratee utilities -

diff --git a/static/docs/0.1.2/snap-core/mini_Snap-Types.html b/static/docs/0.1.2/snap-core/mini_Snap-Types.html deleted file mode 100644 index c751abe..0000000 --- a/static/docs/0.1.2/snap-core/mini_Snap-Types.html +++ /dev/null @@ -1,379 +0,0 @@ - - -Snap.Types diff --git a/static/docs/0.1.2/snap-core/mini_Snap-Util-FileServe.html b/static/docs/0.1.2/snap-core/mini_Snap-Util-FileServe.html deleted file mode 100644 index 0ea73e5..0000000 --- a/static/docs/0.1.2/snap-core/mini_Snap-Util-FileServe.html +++ /dev/null @@ -1,51 +0,0 @@ - - -Snap.Util.FileServe diff --git a/static/docs/0.1.2/snap-core/mini_Snap-Util-GZip.html b/static/docs/0.1.2/snap-core/mini_Snap-Util-GZip.html deleted file mode 100644 index 93f3163..0000000 --- a/static/docs/0.1.2/snap-core/mini_Snap-Util-GZip.html +++ /dev/null @@ -1,29 +0,0 @@ - - -Snap.Util.GZip diff --git a/static/docs/0.1.2/snap-core/minus.gif b/static/docs/0.1.2/snap-core/minus.gif deleted file mode 100644 index 1deac2f..0000000 Binary files a/static/docs/0.1.2/snap-core/minus.gif and /dev/null differ diff --git a/static/docs/0.1.2/snap-core/plus.gif b/static/docs/0.1.2/snap-core/plus.gif deleted file mode 100644 index 2d15c14..0000000 Binary files a/static/docs/0.1.2/snap-core/plus.gif and /dev/null differ diff --git a/static/docs/0.1.2/snap-core/snap-core.haddock b/static/docs/0.1.2/snap-core/snap-core.haddock deleted file mode 100644 index 192e189..0000000 Binary files a/static/docs/0.1.2/snap-core/snap-core.haddock and /dev/null differ diff --git a/static/docs/0.1.2/snap-core/src/Data-CIByteString.html b/static/docs/0.1.2/snap-core/src/Data-CIByteString.html deleted file mode 100644 index f98fa2e..0000000 --- a/static/docs/0.1.2/snap-core/src/Data-CIByteString.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - -src/Data/CIByteString.hs - - - -
{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE OverloadedStrings #-}
-
--- | "Data.CIByteString" is a module containing 'CIByteString', a wrapper for
--- 'ByteString' which provides case-insensitive (ASCII-wise) 'Ord' and 'Eq'
--- instances.
---
--- 'CIByteString' also has an 'IsString' instance, so if you use the
--- \"OverloadedStrings\" LANGUAGE pragma you can write case-insensitive string
--- literals, e.g.:
---
--- @
--- \> let a = \"Foo\" in
---   putStrLn $ (show $ unCI a) ++ \"==\\\"FoO\\\" is \" ++ show (a == \"FoO\")
--- \"Foo\"==\"FoO\" is True
--- @
-
-module Data.CIByteString
- ( CIByteString
- , toCI
- , unCI
- ) where
-
--- for IsString instance
-import           Data.ByteString.Char8 ()
-import           Data.ByteString (ByteString)
-import           Data.ByteString.Internal (c2w, w2c)
-import qualified Data.ByteString as S
-import           Data.Char
-import           Data.String
-
-
--- | A case-insensitive newtype wrapper for 'ByteString'
-data CIByteString = CIByteString { unCI        :: !ByteString
-                                 , _lowercased :: !ByteString }
-
-toCI :: ByteString -> CIByteString
-toCI s = CIByteString s t
-  where
-    t = lowercase s
-
-instance Show CIByteString where
-    show (CIByteString s _) = show s
-
-lowercase :: ByteString -> ByteString
-lowercase = S.map (c2w . toLower . w2c)
-
-instance Eq CIByteString where
-    (CIByteString _ a) == (CIByteString _ b) = a == b
-    (CIByteString _ a) /= (CIByteString _ b) = a /= b
-
-instance Ord CIByteString where
-    (CIByteString _ a) <= (CIByteString _ b) = a <= b
-
-instance IsString CIByteString where
-    fromString = toCI . fromString
-
- diff --git a/static/docs/0.1.2/snap-core/src/Snap-Internal-Debug.html b/static/docs/0.1.2/snap-core/src/Snap-Internal-Debug.html deleted file mode 100644 index c295589..0000000 --- a/static/docs/0.1.2/snap-core/src/Snap-Internal-Debug.html +++ /dev/null @@ -1,86 +0,0 @@ - - - - -src/Snap/Internal/Debug.hs - - - -
-- | An internal Snap module for (optionally) printing debugging
--- messages. Normally 'debug' does nothing, but you can pass \"-fdebug\" to
--- @cabal install@ to build a @snap-core@ which debugs to stderr.
---
--- /N.B./ this is an internal interface, please don't write external code that
--- depends on it.
-
-{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE CPP #-}
-
-module Snap.Internal.Debug where
-
-import           Control.Monad.Trans
-
-#ifdef DEBUG_TEST
-
-debug :: (MonadIO m) => String -> m ()
-debug !s = return $ s `seq` ()
-{-# INLINE debug #-}
-
-debugErrno :: (MonadIO m) => String -> m ()
-debugErrno !s = return $ s `seq` ()
-
-#elif defined(DEBUG)
-
-------------------------------------------------------------------------------
-import           Control.Concurrent
-import           Data.List
-import           Data.Maybe
-import           Foreign.C.Error
-import           System.IO
-import           System.IO.Unsafe
-import           Text.Printf
-------------------------------------------------------------------------------
-
-
-------------------------------------------------------------------------------
-_debugMVar :: MVar ()
-_debugMVar = unsafePerformIO $ newMVar ()
-
-
-------------------------------------------------------------------------------
-debug :: (MonadIO m) => String -> m ()
-debug s = liftIO $ withMVar _debugMVar $ \_ -> do
-              tid <- myThreadId
-              hPutStrLn stderr $ s' tid
-              hFlush stderr
-  where
-    chop x = let y = fromMaybe x $ stripPrefix "ThreadId " x
-             in printf "%8s" y
-
-    s' t   = "[" ++ chop (show t) ++ "] " ++ s
-
-{-# INLINE debug #-}
-
-
-------------------------------------------------------------------------------
-debugErrno :: (MonadIO m) => String -> m ()
-debugErrno loc = liftIO $ do
-    err <- getErrno
-    let ex = errnoToIOError loc err Nothing Nothing
-    debug $ show ex
-------------------------------------------------------------------------------
-
-#else
-
-------------------------------------------------------------------------------
-debug :: (MonadIO m) => String -> m ()
-debug _ = return ()
-{-# INLINE debug #-}
-
-debugErrno :: (MonadIO m) => String -> m ()
-debugErrno _ = return ()
-------------------------------------------------------------------------------
-
-#endif
-
- diff --git a/static/docs/0.1.2/snap-core/src/Snap-Internal-Http-Types.html b/static/docs/0.1.2/snap-core/src/Snap-Internal-Http-Types.html deleted file mode 100644 index 44d3120..0000000 --- a/static/docs/0.1.2/snap-core/src/Snap-Internal-Http-Types.html +++ /dev/null @@ -1,648 +0,0 @@ - - - - -src/Snap/Internal/Http/Types.hs - - - -
-- | An internal Snap module containing HTTP types.
---
--- /N.B./ this is an internal interface, please don't write user code that
--- depends on it. Most of these declarations (except for the
--- unsafe/encapsulation-breaking ones) are re-exported from "Snap.Types".
-
-{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE EmptyDataDecls #-}
-{-# LANGUAGE ForeignFunctionInterface #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RankNTypes #-}
-{-# LANGUAGE TypeSynonymInstances #-}
-
-module Snap.Internal.Http.Types where
-
-
-------------------------------------------------------------------------------
-import           Control.Applicative hiding (empty)
-import           Control.Monad (liftM, when)
-import qualified Data.Attoparsec as Atto
-import           Data.Attoparsec hiding (many, Result(..))
-import           Data.Bits
-import           Data.ByteString (ByteString)
-import           Data.ByteString.Internal (c2w,w2c)
-import qualified Data.ByteString.Nums.Careless.Hex as Cvt
-import qualified Data.ByteString as S
-import           Data.Char
-import           Data.DList (DList)
-import qualified Data.DList as DL
-import           Data.IORef
-import           Data.Map (Map)
-import qualified Data.Map as Map
-import           Data.Monoid
-import           Data.Serialize.Builder
-import           Data.Time.Clock
-import           Data.Time.Format
-import           Data.Word
-import           Foreign hiding (new)
-import           Foreign.C.String
-import           Foreign.C.Types
-import           Prelude hiding (take)
-import           System.Locale (defaultTimeLocale)
-
-------------------------------------------------------------------------------
-import           Data.CIByteString
-import qualified Snap.Iteratee as I
-
-
-------------------------------------------------------------------------------
-foreign import ccall unsafe "set_c_locale"
-        set_c_locale :: IO ()
-
-
-------------------------------------------------------------------------------
-foreign import ccall unsafe "c_parse_http_time"
-        c_parse_http_time :: CString -> IO CTime
-
-
-------------------------------------------------------------------------------
-foreign import ccall unsafe "c_format_http_time"
-        c_format_http_time :: CTime -> CString -> IO ()
-
-------------------------------------------------------------------------------
-type Enumerator a = I.Enumerator IO a
-
-------------------------------------------------------------------------------
--- | A type alias for a case-insensitive key-value mapping.
-type Headers = Map CIByteString [ByteString]
-
-
-------------------------------------------------------------------------------
--- | A typeclass for datatypes which contain HTTP headers.
-class HasHeaders a where
-
-    -- | Modify the datatype's headers.
-    updateHeaders :: (Headers -> Headers) -> a -> a
-
-    -- | Retrieve the headers from a datatype that has headers.
-    headers       :: a -> Headers
-
-
-------------------------------------------------------------------------------
--- | Adds a header key-value-pair to the 'HasHeaders' datatype. If a header with
--- the same name already exists, the new value is appended to the headers list.
-addHeader :: (HasHeaders a) => CIByteString -> ByteString -> a -> a
-addHeader k v = updateHeaders $ Map.insertWith' (++) k [v]
-
-
-------------------------------------------------------------------------------
--- | Sets a header key-value-pair in a 'HasHeaders' datatype. If a header with
--- the same name already exists, it is overwritten with the new value.
-setHeader :: (HasHeaders a) => CIByteString -> ByteString -> a -> a
-setHeader k v = updateHeaders $ Map.insert k [v]
-
-
-------------------------------------------------------------------------------
--- | Gets all of the values for a given header.
-getHeaders :: (HasHeaders a) => CIByteString -> a -> Maybe [ByteString]
-getHeaders k a = Map.lookup k $ headers a
-
-
-------------------------------------------------------------------------------
--- | Gets a header value out of a 'HasHeaders' datatype. If many headers came
--- in with the same name, they will be catenated together.
-getHeader :: (HasHeaders a) => CIByteString -> a -> Maybe ByteString
-getHeader k a = liftM (S.intercalate " ") (Map.lookup k $ headers a)
-
-
-------------------------------------------------------------------------------
--- | Enumerates the HTTP method values (see
--- <http://tools.ietf.org/html/rfc2068.html#section-5.1.1>).
-data Method  = GET | HEAD | POST | PUT | DELETE | TRACE | OPTIONS | CONNECT
-               deriving(Show,Read,Ord,Eq)
-
-
-------------------------------------------------------------------------------
-type HttpVersion = (Int,Int)
-
-
-------------------------------------------------------------------------------
--- | A datatype representing an HTTP cookie.
-data Cookie = Cookie {
-      -- | The name of the cookie.
-      cookieName    :: !ByteString
-
-      -- | The cookie's string value.
-    , cookieValue   :: !ByteString
-
-      -- | The cookie's expiration value, if it has one.
-    , cookieExpires :: !(Maybe UTCTime)
-
-      -- | The cookie's \"domain\" value, if it has one.
-    , cookieDomain  :: !(Maybe ByteString)
-
-      -- | The cookie path.
-    , cookiePath    :: !(Maybe ByteString)
-} deriving (Eq, Show)
-
-
-------------------------------------------------------------------------------
--- | A type alias for the HTTP parameters mapping. Each parameter
--- key maps to a list of ByteString values; if a parameter is specified
--- multiple times (e.g.: \"@GET /foo?param=bar1&param=bar2@\"), looking up
--- \"@param@\" in the mapping will give you @[\"bar1\", \"bar2\"]@.
-type Params = Map ByteString [ByteString]
-
-
-------------------------------------------------------------------------------
--- request type
-------------------------------------------------------------------------------
-
-data SomeEnumerator = SomeEnumerator (forall a . Enumerator a)
-
-
-------------------------------------------------------------------------------
--- | Contains all of the information about an incoming HTTP request.
-data Request = Request
-    { -- | The server name of the request, as it came in from the request's
-      -- @Host:@ header.
-      rqServerName     :: !ByteString
-
-      -- | Returns the port number the HTTP server is listening on.
-    , rqServerPort     :: !Int
-
-      -- | The remote IP address.
-    , rqRemoteAddr     :: !ByteString
-
-      -- | The remote TCP port number.
-    , rqRemotePort     :: !Int
-
-      -- | The local IP address for this request.
-    , rqLocalAddr      :: !ByteString
-
-      -- | Returns the port number the HTTP server is listening on.
-    , rqLocalPort      :: !Int
-
-      -- | Returns the HTTP server's idea of its local hostname.
-    , rqLocalHostname  :: !ByteString
-
-      -- | Returns @True@ if this is an @HTTPS@ session (currently always
-      -- @False@).
-    , rqIsSecure       :: !Bool
-    , rqHeaders        :: Headers
-    , rqBody           :: IORef SomeEnumerator
-
-      -- | Returns the @Content-Length@ of the HTTP request body.
-    , rqContentLength  :: !(Maybe Int)
-
-      -- | Returns the HTTP request method.
-    , rqMethod         :: !Method
-
-      -- | Returns the HTTP version used by the client.
-    , rqVersion        :: !HttpVersion
-
-      -- | Returns a list of the cookies that came in from the HTTP request
-      -- headers.
-    , rqCookies        :: [Cookie]
-
-
-      -- | We'll be doing web components (or \"snaplets\") for version 0.2. The
-      -- \"snaplet path\" refers to the place on the URL where your containing
-      -- snaplet is hung. The value of 'rqSnapletPath' is either @\"\"@ (at the
-      -- top-level context) or is a path beginning with a slash, but not ending
-      -- with one.
-      --
-      -- An identity is that:
-      --
-      -- > rqURI r == 'S.concat' [ rqSnapletPath r
-      -- >                       , rqContextPath r
-      -- >                       , rqPathInfo r ]
-      --
-      -- note that until we introduce snaplets in v0.2, 'rqSnapletPath' will be
-      -- \"\"
-    , rqSnapletPath    :: !ByteString
-
-      -- | Handlers can (/will be; --ed/) be hung on a @URI@ \"entry point\";
-      -- this is called the \"context path\". If a handler is hung on the
-      -- context path @\"\/foo\/\"@, and you request @\"\/foo\/bar\"@, the value
-      -- of 'rqPathInfo' will be @\"bar\"@.
-    , rqPathInfo       :: !ByteString
-
-      -- | The \"context path\" of the request; catenating 'rqContextPath', and
-      -- 'rqPathInfo' should get you back to the original 'rqURI'. The
-      -- 'rqContextPath' always begins and ends with a slash (@\"\/\"@)
-      -- character, and represents the path (relative to your
-      -- component\/snaplet) you took to get to your handler.
-    , rqContextPath    :: !ByteString
-
-      -- | Returns the @URI@ requested by the client.
-    , rqURI            :: !ByteString
-
-      -- | Returns the HTTP query string for this 'Request'.
-    , rqQueryString    :: !ByteString
-
-      -- | Returns the 'Params' mapping for this 'Request'. \"Parameters\" are
-      -- automatically decoded from the query string and @POST@ body and
-      -- entered into this mapping.
-    , rqParams         :: Params
-    }
-
-
-------------------------------------------------------------------------------
-instance Show Request where
-  show r = concat [ "Request <\n"
-                  , body
-                  , ">" ]
-    where
-      body = concat $ map (("    "++) . (++ "\n")) [
-                      sname
-                    , remote
-                    , local
-                    , beginheaders
-                    , hdrs
-                    , endheaders
-                    , contentlength
-                    , method
-                    , version
-                    , cookies
-                    , pathinfo
-                    , contextpath
-                    , snapletpath
-                    , uri
-                    , params
-                    ]
-
-      sname         = concat [ "server-name: ", toStr $ rqServerName r ]
-      remote        = concat [ "remote: "
-                             , toStr $ rqRemoteAddr r
-                             , ":"
-                             , show (rqRemotePort r)
-                             ]
-      local         = concat [ "local: "
-                             , toStr $ rqLocalAddr r
-                             , ":"
-                             , show $ rqServerPort r
-                             ]
-      beginheaders  = "Headers:\n      ========================================"
-      endheaders    = "  ========================================"
-      hdrs          = "      " ++ show (rqHeaders r)
-      contentlength = concat [ "content-length: "
-                             , show $ rqContentLength r
-                             ]
-      method        = concat [ "method: "
-                             , show $ rqMethod r
-                             ]
-      version       = concat [ "version: "
-                             , show $ rqVersion r
-                             ]
-      cookies       = concat [ "cookies:\n"
-                             , "      ========================================\n"
-                             , "      " ++ (show $ rqCookies r)
-                             , "\n      ========================================"
-                             ]
-      pathinfo      = concat [ "pathinfo: ", toStr $ rqPathInfo r ]
-      contextpath   = concat [ "contextpath: ", toStr $ rqContextPath r ]
-      snapletpath   = concat [ "snapletpath: ", toStr $ rqSnapletPath r ]
-      uri           = concat [ "URI: ", toStr $ rqURI r ]
-      params        = concat [ "params:\n"
-                             , "      ========================================\n"
-                             , "      " ++ (show $ rqParams r)
-                             , "\n      ========================================"
-                             ]
-
-
-------------------------------------------------------------------------------
-instance HasHeaders Request where
-    headers           = rqHeaders
-    updateHeaders f r = r { rqHeaders = f (rqHeaders r) }
-
-
-------------------------------------------------------------------------------
-instance HasHeaders Headers where
-    headers       = id
-    updateHeaders = id
-
-------------------------------------------------------------------------------
--- response type
-------------------------------------------------------------------------------
-
-data ResponseBody = Enum (forall a . Enumerator a) -- ^ output body is enumerator
-                  | SendFile FilePath              -- ^ output body is sendfile()
-
-
-------------------------------------------------------------------------------
-rspBodyMap :: (forall a . Enumerator a -> Enumerator a)
-           -> ResponseBody
-           -> ResponseBody
-rspBodyMap f b      = Enum $ f $ rspBodyToEnum b
-
-
-------------------------------------------------------------------------------
-rspBodyToEnum :: ResponseBody -> Enumerator a
-rspBodyToEnum (Enum e) = e
-rspBodyToEnum (SendFile fp) = I.enumFile fp
-
-
-------------------------------------------------------------------------------
--- | Represents an HTTP response.
-data Response = Response
-    { rspHeaders       :: Headers
-    , rspHttpVersion   :: !HttpVersion
-
-      -- | We will need to inspect the content length no matter what, and
-      --   looking up \"content-length\" in the headers and parsing the number
-      --   out of the text will be too expensive.
-    , rspContentLength :: !(Maybe Int)
-    , rspBody          :: ResponseBody
-
-      -- | Returns the HTTP status code.
-    , rspStatus        :: !Int
-
-      -- | Returns the HTTP status explanation string.
-    , rspStatusReason  :: !ByteString
-    }
-
-
-------------------------------------------------------------------------------
-instance Show Response where
-  show r = concat [ "Response <\n"
-                  , body
-                  , ">" ]
-    where
-      body = concat $ map (("    "++) . (++ "\n")) [
-                         hdrs
-                       , version
-                       , status
-                       , reason
-                       ]
-
-      hdrs    = concat [ "headers:\n"
-                       , "      ==============================\n      "
-                       , show $ rspHeaders r
-                       , "\n      ==============================" ]
-
-      version = concat [ "version: ", show $ rspHttpVersion r ]
-      status  = concat [ "status: ", show $ rspStatus r ]
-      reason  = concat [ "reason: ", toStr $ rspStatusReason r ]
-
-
-------------------------------------------------------------------------------
-instance HasHeaders Response where
-    headers = rspHeaders
-    updateHeaders f r = r { rspHeaders = f (rspHeaders r) }
-
-
-------------------------------------------------------------------------------
--- | Looks up the value(s) for the given named parameter. Parameters initially
--- come from the request's query string and any decoded POST body (if the
--- request's @Content-Type@ is @application\/x-www-form-urlencoded@). Parameter
--- values can be modified within handlers using "rqModifyParams".
-rqParam :: ByteString           -- ^ parameter name to look up
-        -> Request              -- ^ HTTP request
-        -> Maybe [ByteString]
-rqParam k rq = Map.lookup k $ rqParams rq
-{-# INLINE rqParam #-}
-
-
-------------------------------------------------------------------------------
--- | Modifies the parameters mapping (which is a @Map ByteString ByteString@) in
--- a 'Request' using the given function.
-rqModifyParams :: (Params -> Params) -> Request -> Request
-rqModifyParams f r = r { rqParams = p }
-  where
-    p = f $ rqParams r
-{-# INLINE rqModifyParams #-}
-
-
-------------------------------------------------------------------------------
--- | Writes a key-value pair to the parameters mapping within the given request.
-rqSetParam :: ByteString        -- ^ parameter name
-           -> [ByteString]      -- ^ parameter values
-           -> Request           -- ^ request
-           -> Request
-rqSetParam k v = rqModifyParams $ Map.insert k v
-{-# INLINE rqSetParam #-}
-
-------------------------------------------------------------------------------
--- responses
-------------------------------------------------------------------------------
-
--- | An empty 'Response'.
-emptyResponse       :: Response
-emptyResponse       = Response Map.empty (1,1) Nothing (Enum return) 200 "OK"
-
-
-------------------------------------------------------------------------------
--- | Sets an HTTP response body to the given 'Enumerator' value.
-setResponseBody     :: (forall a . Enumerator a)  -- ^ new response body
-                                                  -- enumerator
-                    -> Response                   -- ^ response to modify
-                    -> Response
-setResponseBody e r = r { rspBody = Enum e }
-{-# INLINE setResponseBody #-}
-
-
-------------------------------------------------------------------------------
--- | Sets the HTTP response status.
-setResponseStatus   :: Int        -- ^ HTTP response integer code
-                    -> ByteString -- ^ HTTP response explanation
-                    -> Response   -- ^ Response to be modified
-                    -> Response
-setResponseStatus s reason r = r { rspStatus=s, rspStatusReason=reason }
-{-# INLINE setResponseStatus #-}
-
-
-------------------------------------------------------------------------------
--- | Modifies a response body.
-modifyResponseBody  :: (forall a . Enumerator a -> Enumerator a)
-                    -> Response
-                    -> Response
-modifyResponseBody f r = r { rspBody = rspBodyMap f (rspBody r) }
-{-# INLINE modifyResponseBody #-}
-
-
-------------------------------------------------------------------------------
--- | Sets the @Content-Type@ in the 'Response' headers.
-setContentType      :: ByteString -> Response -> Response
-setContentType = setHeader "Content-Type"
-{-# INLINE setContentType #-}
-
-
-------------------------------------------------------------------------------
--- | Adds an HTTP 'Cookie' to the 'Response' headers.
-addCookie :: Cookie            -- ^ cookie value
-          -> Response          -- ^ response to modify
-          -> Response
-addCookie (Cookie k v mbExpTime mbDomain mbPath) = updateHeaders f
-  where
-    f       = Map.insertWith' (++) "Set-Cookie" [cookie]
-    cookie  = S.concat [k, "=", v, path, exptime, domain]
-    path    = maybe "" (S.append "; path=") mbPath
-    domain  = maybe "" (S.append "; domain=") mbDomain
-    exptime = maybe "" (S.append "; expires=" . fmt) mbExpTime
-    fmt     = fromStr . formatTime defaultTimeLocale "%a, %d-%b-%Y %H:%M:%S GMT"
-
-
-------------------------------------------------------------------------------
--- | A note here: if you want to set the @Content-Length@ for the response,
--- Snap forces you to do it with this function rather than by setting it in the
--- headers; the @Content-Length@ in the headers will be ignored.
---
--- The reason for this is that Snap needs to look up the value of
--- @Content-Length@ for each request, and looking the string value up in the
--- headers and parsing the number out of the text will be too expensive.
---
--- If you don't set a content length in your response, HTTP keep-alive will be
--- disabled for HTTP\/1.0 clients, forcing a @Connection: close@. For HTTP\/1.1
--- clients, Snap will switch to the chunked transfer encoding if
--- @Content-Length@ is not specified.
-setContentLength    :: Int -> Response -> Response
-setContentLength l r = r { rspContentLength = Just l }
-{-# INLINE setContentLength #-}
-
-
-------------------------------------------------------------------------------
--- | Removes any @Content-Length@ set in the 'Response'.
-clearContentLength :: Response -> Response
-clearContentLength r = r { rspContentLength = Nothing }
-{-# INLINE clearContentLength #-}
-
-
-------------------------------------------------------------------------------
--- HTTP dates
-
-{-
--- | Converts a 'ClockTime' into an HTTP timestamp.
-formatHttpTime :: UTCTime -> ByteString
-formatHttpTime = fromStr . formatTime defaultTimeLocale "%a, %d %b %Y %X GMT"
-
--- | Converts an HTTP timestamp into a 'UTCTime'.
-parseHttpTime :: ByteString -> Maybe UTCTime
-parseHttpTime s' =
-    parseTime defaultTimeLocale "%a, %d %b %Y %H:%M:%S GMT" s
-  where
-    s = toStr s'
--}
-
--- | Converts a 'CTime' into an HTTP timestamp.
-formatHttpTime :: CTime -> IO ByteString
-formatHttpTime t = allocaBytes 40 $ \ptr -> do
-    c_format_http_time t ptr
-    S.packCString ptr
-
-
-------------------------------------------------------------------------------
--- | Converts an HTTP timestamp into a 'CTime'.
-parseHttpTime :: ByteString -> IO CTime
-parseHttpTime s = S.useAsCString s $ \ptr ->
-    c_parse_http_time ptr
-
-
-------------------------------------------------------------------------------
--- URL ENCODING
-------------------------------------------------------------------------------
-
-parseToCompletion :: Parser a -> ByteString -> Maybe a
-parseToCompletion p s = toResult $ finish r
-  where
-    r = parse p s
-
-    toResult (Atto.Done _ c) = Just c
-    toResult _               = Nothing
-
-
-------------------------------------------------------------------------------
-pUrlEscaped :: Parser ByteString
-pUrlEscaped = do
-    sq <- nextChunk DL.empty
-    return $ S.concat $ DL.toList sq
-
-  where
-    nextChunk :: DList ByteString -> Parser (DList ByteString)
-    nextChunk s = (endOfInput *> pure s) <|> do
-        c <- anyWord8
-        case w2c c of
-          '+' -> plusSpace s
-          '%' -> percentEncoded s
-          _   -> unEncoded c s
-
-    percentEncoded :: DList ByteString -> Parser (DList ByteString)
-    percentEncoded l = do
-        hx <- take 2
-        when (S.length hx /= 2 ||
-               (not $ S.all (isHexDigit . w2c) hx)) $
-             fail "bad hex in url"
-          
-        let code = (Cvt.hex hx) :: Word8
-        nextChunk $ DL.snoc l (S.singleton code)
-
-    unEncoded :: Word8 -> DList ByteString -> Parser (DList ByteString)
-    unEncoded c l' = do
-        let l = DL.snoc l' (S.singleton c)
-        bs <- takeTill (flip elem (map c2w "%+"))
-        if S.null bs
-          then nextChunk l
-          else nextChunk $ DL.snoc l bs
-
-    plusSpace :: DList ByteString -> Parser (DList ByteString)
-    plusSpace l = nextChunk (DL.snoc l (S.singleton $ c2w ' '))
-
-
-------------------------------------------------------------------------------
--- | Decodes an URL-escaped string (see
--- <http://tools.ietf.org/html/rfc2396.html#section-2.4>)
-urlDecode :: ByteString -> Maybe ByteString
-urlDecode = parseToCompletion pUrlEscaped
-
-
-------------------------------------------------------------------------------
--- "...Only alphanumerics [0-9a-zA-Z], the special characters "$-_.+!*'(),"
--- [not including the quotes - ed], and reserved characters used for their
--- reserved purposes may be used unencoded within a URL."
-
--- | URL-escapes a string (see
--- <http://tools.ietf.org/html/rfc2396.html#section-2.4>)
-urlEncode :: ByteString -> ByteString
-urlEncode = toByteString . S.foldl' f empty
-  where
-    f b c =
-        if c == c2w ' '
-          then b `mappend` singleton (c2w '+')
-          else if isKosher c
-                 then b `mappend` singleton c
-                 else b `mappend` hexd c
-
-    isKosher w = any ($ c) [ isAlphaNum
-                           , flip elem ['$', '-', '.', '!', '*'
-                                       , '\'', '(', ')', ',' ]]
-      where
-        c = w2c w
-
-
-------------------------------------------------------------------------------
-hexd :: Word8 -> Builder
-hexd c = singleton (c2w '%') `mappend` singleton hi `mappend` singleton low
-  where
-    d   = c2w . intToDigit
-    low = d $ fromEnum $ c .&. 0xf
-    hi  = d $ fromEnum $ (c .&. 0xf0) `shift` (-4)
-
-
-------------------------------------------------------------------------------
-finish :: Atto.Result a -> Atto.Result a
-finish (Atto.Partial f) = flip feed "" $ f ""
-finish x                = x
-
-
-------------------------------------------------------------------------------
--- local definitions
-fromStr :: String -> ByteString
-fromStr = S.pack . map c2w
-{-# INLINE fromStr #-}
-
-------------------------------------------------------------------------------
--- private helper functions
-toStr :: ByteString -> String
-toStr = map w2c . S.unpack
-
-
- diff --git a/static/docs/0.1.2/snap-core/src/Snap-Internal-Iteratee-Debug.html b/static/docs/0.1.2/snap-core/src/Snap-Internal-Iteratee-Debug.html deleted file mode 100644 index 972fc9d..0000000 --- a/static/docs/0.1.2/snap-core/src/Snap-Internal-Iteratee-Debug.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - -src/Snap/Internal/Iteratee/Debug.hs - - - -
-- | An internal Snap module for debugging iteratees.
---
--- /N.B./ this is an internal interface, please don't write user code that
--- depends on it.
-
-{-# OPTIONS_GHC -fno-warn-orphans #-}
-{-# LANGUAGE FlexibleInstances #-}
-
-module Snap.Internal.Iteratee.Debug ( debugIteratee ) where
-
-------------------------------------------------------------------------------
-import           Data.Iteratee.WrappedByteString
-import           Data.Word (Word8)
-import           System.IO
-------------------------------------------------------------------------------
-import           Snap.Iteratee
-------------------------------------------------------------------------------
-
-
-------------------------------------------------------------------------------
-instance Show (WrappedByteString Word8) where
-    show (WrapBS s) = show s
-
-
-------------------------------------------------------------------------------
-debugIteratee :: Iteratee IO ()
-debugIteratee = IterateeG f
-  where
-    f c@(EOF _) = do
-        putStrLn $ "got chunk: " ++ show c
-        hFlush stdout
-        return (Done () c)
-
-    f c@(Chunk _) = do
-        putStrLn $ "got chunk: " ++ show c
-        hFlush stdout
-        return $ Cont debugIteratee Nothing
-
- diff --git a/static/docs/0.1.2/snap-core/src/Snap-Internal-Routing.html b/static/docs/0.1.2/snap-core/src/Snap-Internal-Routing.html deleted file mode 100644 index ab4539e..0000000 --- a/static/docs/0.1.2/snap-core/src/Snap-Internal-Routing.html +++ /dev/null @@ -1,195 +0,0 @@ - - - - -src/Snap/Internal/Routing.hs - - - -
module Snap.Internal.Routing where
-
-
-------------------------------------------------------------------------------
-import           Control.Applicative ((<|>))
-import           Data.ByteString (ByteString)
-import           Data.ByteString.Internal (c2w)
-import qualified Data.ByteString as B
-import           Data.Monoid
-import qualified Data.Map as Map
-
-------------------------------------------------------------------------------
-import           Snap.Internal.Http.Types
-import           Snap.Internal.Types
-
-
-------------------------------------------------------------------------------
-{-|
-
-The internal data type you use to build a routing tree.  Matching is
-done unambiguously.
-
-'Capture' and 'Dir' routes can have a "fallback" route:
-
-  - For 'Capture', the fallback is routed when there is nothing to capture
-  - For 'Dir', the fallback is routed when we can't find a route in its map
-
-Fallback routes are stacked: i.e. for a route like:
-
-> Dir [("foo", Capture "bar" (Action bar) NoRoute)] baz
-
-visiting the URI foo/ will result in the "bar" capture being empty and
-triggering its fallback. It's NoRoute, so we go to the nearest parent
-fallback and try that, which is the baz action.
-
--}
-data Route a = Action (Snap a)                        -- wraps a 'Snap' action
-             | Capture ByteString (Route a) (Route a) -- captures the dir in a param
-             | Dir (Map.Map ByteString (Route a)) (Route a)  -- match on a dir
-             | NoRoute
-
-
-------------------------------------------------------------------------------
-instance Monoid (Route a) where
-    mempty = NoRoute
-
-    -- Unions two routes, favoring the right-hand side
-    mappend NoRoute r = r
-
-    mappend l@(Action _) r = case r of
-      (Action _)        -> r
-      (Capture p r' fb) -> Capture p r' (mappend fb l)
-      (Dir _ _)         -> mappend (Dir Map.empty l) r
-      NoRoute           -> l
-
-    mappend l@(Capture p r' fb) r = case r of
-      (Action _)           -> Capture p r' (mappend fb r)
-      (Capture p' r'' fb')
-               | p == p'   -> Capture p (mappend r' r'') (mappend fb fb')
-               | otherwise -> r
-      (Dir rm fb')         -> Dir rm (mappend fb' l)
-      NoRoute              -> l
-
-    mappend l@(Dir rm fb) r = case r of
-      (Action _)      -> Dir rm (mappend fb r)
-      (Capture _ _ _) -> Dir rm (mappend fb r)
-      (Dir rm' fb')   -> Dir (Map.unionWith mappend rm rm') (mappend fb fb')
-      NoRoute         -> l
-
-
-------------------------------------------------------------------------------
--- | A web handler which, given a mapping from URL entry points to web
--- handlers, efficiently routes requests to the correct handler.
---
--- The URL entry points are given as relative paths, for example:
---
--- > route [ ("foo/bar/quux", fooBarQuux) ]
---
--- If the URI of the incoming request is
---
--- > /foo/bar/quux
---
--- or
---
--- > /foo/bar/quux/...anything...
---
--- then the request will be routed to \"@fooBarQuux@\", with 'rqContextPath'
--- set to \"@\/foo\/bar\/quux\/@\" and 'rqPathInfo' set to
--- \"@...anything...@\".
---
--- @FIXME@\/@TODO@: we need a version with and without the context path setting
--- behaviour; if the route is \"@article\/:id\/print@\", we probably want the
--- contextPath to be \"@\/article@\" instead of \"@\/article\/whatever\/print@\".
---
--- A path component within an URL entry point beginning with a colon (\"@:@\")
--- is treated as a /variable capture/; the corresponding path component within
--- the request URI will be entered into the 'rqParams' parameters mapping with
--- the given name. For instance, if the routes were:
---
--- > route [ ("foo/:bar/baz", fooBazHandler) ]
---
--- Then a request for \"@\/foo\/saskatchewan\/baz@\" would be routed to
--- @fooBazHandler@ with a mapping for:
---
--- > "bar" => "saskatchewan"
---
--- in its parameters table.
---
--- Longer paths are matched first, and specific routes are matched before
--- captures. That is, if given routes:
---
--- > [ ("a", h1), ("a/b", h2), ("a/:x", h3) ]
---
--- a request for \"@\/a\/b@\" will go to @h2@, \"@\/a\/s@\" for any /s/ will go
--- to @h3@, and \"@\/a@\" will go to @h1@.
---
--- The following example matches \"@\/article@\" to an article index,
--- \"@\/login@\" to a login, and \"@\/article\/...@\" to an article renderer.
---
--- > route [ ("article",     renderIndex)
--- >       , ("article/:id", renderArticle)
--- >       , ("login",       method POST doLogin) ]
---
-route :: [(ByteString, Snap a)] -> Snap a
-route rts = route' (return ()) rts' []
-  where
-    rts' = mconcat (map pRoute rts)
-
-
-------------------------------------------------------------------------------
--- | The 'routeLocal' function is the same as 'route', except it doesn't change
--- the request's context path. This is useful if you want to route to a
--- particular handler but you want that handler to receive the 'rqPathInfo' as
--- it is.
-routeLocal :: [(ByteString, Snap a)] -> Snap a
-routeLocal rts' = do
-    req    <- getRequest
-    let ctx = rqContextPath req
-    let p   = rqPathInfo req
-    let md  = modifyRequest $ \r -> r {rqContextPath=ctx, rqPathInfo=p}
-
-    route' md rts []   <|>   (md >> pass)
-
-  where
-    rts = mconcat (map pRoute rts')
-
-          
-------------------------------------------------------------------------------
-pRoute :: (ByteString, Snap a) -> Route a
-pRoute (r, a) = foldr f (Action a) hier
-  where
-    hier   = filter (not . B.null) $ B.splitWith (== (c2w '/')) r
-    f s rt = if B.head s == c2w ':'
-        then Capture (B.tail s) rt NoRoute
-        else Dir (Map.fromList [(s, rt)]) NoRoute
-
-
-------------------------------------------------------------------------------
-route' :: Snap ()               -- ^ an action to be run before any user
-                                -- handler
-       -> Route a               -- ^ currently active routing table
-       -> [Route a]             -- ^ list of fallback routing tables in case
-                                -- the current table fails
-       -> Snap a
-route' pre (Action action) _ = pre >> action
-
-route' pre (Capture param rt fb) fbs = do
-    cwd <- getRequest >>= return . B.takeWhile (/= (c2w '/')) . rqPathInfo
-    if B.null cwd
-      then route' pre fb fbs
-      else do localRequest (updateContextPath (B.length cwd) . (f cwd)) $
-                           route' pre rt (fb:fbs)
-  where
-    f v req = req { rqParams = Map.insertWith (++) param [v] (rqParams req) }
-
-route' pre (Dir rtm fb) fbs = do
-    cwd <- getRequest >>= return . B.takeWhile (/= (c2w '/')) . rqPathInfo
-    case Map.lookup cwd rtm of
-      Just rt -> do
-          localRequest (updateContextPath (B.length cwd)) $
-                       route' pre rt (fb:fbs)
-      Nothing -> route' pre fb fbs
-
-route' _ NoRoute       []   = pass
-route' pre NoRoute (fb:fbs) = route' pre fb fbs
-
- diff --git a/static/docs/0.1.2/snap-core/src/Snap-Internal-Types.html b/static/docs/0.1.2/snap-core/src/Snap-Internal-Types.html deleted file mode 100644 index 47a4af5..0000000 --- a/static/docs/0.1.2/snap-core/src/Snap-Internal-Types.html +++ /dev/null @@ -1,529 +0,0 @@ - - - - -src/Snap/Internal/Types.hs - - - -
{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE EmptyDataDecls #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RankNTypes #-}
-
-module Snap.Internal.Types where
-
-------------------------------------------------------------------------------
-import           Control.Applicative
-import           Control.Exception (throwIO, ErrorCall(..))
-import           Control.Monad.CatchIO
-import           Control.Monad.State.Strict
-import           Data.ByteString.Char8 (ByteString)
-import qualified Data.ByteString.Char8 as S
-import qualified Data.ByteString.Lazy.Char8 as L
-import           Data.IORef
-import qualified Data.Iteratee as Iter
-import           Data.Maybe
-import qualified Data.Text as T
-import qualified Data.Text.Encoding as T
-import qualified Data.Text.Lazy as LT
-import qualified Data.Text.Lazy.Encoding as LT
-
-import           Data.Typeable
-
-------------------------------------------------------------------------------
-import           Snap.Iteratee hiding (Enumerator)
-import           Snap.Internal.Http.Types
-
-
-------------------------------------------------------------------------------
--- The Snap Monad
-------------------------------------------------------------------------------
-
-{-|
-
-'Snap' is the 'Monad' that user web handlers run in. 'Snap' gives you:
-
-1. stateful access to fetch or modify an HTTP 'Request'
-
-2. stateful access to fetch or modify an HTTP 'Response'
-
-3. failure \/ 'Alternative' \/ 'MonadPlus' semantics: a 'Snap' handler can
-   choose not to handle a given request, using 'empty' or its synonym 'pass',
-   and you can try alternative handlers with the '<|>' operator:
-
-   > a :: Snap String
-   > a = pass
-   >
-   > b :: Snap String
-   > b = return "foo"
-   >
-   > c :: Snap String
-   > c = a <|> b             -- try running a, if it fails then try b
-
-4. convenience functions ('writeBS', 'writeLBS', 'writeText', 'writeLazyText',
-   'addToOutput') for writing output to the 'Response':
-
-   > a :: (forall a . Enumerator a) -> Snap ()
-   > a someEnumerator = do
-   >     writeBS "I'm a strict bytestring"
-   >     writeLBS "I'm a lazy bytestring"
-   >     addToOutput someEnumerator
-
-5. early termination: if you call 'finishWith':
-
-   > a :: Snap ()
-   > a = do
-   >   modifyResponse $ setResponseStatus 500 "Internal Server Error"
-   >   writeBS "500 error"
-   >   r <- getResponse
-   >   finishWith r
-
-   then any subsequent processing will be skipped and supplied 'Response' value
-   will be returned from 'runSnap' as-is.
-
-6. access to the 'IO' monad through a 'MonadIO' instance:
-
-   > a :: Snap ()
-   > a = liftIO fireTheMissiles
--}
-
-
-------------------------------------------------------------------------------
-newtype Snap a = Snap {
-      unSnap :: StateT SnapState (Iteratee IO) (Maybe (Either Response a))
-}
-
-
-------------------------------------------------------------------------------
-data SnapState = SnapState
-    { _snapRequest  :: Request
-    , _snapResponse :: Response }
-
-
-------------------------------------------------------------------------------
-instance Monad Snap where
-    (Snap m) >>= f =
-        Snap $ do
-            eth <- m
-            maybe (return Nothing)
-                  (either (return . Just . Left)
-                          (unSnap . f))
-                  eth
-
-    return = Snap . return . Just . Right
-    fail   = const $ Snap $ return Nothing
-
-
-------------------------------------------------------------------------------
-instance MonadIO Snap where
-    liftIO m = Snap $ liftM (Just . Right) $ liftIO m
-
-
-------------------------------------------------------------------------------
-instance MonadCatchIO Snap where
-    catch (Snap m) handler = Snap $ do
-        x <- try m
-        case x of
-          (Left e)  -> let (Snap z) = handler e in z
-          (Right y) -> return y
-
-    block (Snap m) = Snap $ block m
-    unblock (Snap m) = Snap $ unblock m
-
-
-------------------------------------------------------------------------------
-instance MonadPlus Snap where
-    mzero = Snap $ return Nothing
-
-    a `mplus` b =
-        Snap $ do
-            mb <- unSnap a
-            if isJust mb then return mb else unSnap b
-
-
-------------------------------------------------------------------------------
-instance Functor Snap where
-    fmap = liftM
-
-
-------------------------------------------------------------------------------
-instance Applicative Snap where
-    pure  = return
-    (<*>) = ap
-
-
-------------------------------------------------------------------------------
-instance Alternative Snap where
-    empty = mzero
-    (<|>) = mplus
-
-
-------------------------------------------------------------------------------
-liftIter :: Iteratee IO a -> Snap a
-liftIter i = Snap (lift i >>= return . Just . Right)
-
-
-------------------------------------------------------------------------------
--- | Sends the request body through an iteratee (data consumer) and
--- returns the result.
-runRequestBody :: Iteratee IO a -> Snap a
-runRequestBody iter = do
-    req  <- getRequest
-    senum <- liftIO $ readIORef $ rqBody req
-    let (SomeEnumerator enum) = senum
-
-    -- make sure the iteratee consumes all of the output
-    let iter' = iter >>= (\a -> Iter.skipToEof >> return a)
-
-    -- run the iteratee
-    result <- liftIter $ Iter.joinIM $ enum iter'
-
-    -- stuff a new dummy enumerator into the request, so you can only try to
-    -- read the request body from the socket once
-    liftIO $ writeIORef (rqBody req)
-                        (SomeEnumerator $ return . Iter.joinI . Iter.take 0 )
-
-    return result
-
-
-------------------------------------------------------------------------------
--- | Returns the request body as a bytestring.
-getRequestBody :: Snap L.ByteString
-getRequestBody = liftM fromWrap $ runRequestBody stream2stream
-{-# INLINE getRequestBody #-}
-
-
-------------------------------------------------------------------------------
--- | Detaches the request body's 'Enumerator' from the 'Request' and
--- returns it. You would want to use this if you needed to send the
--- HTTP request body (transformed or otherwise) through to the output
--- in O(1) space. (Examples: transcoding, \"echo\", etc)
--- 
--- Normally Snap is careful to ensure that the request body is fully
--- consumed after your web handler runs; this function is marked
--- \"unsafe\" because it breaks this guarantee and leaves the
--- responsibility up to you. If you don't fully consume the
--- 'Enumerator' you get here, the next HTTP request in the pipeline
--- (if any) will misparse. Be careful with exception handlers.
-unsafeDetachRequestBody :: Snap (Enumerator a)
-unsafeDetachRequestBody = do
-    req <- getRequest
-    let ioref = rqBody req
-    senum <- liftIO $ readIORef ioref
-    let (SomeEnumerator enum) = senum
-    liftIO $ writeIORef ioref
-               (SomeEnumerator $ return . Iter.joinI . Iter.take 0)
-    return enum
-
-
-------------------------------------------------------------------------------
--- | Short-circuits a 'Snap' monad action early, storing the given
--- 'Response' value in its state.
-finishWith :: Response -> Snap ()
-finishWith = Snap . return . Just . Left
-{-# INLINE finishWith #-}
-
-
-------------------------------------------------------------------------------
--- | Fails out of a 'Snap' monad action.  This is used to indicate
--- that you choose not to handle the given request within the given
--- handler.
-pass :: Snap a
-pass = empty
-
-
-------------------------------------------------------------------------------
--- | Runs a 'Snap' monad action only if the request's HTTP method matches
--- the given method.
-method :: Method -> Snap a -> Snap a
-method m action = do
-    req <- getRequest
-    unless (rqMethod req == m) pass
-    action
-{-# INLINE method #-}
-
-
-------------------------------------------------------------------------------
--- Appends n bytes of the path info to the context path with a
--- trailing slash.
-updateContextPath :: Int -> Request -> Request
-updateContextPath n req | n > 0     = req { rqContextPath = ctx
-                                          , rqPathInfo    = pinfo }
-                        | otherwise = req
-  where
-    ctx'  = S.take n (rqPathInfo req)
-    ctx   = S.concat [rqContextPath req, ctx', "/"]
-    pinfo = S.drop (n+1) (rqPathInfo req)
-
-
-------------------------------------------------------------------------------
--- Runs a 'Snap' monad action only if the 'rqPathInfo' matches the given
--- predicate.
-pathWith :: (ByteString -> ByteString -> Bool)
-         -> ByteString
-         -> Snap a
-         -> Snap a
-pathWith c p action = do
-    req <- getRequest
-    unless (c p (rqPathInfo req)) pass
-    localRequest (updateContextPath $ S.length p) action
-
-
-------------------------------------------------------------------------------
--- | Runs a 'Snap' monad action only when the 'rqPathInfo' of the request
--- starts with the given path. For example,
---
--- > dir "foo" handler
---
--- Will fail if 'rqPathInfo' is not \"@\/foo@\" or \"@\/foo\/...@\", and will
--- add @\"foo\/\"@ to the handler's local 'rqContextPath'.
-dir :: ByteString  -- ^ path component to match
-    -> Snap a      -- ^ handler to run
-    -> Snap a
-dir = pathWith f
-  where
-    f dr pinfo = dr == x
-      where
-        (x,_) = S.break (=='/') pinfo
-{-# INLINE dir #-}
-
-
-------------------------------------------------------------------------------
--- | Runs a 'Snap' monad action only for requests where 'rqPathInfo' is exactly
--- equal to the given string. If the path matches, locally sets 'rqContextPath'
--- to the old value of 'rqPathInfo', sets 'rqPathInfo'=\"\", and runs the given
--- handler.
-path :: ByteString  -- ^ path to match against
-     -> Snap a      -- ^ handler to run
-     -> Snap a
-path = pathWith (==)
-{-# INLINE path #-}
-
-
-------------------------------------------------------------------------------
--- | Runs a 'Snap' monad action only when 'rqPathInfo' is empty.
-ifTop :: Snap a -> Snap a
-ifTop = path ""
-{-# INLINE ifTop #-}
-
-
-------------------------------------------------------------------------------
--- | Local Snap version of 'get'.
-sget :: Snap SnapState
-sget = Snap $ liftM (Just . Right) get
-{-# INLINE sget #-}
-
-
-------------------------------------------------------------------------------
--- | Local Snap monad version of 'modify'.
-smodify :: (SnapState -> SnapState) -> Snap ()
-smodify f = Snap $ modify f >> return (Just $ Right ())
-{-# INLINE smodify #-}
-
-
-------------------------------------------------------------------------------
--- | Grabs the 'Request' object out of the 'Snap' monad.
-getRequest :: Snap Request
-getRequest = liftM _snapRequest sget
-{-# INLINE getRequest #-}
-
-
-------------------------------------------------------------------------------
--- | Grabs the 'Response' object out of the 'Snap' monad.
-getResponse :: Snap Response
-getResponse = liftM _snapResponse sget
-{-# INLINE getResponse #-}
-
-
-------------------------------------------------------------------------------
--- | Puts a new 'Response' object into the 'Snap' monad.
-putResponse :: Response -> Snap ()
-putResponse r = smodify $ \ss -> ss { _snapResponse = r }
-{-# INLINE putResponse #-}
-
-
-------------------------------------------------------------------------------
--- | Puts a new 'Request' object into the 'Snap' monad.
-putRequest :: Request -> Snap ()
-putRequest r = smodify $ \ss -> ss { _snapRequest = r }
-{-# INLINE putRequest #-}
-
-
-------------------------------------------------------------------------------
--- | Modifies the 'Request' object stored in a 'Snap' monad.
-modifyRequest :: (Request -> Request) -> Snap ()
-modifyRequest f = smodify $ \ss -> ss { _snapRequest = f $ _snapRequest ss }
-{-# INLINE modifyRequest #-}
-
-
-------------------------------------------------------------------------------
--- | Modifes the 'Response' object stored in a 'Snap' monad.
-modifyResponse :: (Response -> Response) -> Snap () 
-modifyResponse f = smodify $ \ss -> ss { _snapResponse = f $ _snapResponse ss }
-{-# INLINE modifyResponse #-}
-
-
-------------------------------------------------------------------------------
--- | Adds the output from the given enumerator to the 'Response'
--- stored in the 'Snap' monad state.
-addToOutput :: (forall a . Enumerator a)   -- ^ output to add
-            -> Snap ()
-addToOutput enum = modifyResponse $ modifyResponseBody (>. enum)
-
-
-------------------------------------------------------------------------------
--- | Adds the given strict 'ByteString' to the body of the 'Response' stored in
--- the 'Snap' monad state.
-writeBS :: ByteString -> Snap ()
-writeBS s = addToOutput $ enumBS s
-
-
-------------------------------------------------------------------------------
--- | Adds the given lazy 'L.ByteString' to the body of the 'Response' stored in
--- the 'Snap' monad state.
-writeLBS :: L.ByteString -> Snap ()
-writeLBS s = addToOutput $ enumLBS s
-
-
-------------------------------------------------------------------------------
--- | Adds the given strict 'T.Text' to the body of the 'Response' stored in the
--- 'Snap' monad state.
-writeText :: T.Text -> Snap ()
-writeText s = writeBS $ T.encodeUtf8 s
-
-
-------------------------------------------------------------------------------
--- | Adds the given lazy 'LT.Text' to the body of the 'Response' stored in the
--- 'Snap' monad state.
-writeLazyText :: LT.Text -> Snap ()
-writeLazyText s = writeLBS $ LT.encodeUtf8 s
-
-
-------------------------------------------------------------------------------
--- | Sets the output to be the contents of the specified file.
---
--- Calling 'sendFile' will overwrite any output queued to be sent in the
--- 'Response'. If the response body is not modified after the call to
--- 'sendFile', Snap will use the efficient @sendfile()@ system call on
--- platforms that support it.
---
--- If the response body is modified (using 'modifyResponseBody'), the file will
--- be read using @mmap()@.
-sendFile :: FilePath -> Snap ()
-sendFile f = modifyResponse $ \r -> r { rspBody = SendFile f }
-
-
-------------------------------------------------------------------------------
--- | Runs a 'Snap' action with a locally-modified 'Request' state
--- object. The 'Request' object in the Snap monad state after the call
--- to localRequest will be unchanged.
-localRequest :: (Request -> Request) -> Snap a -> Snap a
-localRequest f m = do
-    req <- getRequest
-
-    runAct req <|> (putRequest req >> pass)
-
-  where
-    runAct req = do
-        modifyRequest f
-        result <- m
-        putRequest req
-        return result
-{-# INLINE localRequest #-}
-
-
-------------------------------------------------------------------------------
--- | Fetches the 'Request' from state and hands it to the given action.
-withRequest :: (Request -> Snap a) -> Snap a
-withRequest = (getRequest >>=)
-{-# INLINE withRequest #-}
-
-
-------------------------------------------------------------------------------
--- | Fetches the 'Response' from state and hands it to the given action.
-withResponse :: (Response -> Snap a) -> Snap a
-withResponse = (getResponse >>=)
-{-# INLINE withResponse #-}
-
-
-------------------------------------------------------------------------------
--- | This exception is thrown if the handler you supply to 'runSnap' fails.
-data NoHandlerException = NoHandlerException
-   deriving (Eq, Typeable)
-
-
-------------------------------------------------------------------------------
-instance Show NoHandlerException where
-    show NoHandlerException = "No handler for request"
-
-
-------------------------------------------------------------------------------
-instance Exception NoHandlerException
-
-
-------------------------------------------------------------------------------
--- | Runs a 'Snap' monad action in the 'Iteratee IO' monad.
-runSnap :: Snap a -> Request -> Iteratee IO (Request,Response)
-runSnap (Snap m) req = do
-    (r, ss') <- runStateT m ss
-
-    e <- maybe (return $ Left fourohfour)
-               return
-               r
-
-    -- is this a case of early termination?
-    let resp = case e of 
-                 Left x  -> x
-                 Right _ -> _snapResponse ss'
-
-    return (_snapRequest ss', resp)
-
-  where
-    fourohfour = setContentLength 3 $
-                 setResponseStatus 404 "Not Found" $
-                 modifyResponseBody (>. enumBS "404") $
-                 emptyResponse
-
-    dresp = emptyResponse { rspHttpVersion = rqVersion req }
-
-    ss = SnapState req dresp
-{-# INLINE runSnap #-}
-
-
-------------------------------------------------------------------------------
-evalSnap :: Snap a -> Request -> Iteratee IO a
-evalSnap (Snap m) req = do
-    (r, _) <- runStateT m ss
-
-    e <- maybe (liftIO $ throwIO NoHandlerException)
-               return
-               r
-
-    -- is this a case of early termination?
-    case e of 
-      Left _  -> liftIO $ throwIO $ ErrorCall "no value"
-      Right x -> return x
-  where
-    dresp = emptyResponse { rspHttpVersion = rqVersion req }
-    ss = SnapState req dresp
-{-# INLINE evalSnap #-}
-
-
-
-------------------------------------------------------------------------------
--- | See 'rqParam'. Looks up a value for the given named parameter in the
--- 'Request'. If more than one value was entered for the given parameter name,
--- 'getParam' gloms the values together with:
---
--- @    'S.intercalate' \" \"@
---
-getParam :: ByteString          -- ^ parameter name to look up
-         -> Snap (Maybe ByteString)
-getParam k = do
-    rq <- getRequest
-    return $ liftM (S.intercalate " ") $ rqParam k rq
-
-
-
- diff --git a/static/docs/0.1.2/snap-core/src/Snap-Iteratee.html b/static/docs/0.1.2/snap-core/src/Snap-Iteratee.html deleted file mode 100644 index 0aecc98..0000000 --- a/static/docs/0.1.2/snap-core/src/Snap-Iteratee.html +++ /dev/null @@ -1,267 +0,0 @@ - - - - -src/Snap/Iteratee.hs - - - -
{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE TypeSynonymInstances #-}
-
--- | Snap Framework type aliases and utilities for iteratees. Note that as a
--- convenience, this module also exports everything from @Data.Iteratee@ in the
--- @iteratee@ library.
---
--- /WARNING/: Note that all of these types are scheduled to change in the
--- @darcs@ head version of the @iteratee@ library; John Lato et al. are working
--- on a much improved iteratee formulation.
-
-module Snap.Iteratee
-  ( -- * Convenience aliases around types from @Data.Iteratee@
-    Stream
-  , IterV
-  , Iteratee
-  , Enumerator
-
-    -- * Re-export types and functions from @Data.Iteratee@
-  , module Data.Iteratee
-
-    -- * Helper functions
-
-    -- ** Enumerators
-  , enumBS
-  , enumLBS
-  , enumFile
-
-    -- ** Conversion to/from 'WrappedByteString'
-  , fromWrap
-  , toWrap
-
-    -- ** Iteratee utilities
-  , takeExactly
-  , takeNoMoreThan
-  , countBytes
-  , bufferIteratee
-  ) where
-
-------------------------------------------------------------------------------
-import           Control.Exception (SomeException)
-import           Control.Monad
-import           Control.Monad.CatchIO
-import           Data.ByteString (ByteString)
-import qualified Data.ByteString as S
-import qualified Data.ByteString.Lazy as L
-import           Data.Iteratee
-import qualified Data.Iteratee.Base.StreamChunk as SC
-import           Data.Iteratee.WrappedByteString
-import           Data.Monoid (mappend)
-import           Data.Word (Word8)
-import           Prelude hiding (catch,drop)
-import           System.IO.Posix.MMap
-import qualified Data.DList as D
-------------------------------------------------------------------------------
-
-type Stream         = StreamG WrappedByteString Word8
-type IterV      m   = IterGV WrappedByteString Word8 m
-type Iteratee   m   = IterateeG WrappedByteString Word8 m
-type Enumerator m a = Iteratee m a -> m (Iteratee m a)
-
-
-------------------------------------------------------------------------------
-instance (Functor m, MonadCatchIO m) =>
-         MonadCatchIO (IterateeG s el m) where
-    --catch  :: Exception  e => m a -> (e -> m a) -> m a
-    catch m handler = IterateeG $ \str -> do
-        ee <- try $ runIter m str
-        case ee of 
-          (Left e)  -> runIter (handler e) str
-          (Right v) -> return v
-
-    --block :: m a -> m a        
-    block m = IterateeG $ \str -> block $ runIter m str
-    unblock m = IterateeG $ \str -> unblock $ runIter m str
-
-
-------------------------------------------------------------------------------
--- | Wraps an 'Iteratee', counting the number of bytes consumed by it.
-countBytes :: (Monad m) => Iteratee m a -> Iteratee m (a, Int)
-countBytes = go 0
-  where
-    go !n iter = IterateeG $ f n iter
-
-    f !n !iter ch@(Chunk ws) = do
-        iterv <- runIter iter ch
-        case iterv of
-          Done x rest -> let !n' = n + m - len rest
-                         in return $! Done (x, n') rest
-          Cont i err  -> return $ Cont ((go $! n + m) i) err
-      where
-        m = S.length $ unWrap ws
-
-        len (EOF _) = 0
-        len (Chunk s) = S.length $ unWrap s
-
-    f !n !iter stream = do
-        iterv <- runIter iter stream
-        case iterv of
-          Done x rest -> return $ Done (x, n) rest
-          Cont i err  -> return $ Cont (go n i) err
-
-
-------------------------------------------------------------------------------
--- | Buffers an iteratee.
---
--- Our enumerators produce a lot of little strings; rather than spending all
--- our time doing kernel context switches for 4-byte write() calls, we buffer
--- the iteratee to send 2KB at a time.
-bufferIteratee :: (Monad m) => Enumerator m a
-bufferIteratee = return . go (D.empty,0)
-  where
-    blocksize = 2048
-
-    --go :: (DList ByteString, Int) -> Iteratee m a -> Iteratee m a
-    go (!dl,!n) iter = IterateeG $! f (dl,n) iter
-
-    --f :: (DList ByteString, Int) -> Iteratee m a -> Stream -> m (IterV m a)
-    f _      !iter ch@(EOF (Just _)) = runIter iter ch
-    f (!dl,_) !iter ch@(EOF Nothing) = do
-        iterv <- runIter iter $ Chunk big
-        case iterv of
-          Done x rest     -> return $ Done x rest
-          Cont i (Just e) -> return $ Cont i (Just e)
-          Cont i Nothing  -> runIter i ch
-      where
-        big = toWrap $ L.fromChunks [S.concat $ D.toList dl]
-        
-    f (!dl,!n) iter (Chunk ws) =
-        if n' > blocksize
-           then do
-               iterv <- runIter iter (Chunk big)
-               case iterv of
-                  Done x rest     -> return $ Done x rest
-                  Cont i (Just e) -> return $ Cont i (Just e)
-                  Cont i Nothing  -> return $ Cont (go (D.empty,0) i) Nothing
-           else return $ Cont (go (dl',n') iter) Nothing
-      where
-        s   = S.concat $ L.toChunks $ fromWrap ws
-        m   = S.length s
-        n'  = n+m
-        dl' = D.snoc dl s
-        big = toWrap $ L.fromChunks [S.concat $ D.toList dl']
-        
-
-------------------------------------------------------------------------------
--- | Enumerates a strict bytestring.
-enumBS :: (Monad m) => ByteString -> Enumerator m a
-enumBS bs = enumPure1Chunk $ WrapBS bs
-{-# INLINE enumBS #-}
-
-
-------------------------------------------------------------------------------
--- | Enumerates a lazy bytestring.
-enumLBS :: (Monad m) => L.ByteString -> Enumerator m a
-enumLBS lbs iter = foldM k iter enums
-  where
-    enums = map (enumPure1Chunk . WrapBS) $ L.toChunks lbs
-    k i e = e i
-
-
-------------------------------------------------------------------------------
--- | Converts a lazy bytestring to a wrapped bytestring.
-toWrap :: L.ByteString -> WrappedByteString Word8
-toWrap = WrapBS . S.concat . L.toChunks
-{-# INLINE toWrap #-}
-
-
-------------------------------------------------------------------------------
--- | Converts a wrapped bytestring to a lazy bytestring.
-fromWrap :: WrappedByteString Word8 -> L.ByteString
-fromWrap = L.fromChunks . (:[]) . unWrap
-{-# INLINE fromWrap #-}
-
-
-------------------------------------------------------------------------------
--- | Reads n elements from a stream and applies the given iteratee to
--- the stream of the read elements. Reads exactly n elements, and if
--- the stream is short propagates an error.
-takeExactly :: (SC.StreamChunk s el, Monad m) =>
-               Int ->
-               EnumeratorN s el s el m a
-takeExactly 0 iter = return iter
-takeExactly n' iter =
-    if n' < 0
-      then takeExactly 0 iter
-      else IterateeG (step n')
-  where
-  step n chk@(Chunk str)
-    | SC.null str = return $ Cont (takeExactly n iter) Nothing
-    | SC.length str < n = liftM (flip Cont Nothing) inner
-      where inner = liftM (check (n - SC.length str)) (runIter iter chk)
-  step n (Chunk str) = done (Chunk s1) (Chunk s2)
-    where (s1, s2) = SC.splitAt n str
-  step _n (EOF (Just e))    = return $ Cont undefined (Just e)
-  step _n (EOF Nothing)     = return $ Cont undefined (Just (Err "short write"))
-  check n (Done x _)        = drop n >> return (return x)
-  check n (Cont x Nothing)  = takeExactly n x
-  check n (Cont _ (Just e)) = drop n >> throwErr e
-  done s1 s2 = liftM (flip Done s2) (runIter iter s1 >>= checkIfDone return)
-
-
-------------------------------------------------------------------------------
--- | Reads up to n elements from a stream and applies the given iteratee to the
--- stream of the read elements. If more than n elements are read, propagates an
--- error.
-takeNoMoreThan :: (SC.StreamChunk s el, Monad m) =>
-                  Int ->
-                  EnumeratorN s el s el m a
-takeNoMoreThan n' iter =
-    if n' < 0
-      then takeNoMoreThan 0 iter
-      else IterateeG (step n')
-  where
-    step n chk@(Chunk str)
-      | SC.null str = return $ Cont (takeNoMoreThan n iter) Nothing
-      | SC.length str < n = liftM (flip Cont Nothing) inner
-      | otherwise = done (Chunk s1) (Chunk s2)
-          where inner    = liftM (check (n - SC.length str)) (runIter iter chk)
-                (s1, s2) = SC.splitAt n str
-
-    step _n (EOF (Just e))    = return $ Cont undefined (Just e)
-    step _n chk@(EOF Nothing) = do
-        v  <- runIter iter chk
-
-        case v of
-          (Done x s)        -> return $ Done (return x) s
-          (Cont _ (Just e)) -> return $ Cont undefined (Just e)
-          (Cont _ Nothing)  -> return $ Cont (throwErr $ Err "premature EOF") Nothing
-
-    check _ v@(Done _ _)      = return $ liftI v
-    check n (Cont x Nothing)  = takeNoMoreThan n x
-    check _ (Cont _ (Just e)) = throwErr e
-
-    done _ (EOF _) = error "impossible"
-    done s1 s2@(Chunk s2') = do
-        v <- runIter iter s1
-        case v of
-          (Done x s')       -> return $ Done (return x) (s' `mappend` s2)
-          (Cont _ (Just e)) -> return $ Cont undefined (Just e)
-          (Cont i Nothing)  ->
-              if SC.null s2'
-                then return $ Cont (takeNoMoreThan 0 i) Nothing
-                else return $ Cont undefined (Just $ Err "too many bytes")
-
-
-------------------------------------------------------------------------------
-enumFile :: FilePath -> Iteratee IO a -> IO (Iteratee IO a)
-enumFile fp iter = do
-    es <- (try $
-           liftM WrapBS $
-           unsafeMMapFile fp) :: IO (Either SomeException (WrappedByteString Word8))
-    
-    case es of
-      (Left e)  -> return $ throwErr $ Err $ "IO error" ++ show e
-      (Right s) -> liftM liftI $ runIter iter $ Chunk s
-
- diff --git a/static/docs/0.1.2/snap-core/src/Snap-Types.html b/static/docs/0.1.2/snap-core/src/Snap-Types.html deleted file mode 100644 index 69d5c03..0000000 --- a/static/docs/0.1.2/snap-core/src/Snap-Types.html +++ /dev/null @@ -1,127 +0,0 @@ - - - - -src/Snap/Types.hs - - - -
{-|
-
-This module contains the core type definitions, class instances, and functions
-for HTTP as well as the 'Snap' monad, which is used for web handlers.
-
--}
-module Snap.Types
-  ( 
-    -- * The Snap Monad
-    Snap
-  , runSnap
-  , NoHandlerException(..)
-
-    -- ** Functions for control flow and early termination
-  , finishWith
-  , pass
-
-    -- ** Routing
-  , method
-  , path
-  , dir
-  , ifTop
-  , route
-  , routeLocal
-
-    -- ** Access to state
-  , getRequest
-  , getResponse
-  , putRequest
-  , putResponse
-  , modifyRequest
-  , modifyResponse
-  , localRequest
-  , withRequest
-  , withResponse
-
-    -- ** Grabbing request bodies
-  , runRequestBody
-  , getRequestBody
-  , unsafeDetachRequestBody
-    -- * HTTP Datatypes and Functions
-    -- $httpDoc
-    --
-  , Request
-  , Response
-  , Headers
-  , HasHeaders(..)
-  , Params
-  , Method(..)
-  , Cookie(..)
-  , HttpVersion
-
-    -- ** Headers
-  , addHeader
-  , setHeader
-  , getHeader
-
-    -- ** Requests
-  , rqServerName
-  , rqServerPort
-  , rqRemoteAddr
-  , rqRemotePort
-  , rqLocalAddr
-  , rqLocalHostname
-  , rqIsSecure
-  , rqContentLength
-  , rqMethod
-  , rqVersion
-  , rqCookies
-  , rqPathInfo
-  , rqContextPath
-  , rqURI
-  , rqQueryString
-  , rqParams
-  , rqParam
-  , getParam
-  , rqModifyParams
-  , rqSetParam
-
-    -- ** Responses
-  , emptyResponse
-  , setResponseStatus
-  , rspStatus
-  , rspStatusReason
-  , setContentType
-  , addCookie
-  , setContentLength
-  , clearContentLength
-
-    -- *** Response I/O
-  , setResponseBody
-  , modifyResponseBody
-  , addToOutput
-  , writeBS
-  , writeLazyText
-  , writeText
-  , writeLBS
-  , sendFile
-
-    -- * Iteratee
-  , Enumerator
-
-    -- * HTTP utilities
-  , formatHttpTime
-  , parseHttpTime 
-  , urlEncode
-  , urlDecode
-  ) where
-
-------------------------------------------------------------------------------
-import           Snap.Internal.Http.Types
-import           Snap.Internal.Routing
-import           Snap.Internal.Types
-------------------------------------------------------------------------------
-
--- $httpDoc
--- HTTP-related datatypes: 'Request', 'Response', 'Cookie', etc.
-
- diff --git a/static/docs/0.1.2/snap-core/src/Snap-Util-FileServe.html b/static/docs/0.1.2/snap-core/src/Snap-Util-FileServe.html deleted file mode 100644 index 38c9a3f..0000000 --- a/static/docs/0.1.2/snap-core/src/Snap-Util-FileServe.html +++ /dev/null @@ -1,273 +0,0 @@ - - - - -src/Snap/Util/FileServe.hs - - - -
{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
--- | Contains web handlers to serve files from a directory.
-module Snap.Util.FileServe
-(
-  getSafePath
-, fileServe
-, fileServe'
-, fileServeSingle
-, fileServeSingle'
-, defaultMimeTypes
-, MimeMap
-) where
-
-------------------------------------------------------------------------------
-import           Control.Monad
-import           Control.Monad.Trans
-import qualified Data.ByteString.Char8 as S
-import           Data.ByteString.Char8 (ByteString)
-import           Data.Map (Map)
-import qualified Data.Map as Map
-import           Data.Maybe (fromMaybe)
-import           System.Directory
-import           System.FilePath
-import           System.Posix.Files
-
-------------------------------------------------------------------------------
-import           Snap.Types
-
-
-------------------------------------------------------------------------------
--- | A type alias for MIME type 
-type MimeMap = Map FilePath ByteString
-
-
-------------------------------------------------------------------------------
--- | The default set of mime type mappings we use when serving files. Its
--- value:
---
--- > Map.fromList [
--- >   ( ".asc"     , "text/plain"                        ),
--- >   ( ".asf"     , "video/x-ms-asf"                    ),
--- >   ( ".asx"     , "video/x-ms-asf"                    ),
--- >   ( ".avi"     , "video/x-msvideo"                   ),
--- >   ( ".bz2"     , "application/x-bzip"                ),
--- >   ( ".c"       , "text/plain"                        ),
--- >   ( ".class"   , "application/octet-stream"          ),
--- >   ( ".conf"    , "text/plain"                        ),
--- >   ( ".cpp"     , "text/plain"                        ),
--- >   ( ".css"     , "text/css"                          ),
--- >   ( ".cxx"     , "text/plain"                        ),
--- >   ( ".dtd"     , "text/xml"                          ),
--- >   ( ".dvi"     , "application/x-dvi"                 ),
--- >   ( ".gif"     , "image/gif"                         ),
--- >   ( ".gz"      , "application/x-gzip"                ),
--- >   ( ".hs"      , "text/plain"                        ),
--- >   ( ".htm"     , "text/html"                         ),
--- >   ( ".html"    , "text/html"                         ),
--- >   ( ".jar"     , "application/x-java-archive"        ),
--- >   ( ".jpeg"    , "image/jpeg"                        ),
--- >   ( ".jpg"     , "image/jpeg"                        ),
--- >   ( ".js"      , "text/javascript"                   ),
--- >   ( ".log"     , "text/plain"                        ),
--- >   ( ".m3u"     , "audio/x-mpegurl"                   ),
--- >   ( ".mov"     , "video/quicktime"                   ),
--- >   ( ".mp3"     , "audio/mpeg"                        ),
--- >   ( ".mpeg"    , "video/mpeg"                        ),
--- >   ( ".mpg"     , "video/mpeg"                        ),
--- >   ( ".ogg"     , "application/ogg"                   ),
--- >   ( ".pac"     , "application/x-ns-proxy-autoconfig" ),
--- >   ( ".pdf"     , "application/pdf"                   ),
--- >   ( ".png"     , "image/png"                         ),
--- >   ( ".ps"      , "application/postscript"            ),
--- >   ( ".qt"      , "video/quicktime"                   ),
--- >   ( ".sig"     , "application/pgp-signature"         ),
--- >   ( ".spl"     , "application/futuresplash"          ),
--- >   ( ".swf"     , "application/x-shockwave-flash"     ),
--- >   ( ".tar"     , "application/x-tar"                 ),
--- >   ( ".tar.bz2" , "application/x-bzip-compressed-tar" ),
--- >   ( ".tar.gz"  , "application/x-tgz"                 ),
--- >   ( ".tbz"     , "application/x-bzip-compressed-tar" ),
--- >   ( ".text"    , "text/plain"                        ),
--- >   ( ".tgz"     , "application/x-tgz"                 ),
--- >   ( ".torrent" , "application/x-bittorrent"          ),
--- >   ( ".txt"     , "text/plain"                        ),
--- >   ( ".wav"     , "audio/x-wav"                       ),
--- >   ( ".wax"     , "audio/x-ms-wax"                    ),
--- >   ( ".wma"     , "audio/x-ms-wma"                    ),
--- >   ( ".wmv"     , "video/x-ms-wmv"                    ),
--- >   ( ".xbm"     , "image/x-xbitmap"                   ),
--- >   ( ".xml"     , "text/xml"                          ),
--- >   ( ".xpm"     , "image/x-xpixmap"                   ),
--- >   ( ".xwd"     , "image/x-xwindowdump"               ),
--- >   ( ".zip"     , "application/zip"                   ) ]
---
-defaultMimeTypes :: MimeMap
-defaultMimeTypes = Map.fromList [
-  ( ".asc"     , "text/plain"                        ),
-  ( ".asf"     , "video/x-ms-asf"                    ),
-  ( ".asx"     , "video/x-ms-asf"                    ),
-  ( ".avi"     , "video/x-msvideo"                   ),
-  ( ".bz2"     , "application/x-bzip"                ),
-  ( ".c"       , "text/plain"                        ),
-  ( ".class"   , "application/octet-stream"          ),
-  ( ".conf"    , "text/plain"                        ),
-  ( ".cpp"     , "text/plain"                        ),
-  ( ".css"     , "text/css"                          ),
-  ( ".cxx"     , "text/plain"                        ),
-  ( ".dtd"     , "text/xml"                          ),
-  ( ".dvi"     , "application/x-dvi"                 ),
-  ( ".gif"     , "image/gif"                         ),
-  ( ".gz"      , "application/x-gzip"                ),
-  ( ".hs"      , "text/plain"                        ),
-  ( ".htm"     , "text/html"                         ),
-  ( ".html"    , "text/html"                         ),
-  ( ".jar"     , "application/x-java-archive"        ),
-  ( ".jpeg"    , "image/jpeg"                        ),
-  ( ".jpg"     , "image/jpeg"                        ),
-  ( ".js"      , "text/javascript"                   ),
-  ( ".log"     , "text/plain"                        ),
-  ( ".m3u"     , "audio/x-mpegurl"                   ),
-  ( ".mov"     , "video/quicktime"                   ),
-  ( ".mp3"     , "audio/mpeg"                        ),
-  ( ".mpeg"    , "video/mpeg"                        ),
-  ( ".mpg"     , "video/mpeg"                        ),
-  ( ".ogg"     , "application/ogg"                   ),
-  ( ".pac"     , "application/x-ns-proxy-autoconfig" ),
-  ( ".pdf"     , "application/pdf"                   ),
-  ( ".png"     , "image/png"                         ),
-  ( ".ps"      , "application/postscript"            ),
-  ( ".qt"      , "video/quicktime"                   ),
-  ( ".sig"     , "application/pgp-signature"         ),
-  ( ".spl"     , "application/futuresplash"          ),
-  ( ".swf"     , "application/x-shockwave-flash"     ),
-  ( ".tar"     , "application/x-tar"                 ),
-  ( ".tar.bz2" , "application/x-bzip-compressed-tar" ),
-  ( ".tar.gz"  , "application/x-tgz"                 ),
-  ( ".tbz"     , "application/x-bzip-compressed-tar" ),
-  ( ".text"    , "text/plain"                        ),
-  ( ".tgz"     , "application/x-tgz"                 ),
-  ( ".torrent" , "application/x-bittorrent"          ),
-  ( ".ttf"     , "application/x-font-truetype"       ),
-  ( ".txt"     , "text/plain"                        ),
-  ( ".wav"     , "audio/x-wav"                       ),
-  ( ".wax"     , "audio/x-ms-wax"                    ),
-  ( ".wma"     , "audio/x-ms-wma"                    ),
-  ( ".wmv"     , "video/x-ms-wmv"                    ),
-  ( ".xbm"     , "image/x-xbitmap"                   ),
-  ( ".xml"     , "text/xml"                          ),
-  ( ".xpm"     , "image/x-xpixmap"                   ),
-  ( ".xwd"     , "image/x-xwindowdump"               ),
-  ( ".zip"     , "application/zip"                   ) ]
-
-------------------------------------------------------------------------------
--- | Gets a path from the 'Request' using 'rqPathInfo' and makes sure it is
--- safe to use for opening files.  A path is safe if it is a relative path
--- and has no ".." elements to escape the intended directory structure.
-getSafePath :: Snap FilePath
-getSafePath = do
-    req <- getRequest
-    let p = S.unpack $ rqPathInfo req
-
-    -- check that we don't have any sneaky .. paths
-    let dirs = splitDirectories p
-    when (elem ".." dirs) pass
-    return p
-
-
-------------------------------------------------------------------------------
--- | Serves files out of the given directory. The relative path given in
--- 'rqPathInfo' is searched for the given file, and the file is served with the
--- appropriate mime type if it is found. Absolute paths and \"@..@\" are prohibited
--- to prevent files from being served from outside the sandbox.
---
--- Uses 'defaultMimeTypes' to determine the @Content-Type@ based on the file's
--- extension.
-fileServe :: FilePath  -- ^ root directory
-          -> Snap ()
-fileServe = fileServe' defaultMimeTypes
-{-# INLINE fileServe #-}
-
-
-------------------------------------------------------------------------------
--- | Same as 'fileServe', with control over the MIME mapping used.
-fileServe' :: MimeMap           -- ^ MIME type mapping
-           -> FilePath          -- ^ root directory
-           -> Snap ()
-fileServe' mm root = do
-    sp <- getSafePath
-    let fp   = root </> sp
-
-    -- check that the file exists
-    liftIO (doesFileExist fp) >>= flip unless pass
-
-    let fn   = takeFileName fp
-    let mime = fileType mm fn
-    fileServeSingle' mime fp
-{-# INLINE fileServe' #-}
-
-
-------------------------------------------------------------------------------
--- | Serves a single file specified by a full or relative path.  The
--- path restrictions on fileServe don't apply to this function since
--- the path is not being supplied by the user.
-fileServeSingle :: FilePath          -- ^ path to file
-                -> Snap ()
-fileServeSingle fp =
-    fileServeSingle' (fileType defaultMimeTypes (takeFileName fp)) fp
-{-# INLINE fileServeSingle #-}
-
-
-------------------------------------------------------------------------------
--- | Same as 'fileServeSingle', with control over the MIME mapping used.
-fileServeSingle' :: ByteString        -- ^ MIME type mapping
-                 -> FilePath          -- ^ path to file
-                 -> Snap ()
-fileServeSingle' mime fp = do
-    req <- getRequest
-    
-    let mbH = getHeader "if-modified-since" req
-    mbIfModified <- liftIO $ case mbH of
-                               Nothing  -> return Nothing
-                               (Just s) -> liftM Just $ parseHttpTime s
-
-    -- check modification time and bug out early if the file is not modified.
-    filestat <- liftIO $ getFileStatus fp
-    let mt = modificationTime filestat
-    maybe (return ()) (chkModificationTime mt) mbIfModified
-
-    let sz = fromEnum $ fileSize filestat
-    lm <- liftIO $ formatHttpTime mt
-
-    modifyResponse $ setHeader "Last-Modified" lm
-                   . setContentType mime
-                   . setContentLength sz
-    sendFile fp
-
-  where
-    --------------------------------------------------------------------------
-    chkModificationTime mt lt = when (mt <= lt) notModified
-
-    --------------------------------------------------------------------------
-    notModified = finishWith $
-                  setResponseStatus 304 "Not Modified" emptyResponse
-
-
-------------------------------------------------------------------------------
-fileType :: MimeMap -> FilePath -> ByteString
-fileType mm f =
-    if null ext
-      then defaultMimeType
-      else fromMaybe (fileType mm (drop 1 ext))
-                     mbe
-
-  where
-    ext             = takeExtensions f
-    mbe             = Map.lookup ext mm
-
-
-------------------------------------------------------------------------------
-defaultMimeType :: ByteString
-defaultMimeType = "application/octet-stream"
-
- diff --git a/static/docs/0.1.2/snap-core/src/Snap-Util-GZip.html b/static/docs/0.1.2/snap-core/src/Snap-Util-GZip.html deleted file mode 100644 index 6119f1d..0000000 --- a/static/docs/0.1.2/snap-core/src/Snap-Util-GZip.html +++ /dev/null @@ -1,341 +0,0 @@ - - - - -src/Snap/Util/GZip.hs - - - -
{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE ExistentialQuantification #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module Snap.Util.GZip
-( withCompression
-, withCompression' ) where
-
-import qualified Codec.Compression.GZip as GZip
-import qualified Codec.Compression.Zlib as Zlib
-import           Control.Concurrent
-import           Control.Applicative hiding (many)
-import           Control.Exception
-import           Control.Monad
-import           Control.Monad.Trans
-import           Data.Attoparsec.Char8 hiding (Done)
-import qualified Data.Attoparsec.Char8 as Atto
-import qualified Data.ByteString.Lazy.Char8 as L
-import           Data.ByteString.Char8 (ByteString)
-import           Data.Iteratee.WrappedByteString
-import           Data.Maybe
-import qualified Data.Set as Set
-import           Data.Set (Set)
-import           Data.Typeable
-import           Prelude hiding (catch, takeWhile)
-
-------------------------------------------------------------------------------
-import           Snap.Internal.Debug
-import           Snap.Iteratee hiding (Enumerator)
-import           Snap.Types
-
-
-------------------------------------------------------------------------------
--- | Runs a 'Snap' web handler with compression if available.
---
--- If the client has indicated support for @gzip@ or @compress@ in its
--- @Accept-Encoding@ header, and the @Content-Type@ in the response is one of
--- the following types:
---
---   * @application/x-javascript@
---
---   * @text/css@
---
---   * @text/html@
---
---   * @text/javascript@
---
---   * @text/plain@
---
---   * @text/xml@
---
---   * @application/x-font-truetype@
---
--- Then the given handler's output stream will be compressed,
--- @Content-Encoding@ will be set in the output headers, and the
--- @Content-Length@ will be cleared if it was set. (We can't process the stream
--- in O(1) space if the length is known beforehand.)
---
--- The wrapped handler will be run to completion, and then the 'Response'
--- that's contained within the 'Snap' monad state will be passed to
--- 'finishWith' to prevent further processing.
---
-withCompression :: Snap a   -- ^ the web handler to run
-                -> Snap ()
-withCompression = withCompression' compressibleMimeTypes
-
-
-------------------------------------------------------------------------------
--- | The same as 'withCompression', with control over which MIME types to
--- compress.
-withCompression' :: Set ByteString
-                    -- ^ set of compressible MIME types
-                 -> Snap a
-                    -- ^ the web handler to run
-                 -> Snap ()
-withCompression' mimeTable action = do
-    _    <- action
-    resp <- getResponse
-
-    -- If a content-encoding is already set, do nothing. This prevents
-    -- "withCompression $ withCompression m" from ruining your day.
-    if isJust $ getHeader "Content-Encoding" resp
-       then return ()
-       else do
-           let mbCt = getHeader "Content-Type" resp
-
-           debug $ "withCompression', content-type is " ++ show mbCt
-
-           case mbCt of
-             (Just ct) -> if Set.member ct mimeTable
-                             then chkAcceptEncoding
-                             else return ()
-             _         -> return ()
-
-
-    getResponse >>= finishWith
-
-  where
-    chkAcceptEncoding :: Snap ()
-    chkAcceptEncoding = do
-        req <- getRequest
-        debug $ "checking accept-encoding"
-        let mbAcc = getHeader "Accept-Encoding" req
-        debug $ "accept-encoding is " ++ show mbAcc
-        let s = fromMaybe "" mbAcc
-
-        types <- liftIO $ parseAcceptEncoding s
-
-        chooseType types
-
-
-    chooseType []               = return ()
-    chooseType ("gzip":_)       = gzipCompression
-    chooseType ("compress":_)   = compressCompression
-    chooseType ("x-gzip":_)     = gzipCompression
-    chooseType ("x-compress":_) = compressCompression
-    chooseType (_:xs)           = chooseType xs
-
-
-------------------------------------------------------------------------------
--- private following
-------------------------------------------------------------------------------
-
-
-------------------------------------------------------------------------------
-compressibleMimeTypes :: Set ByteString
-compressibleMimeTypes = Set.fromList [ "application/x-font-truetype"
-                                     , "application/x-javascript"
-                                     , "text/css"
-                                     , "text/html"
-                                     , "text/javascript"
-                                     , "text/plain"
-                                     , "text/xml" ]
-
-
-
-
-------------------------------------------------------------------------------
-gzipCompression :: Snap ()
-gzipCompression = modifyResponse f
-  where
-    f = setHeader "Content-Encoding" "gzip" .
-        clearContentLength .
-        modifyResponseBody gcompress
-
-
-------------------------------------------------------------------------------
-compressCompression :: Snap ()
-compressCompression = modifyResponse f
-  where
-    f = setHeader "Content-Encoding" "compress" .
-        clearContentLength .
-        modifyResponseBody ccompress
-
-
-------------------------------------------------------------------------------
-gcompress :: forall a . Enumerator a -> Enumerator a
-gcompress = compressEnumerator GZip.compress
-
-
-------------------------------------------------------------------------------
-ccompress :: forall a . Enumerator a -> Enumerator a
-ccompress = compressEnumerator Zlib.compress
-
-
-------------------------------------------------------------------------------
-compressEnumerator :: forall a .
-                      (L.ByteString -> L.ByteString)
-                   -> Enumerator a
-                   -> Enumerator a
-compressEnumerator compFunc enum iteratee = do
-    writeEnd <- newChan
-    readEnd  <- newChan
-    tid      <- forkIO $ threadProc readEnd writeEnd
-
-    enum (IterateeG $ f readEnd writeEnd tid iteratee)
-
-  where
-    --------------------------------------------------------------------------
-    streamFinished :: Stream -> Bool
-    streamFinished (EOF _)   = True
-    streamFinished (Chunk _) = False
-
-
-    --------------------------------------------------------------------------
-    consumeSomeOutput :: Chan Stream
-                      -> Iteratee IO a
-                      -> IO (Iteratee IO a)
-    consumeSomeOutput writeEnd iter = do
-        e <- isEmptyChan writeEnd
-        if e
-          then return iter
-          else do
-            ch <- readChan writeEnd
-
-            iter' <- liftM liftI $ runIter iter ch
-            if (streamFinished ch)
-               then return iter'
-               else consumeSomeOutput writeEnd iter'
-
-
-    --------------------------------------------------------------------------
-    consumeRest :: Chan Stream
-                -> Iteratee IO a
-                -> IO (IterV IO a)
-    consumeRest writeEnd iter = do
-        ch <- readChan writeEnd
-
-        iv <- runIter iter ch
-        if (streamFinished ch)
-           then return iv
-           else consumeRest writeEnd $ liftI iv
-
-
-    --------------------------------------------------------------------------
-    f readEnd writeEnd tid i (EOF Nothing) = do
-        writeChan readEnd Nothing
-        x <- consumeRest writeEnd i
-        killThread tid
-        return x
-
-    f _ _ tid i ch@(EOF (Just _)) = do
-        x <- runIter i ch
-        killThread tid
-        return x
-
-    f readEnd writeEnd tid i (Chunk s') = do
-        let s = unWrap s'
-        writeChan readEnd $ Just s
-        i' <- consumeSomeOutput writeEnd i
-        return $ Cont (IterateeG $ f readEnd writeEnd tid i') Nothing
-
-
-    --------------------------------------------------------------------------
-    threadProc :: Chan (Maybe ByteString)
-               -> Chan Stream
-               -> IO ()
-    threadProc readEnd writeEnd = do
-        stream <- getChanContents readEnd
-        let bs = L.fromChunks $ streamToChunks stream
-
-        let output = L.toChunks $ compFunc bs
-        let runIt = do
-            mapM_ (writeChan writeEnd . toChunk) output
-            writeChan writeEnd $ EOF Nothing
-
-        runIt `catch` \(e::SomeException) ->
-            writeChan writeEnd $ EOF (Just $ Err $ show e)
-
-
-    --------------------------------------------------------------------------
-    streamToChunks []            = []
-    streamToChunks (Nothing:_)   = []
-    streamToChunks ((Just x):xs) = x:(streamToChunks xs)
-
-
-    --------------------------------------------------------------------------
-    toChunk = Chunk . WrapBS
-
-
-------------------------------------------------------------------------------
-fullyParse :: ByteString -> Parser a -> Either String a
-fullyParse s p =
-    case r' of
-      (Fail _ _ e)    -> Left e
-      (Partial _)     -> Left "parse failed"
-      (Atto.Done _ x) -> Right x
-  where
-    r  = parse p s
-    r' = feed r ""
-
-
-------------------------------------------------------------------------------
--- We're not gonna bother with quality values; we'll do gzip or compress in
--- that order.
-acceptParser :: Parser [ByteString]
-acceptParser = do
-    xs <- option [] $ (:[]) <$> encoding
-    ys <- many (char ',' *> encoding)
-    endOfInput
-    return $ xs ++ ys
-  where
-    encoding = skipSpace *> c <* skipSpace
-
-    c = do
-        x <- coding
-        option () qvalue
-        return x
-
-    qvalue = do
-        skipSpace
-        char ';'
-        skipSpace
-        char 'q'
-        skipSpace
-        char '='
-        float
-        return ()
-
-    coding = string "*" <|> takeWhile isCodingChar
-
-    isCodingChar c = isAlpha_ascii c || c == '-'
-
-    float = takeWhile isDigit >>
-            option () (char '.' >> takeWhile isDigit >> pure ())
-
-
-------------------------------------------------------------------------------
-data BadAcceptEncodingException = BadAcceptEncodingException
-   deriving (Typeable)
-
-
-------------------------------------------------------------------------------
-instance Show BadAcceptEncodingException where
-    show BadAcceptEncodingException = "bad 'accept-encoding' header"
-
-
-------------------------------------------------------------------------------
-instance Exception BadAcceptEncodingException
-
-
-------------------------------------------------------------------------------
-parseAcceptEncoding :: ByteString -> IO [ByteString]
-parseAcceptEncoding s =
-    case r of
-      Left _ -> throwIO BadAcceptEncodingException
-      Right x -> return x
-  where
-    r = fullyParse s acceptParser
-
-
- diff --git a/static/docs/0.1.2/snap-core/src/hscolour.css b/static/docs/0.1.2/snap-core/src/hscolour.css deleted file mode 100644 index 150e4d0..0000000 --- a/static/docs/0.1.2/snap-core/src/hscolour.css +++ /dev/null @@ -1,15 +0,0 @@ -body { font-size: 90%; } - -pre, code, body { - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; -} - -.hs-keyglyph, .hs-layout {color: #5200A3;} -.hs-keyword {color: #3465a4; font-weight: bold;} -.hs-comment, .hs-comment a {color: #579; } -.hs-str, .hs-chr {color: #141B24;} -.hs-keyword, .hs-conid, .hs-varid, .hs-conop, .hs-varop, .hs-num, .hs-cpp, .hs-sel, .hs-definition {} diff --git a/static/docs/0.1.2/snap-server/Snap-Http-Server-Config.html b/static/docs/0.1.2/snap-server/Snap-Http-Server-Config.html deleted file mode 100644 index 52bc6c1..0000000 --- a/static/docs/0.1.2/snap-server/Snap-Http-Server-Config.html +++ /dev/null @@ -1,287 +0,0 @@ - - -Snap.Http.Server.Config
 snap-server-0.1.1: A fast, iteratee-based, epoll-enabled web server for the Snap FrameworkSource codeContentsIndex
Snap.Http.Server.Config
Documentation
data Config Source
Constructors
Config
localHostname :: !ByteString
bindAddress :: !ByteString
listenPort :: !Int
accessLog :: !(Maybe FilePath)
errorLog :: !(Maybe FilePath)
show/hide Instances
readConfigFromCmdLineArgsSource
:: Stringapplication description, e.g. - "Foo applet v0.2" -
-> IO Config
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.2/snap-server/Snap-Http-Server.html b/static/docs/0.1.2/snap-server/Snap-Http-Server.html deleted file mode 100644 index a99085f..0000000 --- a/static/docs/0.1.2/snap-server/Snap-Http-Server.html +++ /dev/null @@ -1,245 +0,0 @@ - - -Snap.Http.Server
 snap-server-0.1.1: A fast, iteratee-based, epoll-enabled web server for the Snap FrameworkSource codeContentsIndex
Snap.Http.Server
Description
The Snap HTTP server is a high performance, epoll-enabled, iteratee-based - web server library written in Haskell. Together with the snap-core library - upon which it depends, it provides a clean and efficient Haskell programming - interface to the HTTP protocol. -
Synopsis
httpServe :: ByteString -> Int -> ByteString -> Maybe FilePath -> Maybe FilePath -> Snap () -> IO ()
Documentation
httpServeSource
:: ByteStringbind address, or "*" for all -
-> Intport to bind to -
-> ByteStringlocal hostname (server name) -
-> Maybe FilePathpath to the (optional) access log -
-> Maybe FilePathpath to the (optional) error log -
-> Snap ()handler procedure -
-> IO ()
Starts serving HTTP requests on the given port using the given handler. - This function never returns; to shut down the HTTP server, kill the - controlling thread. -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.2/snap-server/System-FastLogger.html b/static/docs/0.1.2/snap-server/System-FastLogger.html deleted file mode 100644 index 9127025..0000000 --- a/static/docs/0.1.2/snap-server/System-FastLogger.html +++ /dev/null @@ -1,510 +0,0 @@ - - -System.FastLogger
 snap-server-0.1.1: A fast, iteratee-based, epoll-enabled web server for the Snap FrameworkSource codeContentsIndex
System.FastLogger
Synopsis
data Logger
timestampedLogEntry :: ByteString -> IO ByteString
combinedLogEntry :: ByteString -> Maybe ByteString -> ByteString -> Int -> Maybe Int -> Maybe ByteString -> ByteString -> IO ByteString
newLogger :: FilePath -> IO Logger
logMsg :: Logger -> ByteString -> IO ()
stopLogger :: Logger -> IO ()
Documentation
data Logger Source
Holds the state for a logger. -
timestampedLogEntry :: ByteString -> IO ByteStringSource
Prepares a log message with the time prepended. -
combinedLogEntrySource
:: ByteStringremote host -
-> Maybe ByteStringremote user -
-> ByteStringrequest line (up to you to ensure - there are no quotes in here) -
-> Intstatus code -
-> Maybe Intnum bytes sent -
-> Maybe ByteStringreferer (up to you to ensure - there are no quotes in here) -
-> ByteStringuser agent (up to you to ensure - there are no quotes in here) -
-> IO ByteString
Prepares a log message in "combined" format. -
newLogger :: FilePath -> IO LoggerSource
Creates a new logger, logging to the given file. If the file argument is - "-", then log to stdout; if it's "stderr" then we log to stderr, - otherwise we log to a regular file in append mode. The file is closed and - re-opened every 15 minutes to facilitate external log rotation. -
logMsg :: Logger -> ByteString -> IO ()Source
Sends out a log message verbatim with a newline appended. Note: - if you want a fancy log message you'll have to format it yourself - (or use combinedLogEntry). -
stopLogger :: Logger -> IO ()Source
Kills a logger thread, causing any unwritten contents to be - flushed out to disk -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.2/snap-server/doc-index.html b/static/docs/0.1.2/snap-server/doc-index.html deleted file mode 100644 index 7713ecc..0000000 --- a/static/docs/0.1.2/snap-server/doc-index.html +++ /dev/null @@ -1,168 +0,0 @@ - - -snap-server-0.1.1: A fast, iteratee-based, epoll-enabled web server for the Snap Framework (Index)
 snap-server-0.1.1: A fast, iteratee-based, epoll-enabled web server for the Snap FrameworkContentsIndex
accessLog
bindAddress
combinedLogEntry
Config
1 (Type/Class)
2 (Data Constructor)
errorLog
httpServe
listenPort
localHostname
Logger
logMsg
newLogger
readConfigFromCmdLineArgs
stopLogger
timestampedLogEntry
diff --git a/static/docs/0.1.2/snap-server/fonts/DroidSerif-Bold.eot b/static/docs/0.1.2/snap-server/fonts/DroidSerif-Bold.eot deleted file mode 100644 index 01b9e1f..0000000 Binary files a/static/docs/0.1.2/snap-server/fonts/DroidSerif-Bold.eot and /dev/null differ diff --git a/static/docs/0.1.2/snap-server/fonts/DroidSerif-Bold.svg b/static/docs/0.1.2/snap-server/fonts/DroidSerif-Bold.svg deleted file mode 100644 index 1f7f2d2..0000000 --- a/static/docs/0.1.2/snap-server/fonts/DroidSerif-Bold.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.1.2/snap-server/fonts/DroidSerif-Bold.ttf b/static/docs/0.1.2/snap-server/fonts/DroidSerif-Bold.ttf deleted file mode 100644 index da0ea11..0000000 Binary files a/static/docs/0.1.2/snap-server/fonts/DroidSerif-Bold.ttf and /dev/null differ diff --git a/static/docs/0.1.2/snap-server/fonts/DroidSerif-Bold.woff b/static/docs/0.1.2/snap-server/fonts/DroidSerif-Bold.woff deleted file mode 100644 index 91549cd..0000000 Binary files a/static/docs/0.1.2/snap-server/fonts/DroidSerif-Bold.woff and /dev/null differ diff --git a/static/docs/0.1.2/snap-server/fonts/DroidSerif-BoldItalic.eot b/static/docs/0.1.2/snap-server/fonts/DroidSerif-BoldItalic.eot deleted file mode 100644 index 47dd0a0..0000000 Binary files a/static/docs/0.1.2/snap-server/fonts/DroidSerif-BoldItalic.eot and /dev/null differ diff --git a/static/docs/0.1.2/snap-server/fonts/DroidSerif-BoldItalic.svg b/static/docs/0.1.2/snap-server/fonts/DroidSerif-BoldItalic.svg deleted file mode 100644 index 1a57dbb..0000000 --- a/static/docs/0.1.2/snap-server/fonts/DroidSerif-BoldItalic.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.1.2/snap-server/fonts/DroidSerif-BoldItalic.ttf b/static/docs/0.1.2/snap-server/fonts/DroidSerif-BoldItalic.ttf deleted file mode 100644 index 8be3fb4..0000000 Binary files a/static/docs/0.1.2/snap-server/fonts/DroidSerif-BoldItalic.ttf and /dev/null differ diff --git a/static/docs/0.1.2/snap-server/fonts/DroidSerif-BoldItalic.woff b/static/docs/0.1.2/snap-server/fonts/DroidSerif-BoldItalic.woff deleted file mode 100644 index 6d5fa3d..0000000 Binary files a/static/docs/0.1.2/snap-server/fonts/DroidSerif-BoldItalic.woff and /dev/null differ diff --git a/static/docs/0.1.2/snap-server/fonts/DroidSerif-Italic.eot b/static/docs/0.1.2/snap-server/fonts/DroidSerif-Italic.eot deleted file mode 100644 index 2d4850c..0000000 Binary files a/static/docs/0.1.2/snap-server/fonts/DroidSerif-Italic.eot and /dev/null differ diff --git a/static/docs/0.1.2/snap-server/fonts/DroidSerif-Italic.svg b/static/docs/0.1.2/snap-server/fonts/DroidSerif-Italic.svg deleted file mode 100644 index 356c374..0000000 --- a/static/docs/0.1.2/snap-server/fonts/DroidSerif-Italic.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.1.2/snap-server/fonts/DroidSerif-Italic.ttf b/static/docs/0.1.2/snap-server/fonts/DroidSerif-Italic.ttf deleted file mode 100644 index 3719dc2..0000000 Binary files a/static/docs/0.1.2/snap-server/fonts/DroidSerif-Italic.ttf and /dev/null differ diff --git a/static/docs/0.1.2/snap-server/fonts/DroidSerif-Italic.woff b/static/docs/0.1.2/snap-server/fonts/DroidSerif-Italic.woff deleted file mode 100644 index b64436f..0000000 Binary files a/static/docs/0.1.2/snap-server/fonts/DroidSerif-Italic.woff and /dev/null differ diff --git a/static/docs/0.1.2/snap-server/fonts/DroidSerif-Regular.eot b/static/docs/0.1.2/snap-server/fonts/DroidSerif-Regular.eot deleted file mode 100644 index 0d17523..0000000 Binary files a/static/docs/0.1.2/snap-server/fonts/DroidSerif-Regular.eot and /dev/null differ diff --git a/static/docs/0.1.2/snap-server/fonts/DroidSerif-Regular.svg b/static/docs/0.1.2/snap-server/fonts/DroidSerif-Regular.svg deleted file mode 100644 index b9b65fb..0000000 --- a/static/docs/0.1.2/snap-server/fonts/DroidSerif-Regular.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.1.2/snap-server/fonts/DroidSerif-Regular.ttf b/static/docs/0.1.2/snap-server/fonts/DroidSerif-Regular.ttf deleted file mode 100644 index 066dcaa..0000000 Binary files a/static/docs/0.1.2/snap-server/fonts/DroidSerif-Regular.ttf and /dev/null differ diff --git a/static/docs/0.1.2/snap-server/fonts/DroidSerif-Regular.woff b/static/docs/0.1.2/snap-server/fonts/DroidSerif-Regular.woff deleted file mode 100644 index cfd3d67..0000000 Binary files a/static/docs/0.1.2/snap-server/fonts/DroidSerif-Regular.woff and /dev/null differ diff --git a/static/docs/0.1.2/snap-server/frames.html b/static/docs/0.1.2/snap-server/frames.html deleted file mode 100644 index 9e904fc..0000000 --- a/static/docs/0.1.2/snap-server/frames.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/static/docs/0.1.2/snap-server/haddock-util.js b/static/docs/0.1.2/snap-server/haddock-util.js deleted file mode 100644 index 364081f..0000000 --- a/static/docs/0.1.2/snap-server/haddock-util.js +++ /dev/null @@ -1,139 +0,0 @@ -// Haddock JavaScript utilities -function toggle(button,id) -{ - var n = document.getElementById(id).style; - if (n.display == "none") - { - button.src = "minus.gif"; - n.display = "block"; - } - else - { - button.src = "plus.gif"; - n.display = "none"; - } -} - - -var max_results = 75; // 50 is not enough to search for map in the base libraries -var shown_range = null; -var last_search = null; - -function quick_search() -{ - perform_search(false); -} - -function full_search() -{ - perform_search(true); -} - - -function perform_search(full) -{ - var text = document.getElementById("searchbox").value.toLowerCase(); - if (text == last_search && !full) return; - last_search = text; - - var table = document.getElementById("indexlist"); - var status = document.getElementById("searchmsg"); - var children = table.firstChild.childNodes; - - // first figure out the first node with the prefix - var first = bisect(-1); - var last = (first == -1 ? -1 : bisect(1)); - - if (first == -1) - { - table.className = ""; - status.innerHTML = "No results found, displaying all"; - } - else if (first == 0 && last == children.length - 1) - { - table.className = ""; - status.innerHTML = ""; - } - else if (last - first >= max_results && !full) - { - table.className = ""; - status.innerHTML = "More than " + max_results + ", press Search to display"; - } - else - { - // decide what you need to clear/show - if (shown_range) - setclass(shown_range[0], shown_range[1], "indexrow"); - setclass(first, last, "indexshow"); - shown_range = [first, last]; - table.className = "indexsearch"; - status.innerHTML = ""; - } - - - function setclass(first, last, status) - { - for (var i = first; i <= last; i++) - { - children[i].className = status; - } - } - - - // do a binary search, treating 0 as ... - // return either -1 (no 0's found) or location of most far match - function bisect(dir) - { - var first = 0, finish = children.length - 1; - var mid, success = false; - - while (finish - first > 3) - { - mid = Math.floor((finish + first) / 2); - - var i = checkitem(mid); - if (i == 0) i = dir; - if (i == -1) - finish = mid; - else - first = mid; - } - var a = (dir == 1 ? first : finish); - var b = (dir == 1 ? finish : first); - for (var i = b; i != a - dir; i -= dir) - { - if (checkitem(i) == 0) return i; - } - return -1; - } - - - // from an index, decide what the result is - // 0 = match, -1 is lower, 1 is higher - function checkitem(i) - { - var s = getitem(i).toLowerCase().substr(0, text.length); - if (s == text) return 0; - else return (s > text ? -1 : 1); - } - - - // from an index, get its string - // this abstracts over alternates - function getitem(i) - { - for ( ; i >= 0; i--) - { - var s = children[i].firstChild.firstChild.data; - if (s.indexOf(' ') == -1) - return s; - } - return ""; // should never be reached - } -} - -function setSynopsis(filename) { - if (parent.window.synopsis) { - parent.window.synopsis.location = filename; - } -} diff --git a/static/docs/0.1.2/snap-server/haddock.css b/static/docs/0.1.2/snap-server/haddock.css deleted file mode 100644 index fe050fe..0000000 --- a/static/docs/0.1.2/snap-server/haddock.css +++ /dev/null @@ -1,478 +0,0 @@ -/* -------- Global things --------- */ - -@font-face { - font-family: 'DroidSerif'; - src: url('fonts/DroidSerif-Regular.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Regular.woff') format('woff'), - url('fonts/DroidSerif-Regular.ttf') format('truetype'), - url('fonts/DroidSerif-Regular.svg#DroidSerif') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - font-style: italic; - src: url('fonts/DroidSerif-Italic.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Italic.woff') format('woff'), - url('fonts/DroidSerif-Italic.ttf') format('truetype'), - url('fonts/DroidSerif-Italic.svg#DroidSerif-Italic') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - font-weight: bold; - src: url('fonts/DroidSerif-Bold.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Bold.woff') format('woff'), - url('fonts/DroidSerif-Bold.ttf') format('truetype'), - url('fonts/DroidSerif-Bold.svg#DroidSerif-Bold') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - src: url('fonts/DroidSerif-BoldItalic.eot'); - font-weight: bold; - font-style: italic; - src: local('Droid Serif'), - url('fonts/DroidSerif-BoldItalic.woff') format('woff'), - url('fonts/DroidSerif-BoldItalic.ttf') format('truetype'), - url('fonts/DroidSerif-BoldItalic.svg#DroidSerif-BoldItalic') format('svg'); -} - - - -HTML { - background-color: #f0f3ff; - width: 100%; -} - -BODY { - -moz-border-radius:5px; - -webkit-border-radius:5px; - width: 50em; - margin: 2em auto; - padding: 0; - background-color: #ffffff; - color: #000000; - font-size: 110%; - font-family: DroidSerif, Georgia, serif; - } - -A:link { color: #5200A3; text-decoration: none } -A:visited { color: #5200A3; text-decoration: none } -A:hover { color: #5200A3; text-decoration: none; border-bottom:#5200A3 dashed 1px; } - -TABLE.vanilla { - width: 100%; - border-width: 0px; - /* I can't seem to specify cellspacing or cellpadding properly using CSS... */ -} - -DL { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - letter-spacing: -0.01em; - margin: 0; -} - -.vanilla .vanilla dl { font-size: 80%; } -.vanilla .vanilla dl dl { padding-left: 0; font-size: 95%; } - -TD.section1, TD.section2, TD.section3, TD.section4, TD.doc, DL { - padding: 0 30px 0 34px; -} - -TABLE.vanilla2 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - border-width: 0px; -} - -/* font is a little too small in MSIE */ -TT, PRE, CODE { - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - font-size: 90%; -} - -LI P { margin: 0pt } - -P { margin-top: 0; margin-bottom: 0.75em; } - -TD { - border-width: 0px; -} - -TABLE.narrow { - border-width: 0px; -} - -TD.s8 { height: 0; margin:0; padding: 0 } -TD.s15 { height: 20px; } - -SPAN.keyword { text-decoration: underline; } - -/* Resize the buttom image to match the text size */ -IMG.coll { width : 0.75em; height: 0.75em; margin-bottom: 0; margin-right: 0.5em } - -/* --------- Contents page ---------- */ - -DIV.node { - padding-left: 3em; -} - -DIV.cnode { - padding-left: 1.75em; -} - -SPAN.pkg { - position: absolute; - left: 50em; -} - -/* --------- Documentation elements ---------- */ - -TD FONT { font-weight: bold; letter-spacing: -0.02em; } - -TD.children { - padding-left: 25px; - } - -TD.synopsis { - padding: 2px; - background-color: #f0f0f0; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - } - -TD.decl { - padding: 4px 8px; - background-color: #FAFAFA; - border-bottom: #F2F2F2 solid 1px; - border-top: #FCFCFC solid 1px; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - vertical-align: top; - } - -TD.decl TD.decl { - font-size: 100%; - padding: 4px 0; - border: 0; -} - -TD.topdecl { - padding: 20px 30px 0.5ex 30px; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; -; - vertical-align: top; -} - -.vanilla .vanilla .vanilla .topdecl { - padding-left: 0; - padding-right: 0; -} - -.vanilla .vanilla .vanilla { - padding-left: 30px; -} - -.decl .vanilla { - padding-left: 0px !important; -} - -.body .vanilla .body { - padding-left: 0; - padding-right: 0; -} - -.body .vanilla .body .decl { - padding-left: 12px; -} - -.body .vanilla .body div .vanilla .decl { - padding-left: 12px; -} - -TABLE.declbar { - background-color: #f0f0f0; - border-spacing: 0px; - border-bottom:1px solid #d7d7df; - border-right:1px solid #d7d7df; - border-top:1px solid #f4f4f9; - border-left:1px solid #f4f4f9; - padding: 4px; - } - -TD.declname { - width: 100%; - padding-right: 4px; - } - -TD.declbut { - padding-left: 8px; - padding-right: 5px; - border-left-width: 1px; - border-left-color: #000099; - border-left-style: solid; - white-space: nowrap; - font-size: x-small; - } - -/* - arg is just like decl, except that wrapping is not allowed. It is - used for function and constructor arguments which have a text box - to the right, where if wrapping is allowed the text box squashes up - the declaration by wrapping it. -*/ -TD.arg { - padding: 2px 12px; - background-color: #f0f0f0; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - vertical-align: top; - white-space: nowrap; - } - -TD.recfield { padding-left: 20px } - -TD.doc { - padding-left: 38px; - font-size: 95%; - line-height: 1.66; - } - -TD.ndoc { - font-size: 95%; - line-height: 1.66; - padding: 2px 4px 2px 8px; - } - -TD.rdoc { - padding: 2px; - padding-left: 30px; - width: 100%; - font-size: 80%; - font-style: italic; - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - } - -TD.body { - padding: 0 30px; - } - -TD.pkg { - width: 100%; - padding-left: 30px -} - -TABLE.indexsearch TR.indexrow { - display: none; -} -TABLE.indexsearch TR.indexshow { - display: table-row; -} - -TD.indexentry { - vertical-align: top; - padding: 0 30px - } - -TD.indexannot { - vertical-align: top; - padding-left: 20px; - white-space: nowrap - } - -TD.indexlinks { - width: 100% - } - -/* ------- Section Headings ------- */ - -TD.section1, TD.section2, TD.section3, TD.section4, TD.section5 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; -} - -TD.section1 { - padding-top: 14px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 140% - } - -TD.section2 { - padding-top: 4px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 120% - } - -TD.section3 { - padding-top: 5px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 105% - } - -TD.section4 { - font-weight: bold; - padding-top: 12px; - padding-bottom: 4px; - letter-spacing: -0.02em; - font-size: 90% - } - -/* -------------- The title bar at the top of the page */ - -TD.infohead { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - font-weight: bold; - padding: 0 30px; - text-align: left; -} - -TD.infoval { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - padding: 0 30px; - text-align: left; -} - -TD.topbar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - background-color: #3465a4; - padding: 5px; - -moz-border-radius-topleft:5px; - -moz-border-radius-topright:5px; - -webkit-border-radius-topleft:5px; - -webkit-border-radius-topright:5px; -} - -TD.title { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - padding-left: 30px; - letter-spacing: -0.02em; - font-weight: bold; - width: 100% - } - -TD.topbut { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - padding-left: 5px; - padding-right: 5px; - border-left-width: 1px; - border-left-color: #ffffff; - border-left-style: solid; - letter-spacing: -0.02em; - font-weight: bold; - white-space: nowrap; - } - -TD.topbut A:link { - color: #ffffff - } - -TD.topbut A:visited { - color: #ffff00 - } - -TD.topbut A:hover { - background-color: #C9D3DE; - } - -TD.topbut:hover { - background-color: #C9D3DE; - } - -TD.modulebar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #141B24; - background-color: #C9D3DE; - padding: 5px; - border-top-width: 1px; - border-top-color: #ffffff; - border-top-style: solid; - -moz-border-radius-bottomleft:5px; - -moz-border-radius-bottomright:5px; - -webkit-border-radius-bottomleft:5px; - -webkit-border-radius-bottomright:5px; - - } - -/* --------- The page footer --------- */ - -TD.botbar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - -moz-border-radius:5px; - -webkit-border-radius:5px; - background-color: #3465a4; - color: #ffffff; - padding: 5px - } -TD.botbar A:link { - color: #ffffff; - text-decoration: underline - } -TD.botbar A:visited { - color: #ffff00 - } -TD.botbar A:hover { - background-color: #6060ff - } - -/* --------- Mini Synopsis for Frame View --------- */ - -.outer { - margin: 0 0; - padding: 0 0; -} - -.mini-synopsis { - padding: 0.25em 0.25em; -} - -.mini-synopsis H1 { font-size: 120%; } -.mini-synopsis H2 { font-size: 107%; } -.mini-synopsis H3 { font-size: 100%; } -.mini-synopsis H1, .mini-synopsis H2, .mini-synopsis H3 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - margin-top: 0.5em; - margin-bottom: 0.25em; - padding: 0 0; - font-weight: bold; letter-spacing: -0.02em; -} - -.mini-synopsis H1 { border-bottom: 1px solid #ccc; } - -.mini-topbar { - font-size: 120%; - background: #0077dd; - padding: 0.25em; -} - - diff --git a/static/docs/0.1.2/snap-server/haskell_icon.gif b/static/docs/0.1.2/snap-server/haskell_icon.gif deleted file mode 100644 index cb2a815..0000000 Binary files a/static/docs/0.1.2/snap-server/haskell_icon.gif and /dev/null differ diff --git a/static/docs/0.1.2/snap-server/index-frames.html b/static/docs/0.1.2/snap-server/index-frames.html deleted file mode 100644 index 8fe09ab..0000000 --- a/static/docs/0.1.2/snap-server/index-frames.html +++ /dev/null @@ -1,28 +0,0 @@ - - -snap-server-0.1.1: A fast, iteratee-based, epoll-enabled web server for the Snap Framework

Snap.Http.Server
Snap.Http.Server.Config
System.FastLogger

diff --git a/static/docs/0.1.2/snap-server/index.html b/static/docs/0.1.2/snap-server/index.html deleted file mode 100644 index 6dddea2..0000000 --- a/static/docs/0.1.2/snap-server/index.html +++ /dev/null @@ -1,178 +0,0 @@ - - -snap-server-0.1.1: A fast, iteratee-based, epoll-enabled web server for the Snap Framework
 snap-server-0.1.1: A fast, iteratee-based, epoll-enabled web server for the Snap FrameworkContentsIndex
snap-server-0.1.1: A fast, iteratee-based, epoll-enabled web server for the Snap Framework

This is the first developer prerelease of the Snap framework. Snap is a -simple and fast web development framework and server written in Haskell. For -more information or to download the latest version, you can visit the Snap -project website at http://snapframework.com/. -

The Snap HTTP server is a high performance, epoll-enabled, iteratee-based web -server library written in Haskell. Together with the snap-core library upon -which it depends, it provides a clean and efficient Haskell programming -interface to the HTTP protocol. -

Higher-level facilities for building web applications (like user/session -management, component interfaces, data modeling, etc.) are planned but not -yet implemented, so this release will mostly be of interest for those who: -

  • need a fast and minimal HTTP API at roughly the same level of abstraction -as Java servlets, or -
  • are interested in contributing to the Snap Framework project. -
Modules
show/hideSnap
show/hideHttp
show/hideSnap.Http.Server
Snap.Http.Server.Config
show/hideSystem
System.FastLogger
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.1.2/snap-server/mini_Snap-Http-Server-Config.html b/static/docs/0.1.2/snap-server/mini_Snap-Http-Server-Config.html deleted file mode 100644 index c4ec20a..0000000 --- a/static/docs/0.1.2/snap-server/mini_Snap-Http-Server-Config.html +++ /dev/null @@ -1,31 +0,0 @@ - - -Snap.Http.Server.Config
Snap.Http.Server.Config
diff --git a/static/docs/0.1.2/snap-server/mini_Snap-Http-Server.html b/static/docs/0.1.2/snap-server/mini_Snap-Http-Server.html deleted file mode 100644 index 3841177..0000000 --- a/static/docs/0.1.2/snap-server/mini_Snap-Http-Server.html +++ /dev/null @@ -1,25 +0,0 @@ - - -Snap.Http.Server
Snap.Http.Server
diff --git a/static/docs/0.1.2/snap-server/mini_System-FastLogger.html b/static/docs/0.1.2/snap-server/mini_System-FastLogger.html deleted file mode 100644 index 891c97c..0000000 --- a/static/docs/0.1.2/snap-server/mini_System-FastLogger.html +++ /dev/null @@ -1,47 +0,0 @@ - - -System.FastLogger diff --git a/static/docs/0.1.2/snap-server/minus.gif b/static/docs/0.1.2/snap-server/minus.gif deleted file mode 100644 index 1deac2f..0000000 Binary files a/static/docs/0.1.2/snap-server/minus.gif and /dev/null differ diff --git a/static/docs/0.1.2/snap-server/plus.gif b/static/docs/0.1.2/snap-server/plus.gif deleted file mode 100644 index 2d15c14..0000000 Binary files a/static/docs/0.1.2/snap-server/plus.gif and /dev/null differ diff --git a/static/docs/0.1.2/snap-server/snap-server.haddock b/static/docs/0.1.2/snap-server/snap-server.haddock deleted file mode 100644 index 7670981..0000000 Binary files a/static/docs/0.1.2/snap-server/snap-server.haddock and /dev/null differ diff --git a/static/docs/0.1.2/snap-server/src/Snap-Http-Server-Config.html b/static/docs/0.1.2/snap-server/src/Snap-Http-Server-Config.html deleted file mode 100644 index 5c11ecf..0000000 --- a/static/docs/0.1.2/snap-server/src/Snap-Http-Server-Config.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - -src/Snap/Http/Server/Config.hs - - - -
{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# OPTIONS_GHC -fno-warn-orphans #-}
-
-module Snap.Http.Server.Config
-  ( Config(..)
-  , readConfigFromCmdLineArgs
-  ) where
-
-import           Data.ByteString (ByteString)
-import qualified Data.ByteString as B
-import           Data.ByteString.Internal (c2w)
-import           Data.ByteString.Char8 ()
-import           Data.Maybe
-import           Data.Monoid
-import           System.Console.GetOpt
-import           System.Environment
-import           System.Exit
-import           System.IO
-
-data Config = Config
-    { localHostname :: !ByteString
-    , bindAddress   :: !ByteString
-    , listenPort    :: !Int
-    , accessLog     :: !(Maybe FilePath)
-    , errorLog      :: !(Maybe FilePath)
-    } deriving (Show)
-
-
-data Flag = Flag
-    { flagLocalHost   :: Maybe String
-    , flagBindAddress :: Maybe String
-    , flagPort        :: Maybe Int
-    , flagAccessLog   :: Maybe String
-    , flagErrorLog    :: Maybe String
-    , flagUsage       :: Bool
-    }
-
-instance Monoid Flag where
-    mempty = Flag Nothing Nothing Nothing Nothing Nothing False
-
-    (Flag a1 b1 c1 d1 e1 f1) `mappend` (Flag a2 b2 c2 d2 e2 f2) =
-        Flag (getLast $ Last a1 `mappend` Last a2)
-             (getLast $ Last b1 `mappend` Last b2)
-             (getLast $ Last c1 `mappend` Last c2)
-             (getLast $ Last d1 `mappend` Last d2)
-             (getLast $ Last e1 `mappend` Last e2)
-             (f1 || f2)
-
-flagLH :: String -> Flag
-flagLH s = mempty { flagLocalHost = Just s }
-
-flagBA :: String -> Flag
-flagBA s = mempty { flagBindAddress = Just s }
-
-flagPt :: String -> Flag
-flagPt p = mempty { flagPort = Just (read p) }
-
-flagAL :: String -> Flag
-flagAL s = mempty { flagAccessLog = Just s }
-
-flagEL :: String -> Flag
-flagEL s = mempty { flagErrorLog = Just s }
-
-flagHelp :: Flag
-flagHelp = mempty { flagUsage = True }
-
-fromStr :: String -> ByteString
-fromStr = B.pack . map c2w
-
-flags2config :: Flag -> Config
-flags2config (Flag a b c d e _) =
-    Config (maybe "localhost" fromStr a)
-           (maybe "*" fromStr b)
-           (fromMaybe 8888 c)
-           d
-           e
-
-
-options :: [OptDescr Flag]
-options =
-    [ Option "l" ["localHostname"]
-                 (ReqArg flagLH "STR")
-                 "local hostname, default 'localhost'"
-    , Option "p" ["listenPort"]
-                 (ReqArg flagPt "NUM")
-                 "port to listen on, default 8888"
-    , Option "b" ["bindAddress"]
-                 (ReqArg flagBA "STR")
-                 "address to bind to, default '*'"
-    , Option "a" ["accessLog"]
-                 (ReqArg flagAL "STR")
-                 "access log in the 'combined' format, optional"
-    , Option "e" ["errorLog"]
-                 (ReqArg flagEL "STR")
-                 "error log, optional"
-    , Option "h" ["help"]
-                 (NoArg flagHelp)
-                 "display this usage statement" ]
-
-
-readConfigFromCmdLineArgs :: String     -- ^ application description, e.g.
-                                        --   \"Foo applet v0.2\"
-                          -> IO Config
-readConfigFromCmdLineArgs appName = do
-    argv     <- getArgs
-    progName <- getProgName
-
-    case getOpt Permute options argv of
-      (f,_,[]  ) -> withFlags progName f
-      (_,_,errs) -> bombout progName errs
-  where
-    bombout progName errs = do
-        let hdr = appName ++ "\n\nUsage: " ++ progName ++ " [OPTIONS]"
-        let msg = concat errs ++ usageInfo hdr options
-        hPutStrLn stderr msg
-        exitFailure
-
-    withFlags progName fs = do
-        let f = mconcat fs
-        if flagUsage f
-           then bombout progName []
-           else return $ flags2config f
-
- diff --git a/static/docs/0.1.2/snap-server/src/Snap-Http-Server.html b/static/docs/0.1.2/snap-server/src/Snap-Http-Server.html deleted file mode 100644 index dbe6ebb..0000000 --- a/static/docs/0.1.2/snap-server/src/Snap-Http-Server.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - -src/Snap/Http/Server.hs - - - -
-- | The Snap HTTP server is a high performance, epoll-enabled, iteratee-based
--- web server library written in Haskell. Together with the @snap-core@ library
--- upon which it depends, it provides a clean and efficient Haskell programming
--- interface to the HTTP protocol.
-module Snap.Http.Server
-(
-  httpServe
-) where
-
-import           Data.ByteString (ByteString)
-import           Snap.Types
-import qualified Snap.Internal.Http.Server as Int
-
-
--- | Starts serving HTTP requests on the given port using the given handler.
--- This function never returns; to shut down the HTTP server, kill the
--- controlling thread.
-httpServe :: ByteString      -- ^ bind address, or \"*\" for all
-          -> Int             -- ^ port to bind to
-          -> ByteString      -- ^ local hostname (server name)
-          -> Maybe FilePath  -- ^ path to the (optional) access log
-          -> Maybe FilePath  -- ^ path to the (optional) error log
-          -> Snap ()         -- ^ handler procedure
-          -> IO ()
-httpServe bindAddress bindPort localHostname alog elog handler =
-    Int.httpServe bindAddress bindPort localHostname alog elog handler'
-  where
-    handler' = runSnap handler
-
- diff --git a/static/docs/0.1.2/snap-server/src/Snap-Internal-Http-Parser.html b/static/docs/0.1.2/snap-server/src/Snap-Internal-Http-Parser.html deleted file mode 100644 index a50a1de..0000000 --- a/static/docs/0.1.2/snap-server/src/Snap-Internal-Http-Parser.html +++ /dev/null @@ -1,450 +0,0 @@ - - - - -src/Snap/Internal/Http/Parser.hs - - - -
{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RankNTypes #-}
-
-module Snap.Internal.Http.Parser
-  ( IRequest(..)
-  , parseRequest
-  , readChunkedTransferEncoding
-  , parserToIteratee
-  , parseCookie
-  , parseUrlEncoded
-  , writeChunkedTransferEncoding
-  , strictize
-  ) where
-
-
-------------------------------------------------------------------------------
-import           Control.Applicative
-import           Control.Arrow (first, second)
-import           Control.Monad (liftM)
-import           Control.Monad.Trans
-import           Data.Attoparsec hiding (many, Result(..))
-import           Data.Attoparsec.Iteratee
-import           Data.Bits
-import           Data.ByteString (ByteString)
-import qualified Data.ByteString as S
-import           Data.ByteString.Internal (c2w, w2c)
-import qualified Data.ByteString.Lazy as L
-import qualified Data.ByteString.Nums.Careless.Hex as Cvt
-import           Data.Char
-import           Data.CIByteString
-import           Data.List (foldl')
-import           Data.Int
-import           Data.Map (Map)
-import qualified Data.Map as Map
-import           Data.Maybe (catMaybes, fromMaybe)
-import           Data.Time.Format (parseTime)
-import qualified Data.Vector.Unboxed as Vec
-import           Data.Vector.Unboxed (Vector)
-import           Data.Word (Word8, Word64)
-import           Prelude hiding (take, takeWhile)
-import           System.Locale (defaultTimeLocale)
-------------------------------------------------------------------------------
-import           Snap.Internal.Http.Types hiding (Enumerator)
-import           Snap.Iteratee hiding (take, foldl')
-
-
-
-------------------------------------------------------------------------------
--- | an internal version of the headers part of an HTTP request
-data IRequest = IRequest
-    { iMethod :: Method
-    , iRequestUri :: ByteString
-    , iHttpVersion :: (Int,Int)
-    , iRequestHeaders :: [(ByteString, ByteString)]
-    }
-
-instance Show IRequest where
-    show (IRequest m u v r) =
-        concat [ show m
-               , " "
-               , show u
-               , " "
-               , show v
-               , " "
-               , show r ]
-
-------------------------------------------------------------------------------
-parseRequest :: (Monad m) => Iteratee m (Maybe IRequest)
-parseRequest = parserToIteratee pRequest
-
-
-readChunkedTransferEncoding :: (Monad m) => Enumerator m a
-readChunkedTransferEncoding iter = do
-      i <- chunkParserToEnumerator (parserToIteratee pGetTransferChunk)
-                                   iter
-
-      return i 
-
-
-toHex :: Int64 -> ByteString
-toHex !i' = S.reverse s
-  where
-    !i     = abs i'
-    (!s,_) = S.unfoldrN 16 f (fromIntegral i)
-
-    f :: Word64 -> Maybe (Word8, Word64)
-    f d = if d == 0
-            then Nothing
-            else Just (ch, theRest)
-
-      where
-        low4    = fromIntegral $ d .&. 0xf
-        ch      = if low4 >= 10
-                    then c2w 'a' + low4 - 10
-                    else c2w '0' + low4
-        theRest = (d .&. (complement 0xf)) `shiftR` 4
-
-
--- | Given an iteratee, produces a new one that wraps chunks sent to it with a
--- chunked transfer-encoding. Example usage:
---
--- > > (writeChunkedTransferEncoding
--- >     (enumLBS (L.fromChunks ["foo","bar","quux"]))
--- >     stream2stream) >>=
--- >     run >>=
--- >     return . fromWrap
--- >
--- > Chunk "3\r\nfoo\r\n3\r\nbar\r\n4\r\nquux\r\n0\r\n\r\n" Empty
---
-writeChunkedTransferEncoding :: (Monad m) => Enumerator m a -> Enumerator m a
-writeChunkedTransferEncoding enum it = do
-    i <- wrap it
-    enum i
-
-  where
-    wrap iter = return $ IterateeG $ \s ->
-        case s of
-          (EOF Nothing) -> do
-              v <- runIter iter (Chunk $ toWrap "0\r\n\r\n")
-              i <- checkIfDone return v
-              runIter i (EOF Nothing)
-          (EOF e) -> return $ Cont undefined e
-          (Chunk x') -> do
-              let x = S.concat $ L.toChunks $ fromWrap x'
-              let n = S.length x
-              let o = L.fromChunks [ toHex (toEnum n)
-                                   , "\r\n"
-                                   , x
-                                   , "\r\n" ]
-              v <- runIter iter (Chunk $ toWrap o)
-              i <- checkIfDone wrap v
-              return $ Cont i Nothing
-
-
-chunkParserToEnumerator :: (Monad m) =>
-                           Iteratee m (Maybe ByteString)
-                        -> Iteratee m a
-                        -> m (Iteratee m a)
-chunkParserToEnumerator getChunk client = return $ do
-    mbB <- getChunk
-    maybe (finishIt client) (sendBS client) mbB
-
-  where
-    sendBS iter s = do
-        v <- lift $ runIter iter (Chunk $ toWrap $ L.fromChunks [s])
-
-        case v of
-          (Done _ (EOF (Just e))) -> throwErr e
-
-          (Done x _) -> return x
-
-          (Cont _ (Just e)) -> throwErr e
-
-          (Cont k Nothing) -> joinIM $
-                              chunkParserToEnumerator getChunk k
-
-    finishIt iter = do
-        e <- lift $ sendEof iter
-
-        case e of
-          Left x  -> throwErr x
-          Right x -> return x
-
-    sendEof iter = do
-        v <- runIter iter (EOF Nothing)
-
-        return $ case v of
-          (Done _ (EOF (Just e))) -> Left e
-          (Done x _)              -> Right x
-          (Cont _ (Just e))       -> Left e
-          (Cont _ _)              -> Left $ Err $ "divergent iteratee"
-
-
-------------------------------------------------------------------------------
--- parse functions
-------------------------------------------------------------------------------
-
--- theft alert: many of these routines adapted from Johan Tibell's hyena
--- package
-
--- | Parsers for different tokens in an HTTP request.
-sp, digit, letter :: Parser Word8
-sp       = word8 $ c2w ' '
-digit    = satisfy (isDigit . w2c)
-letter   = satisfy (isAlpha . w2c)
-
-untilEOL :: Parser ByteString
-untilEOL = takeWhile notend
-  where
-    notend d = let c = w2c d in not $ c == '\r' || c == '\n'
-
-crlf :: Parser ByteString
-crlf = string "\r\n"
-
--- | Parser for zero or more spaces.
-spaces :: Parser [Word8]
-spaces = many sp
-
-pSpaces :: Parser ByteString
-pSpaces = takeWhile (isSpace . w2c)
-
--- | Parser for the internal request data type.
-pRequest :: Parser (Maybe IRequest)
-pRequest = (Just <$> pRequest') <|> (endOfInput *> pure Nothing)
-
-pRequest' :: Parser IRequest
-pRequest' = IRequest
-               <$> (option "" crlf *> pMethod)  <* sp
-               <*> pUri                         <* sp
-               <*> pVersion                     <* crlf
-               <*> pHeaders                     <* crlf
-
-  -- note: the optional crlf is at the beginning because some older browsers
-  -- send an extra crlf after a POST body
-
-
--- | Parser for the request method.
-pMethod :: Parser Method
-pMethod =     (OPTIONS <$ string "OPTIONS")
-          <|> (GET     <$ string "GET")
-          <|> (HEAD    <$ string "HEAD")
-          <|> word8 (c2w 'P') *> ((POST <$ string "OST") <|>
-                                  (PUT  <$ string "UT"))
-          <|> (DELETE  <$ string "DELETE")
-          <|> (TRACE   <$ string "TRACE")
-          <|> (CONNECT <$ string "CONNECT")
-
--- | Parser for the request URI.
-pUri :: Parser ByteString
-pUri = takeWhile (not . isSpace . w2c)
-
--- | Parser for the request's HTTP protocol version.
-pVersion :: Parser (Int, Int)
-pVersion = string "HTTP/" *>
-           liftA2 (,) (digit' <* word8 (c2w '.')) digit'
-    where
-      digit' = fmap (digitToInt . w2c) digit
-
-fieldChars :: Parser ByteString
-fieldChars = takeWhile isFieldChar
-  where
-    isFieldChar c = (Vec.!) fieldCharTable (fromEnum c)
-
-fieldCharTable :: Vector Bool
-fieldCharTable = Vec.generate 256 f
-  where
-    f d = let c=toEnum d in (isDigit c) || (isAlpha c) || c == '-' || c == '_'
-
-
--- | Parser for request headers.
-pHeaders :: Parser [(ByteString, ByteString)]
-pHeaders = many header
-  where
-    header = {-# SCC "pHeaders/header" #-}
-             liftA2 (,)
-                 fieldName
-                 (word8 (c2w ':') *> spaces *> contents)
-
-    fieldName = {-# SCC "pHeaders/fieldName" #-}
-                liftA2 S.cons letter fieldChars
-
-    contents = {-# SCC "pHeaders/contents" #-}
-               liftA2 S.append
-                   (untilEOL <* crlf)
-                   (continuation <|> pure S.empty)
-
-    isLeadingWS w = {-# SCC "pHeaders/isLeadingWS" #-}
-                    elem w wstab
-
-    wstab = map c2w " \t"
-
-    leadingWhiteSpace = {-# SCC "pHeaders/leadingWhiteSpace" #-}
-                        takeWhile1 isLeadingWS
-
-    continuation = {-# SCC "pHeaders/continuation" #-}
-                   liftA2 S.cons
-                          (leadingWhiteSpace *> pure (c2w ' '))
-                          contents
-
-
-pGetTransferChunk :: Parser (Maybe ByteString)
-pGetTransferChunk = do
-    !hex <- liftM fromHex $ (takeWhile (isHexDigit . w2c))
-    takeTill ((== '\r') . w2c)
-    crlf
-    if hex <= 0
-      then return Nothing
-      else do
-          x <- take hex
-          crlf
-          return $ Just x
-  where
-    fromHex :: ByteString -> Int
-    fromHex s = Cvt.hex (L.fromChunks [s])
-
-
-------------------------------------------------------------------------------
--- COOKIE PARSING
-------------------------------------------------------------------------------
-
--- these definitions try to mirror RFC-2068 (the HTTP/1.1 spec) and RFC-2109
--- (cookie spec): please point out any errors!
-
-{-# INLINE matchAll #-}
-matchAll :: [ Char -> Bool ] -> Char -> Bool
-matchAll x c = and $ map ($ c) x
-
-{-# INLINE isToken #-}
-isToken :: Char -> Bool
-isToken c = (Vec.!) tokenTable (fromEnum c)
-  where
-    tokenTable :: Vector Bool
-    tokenTable = Vec.generate 256 (f . toEnum)
-
-    f = matchAll [ isAscii
-                 , not . isControl
-                 , not . isSpace 
-                 , not . flip elem [ '(', ')', '<', '>', '@', ',', ';'
-                                   , ':', '\\', '\"', '/', '[', ']'
-                                   , '?', '=', '{', '}' ]
-                 ]
-
-{-# INLINE isRFCText #-}
-isRFCText :: Char -> Bool
-isRFCText = not . isControl
-
-pToken :: Parser ByteString
-pToken = takeWhile (isToken . w2c)
-
-
-pQuotedString :: Parser ByteString
-pQuotedString = q *> quotedText <* q
-  where
-    quotedText = (S.concat . reverse) <$> f []
-
-    f soFar = do
-        t <- takeWhile qdtext
-
-        let soFar' = t:soFar
-
-        -- RFC says that backslash only escapes for <">
-        choice [ string "\\\"" *> f ("\"" : soFar')
-               , pure soFar' ]
-
-
-    q = word8 $ c2w '\"'
-
-    qdtext = matchAll [ isRFCText, (/= '\"'), (/= '\\') ] . w2c
-    
-
-pCookie :: Parser Cookie
-pCookie = do
-    -- grab kvps and turn to strict bytestrings
-    kvps <- pAvPairs
-
-    -- kvps guaranteed non-null due to grammar. First avpair specifies
-    -- name=value mapping.
-    let ((nm,val):attrs') = kvps
-    let attrs             = map (first toCI) attrs'
-
-    -- and we'll gather the rest of the fields with helper functions.
-    return $ foldl' field (nullCookie nm val) attrs
-
-
-  where
-    nullCookie nm val = Cookie nm val Nothing Nothing Nothing
-
-    fieldFuncs :: [ (CIByteString, Cookie -> ByteString -> Cookie) ]
-    fieldFuncs = [ ("domain", domain)
-                 , ("expires", expires)
-                 , ("path", path) ]
-
-    domain c d     = c { cookieDomain  = Just d }
-    path c p       = c { cookiePath    = Just p }
-    expires c e    = c { cookieExpires = parseExpires e }
-    parseExpires e = parseTime defaultTimeLocale
-                               "%a, %d-%b-%Y %H:%M:%S GMT"
-                               (map w2c $ S.unpack e)
-
-    field c (k,v) = fromMaybe c (flip ($ c) v <$> lookup k fieldFuncs)
-
-
--- unhelpfully, the spec mentions "old-style" cookies that don't have quotes
--- around the value. wonderful.
-pWord :: Parser ByteString
-pWord = pQuotedString <|> (takeWhile ((/= ';') . w2c))
-
-pAvPairs :: Parser [(ByteString, ByteString)]
-pAvPairs = do
-    a <- pAvPair
-    b <- many (pSpaces *> char ';' *> pSpaces *> pAvPair)
-
-    return $ a:b
-
-pAvPair :: Parser (ByteString, ByteString)
-pAvPair = do
-    key <- pToken <* pSpaces
-    val <- option "" $ char '=' *> pSpaces *> pWord
-
-    return (key,val)
-
-parseCookie :: ByteString -> Maybe Cookie
-parseCookie = parseToCompletion pCookie
-
-------------------------------------------------------------------------------
--- MULTIPART/FORMDATA
-------------------------------------------------------------------------------
-
-parseUrlEncoded :: ByteString -> Map ByteString [ByteString]
-parseUrlEncoded s = foldl' (\m (k,v) -> Map.insertWith' (++) k [v] m)
-                           Map.empty
-                           decoded
-  where
-    breakApart = (second (S.drop 1)) . S.break (== (c2w '=')) 
-
-    parts :: [(ByteString,ByteString)]
-    parts = map breakApart $ S.split (c2w '&') s
-
-    urldecode = parseToCompletion pUrlEscaped
-
-    decodeOne (a,b) = do
-        a' <- urldecode a
-        b' <- urldecode b
-        return (a',b')
-
-    decoded = catMaybes $ map decodeOne parts
-
-
-------------------------------------------------------------------------------
--- utility functions
-------------------------------------------------------------------------------
-
-strictize :: L.ByteString -> ByteString
-strictize         = S.concat . L.toChunks
-
-------------------------------------------------------------------------------
-char :: Char -> Parser Word8
-char = word8 . c2w
-
-
- diff --git a/static/docs/0.1.2/snap-server/src/Snap-Internal-Http-Server-Date.html b/static/docs/0.1.2/snap-server/src/Snap-Internal-Http-Server-Date.html deleted file mode 100644 index 40a5e91..0000000 --- a/static/docs/0.1.2/snap-server/src/Snap-Internal-Http-Server-Date.html +++ /dev/null @@ -1,125 +0,0 @@ - - - - -src/Snap/Internal/Http/Server/Date.hs - - - -
{-# LANGUAGE BangPatterns #-}
-
-module Snap.Internal.Http.Server.Date
-( getDateString
-, getLogDateString
-, getCurrentDateTime) where
-
-import           Control.Concurrent
-import           Control.Exception
-import           Control.Monad
-import           Data.ByteString (ByteString)
-import           Data.ByteString.Internal (c2w)
-import qualified Data.ByteString as B
-import           Data.IORef
-import           Data.Time.Clock
-import           Data.Time.LocalTime
-import           Data.Time.Format
-import           System.IO.Unsafe
-import           System.Locale
-
-
--- Here comes a dirty hack. We don't want to be wasting context switches
--- building date strings, so we're only going to compute one every two
--- seconds. (Approximate timestamps to within a couple of seconds are OK here,
--- and we'll reduce overhead.)
---
--- Note that we also don't want to wake up a potentially sleeping CPU by just
--- running the computation on a timer. We'll allow client traffic to trigger
--- the process.
-
-data DateState = DateState {
-      _cachedDateString :: !(IORef ByteString)
-    , _cachedLogString  :: !(IORef ByteString)
-    , _cachedDate       :: !(IORef UTCTime)
-    , _valueIsOld       :: !(IORef Bool)
-    , _morePlease       :: !(MVar ())
-    , _dataAvailable    :: !(MVar ())
-    , _dateThread       :: !(MVar ThreadId)
-    }
-
-dateState :: DateState
-dateState = unsafePerformIO $ do
-    (s1,s2,date) <- fetchTime
-    bs1 <- newIORef s1
-    bs2 <- newIORef s2
-    dt  <- newIORef date
-    ov  <- newIORef False
-    th  <- newEmptyMVar
-    mp  <- newMVar ()
-    da  <- newMVar ()
-
-    let d = DateState bs1 bs2 dt ov mp da th
-
-    t  <- forkIO $ dateThread d
-    putMVar th t
-
-    return d
-
-
-fetchTime :: IO (ByteString,ByteString,UTCTime)
-fetchTime = do
-     now <- getCurrentTime
-     zt  <- liftM zonedTimeToLocalTime getZonedTime
-     return (t1 now, t2 zt, now)
-  where
-    t1 now = B.pack $ map c2w $
-             formatTime defaultTimeLocale "%a, %d %b %Y %H:%M:%S GMT" now
-    t2 now = B.pack $ map c2w $
-             formatTime defaultTimeLocale "%d/%b/%Y:%H:%M:%S %z" now
-
-dateThread :: DateState -> IO ()
-dateThread ds@(DateState dateString logString time valueIsOld morePlease
-                         dataAvailable _) = do
-    -- a lot of effort to make sure we don't deadlock
-    takeMVar morePlease
-
-    (s1,s2,now) <- fetchTime
-    atomicModifyIORef dateString $ const (s1,())
-    atomicModifyIORef logString $ const (s2,())
-    atomicModifyIORef time $ const (now,())
-
-    writeIORef valueIsOld False
-    tryPutMVar dataAvailable ()
-
-    threadDelay 2000000
-
-    takeMVar dataAvailable
-    writeIORef valueIsOld True
-
-    dateThread ds
-
-ensureFreshDate :: IO ()
-ensureFreshDate = block $ do
-    old <- readIORef $ _valueIsOld dateState
-    when old $ do
-        tryPutMVar (_morePlease dateState) ()
-        readMVar $ _dataAvailable dateState
-
-getDateString :: IO ByteString
-getDateString = block $ do
-    ensureFreshDate
-    readIORef $ _cachedDateString dateState
-
-
-getLogDateString :: IO ByteString
-getLogDateString = block $ do
-    ensureFreshDate
-    readIORef $ _cachedLogString dateState
-
-
-getCurrentDateTime :: IO UTCTime
-getCurrentDateTime = block $ do
-    ensureFreshDate
-    readIORef $ _cachedDate dateState
-
-
- diff --git a/static/docs/0.1.2/snap-server/src/Snap-Internal-Http-Server-SimpleBackend.html b/static/docs/0.1.2/snap-server/src/Snap-Internal-Http-Server-SimpleBackend.html deleted file mode 100644 index ae662c5..0000000 --- a/static/docs/0.1.2/snap-server/src/Snap-Internal-Http-Server-SimpleBackend.html +++ /dev/null @@ -1,270 +0,0 @@ - - - - -dist/build/Snap/Internal/Http/Server/SimpleBackend.hs - - - -
{-# LINE 1 "src/Snap/Internal/Http/Server/SimpleBackend.hsc" #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LINE 2 "src/Snap/Internal/Http/Server/SimpleBackend.hsc" #-}
-{-# LANGUAGE ForeignFunctionInterface #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RankNTypes #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module Snap.Internal.Http.Server.SimpleBackend
-( Backend
-, BackendTerminatedException
-, Connection
-, TimeoutException
-, debug
-, bindIt
-, new
-, stop
-, withConnection
-, sendFile
-, getReadEnd
-, getWriteEnd
-, getRemoteAddr
-, getRemotePort
-, getLocalAddr
-, getLocalPort
-) where
-
-------------------------------------------------------------------------------
-import           Control.Concurrent
-import           Control.Exception
-import           Control.Monad.Trans
-import           Data.ByteString (ByteString)
-import           Data.ByteString.Internal (c2w, w2c)
-import qualified Data.ByteString as B
-import           Data.Iteratee.WrappedByteString
-import           Data.Typeable
-
-{-# LINE 38 "src/Snap/Internal/Http/Server/SimpleBackend.hsc" #-}
-import           Foreign.C.Types
-import           GHC.Conc (labelThread, forkOnIO)
-import           Network.Socket
-import qualified Network.Socket.ByteString as SB
-import qualified Network.Socket.SendFile as SF
-import           Prelude hiding (catch)
-------------------------------------------------------------------------------
-import           Snap.Internal.Debug
-import           Snap.Iteratee
-
-
-data BackendTerminatedException = BackendTerminatedException
-   deriving (Typeable)
-
-instance Show BackendTerminatedException where
-    show (BackendTerminatedException) = "Backend terminated"
-
-instance Exception BackendTerminatedException
-
-
--- foreign import ccall unsafe "set_linger"
---   set_linger :: CInt -> IO ()
-
-foreign import ccall unsafe "set_fd_timeout"
-  set_fd_timeout :: CInt -> IO ()
-
-
-data Backend = Backend
-    { _acceptSocket :: Socket }
-
-data Connection = Connection 
-    { _socket      :: Socket
-    , _remoteAddr  :: ByteString
-    , _remotePort  :: Int
-    , _localAddr   :: ByteString
-    , _localPort   :: Int }
-
-
-sendFile :: Connection -> FilePath -> IO ()
-sendFile c fp = do
-    let s = _socket c
-    SF.sendFile s fp
-
-
-bindIt :: ByteString         -- ^ bind address, or \"*\" for all
-       -> Int                -- ^ port to bind to
-       -> IO Socket
-bindIt bindAddress bindPort = do
-    sock <- socket AF_INET Stream 0
-    addr <- getHostAddr bindPort bindAddress
-    setSocketOption sock ReuseAddr 1
-    bindSocket sock addr
-    listen sock bindPort
-    return sock
-
-
-new :: Socket   -- ^ value you got from bindIt
-    -> Int
-    -> IO Backend
-new sock _ = do
-    debug $ "Backend.new: listening"
-    return $ Backend sock
-
-
-stop :: Backend -> IO ()
-stop (Backend s) = do
-    debug $ "Backend.stop"
-    sClose s
-
-
-data AddressNotSupportedException = AddressNotSupportedException String
-   deriving (Typeable)
-
-instance Show AddressNotSupportedException where
-    show (AddressNotSupportedException x) = "Address not supported: " ++ x
-
-instance Exception AddressNotSupportedException
-
-
-withConnection :: Backend -> Int -> (Connection -> IO ()) -> IO ()
-withConnection (Backend asock) cpu proc = do
-    debug $ "Backend.withConnection: calling accept()"
-    (sock,addr) <- accept asock
-
-    let fd = fdSocket sock
-    -- set linger
-    --set_linger fd
-    set_fd_timeout fd
-
-    debug $ "Backend.withConnection: accepted connection"
-    debug $ "Backend.withConnection: remote: " ++ show addr
-
-    (port,host) <-
-        case addr of
-          SockAddrInet p h -> do
-             h' <- inet_ntoa h
-             return (fromIntegral p, B.pack $ map c2w h')
-          x -> throwIO $ AddressNotSupportedException $ show x
-
-    laddr <- getSocketName sock
-
-    (lport,lhost) <-
-        case laddr of
-          SockAddrInet p h -> do
-             h' <- inet_ntoa h
-             return (fromIntegral p, B.pack $ map c2w h')
-          x -> throwIO $ AddressNotSupportedException $ show x
-
-    let c = Connection sock host port lhost lport
-
-    forkOnIO cpu $ do
-        labelMe $ "connHndl " ++ show fd
-        bracket (return c)
-                (\_ -> do
-                     debug "sClose sock"
-                     eatException $ shutdown sock ShutdownBoth
-                     eatException $ sClose sock
-                     eatException $ sClose sock
-                )
-                proc
-
-    return ()
-
-
-labelMe :: String -> IO ()
-labelMe s = do
-    tid <- myThreadId
-    labelThread tid s
-
-
-eatException :: IO a -> IO ()
-eatException act = (act >> return ()) `catch` \(_::SomeException) -> return ()
-
-getReadEnd :: Connection -> Enumerator IO a
-getReadEnd = enumerate
-
-
-getWriteEnd :: Connection -> Iteratee IO ()
-getWriteEnd = writeOut
-
-
-getRemoteAddr :: Connection -> ByteString
-getRemoteAddr = _remoteAddr
-
-getRemotePort :: Connection -> Int
-getRemotePort = _remotePort
-
-getLocalAddr :: Connection -> ByteString
-getLocalAddr = _localAddr
-
-getLocalPort :: Connection -> Int
-getLocalPort = _localPort
-
-------------------------------------------------------------------------------
-getHostAddr :: Int
-            -> ByteString
-            -> IO SockAddr
-getHostAddr p s = do
-    h <- if s == "*"
-          then return iNADDR_ANY
-          else inet_addr (map w2c . B.unpack $ s)
-
-    return $ SockAddrInet (fromIntegral p) h
-
-
-
-data TimeoutException = TimeoutException
-   deriving (Typeable)
-
-instance Show TimeoutException where
-    show TimeoutException = "timeout"
-
-instance Exception TimeoutException
-
-
-timeoutRecv :: Connection -> Int -> IO ByteString
-timeoutRecv conn n = do
-    let sock = _socket conn
-    SB.recv sock n
-
-timeoutSend :: Connection -> ByteString -> IO ()
-timeoutSend conn s = do
-    let sock = _socket conn
-    SB.sendAll sock s
-
-
-bLOCKSIZE :: Int
-bLOCKSIZE = 8192
-
-
-enumerate :: (MonadIO m) => Connection -> Enumerator m a
-enumerate = loop
-  where
-    loop conn f = do
-        s <- liftIO $ timeoutRecv conn bLOCKSIZE
-        sendOne conn f s
-
-    sendOne conn f s = do
-        v <- runIter f (if B.null s
-                         then EOF Nothing
-                         else Chunk $ WrapBS s)
-        case v of
-          r@(Done _ _)      -> return $ liftI r
-          (Cont k Nothing)  -> loop conn k
-          (Cont _ (Just e)) -> return $ throwErr e
-
-
-writeOut :: (MonadIO m) => Connection -> Iteratee m ()
-writeOut conn = IterateeG out
-  where
-    out c@(EOF _)   = return $ Done () c
-
-    out (Chunk s) = do
-        let x = unWrap s
-
-        ee <- liftIO $ ((try $ timeoutSend conn x)
-                            :: IO (Either SomeException ()))
-
-        case ee of
-          (Left e)  -> return $ Done () (EOF $ Just $ Err $ show e)
-          (Right _) -> return $ Cont (writeOut conn) Nothing
-
-
- diff --git a/static/docs/0.1.2/snap-server/src/Snap-Internal-Http-Server.html b/static/docs/0.1.2/snap-server/src/Snap-Internal-Http-Server.html deleted file mode 100644 index e51b977..0000000 --- a/static/docs/0.1.2/snap-server/src/Snap-Internal-Http-Server.html +++ /dev/null @@ -1,633 +0,0 @@ - - - - -src/Snap/Internal/Http/Server.hs - - - -
{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE CPP #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module Snap.Internal.Http.Server where
-
-------------------------------------------------------------------------------
-import           Control.Arrow (first, second)
-import           Control.Monad.State.Strict
-import           Control.Concurrent.MVar
-import           Control.Exception
-import           Data.Char
-import           Data.CIByteString
-import           Data.ByteString (ByteString)
-import qualified Data.ByteString as S
-import qualified Data.ByteString.Lazy as L
-import           Data.ByteString.Internal (c2w, w2c)
-import qualified Data.ByteString.Nums.Careless.Int as Cvt
-import           Data.IORef
-import           Data.List (foldl')
-import qualified Data.Map as Map
-import           Data.Maybe (fromJust, catMaybes, fromMaybe)
-import           Data.Monoid
-import           GHC.Conc
-import           Prelude hiding (catch, show, Show)
-import qualified Prelude
-import           System.Posix.Files hiding (setFileSize)
-import           Text.Show.ByteString hiding (runPut)
-------------------------------------------------------------------------------
-import           System.FastLogger
-import           Snap.Internal.Http.Types hiding (Enumerator)
-import           Snap.Internal.Http.Parser
-import           Snap.Iteratee hiding (foldl', head, take)
-import qualified Snap.Iteratee as I
-
-#ifdef LIBEV
-import qualified Snap.Internal.Http.Server.LibevBackend as Backend
-import           Snap.Internal.Http.Server.LibevBackend (debug)
-#else
-import qualified Snap.Internal.Http.Server.SimpleBackend as Backend
-import           Snap.Internal.Http.Server.SimpleBackend (debug)
-#endif
-
-import           Snap.Internal.Http.Server.Date
-
-------------------------------------------------------------------------------
--- | The handler has to return the request object because we have to clear the
--- HTTP request body before we send the response. If the handler consumes the
--- request body, it is responsible for setting @rqBody=return@ in the returned
--- request (otherwise we will mess up reading the input stream).
---
--- Note that we won't be bothering end users with this -- the details will be
--- hidden inside the Snap monad
-type ServerHandler = Request -> Iteratee IO (Request,Response)
-
-type ServerMonad = StateT ServerState (Iteratee IO)
-
-data ServerState = ServerState
-    { _forceConnectionClose  :: Bool
-    , _localHostname         :: ByteString
-    , _localAddress          :: ByteString
-    , _localPort             :: Int
-    , _remoteAddr            :: ByteString
-    , _remotePort            :: Int
-    , _logAccess             :: Request -> Response -> IO ()
-    , _logError              :: ByteString -> IO ()
-    }
-
-
-------------------------------------------------------------------------------
-runServerMonad :: ByteString                     -- ^ local host name
-               -> ByteString                     -- ^ local ip address
-               -> Int                            -- ^ local port
-               -> ByteString                     -- ^ remote ip address
-               -> Int                            -- ^ remote port
-               -> (Request -> Response -> IO ()) -- ^ access log function
-               -> (ByteString -> IO ())          -- ^ error log function
-               -> ServerMonad a                  -- ^ monadic action to run
-               -> Iteratee IO a
-runServerMonad lh lip lp rip rp la le m = evalStateT m st
-  where
-    st = ServerState False lh lip lp rip rp la le
-
-
-
-------------------------------------------------------------------------------
--- input/output
-
-
-------------------------------------------------------------------------------
-httpServe :: ByteString         -- ^ bind address, or \"*\" for all
-          -> Int                -- ^ port to bind to
-          -> ByteString         -- ^ local hostname (server name)
-          -> Maybe FilePath     -- ^ path to the access log
-          -> Maybe FilePath     -- ^ path to the error log
-          -> ServerHandler      -- ^ handler procedure
-          -> IO ()
-httpServe bindAddress bindPort localHostname alogPath elogPath handler =
-    withLoggers alogPath elogPath
-                (\(alog, elog) -> spawnAll alog elog)
-
-  where
-    spawnAll alog elog = do
-        let n = numCapabilities
-        bracket (spawn n)
-                (\xs -> do
-                     logE elog "Server.httpServe: SHUTDOWN"
-                     mapM_ (Backend.stop . fst) xs
-                     logE elog "Server.httpServe: BACKEND STOPPED")
-                (runAll alog elog)
-
-
-    runAll alog elog xs = do
-        mapM_ f $ xs `zip` [0..]
-        mapM_ (takeMVar . snd) xs
-      where
-        f ((backend,mvar),cpu) =
-            forkOnIO cpu $ do
-                labelMe $ map w2c $ S.unpack $
-                          S.concat ["accThread ", l2s $ show cpu]
-                (try $ (goooo alog elog backend cpu)) :: IO (Either SomeException ())
-                putMVar mvar ()
-
-    goooo alog elog backend cpu =
-        let loop = go alog elog backend cpu >> loop
-        in loop
-
-    maybeSpawnLogger = maybe (return Nothing) $ (liftM Just) . newLogger
-
-    withLoggers afp efp =
-        bracket (do alog <- maybeSpawnLogger afp
-                    elog <- maybeSpawnLogger efp
-                    return (alog, elog))
-                (\(alog, elog) -> do
-                    threadDelay 1000000
-                    maybe (return ()) stopLogger alog
-                    maybe (return ()) stopLogger elog)
-
-    labelMe :: String -> IO ()
-    labelMe s = do
-        tid <- myThreadId
-        labelThread tid s
-
-    spawn n = do
-        sock <- Backend.bindIt bindAddress bindPort
-        backends <- mapM (Backend.new sock) $ [0..(n-1)]
-        mvars <- replicateM n newEmptyMVar
-
-        return (backends `zip` mvars)
-
-
-    runOne alog elog backend cpu = Backend.withConnection backend cpu $ \conn -> do
-        debug "Server.httpServe.runOne: entered"
-        let readEnd = Backend.getReadEnd conn
-        writeEnd <- I.bufferIteratee $ Backend.getWriteEnd conn
-
-        let raddr = Backend.getRemoteAddr conn
-        let rport = Backend.getRemotePort conn
-        let laddr = Backend.getLocalAddr conn
-        let lport = Backend.getLocalPort conn
-
-        runHTTP localHostname laddr lport raddr rport
-                alog elog readEnd writeEnd (Backend.sendFile conn)
-                handler
-
-        debug "Server.httpServe.runHTTP: finished"
-
-
-    go alog elog backend cpu = runOne alog elog backend cpu
-        `catches`
-        [ Handler $ \(_ :: Backend.TimeoutException) -> return ()
-
-        , Handler $ \(e :: AsyncException) -> do
-              logE elog $
-                   S.concat [ "Server.httpServe.go: got async exception, "
-                            , "terminating:\n", bshow e ]
-              throwIO e
-
-        , Handler $ \(e :: Backend.BackendTerminatedException) -> do
-              logE elog $ "Server.httpServe.go: got backend terminated, waiting for cleanup"
-              throwIO e
-
-        , Handler $ \(e :: IOException) -> do
-              logE elog $ S.concat [ "Server.httpServe.go: got io exception: "
-                                   , bshow e ]
-
-        , Handler $ \(e :: SomeException) -> do
-              logE elog $ S.concat [
-                        "Server.httpServe.go: got someexception: "
-                       , bshow e ]
-              return () ]
-
-------------------------------------------------------------------------------
-debugE :: (MonadIO m) => ByteString -> m ()
-debugE s = debug $ "Server: " ++ (map w2c $ S.unpack s)
-
-
-------------------------------------------------------------------------------
-logE :: Maybe Logger -> ByteString -> IO ()
-logE elog = maybe debugE (\l s -> debugE s >> logE' l s) elog
-
-logE' :: Logger -> ByteString -> IO ()
-logE' logger s = (timestampedLogEntry s) >>= logMsg logger
-
-
-bshow :: (Prelude.Show a) => a -> ByteString
-bshow = toBS . Prelude.show
-
-------------------------------------------------------------------------------
-logA ::Maybe Logger -> Request -> Response -> IO ()
-logA alog = maybe (\_ _ -> return ()) logA' alog
-
-logA' :: Logger -> Request -> Response -> IO ()
-logA' logger req rsp = do
-    let hdrs      = rqHeaders req
-    let host      = rqRemoteAddr req
-    let user      = Nothing -- TODO we don't do authentication yet
-    let (v, v')   = rqVersion req
-    let ver       = S.concat [ "HTTP/", bshow v, ".", bshow v' ]
-    let method    = toBS $ Prelude.show (rqMethod req)
-    let reql      = S.intercalate " " [ method, rqURI req, ver ]
-    let status    = rspStatus rsp
-    let cl        = rspContentLength rsp
-    let referer   = maybe Nothing (Just . head) $ Map.lookup "referer" hdrs
-    let userAgent = maybe "-" head $ Map.lookup "user-agent" hdrs
-
-    msg <- combinedLogEntry host user reql status cl referer userAgent
-    logMsg logger msg
-
-
-------------------------------------------------------------------------------
-runHTTP :: ByteString           -- ^ local host name
-        -> ByteString           -- ^ local ip address
-        -> Int                  -- ^ local port
-        -> ByteString           -- ^ remote ip address
-        -> Int                  -- ^ remote port
-        -> Maybe Logger         -- ^ access logger
-        -> Maybe Logger         -- ^ error logger
-        -> Enumerator IO ()     -- ^ read end of socket
-        -> Iteratee IO ()       -- ^ write end of socket
-        -> (FilePath -> IO ())  -- ^ sendfile end
-        -> ServerHandler        -- ^ handler procedure
-        -> IO ()
-runHTTP lh lip lp rip rp alog elog readEnd writeEnd onSendFile handler =
-    go `catches` [ Handler $ \(e :: AsyncException) -> do
-                       throwIO e
-
-                 , Handler $ \(_ :: Backend.TimeoutException) -> return ()
-
-                 , Handler $ \(e :: SomeException) ->
-                             logE elog $ toBS $ Prelude.show e ]
-
-  where
-    go = do
-        let iter = runServerMonad lh lip lp rip rp (logA alog) (logE elog) $
-                                  httpSession writeEnd onSendFile handler
-        readEnd iter >>= run
-
-
-------------------------------------------------------------------------------
-sERVER_HEADER :: [ByteString]
-sERVER_HEADER = ["Snap/0.pre-1"]
-
-
-------------------------------------------------------------------------------
-logAccess :: Request -> Response -> ServerMonad ()
-logAccess req rsp = gets _logAccess >>= (\l -> liftIO $ l req rsp)
-
-------------------------------------------------------------------------------
-logError :: ByteString -> ServerMonad ()
-logError s = gets _logError >>= (\l -> liftIO $ l s)
-
-------------------------------------------------------------------------------
--- | Runs an HTTP session.
-httpSession :: Iteratee IO ()       -- ^ write end of socket
-            -> (FilePath -> IO ())  -- ^ sendfile continuation
-            -> ServerHandler        -- ^ handler procedure
-            -> ServerMonad ()
-httpSession writeEnd onSendFile handler = do
-    liftIO $ debug "Server.httpSession: entered"
-    mreq       <- receiveRequest
-
-    case mreq of
-      (Just req) -> do
-          (req',rspOrig) <- lift $ handler req
-          let rspTmp = rspOrig { rspHttpVersion = rqVersion req }
-          checkConnectionClose (rspHttpVersion rspTmp) (rspHeaders rspTmp)
-
-          cc <- gets _forceConnectionClose
-          let rsp = if cc
-                      then (setHeader "Connection" "close" rspTmp)
-                      else rspTmp
-
-
-          liftIO $ debug "Server.httpSession: handled, skipping request body"
-          srqEnum <- liftIO $ readIORef $ rqBody req'
-          let (SomeEnumerator rqEnum) = srqEnum
-          lift $ joinIM $ rqEnum skipToEof
-          liftIO $ debug "Server.httpSession: request body skipped, sending response"
-
-          date <- liftIO getDateString
-          let ins = (Map.insert "Date" [date] . Map.insert "Server" sERVER_HEADER)
-          let rsp' = updateHeaders ins rsp
-          (bytesSent,_) <- sendResponse rsp' writeEnd onSendFile
-
-          maybe (logAccess req rsp')
-                (\_ -> logAccess req $ setContentLength bytesSent rsp')
-                (rspContentLength rsp')
-
-          if cc
-             then return ()
-             else httpSession writeEnd onSendFile handler
-
-      Nothing -> return ()
-
-------------------------------------------------------------------------------
-receiveRequest :: ServerMonad (Maybe Request)
-receiveRequest = do
-    mreq <- lift parseRequest
-
-    case mreq of
-      (Just ireq) -> do
-          req' <- toRequest ireq
-          setEnumerator req'
-          req  <- parseForm req'
-          checkConnectionClose (rqVersion req) (rqHeaders req)
-          return $ Just req
-
-      Nothing     -> return Nothing
-
-
-  where
-    -- check: did the client specify "transfer-encoding: chunked"? then we have
-    -- to honor that.
-    --
-    -- otherwise: check content-length header. if set: only take N bytes from
-    -- the read end of the socket
-    --
-    -- if no content-length and no chunked encoding, enumerate the entire
-    -- socket and close afterwards
-    setEnumerator :: Request -> ServerMonad ()
-    setEnumerator req =
-        if isChunked
-          then liftIO $ writeIORef (rqBody req)
-                                   (SomeEnumerator readChunkedTransferEncoding)
-          else maybe noContentLength hasContentLength mbCL
-
-      where
-        isChunked = maybe False
-                          ((== ["chunked"]) . map toCI)
-                          (Map.lookup "transfer-encoding" hdrs)
-
-        hasContentLength :: Int -> ServerMonad ()
-        hasContentLength l = do
-            liftIO $ writeIORef (rqBody req)
-                         (SomeEnumerator e)
-          where
-            e :: Enumerator IO a
-            e = return . joinI . I.take l
-
-        noContentLength :: ServerMonad ()
-        noContentLength =
-            liftIO $ writeIORef (rqBody req)
-                (SomeEnumerator $ return . joinI . I.take 0 )
-
-
-        hdrs = rqHeaders req
-        mbCL = Map.lookup "content-length" hdrs >>= return . Cvt.int . head
-
-
-    parseForm :: Request -> ServerMonad Request
-    parseForm req = if doIt then getIt else return req
-      where
-        doIt = mbCT == Just "application/x-www-form-urlencoded"
-        mbCT = liftM head $ Map.lookup "content-type" (rqHeaders req)
-
-        maximumPOSTBodySize :: Int
-        maximumPOSTBodySize = 10*1024*1024
-
-        getIt :: ServerMonad Request
-        getIt = do
-            senum <- liftIO $ readIORef $ rqBody req
-            let (SomeEnumerator enum) = senum
-            let i = joinI $ takeNoMoreThan maximumPOSTBodySize stream2stream
-            iter <- liftIO $ enum i
-            body <- lift iter
-            let newParams = parseUrlEncoded $ strictize $ fromWrap body
-            liftIO $ writeIORef (rqBody req)
-                         (SomeEnumerator $ return . I.joinI . I.take 0)
-            return $ req { rqParams = rqParams req `mappend` newParams }
-
-
-    toRequest (IRequest method uri version kvps) = do
-        localAddr     <- gets _localAddress
-        localPort     <- gets _localPort
-        remoteAddr    <- gets _remoteAddr
-        remotePort    <- gets _remotePort
-        localHostname <- gets _localHostname
-
-        let (serverName, serverPort) = fromMaybe
-                                         (localHostname, localPort)
-                                         (liftM (parseHost . head)
-                                                (Map.lookup "host" hdrs))
-
-        -- will override in "setEnumerator"
-        enum <- liftIO $ newIORef $ SomeEnumerator return
-
-
-        return $ Request serverName
-                         serverPort
-                         remoteAddr
-                         remotePort
-                         localAddr
-                         localPort
-                         localHostname
-                         isSecure
-                         hdrs
-                         enum
-                         mbContentLength
-                         method
-                         version
-                         cookies
-                         snapletPath
-                         pathInfo
-                         contextPath
-                         uri
-                         queryString
-                         params
-
-      where
-        snapletPath = ""        -- TODO: snaplets in v0.2
-
-        dropLeadingSlash s = maybe s f mbS
-          where
-            f (a,s') = if a == c2w '/' then s' else s
-            mbS = S.uncons s
-
-        isSecure        = False
-
-        hdrs            = toHeaders kvps
-
-        mbContentLength = liftM (Cvt.int . head) $
-                          Map.lookup "content-length" hdrs
-
-        cookies         = maybe []
-                                (catMaybes . map parseCookie)
-                                (Map.lookup "set-cookie" hdrs)
-
-        contextPath     = "/"
-
-        parseHost h = (a, Cvt.int (S.drop 1 b))
-          where
-            (a,b) = S.break (== (c2w ':')) h
-
-        params          = parseUrlEncoded queryString
-
-        (pathInfo, queryString) = first dropLeadingSlash . second (S.drop 1) $
-                                  S.break (== (c2w '?')) uri
-
-
-------------------------------------------------------------------------------
--- Response must be well-formed here
-sendResponse :: Response
-             -> Iteratee IO a
-             -> (FilePath -> IO a)
-             -> ServerMonad (Int,a)
-sendResponse rsp' writeEnd onSendFile = do
-    rsp <- fixupResponse rsp'
-    let !headerString = mkHeaderString rsp
-
-    (!x,!bs) <- case (rspBody rsp) of
-                  (Enum e)     -> liftIO $ whenEnum headerString e
-                  (SendFile f) -> liftIO $ whenSendFile headerString rsp f
-
-    return $! (bs,x)
-
-  where
-    whenEnum hs e = do
-        let enum = enumBS hs >. e
-        let hl = S.length hs
-        (x,bs) <- liftIO $ enum (countBytes writeEnd) >>= run
-
-        return (x, bs-hl)
-
-    whenSendFile hs r f = do
-        -- guaranteed to have a content length here.
-        enumBS hs writeEnd >>= run
-
-        let !cl = fromJust $ rspContentLength r
-        x <- onSendFile f
-        return (x, cl)
-
-    (major,minor) = rspHttpVersion rsp'
-
-
-    fmtHdrs hdrs =
-        {-# SCC "fmtHdrs" #-}
-        concat xs
-      where
-        xs = map f $ Map.toList hdrs
-
-        f (k, ys) = map (g k) ys
-
-        g k y = S.concat [ unCI k, ": ", y, "\r\n" ]
-
-
-    noCL :: Response -> ServerMonad Response
-    noCL r =
-        {-# SCC "noCL" #-}
-        do
-            -- are we in HTTP/1.1?
-            let sendChunked = (rspHttpVersion r) == (1,1)
-            if sendChunked
-              then do
-                  let r' = setHeader "Transfer-Encoding" "chunked" r
-                  let e  = writeChunkedTransferEncoding $ rspBodyToEnum $ rspBody r
-                  return $ r' { rspBody = Enum e }
-
-              else do
-                  -- HTTP/1.0 and no content-length? We'll have to close the
-                  -- socket.
-                  modify $! \s -> s { _forceConnectionClose = True }
-                  return $ setHeader "Connection" "close" r
-
-
-    hasCL :: Int -> Response -> ServerMonad Response
-    hasCL cl r =
-        {-# SCC "hasCL" #-}
-        do
-            -- set the content-length header
-            let r' = setHeader "Content-Length" (l2s $ show cl) r
-            let b = case (rspBody r') of
-                      (Enum e)     -> Enum (i e)
-                      (SendFile f) -> SendFile f
-
-            return $ r' { rspBody = b }
-
-      where
-        i :: Enumerator IO a -> Enumerator IO a
-        i enum iter = enum (joinI $ takeExactly cl iter)
-
-
-    setFileSize :: FilePath -> Response -> ServerMonad Response
-    setFileSize fp r =
-        {-# SCC "setFileSize" #-}
-        do
-            fs <- liftM fromEnum $ liftIO $ getFileSize fp
-            return $ r { rspContentLength = Just fs }
-
-
-    fixupResponse :: Response -> ServerMonad Response
-    fixupResponse r =
-        {-# SCC "fixupResponse" #-}
-        do
-            let r' = updateHeaders (Map.delete "Content-Length") r
-            r'' <- case (rspBody r') of
-                     (Enum _)     -> return r'
-                     (SendFile f) -> setFileSize f r'
-            case (rspContentLength r'') of
-              Nothing   -> noCL r''
-              (Just sz) -> hasCL sz r''
-
-
-    bsshow = l2s . show
-
-
-    mkHeaderString :: Response -> ByteString
-    mkHeaderString r =
-        {-# SCC "mkHeaderString" #-}
-        S.concat $ concat [hl, hdr, eol]
-      where
-        hl = [ "HTTP/"
-             , bsshow major
-             , "."
-             , bsshow minor
-             , " "
-             , bsshow $ rspStatus r
-             , " "
-             , rspStatusReason r
-             , "\r\n" ]
-
-        hdr = fmtHdrs $ headers r
-
-        eol = ["\r\n"]
-
-
-------------------------------------------------------------------------------
-checkConnectionClose :: (Int, Int) -> Headers -> ServerMonad ()
-checkConnectionClose ver hdrs =
-    -- For HTTP/1.1:
-    --   if there is an explicit Connection: close, close the socket.
-    -- For HTTP/1.0:
-    --   if there is no explicit Connection: Keep-Alive, close the socket.
-    if (ver == (1,1) && l == Just ["close"]) ||
-       (ver == (1,0) && l /= Just ["Keep-Alive"])
-       then modify $ \s -> s { _forceConnectionClose = True }
-       else return ()
-  where
-    l  = liftM (map tl) $ Map.lookup "Connection" hdrs
-    tl = S.map (c2w . toLower . w2c)
-
-
-------------------------------------------------------------------------------
--- FIXME: whitespace-trim the values here.
-toHeaders :: [(ByteString,ByteString)] -> Headers
-toHeaders kvps = foldl' f Map.empty kvps'
-  where
-    kvps'     = map (first toCI . second (:[])) kvps
-    f m (k,v) = Map.insertWith' (flip (++)) k v m
-
-
-------------------------------------------------------------------------------
-getFileSize :: FilePath -> IO FileOffset
-getFileSize fp = liftM fileSize $ getFileStatus fp
-
-
-l2s :: L.ByteString -> S.ByteString
-l2s = S.concat . L.toChunks
-
-
-toBS :: String -> ByteString
-toBS = S.pack . map c2w
-
- diff --git a/static/docs/0.1.2/snap-server/src/System-FastLogger.html b/static/docs/0.1.2/snap-server/src/System-FastLogger.html deleted file mode 100644 index 0a9d919..0000000 --- a/static/docs/0.1.2/snap-server/src/System-FastLogger.html +++ /dev/null @@ -1,211 +0,0 @@ - - - - -src/System/FastLogger.hs - - - -
{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module System.FastLogger 
-( Logger
-, timestampedLogEntry
-, combinedLogEntry
-, newLogger
-, logMsg
-, stopLogger
-) where
-
-import           Control.Concurrent
-import           Control.Exception
-import           Control.Monad
-import           Data.ByteString.Char8 (ByteString)
-import qualified Data.ByteString.Char8 as S
-import qualified Data.ByteString.Lazy.Char8 as L
-import           Data.ByteString.Internal (c2w)
-import           Data.DList (DList)
-import qualified Data.DList as D
-import           Data.IORef
-import           Data.Maybe
-import           Data.Serialize.Put
-import           Data.Time.Clock
-import           Prelude hiding (catch, show)
-import qualified Prelude
-import           System.IO
-import           Text.Show.ByteString hiding (runPut)
-
-import           Snap.Internal.Http.Server.Date
-
-
--- | Holds the state for a logger.
-data Logger = Logger
-    { _queuedMessages :: !(IORef (DList ByteString))
-    , _dataWaiting    :: !(MVar ())
-    , _loggerPath     :: !(FilePath)
-    , _loggingThread  :: !(MVar ThreadId) }
-
-
--- | Creates a new logger, logging to the given file. If the file argument is
--- \"-\", then log to stdout; if it's \"stderr\" then we log to stderr,
--- otherwise we log to a regular file in append mode. The file is closed and
--- re-opened every 15 minutes to facilitate external log rotation.
-newLogger :: FilePath -> IO Logger
-newLogger fp = do
-    q  <- newIORef D.empty
-    dw <- newEmptyMVar
-    th <- newEmptyMVar
-
-    let lg = Logger q dw fp th
-
-    tid <- forkIO $ loggingThread lg
-    putMVar th tid
-
-    return lg
-
--- | Prepares a log message with the time prepended.
-timestampedLogEntry :: ByteString -> IO ByteString
-timestampedLogEntry msg = do
-    timeStr <- getLogDateString
-
-    return $ runPut $ do
-        putWord8 $ c2w '['
-        putByteString timeStr
-        putByteString "] "
-        putByteString msg
-
-
--- | Prepares a log message in \"combined\" format.
-combinedLogEntry :: ByteString        -- ^ remote host
-                 -> Maybe ByteString  -- ^ remote user
-                 -> ByteString        -- ^ request line (up to you to ensure
-                                      --   there are no quotes in here)
-                 -> Int               -- ^ status code
-                 -> Maybe Int         -- ^ num bytes sent
-                 -> Maybe ByteString  -- ^ referer (up to you to ensure
-                                      --   there are no quotes in here)
-                 -> ByteString        -- ^ user agent (up to you to ensure
-                                      --   there are no quotes in here)
-                 -> IO ByteString
-combinedLogEntry host mbUser req status mbNumBytes mbReferer userAgent = do
-    let user = fromMaybe "-" mbUser
-    let numBytes = maybe "-" (\s -> strict $ show s) mbNumBytes
-    let referer = maybe "-" (\s -> S.concat ["\"", s, "\""]) mbReferer
-
-    timeStr <- getLogDateString
-
-    let p = [ host
-            , " - "
-            , user
-            , " ["
-            , timeStr
-            , "] \""
-            , req
-            , "\" "
-            , strict $ show status
-            , " "
-            , numBytes
-            , " "
-            , referer
-            , " \""
-            , userAgent
-            , "\"" ]
-
-    return $ S.concat p
-
-
-  where
-    strict = S.concat . L.toChunks
-
-
--- | Sends out a log message verbatim with a newline appended. Note:
--- if you want a fancy log message you'll have to format it yourself
--- (or use 'combinedLogEntry').
-logMsg :: Logger -> ByteString -> IO ()
-logMsg lg s = do
-    let s' = S.snoc s '\n'
-    atomicModifyIORef (_queuedMessages lg) $ \d -> (D.snoc d s',())
-    tryPutMVar (_dataWaiting lg) () >> return ()
-
-
-loggingThread :: Logger -> IO ()
-loggingThread (Logger queue notifier filePath _) = do
-    initialize >>= go
-
-  where
-    openIt = if filePath == "-"
-               then return stdout
-               else if filePath == "stderr"
-                      then return stderr
-                      else openFile filePath AppendMode
-
-    closeIt h = if filePath == "-" || filePath == "stderr"
-                  then return ()
-                  else hClose h
-
-    go (href, lastOpened) =
-        (loop (href, lastOpened))
-          `catches`
-          [ Handler $ \(_::AsyncException) -> killit (href, lastOpened)
-          , Handler $ \(e::SomeException)  -> do
-                hPutStrLn stderr $ "logger got exception: " ++ Prelude.show e
-                threadDelay 20000000
-                go (href, lastOpened) ]
-
-
-    initialize = do
-        lh   <- openIt
-        href <- newIORef lh
-        t    <- getCurrentTime
-        tref <- newIORef t
-        return (href, tref)
-
-
-    killit (href, lastOpened) = do
-        flushIt (href, lastOpened)
-        h <- readIORef href
-        closeIt h
-
-
-    flushIt (href, lastOpened) = do
-        dl <- atomicModifyIORef queue $ \x -> (D.empty,x)
-
-        let msgs = D.toList dl
-        let s = L.fromChunks msgs
-        h <- readIORef href
-        L.hPut h s
-        hFlush h
-
-        -- close the file every 15 minutes (for log rotation)
-        t <- getCurrentTime
-        old <- readIORef lastOpened
-
-        if diffUTCTime t old > 900
-          then do
-              closeIt h
-              openIt >>= writeIORef href
-              writeIORef lastOpened t
-          else return ()
-
-
-    loop (href, lastOpened) = do
-        -- wait on the notification mvar
-        _ <- takeMVar notifier
-
-        -- grab the queued messages and write them out
-        flushIt (href, lastOpened)
-
-        -- at least five seconds between log dumps
-        threadDelay 5000000
-
-        loop (href, lastOpened)
-
-
--- | Kills a logger thread, causing any unwritten contents to be
--- flushed out to disk
-stopLogger :: Logger -> IO ()
-stopLogger lg = withMVar (_loggingThread lg) killThread
-
- diff --git a/static/docs/0.1.2/snap-server/src/hscolour.css b/static/docs/0.1.2/snap-server/src/hscolour.css deleted file mode 100644 index 150e4d0..0000000 --- a/static/docs/0.1.2/snap-server/src/hscolour.css +++ /dev/null @@ -1,15 +0,0 @@ -body { font-size: 90%; } - -pre, code, body { - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; -} - -.hs-keyglyph, .hs-layout {color: #5200A3;} -.hs-keyword {color: #3465a4; font-weight: bold;} -.hs-comment, .hs-comment a {color: #579; } -.hs-str, .hs-chr {color: #141B24;} -.hs-keyword, .hs-conid, .hs-varid, .hs-conop, .hs-varop, .hs-num, .hs-cpp, .hs-sel, .hs-definition {} diff --git a/static/docs/0.2.1/heist/Text-Templating-Heist-Splices-Apply.html b/static/docs/0.2.1/heist/Text-Templating-Heist-Splices-Apply.html deleted file mode 100644 index b53b781..0000000 --- a/static/docs/0.2.1/heist/Text-Templating-Heist-Splices-Apply.html +++ /dev/null @@ -1,225 +0,0 @@ - - -Text.Templating.Heist.Splices.Apply
 heist-0.1.2: An xhtml templating systemSource codeContentsIndex
Text.Templating.Heist.Splices.Apply
Synopsis
applyTag :: ByteString
applyAttr :: ByteString
applyImpl :: Monad m => Splice m
Documentation
applyTag :: ByteStringSource
Default name for the apply splice. -
applyAttr :: ByteStringSource
Default attribute name for the apply tag. -
applyImpl :: Monad m => Splice mSource
Implementation of the apply splice. -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.1/heist/Text-Templating-Heist-Splices-Bind.html b/static/docs/0.2.1/heist/Text-Templating-Heist-Splices-Bind.html deleted file mode 100644 index 35bffae..0000000 --- a/static/docs/0.2.1/heist/Text-Templating-Heist-Splices-Bind.html +++ /dev/null @@ -1,225 +0,0 @@ - - -Text.Templating.Heist.Splices.Bind
 heist-0.1.2: An xhtml templating systemSource codeContentsIndex
Text.Templating.Heist.Splices.Bind
Synopsis
bindTag :: ByteString
bindAttr :: ByteString
bindImpl :: Monad m => Splice m
Documentation
bindTag :: ByteStringSource
Default name for the bind splice. -
bindAttr :: ByteStringSource
Default attribute name for the bind tag. -
bindImpl :: Monad m => Splice mSource
Implementation of the bind splice. -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.1/heist/Text-Templating-Heist-Splices-Ignore.html b/static/docs/0.2.1/heist/Text-Templating-Heist-Splices-Ignore.html deleted file mode 100644 index d0b1677..0000000 --- a/static/docs/0.2.1/heist/Text-Templating-Heist-Splices-Ignore.html +++ /dev/null @@ -1,183 +0,0 @@ - - -Text.Templating.Heist.Splices.Ignore
 heist-0.1.2: An xhtml templating systemSource codeContentsIndex
Text.Templating.Heist.Splices.Ignore
Synopsis
ignoreTag :: ByteString
ignoreImpl :: Monad m => Splice m
Documentation
ignoreTag :: ByteStringSource
Default name for the ignore splice. -
ignoreImpl :: Monad m => Splice mSource
The ignore tag and everything it surrounds disappears in the - rendered output. -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.1/heist/Text-Templating-Heist-Splices-Markdown.html b/static/docs/0.2.1/heist/Text-Templating-Heist-Splices-Markdown.html deleted file mode 100644 index db6b06d..0000000 --- a/static/docs/0.2.1/heist/Text-Templating-Heist-Splices-Markdown.html +++ /dev/null @@ -1,592 +0,0 @@ - - -Text.Templating.Heist.Splices.Markdown
 heist-0.1.2: An xhtml templating systemSource codeContentsIndex
Text.Templating.Heist.Splices.Markdown
Synopsis
data PandocMissingException = PandocMissingException
data MarkdownException = MarkdownException ByteString
markdownTag :: ByteString
markdownSplice :: MonadIO m => Splice m
pandoc :: FilePath -> FilePath -> IO ByteString
pandocBS :: FilePath -> ByteString -> IO ByteString
readProcessWithExitCode' :: FilePath -> [String] -> ByteString -> IO (ExitCode, ByteString, ByteString)
Documentation
data PandocMissingException Source
Constructors
PandocMissingException
show/hide Instances
data MarkdownException Source
Constructors
MarkdownException ByteString
show/hide Instances
markdownTag :: ByteStringSource
Default name for the markdown splice. -
markdownSplice :: MonadIO m => Splice mSource
Implementation of the markdown splice. -
pandoc :: FilePath -> FilePath -> IO ByteStringSource
pandocBS :: FilePath -> ByteString -> IO ByteStringSource
readProcessWithExitCode'Source
:: FilePathcommand to run -
-> [String]any arguments -
-> ByteStringstandard input -
-> IO (ExitCode, ByteString, ByteString)exitcode, stdout, stderr -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.1/heist/Text-Templating-Heist-Splices-Static.html b/static/docs/0.2.1/heist/Text-Templating-Heist-Splices-Static.html deleted file mode 100644 index 31c6ceb..0000000 --- a/static/docs/0.2.1/heist/Text-Templating-Heist-Splices-Static.html +++ /dev/null @@ -1,253 +0,0 @@ - - -Text.Templating.Heist.Splices.Static
 heist-0.1.2: An xhtml templating systemSource codeContentsIndex
Text.Templating.Heist.Splices.Static
Synopsis
data StaticTagState
bindStaticTag :: MonadIO m => TemplateState m -> IO (TemplateState m, StaticTagState)
clearStaticTagCache :: StaticTagState -> IO ()
Documentation
data StaticTagState Source
State for storing static tag information -
bindStaticTag :: MonadIO m => TemplateState m -> IO (TemplateState m, StaticTagState)Source
Modifies a TemplateState to include a static tag. -
clearStaticTagCache :: StaticTagState -> IO ()Source
Clears the static tag state. -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.1/heist/Text-Templating-Heist-Splices.html b/static/docs/0.2.1/heist/Text-Templating-Heist-Splices.html deleted file mode 100644 index 8452a3d..0000000 --- a/static/docs/0.2.1/heist/Text-Templating-Heist-Splices.html +++ /dev/null @@ -1,132 +0,0 @@ - - -Text.Templating.Heist.Splices
 heist-0.1.2: An xhtml templating systemSource codeContentsIndex
Text.Templating.Heist.Splices
Documentation
module Text.Templating.Heist.Splices.Apply
module Text.Templating.Heist.Splices.Bind
module Text.Templating.Heist.Splices.Ignore
module Text.Templating.Heist.Splices.Markdown
module Text.Templating.Heist.Splices.Static
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.1/heist/Text-Templating-Heist.html b/static/docs/0.2.1/heist/Text-Templating-Heist.html deleted file mode 100644 index e7fde96..0000000 --- a/static/docs/0.2.1/heist/Text-Templating-Heist.html +++ /dev/null @@ -1,2303 +0,0 @@ - - -Text.Templating.Heist
 heist-0.1.2: An xhtml templating systemSource codeContentsIndex
Text.Templating.Heist
Contents
Types -
Functions and declarations on TemplateState values -
Hook functions -
TemplateMonad functions -
Functions for running splices and templates -
Misc functions -
Description

This module contains the core definitions for the Heist template system. -

The Heist template system is based on XML/xhtml. It allows you to build - custom XML-based markup languages. With Heist you can define your own - domain-specific XML tags implemented with Haskell and use them in your - templates. -

The most important concept in Heist is the Splice. Splices can be thought - of as functions that transform a node into a list of nodes. Heist then - substitutes the resulting list of nodes into your template in place of the - input node. Splice is implemented as a type synonym type Splice m = - TemplateMonad m [Node], and TemplateMonad has a function getParamNode - that lets you get the input node. -

Suppose you have a place on your page where you want to display a link with - the text "Logout username" if the user is currently logged in or a link to - the login page if no user is logged in. Assume you have a function - getUser :: MyAppMonad (Maybe ByteString) that gets the current user. - You can implement this functionality with a Splice as follows: -

- import Text.XML.Expat.Tree
-
- link :: ByteString -> ByteString -> Node
- link target text = X.Element "a" [("href", target)] [X.Text text]
- 
- loginLink :: Node
- loginLink = link "/login" "Login"
- 
- logoutLink :: ByteString -> Node
- logoutLink user = link "/logout" (B.append "Logout " user)
- 
- loginLogoutSplice :: Splice MyAppMonad
- loginLogoutSplice = do
-     user <- lift getUser
-     return $ [maybe loginLink logoutLink user]
-
-

Next, you need to bind that splice to an XML tag. Heist stores information - about splices and templates in the TemplateState data structure. The - following code demonstrates how this splice would be used. -

 mySplices = [ ("loginLogout", loginLogoutSplice) ]
- 
- main = do
-     ets <- loadTemplates "templates" $
-            foldr (uncurry bindSplice) emptyTemplateState mySplices
-     let ts = either error id ets
-     t <- runMyAppMonad $ renderTemplate ts "index"
-     print $ maybe "Page not found" id t
-

Here we build up our TemplateState by starting with emptyTemplateState and - applying bindSplice for all the splices we want to add. Then we pass this - to loadTemplates our final TemplateState wrapped in an Either to handle - errors. Then we use this TemplateState to render our templates. -

Synopsis
type Node = Node ByteString ByteString
type Splice m = TemplateMonad m Template
type Template = [Node]
data TemplateMonad m a
data TemplateState m
addTemplate :: Monad m => ByteString -> Template -> TemplateState m -> TemplateState m
emptyTemplateState :: MonadIO m => TemplateState m
bindSplice :: Monad m => ByteString -> Splice m -> TemplateState m -> TemplateState m
lookupSplice :: Monad m => ByteString -> TemplateState m -> Maybe (Splice m)
setTemplates :: Monad m => TemplateMap -> TemplateState m -> TemplateState m
loadTemplates :: Monad m => FilePath -> TemplateState m -> IO (Either String (TemplateState m))
addOnLoadHook :: Monad m => (Template -> IO Template) -> TemplateState m -> TemplateState m
addPreRunHook :: Monad m => (Template -> m Template) -> TemplateState m -> TemplateState m
addPostRunHook :: Monad m => (Template -> m Template) -> TemplateState m -> TemplateState m
stopRecursion :: Monad m => TemplateMonad m ()
getParamNode :: Monad m => TemplateMonad m Node
runNodeList :: Monad m => [Node] -> Splice m
getContext :: Monad m => TemplateMonad m TPath
runTemplate :: Monad m => TemplateState m -> ByteString -> m (Maybe [Node])
evalTemplate :: Monad m => ByteString -> TemplateMonad m (Maybe [Node])
callTemplate :: Monad m => ByteString -> [(ByteString, ByteString)] -> TemplateMonad m (Maybe Template)
renderTemplate :: Monad m => TemplateState m -> ByteString -> m (Maybe ByteString)
bindStrings :: Monad m => [(ByteString, ByteString)] -> TemplateState m -> TemplateState m
runSplice :: Monad m => TemplateState m -> Node -> Splice m -> m [Node]
runRawTemplate :: Monad m => TemplateState m -> Template -> m [Node]
getDoc :: String -> IO (Either String Template)
bindStaticTag :: MonadIO m => TemplateState m -> IO (TemplateState m, StaticTagState)
heistExpatOptions :: ParserOptions ByteString ByteString
htmlEntityLookupTable :: Map ByteString ByteString
Types -
type Node = Node ByteString ByteStringSource
Heist templates are XML documents. The hexpat library is polymorphic over - the type of strings, so here we define a Node alias to fix the string - types of the tag names and tag bodies to ByteString. -
type Splice m = TemplateMonad m TemplateSource
A Splice is a TemplateMonad computation that returns [Node]. -
type Template = [Node]Source
A Template is a forest of XML nodes. -
data TemplateMonad m a Source
TemplateMonad is a monad transformer that gives you access to the Node - being processed (using the MonadReader instance) as well as holding the - TemplateState that contains splice and template mappings (accessible - using the MonadState instance. -
show/hide Instances
data TemplateState m Source

Holds all the state information needed for template processing: -

  • a collection of named templates. If you use the <apply - template="foo"> tag to include another template by name, "foo" - is looked up in here. -
  • the mapping from tag names to Splices. -
  • a flag to control whether we will recurse during splice processing. -

We'll illustrate the recursion flag with a small example template: -

 <foo>
-   <bar>
-     ...
-   </bar>
- </foo>
-

Assume that "foo" is bound to a splice procedure. Running the foo - splice will result in a list of nodes L; if the recursion flag is on we - will recursively scan L for splices, otherwise L will be included in the - output verbatim. -

show/hide Instances
Functions and declarations on TemplateState values -
addTemplate :: Monad m => ByteString -> Template -> TemplateState m -> TemplateState mSource
Adds a template to the template state. -
emptyTemplateState :: MonadIO m => TemplateState mSource
An empty template state, with Heist's default splices (<bind> and - <apply>) mapped. -
bindSpliceSource
:: Monad m
=> ByteStringtag name -
-> Splice msplice action -
-> TemplateState msource state -
-> TemplateState m
Bind a new splice declaration to a tag name within a TemplateState. -
lookupSplice :: Monad m => ByteString -> TemplateState m -> Maybe (Splice m)Source
Convenience function for looking up a splice. -
setTemplates :: Monad m => TemplateMap -> TemplateState m -> TemplateState mSource
Sets the templateMap in a TemplateState. -
loadTemplates :: Monad m => FilePath -> TemplateState m -> IO (Either String (TemplateState m))Source
Traverses the specified directory structure and builds a - TemplateState by loading all the files with a .tpl extension. -
Hook functions -

Heist hooks allow you to modify templates when they are loaded and before - and after they are run. Every time you call one of the addAbcHook - functions the hook is added to onto the processing pipeline. The hooks - processes the template in the order that they were added to the - TemplateState. -

The pre-run and post-run hooks are run before and after every template is - run/rendered. You should be careful what code you put in these hooks - because it can significantly affect the performance of your site. -

addOnLoadHook :: Monad m => (Template -> IO Template) -> TemplateState m -> TemplateState mSource
Adds an on-load hook to a TemplateState. -
addPreRunHook :: Monad m => (Template -> m Template) -> TemplateState m -> TemplateState mSource
Adds a pre-run hook to a TemplateState. -
addPostRunHook :: Monad m => (Template -> m Template) -> TemplateState m -> TemplateState mSource
Adds a post-run hook to a TemplateState. -
TemplateMonad functions -
stopRecursion :: Monad m => TemplateMonad m ()Source
Stops the recursive processing of splices. -
getParamNode :: Monad m => TemplateMonad m NodeSource
Gets the node currently being processed. -
runNodeList :: Monad m => [Node] -> Splice mSource
Performs splice processing on a list of nodes. -
getContext :: Monad m => TemplateMonad m TPathSource
Gets the current context -
Functions for running splices and templates -
runTemplate :: Monad m => TemplateState m -> ByteString -> m (Maybe [Node])Source
Looks up a template name in the supplied TemplateState and runs - it in the underlying monad. -
evalTemplate :: Monad m => ByteString -> TemplateMonad m (Maybe [Node])Source
Looks up a template name evaluates it. Same as runTemplate except it - runs in TemplateMonad instead of m. -
callTemplateSource
:: Monad m
=> ByteStringThe name of the template -
-> [(ByteString, ByteString)]Association list of - (name,value) parameter pairs -
-> TemplateMonad m (Maybe Template)
Renders a template with the specified parameters. This is the function - to use when you want to call a template and pass in parameters from code. -
renderTemplate :: Monad m => TemplateState m -> ByteString -> m (Maybe ByteString)Source
Renders a template from the specified TemplateState. -
bindStrings :: Monad m => [(ByteString, ByteString)] -> TemplateState m -> TemplateState mSource
Binds a list of constant string splices -
Misc functions -
runSpliceSource
:: Monad m
=> TemplateState mThe initial template state -
-> NodeThe splice's input node -
-> Splice mThe splice -
-> m [Node]
Runs a splice in the underlying monad. Splices require two - parameters, the template state, and an input node. -
runRawTemplate :: Monad m => TemplateState m -> Template -> m [Node]Source
Runs a template in the underlying monad. Similar to runSplice - except that templates don't require a Node as a parameter. -
getDoc :: String -> IO (Either String Template)Source
Reads an XML document from disk. -
bindStaticTag :: MonadIO m => TemplateState m -> IO (TemplateState m, StaticTagState)Source
Modifies a TemplateState to include a static tag. -
heistExpatOptions :: ParserOptions ByteString ByteStringSource
htmlEntityLookupTable :: Map ByteString ByteStringSource
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.1/heist/doc-index.html b/static/docs/0.2.1/heist/doc-index.html deleted file mode 100644 index ff07ebe..0000000 --- a/static/docs/0.2.1/heist/doc-index.html +++ /dev/null @@ -1,438 +0,0 @@ - - -heist-0.1.2: An xhtml templating system (Index)
 heist-0.1.2: An xhtml templating systemContentsIndex
addOnLoadHook
addPostRunHook
addPreRunHook
addTemplate
applyAttr
applyImpl
applyTag
bindAttr
bindImpl
bindSplice
bindStaticTag
bindStrings
bindTag
callTemplate
clearStaticTagCache
emptyTemplateState
evalTemplate
getContext
getDoc
getParamNode
heistExpatOptions
htmlEntityLookupTable
ignoreImpl
ignoreTag
loadTemplates
lookupSplice
MarkdownException
1 (Type/Class)
2 (Data Constructor)
markdownSplice
markdownTag
Node
pandoc
pandocBS
PandocMissingException
1 (Type/Class)
2 (Data Constructor)
readProcessWithExitCode'
renderTemplate
runNodeList
runRawTemplate
runSplice
runTemplate
setTemplates
Splice
StaticTagState
stopRecursion
Template
TemplateMonad
TemplateState
diff --git a/static/docs/0.2.1/heist/fonts/DroidSerif-Bold.eot b/static/docs/0.2.1/heist/fonts/DroidSerif-Bold.eot deleted file mode 100644 index 01b9e1f..0000000 Binary files a/static/docs/0.2.1/heist/fonts/DroidSerif-Bold.eot and /dev/null differ diff --git a/static/docs/0.2.1/heist/fonts/DroidSerif-Bold.svg b/static/docs/0.2.1/heist/fonts/DroidSerif-Bold.svg deleted file mode 100644 index 1f7f2d2..0000000 --- a/static/docs/0.2.1/heist/fonts/DroidSerif-Bold.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.2.1/heist/fonts/DroidSerif-Bold.ttf b/static/docs/0.2.1/heist/fonts/DroidSerif-Bold.ttf deleted file mode 100644 index da0ea11..0000000 Binary files a/static/docs/0.2.1/heist/fonts/DroidSerif-Bold.ttf and /dev/null differ diff --git a/static/docs/0.2.1/heist/fonts/DroidSerif-Bold.woff b/static/docs/0.2.1/heist/fonts/DroidSerif-Bold.woff deleted file mode 100644 index 91549cd..0000000 Binary files a/static/docs/0.2.1/heist/fonts/DroidSerif-Bold.woff and /dev/null differ diff --git a/static/docs/0.2.1/heist/fonts/DroidSerif-BoldItalic.eot b/static/docs/0.2.1/heist/fonts/DroidSerif-BoldItalic.eot deleted file mode 100644 index 47dd0a0..0000000 Binary files a/static/docs/0.2.1/heist/fonts/DroidSerif-BoldItalic.eot and /dev/null differ diff --git a/static/docs/0.2.1/heist/fonts/DroidSerif-BoldItalic.svg b/static/docs/0.2.1/heist/fonts/DroidSerif-BoldItalic.svg deleted file mode 100644 index 1a57dbb..0000000 --- a/static/docs/0.2.1/heist/fonts/DroidSerif-BoldItalic.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.2.1/heist/fonts/DroidSerif-BoldItalic.ttf b/static/docs/0.2.1/heist/fonts/DroidSerif-BoldItalic.ttf deleted file mode 100644 index 8be3fb4..0000000 Binary files a/static/docs/0.2.1/heist/fonts/DroidSerif-BoldItalic.ttf and /dev/null differ diff --git a/static/docs/0.2.1/heist/fonts/DroidSerif-BoldItalic.woff b/static/docs/0.2.1/heist/fonts/DroidSerif-BoldItalic.woff deleted file mode 100644 index 6d5fa3d..0000000 Binary files a/static/docs/0.2.1/heist/fonts/DroidSerif-BoldItalic.woff and /dev/null differ diff --git a/static/docs/0.2.1/heist/fonts/DroidSerif-Italic.eot b/static/docs/0.2.1/heist/fonts/DroidSerif-Italic.eot deleted file mode 100644 index 2d4850c..0000000 Binary files a/static/docs/0.2.1/heist/fonts/DroidSerif-Italic.eot and /dev/null differ diff --git a/static/docs/0.2.1/heist/fonts/DroidSerif-Italic.svg b/static/docs/0.2.1/heist/fonts/DroidSerif-Italic.svg deleted file mode 100644 index 356c374..0000000 --- a/static/docs/0.2.1/heist/fonts/DroidSerif-Italic.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.2.1/heist/fonts/DroidSerif-Italic.ttf b/static/docs/0.2.1/heist/fonts/DroidSerif-Italic.ttf deleted file mode 100644 index 3719dc2..0000000 Binary files a/static/docs/0.2.1/heist/fonts/DroidSerif-Italic.ttf and /dev/null differ diff --git a/static/docs/0.2.1/heist/fonts/DroidSerif-Italic.woff b/static/docs/0.2.1/heist/fonts/DroidSerif-Italic.woff deleted file mode 100644 index b64436f..0000000 Binary files a/static/docs/0.2.1/heist/fonts/DroidSerif-Italic.woff and /dev/null differ diff --git a/static/docs/0.2.1/heist/fonts/DroidSerif-Regular.eot b/static/docs/0.2.1/heist/fonts/DroidSerif-Regular.eot deleted file mode 100644 index 0d17523..0000000 Binary files a/static/docs/0.2.1/heist/fonts/DroidSerif-Regular.eot and /dev/null differ diff --git a/static/docs/0.2.1/heist/fonts/DroidSerif-Regular.svg b/static/docs/0.2.1/heist/fonts/DroidSerif-Regular.svg deleted file mode 100644 index b9b65fb..0000000 --- a/static/docs/0.2.1/heist/fonts/DroidSerif-Regular.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.2.1/heist/fonts/DroidSerif-Regular.ttf b/static/docs/0.2.1/heist/fonts/DroidSerif-Regular.ttf deleted file mode 100644 index 066dcaa..0000000 Binary files a/static/docs/0.2.1/heist/fonts/DroidSerif-Regular.ttf and /dev/null differ diff --git a/static/docs/0.2.1/heist/fonts/DroidSerif-Regular.woff b/static/docs/0.2.1/heist/fonts/DroidSerif-Regular.woff deleted file mode 100644 index cfd3d67..0000000 Binary files a/static/docs/0.2.1/heist/fonts/DroidSerif-Regular.woff and /dev/null differ diff --git a/static/docs/0.2.1/heist/frames.html b/static/docs/0.2.1/heist/frames.html deleted file mode 100644 index 9e904fc..0000000 --- a/static/docs/0.2.1/heist/frames.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/static/docs/0.2.1/heist/haddock-util.js b/static/docs/0.2.1/heist/haddock-util.js deleted file mode 100644 index 364081f..0000000 --- a/static/docs/0.2.1/heist/haddock-util.js +++ /dev/null @@ -1,139 +0,0 @@ -// Haddock JavaScript utilities -function toggle(button,id) -{ - var n = document.getElementById(id).style; - if (n.display == "none") - { - button.src = "minus.gif"; - n.display = "block"; - } - else - { - button.src = "plus.gif"; - n.display = "none"; - } -} - - -var max_results = 75; // 50 is not enough to search for map in the base libraries -var shown_range = null; -var last_search = null; - -function quick_search() -{ - perform_search(false); -} - -function full_search() -{ - perform_search(true); -} - - -function perform_search(full) -{ - var text = document.getElementById("searchbox").value.toLowerCase(); - if (text == last_search && !full) return; - last_search = text; - - var table = document.getElementById("indexlist"); - var status = document.getElementById("searchmsg"); - var children = table.firstChild.childNodes; - - // first figure out the first node with the prefix - var first = bisect(-1); - var last = (first == -1 ? -1 : bisect(1)); - - if (first == -1) - { - table.className = ""; - status.innerHTML = "No results found, displaying all"; - } - else if (first == 0 && last == children.length - 1) - { - table.className = ""; - status.innerHTML = ""; - } - else if (last - first >= max_results && !full) - { - table.className = ""; - status.innerHTML = "More than " + max_results + ", press Search to display"; - } - else - { - // decide what you need to clear/show - if (shown_range) - setclass(shown_range[0], shown_range[1], "indexrow"); - setclass(first, last, "indexshow"); - shown_range = [first, last]; - table.className = "indexsearch"; - status.innerHTML = ""; - } - - - function setclass(first, last, status) - { - for (var i = first; i <= last; i++) - { - children[i].className = status; - } - } - - - // do a binary search, treating 0 as ... - // return either -1 (no 0's found) or location of most far match - function bisect(dir) - { - var first = 0, finish = children.length - 1; - var mid, success = false; - - while (finish - first > 3) - { - mid = Math.floor((finish + first) / 2); - - var i = checkitem(mid); - if (i == 0) i = dir; - if (i == -1) - finish = mid; - else - first = mid; - } - var a = (dir == 1 ? first : finish); - var b = (dir == 1 ? finish : first); - for (var i = b; i != a - dir; i -= dir) - { - if (checkitem(i) == 0) return i; - } - return -1; - } - - - // from an index, decide what the result is - // 0 = match, -1 is lower, 1 is higher - function checkitem(i) - { - var s = getitem(i).toLowerCase().substr(0, text.length); - if (s == text) return 0; - else return (s > text ? -1 : 1); - } - - - // from an index, get its string - // this abstracts over alternates - function getitem(i) - { - for ( ; i >= 0; i--) - { - var s = children[i].firstChild.firstChild.data; - if (s.indexOf(' ') == -1) - return s; - } - return ""; // should never be reached - } -} - -function setSynopsis(filename) { - if (parent.window.synopsis) { - parent.window.synopsis.location = filename; - } -} diff --git a/static/docs/0.2.1/heist/haddock.css b/static/docs/0.2.1/heist/haddock.css deleted file mode 100644 index fe050fe..0000000 --- a/static/docs/0.2.1/heist/haddock.css +++ /dev/null @@ -1,478 +0,0 @@ -/* -------- Global things --------- */ - -@font-face { - font-family: 'DroidSerif'; - src: url('fonts/DroidSerif-Regular.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Regular.woff') format('woff'), - url('fonts/DroidSerif-Regular.ttf') format('truetype'), - url('fonts/DroidSerif-Regular.svg#DroidSerif') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - font-style: italic; - src: url('fonts/DroidSerif-Italic.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Italic.woff') format('woff'), - url('fonts/DroidSerif-Italic.ttf') format('truetype'), - url('fonts/DroidSerif-Italic.svg#DroidSerif-Italic') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - font-weight: bold; - src: url('fonts/DroidSerif-Bold.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Bold.woff') format('woff'), - url('fonts/DroidSerif-Bold.ttf') format('truetype'), - url('fonts/DroidSerif-Bold.svg#DroidSerif-Bold') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - src: url('fonts/DroidSerif-BoldItalic.eot'); - font-weight: bold; - font-style: italic; - src: local('Droid Serif'), - url('fonts/DroidSerif-BoldItalic.woff') format('woff'), - url('fonts/DroidSerif-BoldItalic.ttf') format('truetype'), - url('fonts/DroidSerif-BoldItalic.svg#DroidSerif-BoldItalic') format('svg'); -} - - - -HTML { - background-color: #f0f3ff; - width: 100%; -} - -BODY { - -moz-border-radius:5px; - -webkit-border-radius:5px; - width: 50em; - margin: 2em auto; - padding: 0; - background-color: #ffffff; - color: #000000; - font-size: 110%; - font-family: DroidSerif, Georgia, serif; - } - -A:link { color: #5200A3; text-decoration: none } -A:visited { color: #5200A3; text-decoration: none } -A:hover { color: #5200A3; text-decoration: none; border-bottom:#5200A3 dashed 1px; } - -TABLE.vanilla { - width: 100%; - border-width: 0px; - /* I can't seem to specify cellspacing or cellpadding properly using CSS... */ -} - -DL { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - letter-spacing: -0.01em; - margin: 0; -} - -.vanilla .vanilla dl { font-size: 80%; } -.vanilla .vanilla dl dl { padding-left: 0; font-size: 95%; } - -TD.section1, TD.section2, TD.section3, TD.section4, TD.doc, DL { - padding: 0 30px 0 34px; -} - -TABLE.vanilla2 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - border-width: 0px; -} - -/* font is a little too small in MSIE */ -TT, PRE, CODE { - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - font-size: 90%; -} - -LI P { margin: 0pt } - -P { margin-top: 0; margin-bottom: 0.75em; } - -TD { - border-width: 0px; -} - -TABLE.narrow { - border-width: 0px; -} - -TD.s8 { height: 0; margin:0; padding: 0 } -TD.s15 { height: 20px; } - -SPAN.keyword { text-decoration: underline; } - -/* Resize the buttom image to match the text size */ -IMG.coll { width : 0.75em; height: 0.75em; margin-bottom: 0; margin-right: 0.5em } - -/* --------- Contents page ---------- */ - -DIV.node { - padding-left: 3em; -} - -DIV.cnode { - padding-left: 1.75em; -} - -SPAN.pkg { - position: absolute; - left: 50em; -} - -/* --------- Documentation elements ---------- */ - -TD FONT { font-weight: bold; letter-spacing: -0.02em; } - -TD.children { - padding-left: 25px; - } - -TD.synopsis { - padding: 2px; - background-color: #f0f0f0; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - } - -TD.decl { - padding: 4px 8px; - background-color: #FAFAFA; - border-bottom: #F2F2F2 solid 1px; - border-top: #FCFCFC solid 1px; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - vertical-align: top; - } - -TD.decl TD.decl { - font-size: 100%; - padding: 4px 0; - border: 0; -} - -TD.topdecl { - padding: 20px 30px 0.5ex 30px; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; -; - vertical-align: top; -} - -.vanilla .vanilla .vanilla .topdecl { - padding-left: 0; - padding-right: 0; -} - -.vanilla .vanilla .vanilla { - padding-left: 30px; -} - -.decl .vanilla { - padding-left: 0px !important; -} - -.body .vanilla .body { - padding-left: 0; - padding-right: 0; -} - -.body .vanilla .body .decl { - padding-left: 12px; -} - -.body .vanilla .body div .vanilla .decl { - padding-left: 12px; -} - -TABLE.declbar { - background-color: #f0f0f0; - border-spacing: 0px; - border-bottom:1px solid #d7d7df; - border-right:1px solid #d7d7df; - border-top:1px solid #f4f4f9; - border-left:1px solid #f4f4f9; - padding: 4px; - } - -TD.declname { - width: 100%; - padding-right: 4px; - } - -TD.declbut { - padding-left: 8px; - padding-right: 5px; - border-left-width: 1px; - border-left-color: #000099; - border-left-style: solid; - white-space: nowrap; - font-size: x-small; - } - -/* - arg is just like decl, except that wrapping is not allowed. It is - used for function and constructor arguments which have a text box - to the right, where if wrapping is allowed the text box squashes up - the declaration by wrapping it. -*/ -TD.arg { - padding: 2px 12px; - background-color: #f0f0f0; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - vertical-align: top; - white-space: nowrap; - } - -TD.recfield { padding-left: 20px } - -TD.doc { - padding-left: 38px; - font-size: 95%; - line-height: 1.66; - } - -TD.ndoc { - font-size: 95%; - line-height: 1.66; - padding: 2px 4px 2px 8px; - } - -TD.rdoc { - padding: 2px; - padding-left: 30px; - width: 100%; - font-size: 80%; - font-style: italic; - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - } - -TD.body { - padding: 0 30px; - } - -TD.pkg { - width: 100%; - padding-left: 30px -} - -TABLE.indexsearch TR.indexrow { - display: none; -} -TABLE.indexsearch TR.indexshow { - display: table-row; -} - -TD.indexentry { - vertical-align: top; - padding: 0 30px - } - -TD.indexannot { - vertical-align: top; - padding-left: 20px; - white-space: nowrap - } - -TD.indexlinks { - width: 100% - } - -/* ------- Section Headings ------- */ - -TD.section1, TD.section2, TD.section3, TD.section4, TD.section5 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; -} - -TD.section1 { - padding-top: 14px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 140% - } - -TD.section2 { - padding-top: 4px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 120% - } - -TD.section3 { - padding-top: 5px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 105% - } - -TD.section4 { - font-weight: bold; - padding-top: 12px; - padding-bottom: 4px; - letter-spacing: -0.02em; - font-size: 90% - } - -/* -------------- The title bar at the top of the page */ - -TD.infohead { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - font-weight: bold; - padding: 0 30px; - text-align: left; -} - -TD.infoval { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - padding: 0 30px; - text-align: left; -} - -TD.topbar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - background-color: #3465a4; - padding: 5px; - -moz-border-radius-topleft:5px; - -moz-border-radius-topright:5px; - -webkit-border-radius-topleft:5px; - -webkit-border-radius-topright:5px; -} - -TD.title { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - padding-left: 30px; - letter-spacing: -0.02em; - font-weight: bold; - width: 100% - } - -TD.topbut { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - padding-left: 5px; - padding-right: 5px; - border-left-width: 1px; - border-left-color: #ffffff; - border-left-style: solid; - letter-spacing: -0.02em; - font-weight: bold; - white-space: nowrap; - } - -TD.topbut A:link { - color: #ffffff - } - -TD.topbut A:visited { - color: #ffff00 - } - -TD.topbut A:hover { - background-color: #C9D3DE; - } - -TD.topbut:hover { - background-color: #C9D3DE; - } - -TD.modulebar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #141B24; - background-color: #C9D3DE; - padding: 5px; - border-top-width: 1px; - border-top-color: #ffffff; - border-top-style: solid; - -moz-border-radius-bottomleft:5px; - -moz-border-radius-bottomright:5px; - -webkit-border-radius-bottomleft:5px; - -webkit-border-radius-bottomright:5px; - - } - -/* --------- The page footer --------- */ - -TD.botbar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - -moz-border-radius:5px; - -webkit-border-radius:5px; - background-color: #3465a4; - color: #ffffff; - padding: 5px - } -TD.botbar A:link { - color: #ffffff; - text-decoration: underline - } -TD.botbar A:visited { - color: #ffff00 - } -TD.botbar A:hover { - background-color: #6060ff - } - -/* --------- Mini Synopsis for Frame View --------- */ - -.outer { - margin: 0 0; - padding: 0 0; -} - -.mini-synopsis { - padding: 0.25em 0.25em; -} - -.mini-synopsis H1 { font-size: 120%; } -.mini-synopsis H2 { font-size: 107%; } -.mini-synopsis H3 { font-size: 100%; } -.mini-synopsis H1, .mini-synopsis H2, .mini-synopsis H3 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - margin-top: 0.5em; - margin-bottom: 0.25em; - padding: 0 0; - font-weight: bold; letter-spacing: -0.02em; -} - -.mini-synopsis H1 { border-bottom: 1px solid #ccc; } - -.mini-topbar { - font-size: 120%; - background: #0077dd; - padding: 0.25em; -} - - diff --git a/static/docs/0.2.1/heist/haskell_icon.gif b/static/docs/0.2.1/heist/haskell_icon.gif deleted file mode 100644 index cb2a815..0000000 Binary files a/static/docs/0.2.1/heist/haskell_icon.gif and /dev/null differ diff --git a/static/docs/0.2.1/heist/heist.haddock b/static/docs/0.2.1/heist/heist.haddock deleted file mode 100644 index d463331..0000000 Binary files a/static/docs/0.2.1/heist/heist.haddock and /dev/null differ diff --git a/static/docs/0.2.1/heist/index-frames.html b/static/docs/0.2.1/heist/index-frames.html deleted file mode 100644 index 261bcbe..0000000 --- a/static/docs/0.2.1/heist/index-frames.html +++ /dev/null @@ -1,40 +0,0 @@ - - -heist-0.1.2: An xhtml templating system

Text.Templating.Heist
Text.Templating.Heist.Splices
Text.Templating.Heist.Splices.Apply
Text.Templating.Heist.Splices.Bind
Text.Templating.Heist.Splices.Ignore
Text.Templating.Heist.Splices.Markdown
Text.Templating.Heist.Splices.Static

diff --git a/static/docs/0.2.1/heist/index.html b/static/docs/0.2.1/heist/index.html deleted file mode 100644 index f7da523..0000000 --- a/static/docs/0.2.1/heist/index.html +++ /dev/null @@ -1,181 +0,0 @@ - - -heist-0.1.2: An xhtml templating system
 heist-0.1.2: An xhtml templating systemContentsIndex
heist-0.1.2: An xhtml templating system
An xhtml templating system -
Modules
show/hideText
show/hideTemplating
show/hideText.Templating.Heist
show/hideText.Templating.Heist.Splices
Text.Templating.Heist.Splices.Apply
Text.Templating.Heist.Splices.Bind
Text.Templating.Heist.Splices.Ignore
Text.Templating.Heist.Splices.Markdown
Text.Templating.Heist.Splices.Static
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.1/heist/mini_Text-Templating-Heist-Splices-Apply.html b/static/docs/0.2.1/heist/mini_Text-Templating-Heist-Splices-Apply.html deleted file mode 100644 index b3a2987..0000000 --- a/static/docs/0.2.1/heist/mini_Text-Templating-Heist-Splices-Apply.html +++ /dev/null @@ -1,33 +0,0 @@ - - -Text.Templating.Heist.Splices.Apply
Text.Templating.Heist.Splices.Apply
diff --git a/static/docs/0.2.1/heist/mini_Text-Templating-Heist-Splices-Bind.html b/static/docs/0.2.1/heist/mini_Text-Templating-Heist-Splices-Bind.html deleted file mode 100644 index 347bf97..0000000 --- a/static/docs/0.2.1/heist/mini_Text-Templating-Heist-Splices-Bind.html +++ /dev/null @@ -1,33 +0,0 @@ - - -Text.Templating.Heist.Splices.Bind
Text.Templating.Heist.Splices.Bind
diff --git a/static/docs/0.2.1/heist/mini_Text-Templating-Heist-Splices-Ignore.html b/static/docs/0.2.1/heist/mini_Text-Templating-Heist-Splices-Ignore.html deleted file mode 100644 index cf11fd3..0000000 --- a/static/docs/0.2.1/heist/mini_Text-Templating-Heist-Splices-Ignore.html +++ /dev/null @@ -1,29 +0,0 @@ - - -Text.Templating.Heist.Splices.Ignore
Text.Templating.Heist.Splices.Ignore
diff --git a/static/docs/0.2.1/heist/mini_Text-Templating-Heist-Splices-Markdown.html b/static/docs/0.2.1/heist/mini_Text-Templating-Heist-Splices-Markdown.html deleted file mode 100644 index 70738c6..0000000 --- a/static/docs/0.2.1/heist/mini_Text-Templating-Heist-Splices-Markdown.html +++ /dev/null @@ -1,53 +0,0 @@ - - -Text.Templating.Heist.Splices.Markdown diff --git a/static/docs/0.2.1/heist/mini_Text-Templating-Heist-Splices-Static.html b/static/docs/0.2.1/heist/mini_Text-Templating-Heist-Splices-Static.html deleted file mode 100644 index 482ea55..0000000 --- a/static/docs/0.2.1/heist/mini_Text-Templating-Heist-Splices-Static.html +++ /dev/null @@ -1,35 +0,0 @@ - - -Text.Templating.Heist.Splices.Static
Text.Templating.Heist.Splices.Static
diff --git a/static/docs/0.2.1/heist/mini_Text-Templating-Heist-Splices.html b/static/docs/0.2.1/heist/mini_Text-Templating-Heist-Splices.html deleted file mode 100644 index f3e9a96..0000000 --- a/static/docs/0.2.1/heist/mini_Text-Templating-Heist-Splices.html +++ /dev/null @@ -1,21 +0,0 @@ - - -Text.Templating.Heist.Splices
Text.Templating.Heist.Splices
diff --git a/static/docs/0.2.1/heist/mini_Text-Templating-Heist.html b/static/docs/0.2.1/heist/mini_Text-Templating-Heist.html deleted file mode 100644 index d0342ea..0000000 --- a/static/docs/0.2.1/heist/mini_Text-Templating-Heist.html +++ /dev/null @@ -1,165 +0,0 @@ - - -Text.Templating.Heist
Text.Templating.Heist

Types -

type Node
type Splice m
type Template
data TemplateMonad m a

Functions and declarations on TemplateState values -

Hook functions -

TemplateMonad functions -

Functions for running splices and templates -

Misc functions -

diff --git a/static/docs/0.2.1/heist/minus.gif b/static/docs/0.2.1/heist/minus.gif deleted file mode 100644 index 1deac2f..0000000 Binary files a/static/docs/0.2.1/heist/minus.gif and /dev/null differ diff --git a/static/docs/0.2.1/heist/plus.gif b/static/docs/0.2.1/heist/plus.gif deleted file mode 100644 index 2d15c14..0000000 Binary files a/static/docs/0.2.1/heist/plus.gif and /dev/null differ diff --git a/static/docs/0.2.1/heist/src/Text-Templating-Heist-Constants.html b/static/docs/0.2.1/heist/src/Text-Templating-Heist-Constants.html deleted file mode 100644 index 1f8683a..0000000 --- a/static/docs/0.2.1/heist/src/Text-Templating-Heist-Constants.html +++ /dev/null @@ -1,265 +0,0 @@ - - - - -src/Text/Templating/Heist/Constants.hs - - - -
{-# LANGUAGE OverloadedStrings #-}
-module Text.Templating.Heist.Constants where
-
-import           Data.ByteString.Char8 (ByteString)
-import qualified Data.Map as Map
-import           Data.Map (Map)
-
-htmlEntityLookupTable :: Map ByteString ByteString
-htmlEntityLookupTable = Map.fromList [
-                         ("acute"      , "\xc2\xb4")
-                       , ("cedil"      , "\xc2\xb8")
-                       , ("circ"       , "\xcb\x86")
-                       , ("macr"       , "\xc2\xaf")
-                       , ("middot"     , "\xc2\xb7")
-                       , ("tilde"      , "\xcb\x9c")
-                       , ("uml"        , "\xc2\xa8")
-                       , ("Aacute"     , "\xc3\x81")
-                       , ("aacute"     , "\xc3\xa1")
-                       , ("Acirc"      , "\xc3\x82")
-                       , ("acirc"      , "\xc3\xa2")
-                       , ("AElig"      , "\xc3\x86")
-                       , ("aelig"      , "\xc3\xa6")
-                       , ("Agrave"     , "\xc3\x80")
-                       , ("agrave"     , "\xc3\xa0")
-                       , ("Aring"      , "\xc3\x85")
-                       , ("aring"      , "\xc3\xa5")
-                       , ("Atilde"     , "\xc3\x83")
-                       , ("atilde"     , "\xc3\xa3")
-                       , ("Auml"       , "\xc3\x84")
-                       , ("auml"       , "\xc3\xa4")
-                       , ("Ccedil"     , "\xc3\x87")
-                       , ("ccedil"     , "\xc3\xa7")
-                       , ("Eacute"     , "\xc3\x89")
-                       , ("eacute"     , "\xc3\xa9")
-                       , ("Ecirc"      , "\xc3\x8a")
-                       , ("ecirc"      , "\xc3\xaa")
-                       , ("Egrave"     , "\xc3\x88")
-                       , ("egrave"     , "\xc3\xa8")
-                       , ("ETH"        , "\xc3\x90")
-                       , ("eth"        , "\xc3\xb0")
-                       , ("Euml"       , "\xc3\x8b")
-                       , ("euml"       , "\xc3\xab")
-                       , ("Iacute"     , "\xc3\x8d")
-                       , ("iacute"     , "\xc3\xad")
-                       , ("Icirc"      , "\xc3\x8e")
-                       , ("icirc"      , "\xc3\xae")
-                       , ("Igrave"     , "\xc3\x8c")
-                       , ("igrave"     , "\xc3\xac")
-                       , ("Iuml"       , "\xc3\x8f")
-                       , ("iuml"       , "\xc3\xaf")
-                       , ("Ntilde"     , "\xc3\x91")
-                       , ("ntilde"     , "\xc3\xb1")
-                       , ("Oacute"     , "\xc3\x93")
-                       , ("oacute"     , "\xc3\xb3")
-                       , ("Ocirc"      , "\xc3\x94")
-                       , ("ocirc"      , "\xc3\xb4")
-                       , ("OElig"      , "\xc5\x92")
-                       , ("oelig"      , "\xc5\x93")
-                       , ("Ograve"     , "\xc3\x92")
-                       , ("ograve"     , "\xc3\xb2")
-                       , ("Oslash"     , "\xc3\x98")
-                       , ("oslash"     , "\xc3\xb8")
-                       , ("Otilde"     , "\xc3\x95")
-                       , ("otilde"     , "\xc3\xb5")
-                       , ("Ouml"       , "\xc3\x96")
-                       , ("ouml"       , "\xc3\xb6")
-                       , ("Scaron"     , "\xc5\xa0")
-                       , ("scaron"     , "\xc5\xa1")
-                       , ("szlig"      , "\xc3\x9f")
-                       , ("THORN"      , "\xc3\x9e")
-                       , ("thorn"      , "\xc3\xbe")
-                       , ("Uacute"     , "\xc3\x9a")
-                       , ("uacute"     , "\xc3\xba")
-                       , ("Ucirc"      , "\xc3\x9b")
-                       , ("ucirc"      , "\xc3\xbb")
-                       , ("Ugrave"     , "\xc3\x99")
-                       , ("ugrave"     , "\xc3\xb9")
-                       , ("Uuml"       , "\xc3\x9c")
-                       , ("uuml"       , "\xc3\xbc")
-                       , ("Yacute"     , "\xc3\x9d")
-                       , ("yacute"     , "\xc3\xbd")
-                       , ("yuml"       , "\xc3\xbf")
-                       , ("Yuml"       , "\xc5\xb8")
-                       , ("cent"       , "\xc2\xa2")
-                       , ("curren"     , "\xc2\xa4")
-                       , ("euro"       , "\xe2\x82\xac")
-                       , ("pound"      , "\xc2\xa3")
-                       , ("yen"        , "\xc2\xa5")
-                       , ("brvbar"     , "\xc2\xa6")
-                       , ("bull"       , "\xe2\x80\xa2")
-                       , ("copy"       , "\xc2\xa9")
-                       , ("dagger"     , "\xe2\x80\xa0")
-                       , ("Dagger"     , "\xe2\x80\xa1")
-                       , ("frasl"      , "\xe2\x81\x84")
-                       , ("hellip"     , "\xe2\x80\xa6")
-                       , ("iexcl"      , "\xc2\xa1")
-                       , ("image"      , "\xe2\x84\x91")
-                       , ("iquest"     , "\xc2\xbf")
-                       , ("mdash"      , "\xe2\x80\x94")
-                       , ("ndash"      , "\xe2\x80\x93")
-                       , ("not"        , "\xc2\xac")
-                       , ("oline"      , "\xe2\x80\xbe")
-                       , ("ordf"       , "\xc2\xaa")
-                       , ("ordm"       , "\xc2\xba")
-                       , ("para"       , "\xc2\xb6")
-                       , ("permil"     , "\xe2\x80\xb0")
-                       , ("prime"      , "\xe2\x80\xb2")
-                       , ("Prime"      , "\xe2\x80\xb3")
-                       , ("real"       , "\xe2\x84\x9c")
-                       , ("reg"        , "\xc2\xae")
-                       , ("sect"       , "\xc2\xa7")
-                       , ("shy"        , "\173")
-                       , ("sup1"       , "\xc2\xb9")
-                       , ("trade"      , "\xe2\x84\xa2")
-                       , ("weierp"     , "\xe2\x84\x98")
-                       , ("bdquo"      , "\xe2\x80\x9e")
-                       , ("laquo"      , "\xc2\xab")
-                       , ("ldquo"      , "\xe2\x80\x9c")
-                       , ("lsaquo"     , "\xe2\x80\xb9")
-                       , ("lsquo"      , "\xe2\x80\x98")
-                       , ("raquo"      , "\xc2\xbb")
-                       , ("rdquo"      , "\xe2\x80\x9d")
-                       , ("rsaquo"     , "\xe2\x80\xba")
-                       , ("rsquo"      , "\xe2\x80\x99")
-                       , ("sbquo"      , "\xe2\x80\x9a")
-                       , ("emsp"       , "\xe2\x80\x83")
-                       , ("ensp"       , "\xe2\x80\x82")
-                       , ("nbsp"       , "\x20")
-                       , ("thinsp"     , "\xe2\x80\x89")
-                       , ("zwj"        , "\xe2\x80\x8d")
-                       , ("zwnj"       , "\xe2\x80\x8c")
-                       , ("deg"        , "\xc2\xb0")
-                       , ("divide"     , "\xc3\xb7")
-                       , ("frac12"     , "\xc2\xbd")
-                       , ("frac14"     , "\xc2\xbc")
-                       , ("frac34"     , "\xc2\xbe")
-                       , ("ge"         , "\xe2\x89\xa5")
-                       , ("le"         , "\xe2\x89\xa4")
-                       , ("minus"      , "\xe2\x88\x92")
-                       , ("sup2"       , "\xc2\xb2")
-                       , ("sup3"       , "\xc2\xb3")
-                       , ("times"      , "\xc3\x97")
-                       , ("alefsym"    , "\xe2\x84\xb5")
-                       , ("and"        , "\xe2\x88\xa7")
-                       , ("ang"        , "\xe2\x88\xa0")
-                       , ("asymp"      , "\xe2\x89\x88")
-                       , ("cap"        , "\xe2\x88\xa9")
-                       , ("cong"       , "\xe2\x89\x85")
-                       , ("cup"        , "\xe2\x88\xaa")
-                       , ("empty"      , "\xe2\x88\x85")
-                       , ("equiv"      , "\xe2\x89\xa1")
-                       , ("exist"      , "\xe2\x88\x83")
-                       , ("fnof"       , "\xc6\x92")
-                       , ("forall"     , "\xe2\x88\x80")
-                       , ("infin"      , "\xe2\x88\x9e")
-                       , ("int"        , "\xe2\x88\xab")
-                       , ("isin"       , "\xe2\x88\x88")
-                       , ("lang"       , "\xe3\x80\x88")
-                       , ("lceil"      , "\xe2\x8c\x88")
-                       , ("lfloor"     , "\xe2\x8c\x8a")
-                       , ("lowast"     , "\xe2\x88\x97")
-                       , ("micro"      , "\xc2\xb5")
-                       , ("nabla"      , "\xe2\x88\x87")
-                       , ("ne"         , "\xe2\x89\xa0")
-                       , ("ni"         , "\xe2\x88\x8b")
-                       , ("notin"      , "\xe2\x88\x89")
-                       , ("nsub"       , "\xe2\x8a\x84")
-                       , ("oplus"      , "\xe2\x8a\x95")
-                       , ("or"         , "\xe2\x88\xa8")
-                       , ("otimes"     , "\xe2\x8a\x97")
-                       , ("part"       , "\xe2\x88\x82")
-                       , ("perp"       , "\xe2\x8a\xa5")
-                       , ("plusmn"     , "\xc2\xb1")
-                       , ("prod"       , "\xe2\x88\x8f")
-                       , ("prop"       , "\xe2\x88\x9d")
-                       , ("radic"      , "\xe2\x88\x9a")
-                       , ("rang"       , "\xe3\x80\x89")
-                       , ("rceil"      , "\xe2\x8c\x89")
-                       , ("rfloor"     , "\xe2\x8c\x8b")
-                       , ("sdot"       , "\xe2\x8b\x85")
-                       , ("sim"        , "\xe2\x88\xbc")
-                       , ("sub"        , "\xe2\x8a\x82")
-                       , ("sube"       , "\xe2\x8a\x86")
-                       , ("sum"        , "\xe2\x88\x91")
-                       , ("sup"        , "\xe2\x8a\x83")
-                       , ("supe"       , "\xe2\x8a\x87")
-                       , ("there4"     , "\xe2\x88\xb4")
-                       , ("Alpha"      , "\xce\x91")
-                       , ("alpha"      , "\xce\xb1")
-                       , ("Beta"       , "\xce\x92")
-                       , ("beta"       , "\xce\xb2")
-                       , ("Chi"        , "\xce\xa7")
-                       , ("chi"        , "\xcf\x87")
-                       , ("Delta"      , "\xce\x94")
-                       , ("delta"      , "\xce\xb4")
-                       , ("Epsilon"    , "\xce\x95")
-                       , ("epsilon"    , "\xce\xb5")
-                       , ("Eta"        , "\xce\x97")
-                       , ("eta"        , "\xce\xb7")
-                       , ("Gamma"      , "\xce\x93")
-                       , ("gamma"      , "\xce\xb3")
-                       , ("Iota"       , "\xce\x99")
-                       , ("iota"       , "\xce\xb9")
-                       , ("Kappa"      , "\xce\x9a")
-                       , ("kappa"      , "\xce\xba")
-                       , ("Lambda"     , "\xce\x9b")
-                       , ("lambda"     , "\xce\xbb")
-                       , ("Mu"         , "\xce\x9c")
-                       , ("mu"         , "\xce\xbc")
-                       , ("Nu"         , "\xce\x9d")
-                       , ("nu"         , "\xce\xbd")
-                       , ("Omega"      , "\xce\xa9")
-                       , ("omega"      , "\xcf\x89")
-                       , ("Omicron"    , "\xce\x9f")
-                       , ("omicron"    , "\xce\xbf")
-                       , ("Phi"        , "\xce\xa6")
-                       , ("phi"        , "\xcf\x86")
-                       , ("Pi"         , "\xce\xa0")
-                       , ("pi"         , "\xcf\x80")
-                       , ("piv"        , "\xcf\x96")
-                       , ("Psi"        , "\xce\xa8")
-                       , ("psi"        , "\xcf\x88")
-                       , ("Rho"        , "\xce\xa1")
-                       , ("rho"        , "\xcf\x81")
-                       , ("Sigma"      , "\xce\xa3")
-                       , ("sigma"      , "\xcf\x83")
-                       , ("sigmaf"     , "\xcf\x82")
-                       , ("Tau"        , "\xce\xa4")
-                       , ("tau"        , "\xcf\x84")
-                       , ("Theta"      , "\xce\x98")
-                       , ("theta"      , "\xce\xb8")
-                       , ("thetasym"   , "\xcf\x91")
-                       , ("upsih"      , "\xcf\x92")
-                       , ("Upsilon"    , "\xce\xa5")
-                       , ("upsilon"    , "\xcf\x85")
-                       , ("Xi"         , "\xce\x9e")
-                       , ("xi"         , "\xce\xbe")
-                       , ("Zeta"       , "\xce\x96")
-                       , ("zeta"       , "\xce\xb6")
-                       , ("crarr"      , "\xe2\x86\xb5")
-                       , ("darr"       , "\xe2\x86\x93")
-                       , ("dArr"       , "\xe2\x87\x93")
-                       , ("harr"       , "\xe2\x86\x94")
-                       , ("hArr"       , "\xe2\x87\x94")
-                       , ("larr"       , "\xe2\x86\x90")
-                       , ("lArr"       , "\xe2\x87\x90")
-                       , ("rarr"       , "\xe2\x86\x92")
-                       , ("rArr"       , "\xe2\x87\x92")
-                       , ("uarr"       , "\xe2\x86\x91")
-                       , ("uArr"       , "\xe2\x87\x91")
-                       , ("clubs"      , "\xe2\x99\xa3")
-                       , ("diams"      , "\xe2\x99\xa6")
-                       , ("hearts"     , "\xe2\x99\xa5")
-                       , ("spades"     , "\xe2\x99\xa0")
-                       , ("loz"        , "\xe2\x97\x8a") ]
-
- diff --git a/static/docs/0.2.1/heist/src/Text-Templating-Heist-Internal.html b/static/docs/0.2.1/heist/src/Text-Templating-Heist-Internal.html deleted file mode 100644 index 1d76a70..0000000 --- a/static/docs/0.2.1/heist/src/Text-Templating-Heist-Internal.html +++ /dev/null @@ -1,513 +0,0 @@ - - - - -src/Text/Templating/Heist/Internal.hs - - - -
{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-
-module Text.Templating.Heist.Internal where
-
-------------------------------------------------------------------------------
-import           Control.Exception (SomeException)
-import           Control.Monad.CatchIO
-import           Control.Monad.RWS.Strict
-import           Data.ByteString.Char8 (ByteString)
-import qualified Data.ByteString.Char8 as B
-import qualified Data.ByteString.Lazy as L
-import           Data.Either
-import qualified Data.Foldable as F
-import           Data.List
-import qualified Data.Map as Map
-import           Data.Map (Map)
-import           Prelude hiding (catch)
-import           System.Directory.Tree hiding (name)
-import           Text.XML.Expat.Format
-import qualified Text.XML.Expat.Tree as X
-
-------------------------------------------------------------------------------
-import           Text.Templating.Heist.Constants
-
-------------------------------------------------------------------------------
--- Types
-------------------------------------------------------------------------------
-
--- | Heist templates are XML documents. The hexpat library is polymorphic over
--- the type of strings, so here we define a 'Node' alias to fix the string
--- types of the tag names and tag bodies to 'ByteString'.
-type Node = X.Node ByteString ByteString
-
-
-------------------------------------------------------------------------------
--- | A 'Template' is a forest of XML nodes.
-type Template = [Node]
-
-
-------------------------------------------------------------------------------
--- | Reversed list of directories
-type TPath = [ByteString]
-
-
-------------------------------------------------------------------------------
-type TemplateMap = Map TPath Template
-
-
-------------------------------------------------------------------------------
--- | Holds all the state information needed for template processing:
---
---     * a collection of named templates. If you use the @\<apply
---       template=\"foo\"\>@ tag to include another template by name, @\"foo\"@
---       is looked up in here.
---
---     * the mapping from tag names to 'Splice's.
---
---     * a flag to control whether we will recurse during splice processing.
---
--- We'll illustrate the recursion flag with a small example template:
---
---   > <foo>
---   >   <bar>
---   >     ...
---   >   </bar>
---   > </foo>
---
--- Assume that @\"foo\"@ is bound to a splice procedure. Running the @foo@
--- splice will result in a list of nodes @L@; if the recursion flag is on we
--- will recursively scan @L@ for splices, otherwise @L@ will be included in the
--- output verbatim.
-data TemplateState m = TemplateState {
-    -- | A mapping of splice names to splice actions
-      _spliceMap      :: SpliceMap m
-    -- | A mapping of template names to templates
-    , _templateMap    :: TemplateMap
-    -- | A flag to control splice recursion
-    , _recurse        :: Bool
-    , _curContext     :: TPath
-    , _recursionDepth :: Int
-    , _onLoadHook     :: Template -> IO Template
-    , _preRunHook     :: Template -> m Template
-    , _postRunHook    :: Template -> m Template
-}
-
-
-------------------------------------------------------------------------------
-instance Eq (TemplateState m) where
-    a == b = (_recurse a == _recurse b) &&
-             (_templateMap a == _templateMap b) &&
-             (_curContext a == _curContext b)
-
-
-------------------------------------------------------------------------------
--- | 'TemplateMonad' is a monad transformer that gives you access to the 'Node'
---   being processed (using the 'MonadReader' instance) as well as holding the
---   'TemplateState' that contains splice and template mappings (accessible
---   using the 'MonadState' instance.
-newtype TemplateMonad m a = TemplateMonad (RWST Node () (TemplateState m) m a)
-  deriving ( Monad
-           , MonadIO
-           , MonadCatchIO
-           , MonadReader Node
-           , MonadState (TemplateState m) )
-
-
-------------------------------------------------------------------------------
-instance (Monad m) => Monoid (TemplateState m) where
-    mempty = TemplateState Map.empty Map.empty True [] 0
-                           return return return
-
-    (TemplateState s1 t1 r1 _ d1 o1 b1 a1) `mappend`
-        (TemplateState s2 t2 r2 c2 d2 o2 b2 a2) =
-        TemplateState s t r c2 d (o1 >=> o2) (b1 >=> b2) (a1 >=> a2)
-      where
-        s = s1 `mappend` s2
-        t = t1 `mappend` t2
-        r = r1 && r2
-        d = max d1 d2
-
-
-------------------------------------------------------------------------------
-instance MonadTrans TemplateMonad where
-  lift = TemplateMonad . lift
-
-------------------------------------------------------------------------------
--- | A Splice is a TemplateMonad computation that returns [Node].
-type Splice m = TemplateMonad m Template
-
-
-------------------------------------------------------------------------------
--- | SpliceMap associates a name and a Splice.
-type SpliceMap m = Map ByteString (Splice m)
-
-
-------------------------------------------------------------------------------
--- TemplateState functions
-------------------------------------------------------------------------------
-
-
-------------------------------------------------------------------------------
--- | Adds an on-load hook to a `TemplateState`.
-addOnLoadHook :: (Monad m) =>
-                 (Template -> IO Template)
-              -> TemplateState m
-              -> TemplateState m
-addOnLoadHook hook ts = ts { _onLoadHook = _onLoadHook ts >=> hook }
-
-
-------------------------------------------------------------------------------
--- | Adds a pre-run hook to a `TemplateState`.
-addPreRunHook :: (Monad m) =>
-                 (Template -> m Template)
-              -> TemplateState m
-              -> TemplateState m
-addPreRunHook hook ts = ts { _preRunHook = _preRunHook ts >=> hook }
-
-
-------------------------------------------------------------------------------
--- | Adds a post-run hook to a `TemplateState`.
-addPostRunHook :: (Monad m) =>
-                  (Template -> m Template)
-               -> TemplateState m
-               -> TemplateState m
-addPostRunHook hook ts = ts { _postRunHook = _postRunHook ts >=> hook }
-
-
-------------------------------------------------------------------------------
--- | Bind a new splice declaration to a tag name within a 'TemplateState'.
-bindSplice :: Monad m =>
-              ByteString        -- ^ tag name
-           -> Splice m          -- ^ splice action
-           -> TemplateState m   -- ^ source state
-           -> TemplateState m
-bindSplice n v ts = ts {_spliceMap = Map.insert n v (_spliceMap ts)}
-
-
-------------------------------------------------------------------------------
--- | Convenience function for looking up a splice.
-lookupSplice :: Monad m =>
-                ByteString
-             -> TemplateState m
-             -> Maybe (Splice m)
-lookupSplice nm ts = Map.lookup nm $ _spliceMap ts
-
-
-------------------------------------------------------------------------------
--- | Converts a path into an array of the elements in reverse order.  If the
--- path is absolute, we need to remove the leading slash so the split doesn't
--- leave @\"\"@ as the last element of the TPath.
---
--- FIXME @\"..\"@ currently doesn't work in paths, the solution is non-trivial
-splitPaths :: ByteString -> TPath
-splitPaths p = if B.null p then [] else (reverse $ B.split '/' path)
-  where
-    path = if B.head p == '/' then B.tail p else p
-
-
-------------------------------------------------------------------------------
--- | Does a single template lookup without cascading up.
-singleLookup :: TemplateMap
-             -> TPath
-             -> ByteString
-             -> Maybe (Template, TPath)
-singleLookup tm path name = fmap (\a -> (a,path)) $ Map.lookup (name:path) tm
-
-
-------------------------------------------------------------------------------
--- | Searches for a template by looking in the full path then backing up into each
--- of the parent directories until the template is found.
-traversePath :: TemplateMap
-             -> TPath
-             -> ByteString
-             -> Maybe (Template, TPath)
-traversePath tm [] name = fmap (\a -> (a,[])) (Map.lookup [name] tm)
-traversePath tm path name =
-    singleLookup tm path name `mplus`
-    traversePath tm (tail path) name
-
-
-------------------------------------------------------------------------------
--- | Convenience function for looking up a template.
-lookupTemplate :: Monad m =>
-                  ByteString
-               -> TemplateState m
-               -> Maybe (Template, TPath)
-lookupTemplate nameStr ts = 
-    f (_templateMap ts) path name
-  where (name:p) = case splitPaths nameStr of
-                       [] -> [""]
-                       ps -> ps
-        path = p ++ (_curContext ts)
-        f = if '/' `B.elem` nameStr
-                then singleLookup
-                else traversePath
-
-
-------------------------------------------------------------------------------
--- | Sets the templateMap in a TemplateState.
-setTemplates :: Monad m => TemplateMap -> TemplateState m -> TemplateState m
-setTemplates m ts = ts { _templateMap = m }
-
-
-------------------------------------------------------------------------------
--- | Adds a template to the template state.
-insertTemplate :: Monad m =>
-               TPath
-            -> Template
-            -> TemplateState m
-            -> TemplateState m
-insertTemplate p t st =
-    setTemplates (Map.insert p t (_templateMap st)) st
-
-
-------------------------------------------------------------------------------
--- | Adds a template to the template state.
-addTemplate :: Monad m =>
-               ByteString
-            -> Template
-            -> TemplateState m
-            -> TemplateState m
-addTemplate n t st = insertTemplate (splitPaths n) t st
-
-
-------------------------------------------------------------------------------
--- | Gets the node currently being processed.
-getParamNode :: Monad m => TemplateMonad m Node
-getParamNode = ask
-
-
-------------------------------------------------------------------------------
--- | Stops the recursive processing of splices.
-stopRecursion :: Monad m => TemplateMonad m ()
-stopRecursion = modify (\st -> st { _recurse = False })
-
-
-------------------------------------------------------------------------------
--- | Sets the current context
-setContext :: Monad m => TPath -> TemplateMonad m ()
-setContext c = modify (\st -> st { _curContext = c })
-
-
-------------------------------------------------------------------------------
--- | Gets the current context
-getContext :: Monad m => TemplateMonad m TPath
-getContext = gets _curContext
-  
-
-------------------------------------------------------------------------------
--- | Performs splice processing on a list of nodes.
-runNodeList :: Monad m => [Node] -> Splice m
-runNodeList nodes = liftM concat $ sequence (map runNode nodes)
-
-
-------------------------------------------------------------------------------
--- | Performs splice processing on a single node.
-runNode :: Monad m => Node -> Splice m
-runNode n@(X.Text _)          = return [n]
-runNode n@(X.Element nm _ ch) = do
-    s <- liftM (lookupSplice nm) get
-    maybe runChildren (recurseSplice n) s
-
-  where
-    runChildren = do
-        newKids <- runNodeList ch
-        return [X.modifyChildren (const newKids) n]
-
-
-------------------------------------------------------------------------------
--- | The maximum recursion depth.  (Used to prevent infinite loops.)
-mAX_RECURSION_DEPTH :: Int
-mAX_RECURSION_DEPTH = 20
-
-
-------------------------------------------------------------------------------
--- | Checks the recursion flag and recurses accordingly.  Does not recurse
--- deeper than mAX_RECURSION_DEPTH to avoid infinite loops.
-recurseSplice :: Monad m => Node -> Splice m -> Splice m
-recurseSplice node splice = do
-    result <- local (const node) splice
-    ts' <- get
-    if _recurse ts' && _recursionDepth ts' < mAX_RECURSION_DEPTH
-        then do modify (\st -> st { _recursionDepth = _recursionDepth st + 1 })
-                res <- runNodeList result
-                put ts'
-                return res
-        else return result
-
-
-------------------------------------------------------------------------------
--- | Runs a splice in the underlying monad.  Splices require two
--- parameters, the template state, and an input node.
-runSplice :: Monad m =>
-             TemplateState m -- ^ The initial template state
-          -> Node            -- ^ The splice's input node
-          -> Splice m        -- ^ The splice
-          -> m [Node]
-runSplice ts node (TemplateMonad splice) = do
-    (result,_,_) <- runRWST splice node ts
-    return result
-
-
-------------------------------------------------------------------------------
--- | Runs a template in the underlying monad.  Similar to runSplice
--- except that templates don't require a Node as a parameter.
-runRawTemplate :: Monad m => TemplateState m -> Template -> m [Node]
-runRawTemplate ts template =
-    _preRunHook ts template >>=
-    runSplice ts (X.Text "") . runNodeList >>=
-    _postRunHook ts
-
-
-------------------------------------------------------------------------------
--- | Looks up a template name in the supplied 'TemplateState' and runs
--- it in the underlying monad.
-runTemplate :: Monad m
-            => TemplateState m
-            -> ByteString
-            -> m (Maybe [Node])
-runTemplate ts name =
-    maybe (return Nothing)
-          (\(t,ctx) ->
-              return . Just =<<
-              runRawTemplate (ts {_curContext = ctx}) t)
-          (lookupTemplate name ts)
-
-
-------------------------------------------------------------------------------
--- | Looks up a template name evaluates it.  Same as runTemplate except it
--- runs in TemplateMonad instead of m.
-evalTemplate :: Monad m
-            => ByteString
-            -> TemplateMonad m (Maybe [Node])
-evalTemplate name = do
-    ts <- get
-    lift $ runTemplate ts name
-
-
-------------------------------------------------------------------------------
--- | Binds a list of constant string splices
-bindStrings :: Monad m
-            => [(ByteString, ByteString)]
-            -> TemplateState m
-            -> TemplateState m
-bindStrings pairs ts = foldr add ts pairs
-  where
-    add (n,v) = bindSplice n (return [X.Text v])
-
-
-------------------------------------------------------------------------------
--- | Renders a template with the specified parameters.  This is the function
--- to use when you want to "call" a template and pass in parameters from code.
-callTemplate :: Monad m
-             => ByteString                 -- ^ The name of the template
-             -> [(ByteString, ByteString)] -- ^ Association list of
-                                           -- (name,value) parameter pairs
-             -> TemplateMonad m (Maybe Template)
-callTemplate name params = do
-    modify $ bindStrings params
-    evalTemplate name
-
-
-------------------------------------------------------------------------------
--- | Renders a template from the specified TemplateState.
-renderTemplate :: Monad m
-               => TemplateState m
-               -> ByteString
-               -> m (Maybe ByteString)
-renderTemplate ts name = do
-    ns <- runTemplate ts name
-    return $ (Just . formatList') =<< ns
-
-
-------------------------------------------------------------------------------
-heistExpatOptions :: X.ParserOptions ByteString ByteString
-heistExpatOptions =
-    X.defaultParserOptions {
-           X.parserEncoding = Just X.UTF8
-         , X.entityDecoder  = Just (\k -> Map.lookup k htmlEntityLookupTable)
-         }
-
-------------------------------------------------------------------------------
--- Template loading
-------------------------------------------------------------------------------
-
--- | Reads an XML document from disk.
-getDoc :: String -> IO (Either String Template)
-getDoc f = do
-    bs <- catch (liftM Right $ B.readFile f)
-                (\(e::SomeException) -> return $ Left $ show e)
-    let wrap b = "<snap:root>\n" `B.append` b `B.append` "\n</snap:root>"
-    return $ (mapRight X.getChildren .
-              mapLeft genErrorMsg .
-              X.parse' heistExpatOptions . wrap) =<< bs
-  where
-    genErrorMsg (X.XMLParseError str loc) = f ++ " " ++ locMsg loc ++ ": " ++ translate str
-    locMsg (X.XMLParseLocation line col _ _) =
-        "(line " ++ show (line-1) ++ ", col " ++ show col ++ ")"
-    translate "junk after document element" = "document must have a single root element"
-    translate s = s
-
-------------------------------------------------------------------------------
-mapLeft :: (a -> b) -> Either a c -> Either b c
-mapLeft g = either (Left . g) Right
-mapRight :: (b -> c) -> Either a b -> Either a c
-mapRight g = either Left (Right . g)
-
-
-------------------------------------------------------------------------------
--- | Loads a template with the specified path and filename.  The
--- template is only loaded if it has a ".tpl" extension.
-loadTemplate :: String -- ^ path of the template root
-             -> String -- ^ full file path (includes the template root)
-             -> IO [Either String (TPath, Template)] --TemplateMap
-loadTemplate templateRoot fname
-    | ".tpl" `isSuffixOf` fname = do
-        c <- getDoc fname
-        return [fmap (\t -> (splitPaths $ B.pack tName, t)) c]
-    | otherwise = return []
-  where -- tName is path relative to the template root directory
-        tName = drop ((length templateRoot)+1) $
-                -- We're only dropping the template root, not the whole path
-                take ((length fname) - 4) fname
-
-
-------------------------------------------------------------------------------
--- | Traverses the specified directory structure and builds a
--- TemplateState by loading all the files with a ".tpl" extension.
-loadTemplates :: Monad m => FilePath -> TemplateState m -> IO (Either String (TemplateState m))
-loadTemplates dir ts = do
-    d <- readDirectoryWith (loadTemplate dir) dir
-    let tlist = F.fold (free d)
-        errs = lefts tlist
-    case errs of
-        [] -> liftM Right $ foldM loadHook ts $ rights tlist
-        _  -> return $ Left $ unlines errs
-
-
-------------------------------------------------------------------------------
--- | Runs the onLoad hook on the template and returns the `TemplateState`
--- with the result inserted.
-loadHook :: Monad m => TemplateState m -> (TPath, Template) -> IO (TemplateState m)
-loadHook ts (tp, t) = do
-    t' <- _onLoadHook ts t
-    return $ insertTemplate tp t' ts
-
-
-------------------------------------------------------------------------------
--- These are here until we can get them into hexpat.
-------------------------------------------------------------------------------
-
-formatList :: (X.GenericXMLString tag, X.GenericXMLString text) =>
-              [X.Node tag text]
-           -> L.ByteString
-formatList nodes = foldl L.append L.empty $ map formatNode nodes
-
-formatList' :: (X.GenericXMLString tag, X.GenericXMLString text) =>
-               [X.Node tag text]
-            -> B.ByteString
-formatList' = B.concat . L.toChunks . formatList
-
-
- diff --git a/static/docs/0.2.1/heist/src/Text-Templating-Heist-Splices-Apply.html b/static/docs/0.2.1/heist/src/Text-Templating-Heist-Splices-Apply.html deleted file mode 100644 index 83efe53..0000000 --- a/static/docs/0.2.1/heist/src/Text-Templating-Heist-Splices-Apply.html +++ /dev/null @@ -1,57 +0,0 @@ - - - - -src/Text/Templating/Heist/Splices/Apply.hs - - - -
{-# LANGUAGE OverloadedStrings #-}
-
-module Text.Templating.Heist.Splices.Apply where
-
-------------------------------------------------------------------------------
-import           Control.Monad.RWS.Strict
-import           Data.ByteString.Char8 (ByteString)
-import qualified Data.ByteString.Char8 as B
-import qualified Text.XML.Expat.Tree as X
-
-------------------------------------------------------------------------------
-import           Text.Templating.Heist.Internal
-
-------------------------------------------------------------------------------
--- | Default name for the apply splice.
-applyTag :: ByteString
-applyTag = "apply"
-
-
-------------------------------------------------------------------------------
--- | Default attribute name for the apply tag.
-applyAttr :: ByteString
-applyAttr = "template"
-
-
-------------------------------------------------------------------------------
--- | Implementation of the apply splice.
-applyImpl :: Monad m => Splice m
-applyImpl = do
-    node <- getParamNode
-    case X.getAttribute node applyAttr of
-        Nothing   -> return [] -- TODO: error handling
-        Just attr -> do 
-            st <- get
-            processedChildren <- runNodeList $ X.getChildren node
-            modify (bindSplice "content" $ return processedChildren)
-            maybe (return []) -- TODO: error handling
-                  (\(t,ctx) -> do setContext ctx
-                                  result <- runNodeList t
-                                  put st
-                                  return result)
-                  (lookupTemplate attr (st {_curContext = nextCtx attr st}))
-  where nextCtx name st
-            | B.isPrefixOf "/" name = []
-            | otherwise             = _curContext st
-
-
-
- diff --git a/static/docs/0.2.1/heist/src/Text-Templating-Heist-Splices-Bind.html b/static/docs/0.2.1/heist/src/Text-Templating-Heist-Splices-Bind.html deleted file mode 100644 index 27c602f..0000000 --- a/static/docs/0.2.1/heist/src/Text-Templating-Heist-Splices-Bind.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - -src/Text/Templating/Heist/Splices/Bind.hs - - - -
{-# LANGUAGE OverloadedStrings #-}
-
-module Text.Templating.Heist.Splices.Bind where
-
-------------------------------------------------------------------------------
-import           Control.Monad.RWS.Strict
-import           Data.ByteString.Char8 (ByteString)
-import qualified Text.XML.Expat.Tree as X
-
-------------------------------------------------------------------------------
-import           Text.Templating.Heist.Internal
-
--- | Default name for the bind splice.
-bindTag :: ByteString
-bindTag = "bind"
-
-
-------------------------------------------------------------------------------
--- | Default attribute name for the bind tag.
-bindAttr :: ByteString
-bindAttr = "tag"
-
-
-------------------------------------------------------------------------------
--- | Implementation of the bind splice.
-bindImpl :: Monad m => Splice m
-bindImpl = do
-    node <- getParamNode
-    maybe (return ())
-          (add node)
-          (X.getAttribute node bindAttr)
-    return []
-
-  where
-    add node nm = modify $ bindSplice nm (return $ X.getChildren node)
-
-
-
- diff --git a/static/docs/0.2.1/heist/src/Text-Templating-Heist-Splices-Ignore.html b/static/docs/0.2.1/heist/src/Text-Templating-Heist-Splices-Ignore.html deleted file mode 100644 index 94cfc79..0000000 --- a/static/docs/0.2.1/heist/src/Text-Templating-Heist-Splices-Ignore.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - -src/Text/Templating/Heist/Splices/Ignore.hs - - - -
{-# LANGUAGE OverloadedStrings #-}
-
-module Text.Templating.Heist.Splices.Ignore where
-
-------------------------------------------------------------------------------
-import           Data.ByteString.Char8 (ByteString)
-
-------------------------------------------------------------------------------
-import           Text.Templating.Heist.Internal
-
-
-------------------------------------------------------------------------------
--- | Default name for the ignore splice.
-ignoreTag :: ByteString
-ignoreTag = "ignore"
-
-
-------------------------------------------------------------------------------
--- | The ignore tag and everything it surrounds disappears in the
--- rendered output.
-ignoreImpl :: Monad m => Splice m
-ignoreImpl = return []
-
-
-
- diff --git a/static/docs/0.2.1/heist/src/Text-Templating-Heist-Splices-Markdown.html b/static/docs/0.2.1/heist/src/Text-Templating-Heist-Splices-Markdown.html deleted file mode 100644 index 56cc561..0000000 --- a/static/docs/0.2.1/heist/src/Text-Templating-Heist-Splices-Markdown.html +++ /dev/null @@ -1,160 +0,0 @@ - - - - -src/Text/Templating/Heist/Splices/Markdown.hs - - - -
{-# LANGUAGE OverloadedStrings, DeriveDataTypeable #-}
-
-module Text.Templating.Heist.Splices.Markdown where
-
-import           Data.ByteString (ByteString)
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Char8 as BC
-import           Data.Maybe
-import           Control.Concurrent
-import           Control.Exception (evaluate, throwIO)
-import           Control.Monad
-import           Control.Monad.CatchIO
-import           Control.Monad.Trans
-import           Data.Typeable
-import           Prelude hiding (catch)
-import           System.Directory
-import           System.Exit
-import           System.IO
-import           System.Process
-import           Text.Templating.Heist.Internal
-import           Text.XML.Expat.Tree hiding (Node)
-
-
-data PandocMissingException = PandocMissingException
-   deriving (Typeable)
-
-instance Show PandocMissingException where
-    show PandocMissingException =
-        "Cannot find the \"pandoc\" executable; is it on your $PATH?"
-
-instance Exception PandocMissingException
-
-
-data MarkdownException = MarkdownException ByteString
-   deriving (Typeable)
-
-instance Show MarkdownException where
-    show (MarkdownException e) =
-        "Markdown error: pandoc replied:\n\n" ++ BC.unpack e
-
-instance Exception MarkdownException
-
-
-------------------------------------------------------------------------------
--- | Default name for the markdown splice.
-markdownTag :: ByteString
-markdownTag = "markdown"
-
-------------------------------------------------------------------------------
--- | Implementation of the markdown splice.
-markdownSplice :: MonadIO m => Splice m
-markdownSplice = do
-    pdMD <- liftIO $ findExecutable "pandoc"
-
-    when (isNothing pdMD) $ liftIO $ throwIO PandocMissingException
-
-    tree <- getParamNode
-    markup <- liftIO $
-        case getAttribute tree "file" of
-            Just f  -> pandoc (fromJust pdMD) $ BC.unpack f
-            Nothing -> pandocBS (fromJust pdMD) $ textContent tree
-
-    let ee = parse' heistExpatOptions markup
-    case ee of
-      (Left e) -> throw $ MarkdownException
-                        $ BC.pack ("Error parsing markdown output: " ++ show e)
-      (Right n) -> return [n]
-
-
-pandoc :: FilePath -> FilePath -> IO ByteString
-pandoc pandocPath inputFile = do
-    (ex, sout, serr) <- readProcessWithExitCode' pandocPath args ""
-
-    when (isFail ex) $ throw $ MarkdownException serr
-    return $ BC.concat [ "<div class=\"markdown\">\n"
-                       , sout
-                       , "\n</div>" ]
-
-  where
-    isFail ExitSuccess = False
-    isFail _           = True
-
-    -- FIXME: hardcoded path
-    args = [ "-S", "--no-wrap", "templates/"++inputFile ]
-
-
-pandocBS :: FilePath -> ByteString -> IO ByteString
-pandocBS pandocPath s = do
-    -- using the crummy string functions for convenience here
-    (ex, sout, serr) <- readProcessWithExitCode' pandocPath args s
-
-    when (isFail ex) $ throw $ MarkdownException serr
-    return $ BC.concat [ "<div class=\"markdown\">\n"
-                       , sout
-                       , "\n</div>" ]
-
-  where
-    isFail ExitSuccess = False
-    isFail _           = True
-    args = [ "-S", "--no-wrap" ]
-
-
--- a version of readProcessWithExitCode that does I/O properly
-readProcessWithExitCode'
-    :: FilePath                 -- ^ command to run
-    -> [String]                 -- ^ any arguments
-    -> ByteString               -- ^ standard input
-    -> IO (ExitCode,ByteString,ByteString) -- ^ exitcode, stdout, stderr
-readProcessWithExitCode' cmd args input = do
-    (Just inh, Just outh, Just errh, pid) <-
-        createProcess (proc cmd args){ std_in  = CreatePipe,
-                                       std_out = CreatePipe,
-                                       std_err = CreatePipe }
-    outMVar <- newEmptyMVar
-
-    outM <- newEmptyMVar
-    errM <- newEmptyMVar
-
-    -- fork off a thread to start consuming stdout
-    forkIO $ do
-        out <- B.hGetContents outh
-        putMVar outM out
-        putMVar outMVar ()
-
-    -- fork off a thread to start consuming stderr
-    forkIO $ do
-        err  <- B.hGetContents errh
-        putMVar errM err
-        putMVar outMVar ()
-
-    -- now write and flush any input
-    when (not (B.null input)) $ do B.hPutStr inh input; hFlush inh
-    hClose inh -- done with stdin
-
-    -- wait on the output
-    takeMVar outMVar
-    takeMVar outMVar
-    hClose outh
-
-    -- wait on the process
-    ex <- waitForProcess pid
-
-    out <- readMVar outM
-    err <- readMVar errM
-
-    return (ex, out, err)
-
-
-
-
-
- diff --git a/static/docs/0.2.1/heist/src/Text-Templating-Heist-Splices-Static.html b/static/docs/0.2.1/heist/src/Text-Templating-Heist-Splices-Static.html deleted file mode 100644 index 734781d..0000000 --- a/static/docs/0.2.1/heist/src/Text-Templating-Heist-Splices-Static.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - -src/Text/Templating/Heist/Splices/Static.hs - - - -
{-# LANGUAGE OverloadedStrings #-}
-
-module Text.Templating.Heist.Splices.Static 
-  ( StaticTagState
-  , bindStaticTag
-  , clearStaticTagCache
-  ) where
-
-------------------------------------------------------------------------------
-import           Control.Concurrent
-import           Control.Monad
-import           Control.Monad.Trans
-import           Data.ByteString.Char8 (ByteString)
-import qualified Data.ByteString.Char8 as B
-import           Data.IORef
-import qualified Data.Map as Map
-import           Data.Map (Map)
-import           Data.Maybe
-import qualified Data.Set as Set
-import           System.Random
-import           Text.XML.Expat.Cursor
-import           Text.XML.Expat.Tree hiding (Node)
-
-
-------------------------------------------------------------------------------
-import           Text.Templating.Heist.Internal
-
-
-------------------------------------------------------------------------------
--- | State for storing static tag information
-newtype StaticTagState = STS (MVar (Map ByteString Template))
-
-
-------------------------------------------------------------------------------
--- | Clears the static tag state.
-clearStaticTagCache :: StaticTagState -> IO ()
-clearStaticTagCache (STS staticMVar) =
-    modifyMVar_ staticMVar (const $ return Map.empty)
-
-
-------------------------------------------------------------------------------
--- | The "static" splice ensures that its contents are evaluated once and then
--- cached.  The cached contents are returned every time the splice is
--- referenced.
-staticImpl :: (MonadIO m)
-           => StaticTagState
-           -> TemplateMonad m Template
-staticImpl (STS mv) = do
-    tree <- getParamNode
-    let i = fromJust $ getAttribute tree "id"
-
-    mp <- liftIO $ readMVar mv
-
-    (mp',ns) <- do
-                   let mbn = Map.lookup i mp
-                   case mbn of
-                       Nothing -> do
-                           nodes' <- runNodeList $ getChildren tree
-                           return $! (Map.insert i nodes' mp, nodes')
-                       (Just n) -> do
-                           stopRecursion
-                           return $! (mp,n)
-
-    liftIO $ modifyMVar_ mv (const $ return mp')
-
-    return ns
-
-
-------------------------------------------------------------------------------
--- | Modifies a TemplateState to include a "static" tag.
-bindStaticTag :: MonadIO m
-              => TemplateState m
-              -> IO (TemplateState m, StaticTagState)
-bindStaticTag ts = do
-    sr <- newIORef $ Set.empty
-    mv <- liftM STS $ newMVar Map.empty
-
-    return $ (addOnLoadHook (assignIds sr) $
-                bindSplice "static" (staticImpl mv) ts,
-              mv)
-
-  where
-    generateId :: IO Int
-    generateId = getStdRandom random
-
-    assignIds setref = mapM f
-        where
-          f node = g $ fromTree node
-
-          getId = do
-              i  <- liftM (B.pack . show) generateId
-              st <- readIORef setref
-              if Set.member i st
-                then getId
-                else do
-                    writeIORef setref $ Set.insert i st
-                    return i
-
-          g curs = do
-              let node = current curs
-              curs' <- if getName node == "static"
-                         then do
-                             i <- getId
-                             return $ modifyContent (setAttribute "id" i) curs
-                         else return curs
-              let mbc = nextDF curs'
-              maybe (return $ toTree curs') g mbc
-
-
-
-
-
- diff --git a/static/docs/0.2.1/heist/src/Text-Templating-Heist-Splices.html b/static/docs/0.2.1/heist/src/Text-Templating-Heist-Splices.html deleted file mode 100644 index 9919a2e..0000000 --- a/static/docs/0.2.1/heist/src/Text-Templating-Heist-Splices.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - -src/Text/Templating/Heist/Splices.hs - - - -
module Text.Templating.Heist.Splices
-  ( module Text.Templating.Heist.Splices.Apply
-  , module Text.Templating.Heist.Splices.Bind
-  , module Text.Templating.Heist.Splices.Ignore
-  , module Text.Templating.Heist.Splices.Markdown
-  , module Text.Templating.Heist.Splices.Static
-  ) where
-
-import Text.Templating.Heist.Splices.Apply
-import Text.Templating.Heist.Splices.Bind
-import Text.Templating.Heist.Splices.Ignore
-import Text.Templating.Heist.Splices.Markdown
-import Text.Templating.Heist.Splices.Static
-
-
- diff --git a/static/docs/0.2.1/heist/src/Text-Templating-Heist.html b/static/docs/0.2.1/heist/src/Text-Templating-Heist.html deleted file mode 100644 index d02f5a7..0000000 --- a/static/docs/0.2.1/heist/src/Text-Templating-Heist.html +++ /dev/null @@ -1,155 +0,0 @@ - - - - -src/Text/Templating/Heist.hs - - - -
{-# LANGUAGE OverloadedStrings, GeneralizedNewtypeDeriving #-}
-
-{-|
-
-  This module contains the core definitions for the Heist template system.
-
-  The Heist template system is based on XML\/xhtml.  It allows you to build
-  custom XML-based markup languages.  With Heist you can define your own
-  domain-specific XML tags implemented with Haskell and use them in your
-  templates.  
-
-  The most important concept in Heist is the 'Splice'.  Splices can be thought
-  of as functions that transform a node into a list of nodes.  Heist then
-  substitutes the resulting list of nodes into your template in place of the
-  input node.  'Splice' is implemented as a type synonym @type Splice m =
-  TemplateMonad m [Node]@, and 'TemplateMonad' has a function 'getParamNode'
-  that lets you get the input node.
-
-  Suppose you have a place on your page where you want to display a link with
-  the text \"Logout username\" if the user is currently logged in or a link to
-  the login page if no user is logged in.  Assume you have a function
-  @getUser :: MyAppMonad (Maybe ByteString)@ that gets the current user.
-  You can implement this functionality with a 'Splice' as follows:
-
-  >
-  > import Text.XML.Expat.Tree
-  >
-  > link :: ByteString -> ByteString -> Node
-  > link target text = X.Element "a" [("href", target)] [X.Text text]
-  > 
-  > loginLink :: Node
-  > loginLink = link "/login" "Login"
-  > 
-  > logoutLink :: ByteString -> Node
-  > logoutLink user = link "/logout" (B.append "Logout " user)
-  > 
-  > loginLogoutSplice :: Splice MyAppMonad
-  > loginLogoutSplice = do
-  >     user <- lift getUser
-  >     return $ [maybe loginLink logoutLink user]
-  >
-
-  Next, you need to bind that splice to an XML tag.  Heist stores information
-  about splices and templates in the 'TemplateState' data structure.  The
-  following code demonstrates how this splice would be used.
-
-  > mySplices = [ ("loginLogout", loginLogoutSplice) ]
-  > 
-  > main = do
-  >     ets <- loadTemplates "templates" $
-  >            foldr (uncurry bindSplice) emptyTemplateState mySplices
-  >     let ts = either error id ets
-  >     t <- runMyAppMonad $ renderTemplate ts "index"
-  >     print $ maybe "Page not found" id t
-
-  Here we build up our 'TemplateState' by starting with emptyTemplateState and
-  applying bindSplice for all the splices we want to add.  Then we pass this
-  to loadTemplates our final 'TemplateState' wrapped in an Either to handle
-  errors.  Then we use this 'TemplateState' to render our templates.
-
--}
-
-module Text.Templating.Heist
-  (
-    -- * Types
-    Node
-  , Splice
-  , Template
-  , TemplateMonad
-  , TemplateState
-
-    -- * Functions and declarations on TemplateState values
-  , addTemplate
-  , emptyTemplateState
-  , bindSplice
-  , lookupSplice
-  , setTemplates
-  , loadTemplates
-
-    -- * Hook functions
-    -- $hookDoc
-  , addOnLoadHook
-  , addPreRunHook
-  , addPostRunHook
-
-    -- * TemplateMonad functions
-  , stopRecursion
-  , getParamNode
-  , runNodeList
-  , getContext
-
-    -- * Functions for running splices and templates
-  , runTemplate
-  , evalTemplate
-  , callTemplate
-  , renderTemplate
-  , bindStrings
-
-    -- * Misc functions
-  , runSplice
-  , runRawTemplate
-  , getDoc
-  , bindStaticTag
-
-  , heistExpatOptions
-  , module Text.Templating.Heist.Constants
-  ) where
-
-import           Control.Monad.Trans
-import qualified Data.Map as Map
-import           Text.Templating.Heist.Internal
-import           Text.Templating.Heist.Constants
-import           Text.Templating.Heist.Splices
-
-
-------------------------------------------------------------------------------
--- | The default set of built-in splices.
-defaultSpliceMap :: MonadIO m => SpliceMap m
-defaultSpliceMap = Map.fromList
-    [(applyTag, applyImpl)
-    ,(bindTag, bindImpl)
-    ,(ignoreTag, ignoreImpl)
-    ,(markdownTag, markdownSplice)
-    ]
-
-
-------------------------------------------------------------------------------
--- | An empty template state, with Heist's default splices (@\<bind\>@ and
--- @\<apply\>@) mapped.
-emptyTemplateState :: MonadIO m => TemplateState m
-emptyTemplateState = TemplateState defaultSpliceMap Map.empty True [] 0
-                                   return return return
-
-
--- $hookDoc
--- Heist hooks allow you to modify templates when they are loaded and before
--- and after they are run.  Every time you call one of the addAbcHook
--- functions the hook is added to onto the processing pipeline.  The hooks
--- processes the template in the order that they were added to the
--- TemplateState.
---
--- The pre-run and post-run hooks are run before and after every template is
--- run/rendered.  You should be careful what code you put in these hooks
--- because it can significantly affect the performance of your site.
-
-
- diff --git a/static/docs/0.2.1/heist/src/hscolour.css b/static/docs/0.2.1/heist/src/hscolour.css deleted file mode 100644 index 150e4d0..0000000 --- a/static/docs/0.2.1/heist/src/hscolour.css +++ /dev/null @@ -1,15 +0,0 @@ -body { font-size: 90%; } - -pre, code, body { - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; -} - -.hs-keyglyph, .hs-layout {color: #5200A3;} -.hs-keyword {color: #3465a4; font-weight: bold;} -.hs-comment, .hs-comment a {color: #579; } -.hs-str, .hs-chr {color: #141B24;} -.hs-keyword, .hs-conid, .hs-varid, .hs-conop, .hs-varop, .hs-num, .hs-cpp, .hs-sel, .hs-definition {} diff --git a/static/docs/0.2.1/snap-core/Data-CIByteString.html b/static/docs/0.2.1/snap-core/Data-CIByteString.html deleted file mode 100644 index cb6f466..0000000 --- a/static/docs/0.2.1/snap-core/Data-CIByteString.html +++ /dev/null @@ -1,366 +0,0 @@ - - -Data.CIByteString
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Data.CIByteString
Description

Data.CIByteString is a module containing CIByteString, a wrapper for - ByteString which provides case-insensitive (ASCII-wise) Ord and Eq - instances. -

CIByteString also has an IsString instance, so if you use the - "OverloadedStrings" LANGUAGE pragma you can write case-insensitive string - literals, e.g.: -

- > let a = "Foo" in
-   putStrLn $ (show $ unCI a) ++ "==\"FoO\" is " ++ show (a == "FoO")
- "Foo"=="FoO" is True
-
Synopsis
data CIByteString
toCI :: ByteString -> CIByteString
unCI :: CIByteString -> ByteString
ciToLower :: CIByteString -> ByteString
Documentation
data CIByteString Source
A case-insensitive newtype wrapper for ByteString -
show/hide Instances
toCI :: ByteString -> CIByteStringSource
unCI :: CIByteString -> ByteStringSource
ciToLower :: CIByteString -> ByteStringSource
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.1/snap-core/Snap-Internal-Debug.html b/static/docs/0.2.1/snap-core/Snap-Internal-Debug.html deleted file mode 100644 index a5445bc..0000000 --- a/static/docs/0.2.1/snap-core/Snap-Internal-Debug.html +++ /dev/null @@ -1,169 +0,0 @@ - - -Snap.Internal.Debug
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Snap.Internal.Debug
Description

An internal Snap module for (optionally) printing debugging - messages. Normally debug does nothing, but you can pass "-fdebug" to - cabal install to build a snap-core which debugs to stderr. -

N.B. this is an internal interface, please don't write external code that - depends on it. -

Documentation
debug :: MonadIO m => String -> m ()Source
debugErrno :: MonadIO m => String -> m ()Source
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.1/snap-core/Snap-Internal-Http-Types.html b/static/docs/0.2.1/snap-core/Snap-Internal-Http-Types.html deleted file mode 100644 index 2c6ef5a..0000000 --- a/static/docs/0.2.1/snap-core/Snap-Internal-Http-Types.html +++ /dev/null @@ -1,3854 +0,0 @@ - - -Snap.Internal.Http.Types
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Snap.Internal.Http.Types
Description

An internal Snap module containing HTTP types. -

N.B. this is an internal interface, please don't write user code that - depends on it. Most of these declarations (except for the - unsafe/encapsulation-breaking ones) are re-exported from Snap.Types. -

Synopsis
set_c_locale :: IO ()
c_parse_http_time :: CString -> IO CTime
c_format_http_time :: CTime -> CString -> IO ()
type Enumerator a = Enumerator IO a
type Headers = Map CIByteString [ByteString]
class HasHeaders a where
updateHeaders :: (Headers -> Headers) -> a -> a
headers :: a -> Headers
addHeader :: HasHeaders a => CIByteString -> ByteString -> a -> a
setHeader :: HasHeaders a => CIByteString -> ByteString -> a -> a
getHeaders :: HasHeaders a => CIByteString -> a -> Maybe [ByteString]
getHeader :: HasHeaders a => CIByteString -> a -> Maybe ByteString
data Method
= GET
| HEAD
| POST
| PUT
| DELETE
| TRACE
| OPTIONS
| CONNECT
type HttpVersion = (Int, Int)
data Cookie = Cookie {
cookieName :: !ByteString
cookieValue :: !ByteString
cookieExpires :: !(Maybe UTCTime)
cookieDomain :: !(Maybe ByteString)
cookiePath :: !(Maybe ByteString)
}
type Params = Map ByteString [ByteString]
data SomeEnumerator = SomeEnumerator (forall a. Enumerator a)
data Request = Request {
rqServerName :: !ByteString
rqServerPort :: !Int
rqRemoteAddr :: !ByteString
rqRemotePort :: !Int
rqLocalAddr :: !ByteString
rqLocalPort :: !Int
rqLocalHostname :: !ByteString
rqIsSecure :: !Bool
rqHeaders :: Headers
rqBody :: IORef SomeEnumerator
rqContentLength :: !(Maybe Int)
rqMethod :: !Method
rqVersion :: !HttpVersion
rqCookies :: [Cookie]
rqSnapletPath :: !ByteString
rqPathInfo :: !ByteString
rqContextPath :: !ByteString
rqURI :: !ByteString
rqQueryString :: !ByteString
rqParams :: Params
}
data ResponseBody
= Enum (forall a. Enumerator a)
| SendFile FilePath
rspBodyMap :: (forall a. Enumerator a -> Enumerator a) -> ResponseBody -> ResponseBody
rspBodyToEnum :: ResponseBody -> Enumerator a
data Response = Response {
rspHeaders :: Headers
rspHttpVersion :: !HttpVersion
rspContentLength :: !(Maybe Int)
rspBody :: ResponseBody
rspStatus :: !Int
rspStatusReason :: !ByteString
}
rqParam :: ByteString -> Request -> Maybe [ByteString]
rqModifyParams :: (Params -> Params) -> Request -> Request
rqSetParam :: ByteString -> [ByteString] -> Request -> Request
emptyResponse :: Response
setResponseBody :: (forall a. Enumerator a) -> Response -> Response
setResponseStatus :: Int -> ByteString -> Response -> Response
modifyResponseBody :: (forall a. Enumerator a -> Enumerator a) -> Response -> Response
setContentType :: ByteString -> Response -> Response
addCookie :: Cookie -> Response -> Response
setContentLength :: Int -> Response -> Response
clearContentLength :: Response -> Response
formatHttpTime :: CTime -> IO ByteString
parseHttpTime :: ByteString -> IO CTime
parseToCompletion :: Parser a -> ByteString -> Maybe a
pUrlEscaped :: Parser ByteString
urlDecode :: ByteString -> Maybe ByteString
urlEncode :: ByteString -> ByteString
hexd :: Word8 -> Builder
finish :: Result a -> Result a
fromStr :: String -> ByteString
toStr :: ByteString -> String
Documentation
set_c_locale :: IO ()Source
c_parse_http_time :: CString -> IO CTimeSource
c_format_http_time :: CTime -> CString -> IO ()Source
type Enumerator a = Enumerator IO aSource
type Headers = Map CIByteString [ByteString]Source
A type alias for a case-insensitive key-value mapping. -
class HasHeaders a whereSource
A typeclass for datatypes which contain HTTP headers. -
Methods
updateHeaders :: (Headers -> Headers) -> a -> aSource
Modify the datatype's headers. -
headers :: a -> HeadersSource
Retrieve the headers from a datatype that has headers. -
show/hide Instances
addHeader :: HasHeaders a => CIByteString -> ByteString -> a -> aSource
Adds a header key-value-pair to the HasHeaders datatype. If a header with - the same name already exists, the new value is appended to the headers list. -
setHeader :: HasHeaders a => CIByteString -> ByteString -> a -> aSource
Sets a header key-value-pair in a HasHeaders datatype. If a header with - the same name already exists, it is overwritten with the new value. -
getHeaders :: HasHeaders a => CIByteString -> a -> Maybe [ByteString]Source
Gets all of the values for a given header. -
getHeader :: HasHeaders a => CIByteString -> a -> Maybe ByteStringSource
Gets a header value out of a HasHeaders datatype. If many headers came - in with the same name, they will be catenated together. -
data Method Source
Enumerates the HTTP method values (see - http://tools.ietf.org/html/rfc2068.html#section-5.1.1). -
Constructors
GET
HEAD
POST
PUT
DELETE
TRACE
OPTIONS
CONNECT
show/hide Instances
type HttpVersion = (Int, Int)Source
data Cookie Source
A datatype representing an HTTP cookie. -
Constructors
Cookie
cookieName :: !ByteStringThe name of the cookie. -
cookieValue :: !ByteStringThe cookie's string value. -
cookieExpires :: !(Maybe UTCTime)The cookie's expiration value, if it has one. -
cookieDomain :: !(Maybe ByteString)The cookie's "domain" value, if it has one. -
cookiePath :: !(Maybe ByteString)The cookie path. -
show/hide Instances
type Params = Map ByteString [ByteString]Source
A type alias for the HTTP parameters mapping. Each parameter - key maps to a list of ByteString values; if a parameter is specified - multiple times (e.g.: "GET /foo?param=bar1&param=bar2"), looking up - "param" in the mapping will give you ["bar1", "bar2"]. -
data SomeEnumerator Source
Constructors
SomeEnumerator (forall a. Enumerator a)
data Request Source
Contains all of the information about an incoming HTTP request. -
Constructors
Request
rqServerName :: !ByteStringThe server name of the request, as it came in from the request's - Host: header. -
rqServerPort :: !IntReturns the port number the HTTP server is listening on. -
rqRemoteAddr :: !ByteStringThe remote IP address. -
rqRemotePort :: !IntThe remote TCP port number. -
rqLocalAddr :: !ByteStringThe local IP address for this request. -
rqLocalPort :: !IntReturns the port number the HTTP server is listening on. -
rqLocalHostname :: !ByteStringReturns the HTTP server's idea of its local hostname. -
rqIsSecure :: !BoolReturns True if this is an HTTPS session (currently always - False). -
rqHeaders :: Headers
rqBody :: IORef SomeEnumerator
rqContentLength :: !(Maybe Int)Returns the Content-Length of the HTTP request body. -
rqMethod :: !MethodReturns the HTTP request method. -
rqVersion :: !HttpVersionReturns the HTTP version used by the client. -
rqCookies :: [Cookie]Returns a list of the cookies that came in from the HTTP request - headers. -
rqSnapletPath :: !ByteString

We'll be doing web components (or "snaplets") for version 0.2. The - "snaplet path" refers to the place on the URL where your containing - snaplet is hung. The value of rqSnapletPath is either "" (at the - top-level context) or is a path beginning with a slash, but not ending - with one. -

An identity is that: -

 rqURI r == 'S.concat' [ rqSnapletPath r
-                       , rqContextPath r
-                       , rqPathInfo r ]
-

note that until we introduce snaplets in v0.2, rqSnapletPath will be - "" -

rqPathInfo :: !ByteStringHandlers can (will be; --ed) be hung on a URI "entry point"; - this is called the "context path". If a handler is hung on the - context path "/foo/", and you request "/foo/bar", the value - of rqPathInfo will be "bar". -
rqContextPath :: !ByteStringThe "context path" of the request; catenating rqContextPath, and - rqPathInfo should get you back to the original rqURI. The - rqContextPath always begins and ends with a slash ("/") - character, and represents the path (relative to your - component/snaplet) you took to get to your handler. -
rqURI :: !ByteStringReturns the URI requested by the client. -
rqQueryString :: !ByteStringReturns the HTTP query string for this Request. -
rqParams :: ParamsReturns the Params mapping for this Request. "Parameters" are - automatically decoded from the query string and POST body and - entered into this mapping. -
show/hide Instances
data ResponseBody Source
Constructors
Enum (forall a. Enumerator a)output body is enumerator -
SendFile FilePathoutput body is sendfile() -
rspBodyMap :: (forall a. Enumerator a -> Enumerator a) -> ResponseBody -> ResponseBodySource
rspBodyToEnum :: ResponseBody -> Enumerator aSource
data Response Source
Represents an HTTP response. -
Constructors
Response
rspHeaders :: Headers
rspHttpVersion :: !HttpVersion
rspContentLength :: !(Maybe Int)We will need to inspect the content length no matter what, and - looking up "content-length" in the headers and parsing the number - out of the text will be too expensive. -
rspBody :: ResponseBody
rspStatus :: !IntReturns the HTTP status code. -
rspStatusReason :: !ByteStringReturns the HTTP status explanation string. -
show/hide Instances
rqParamSource
:: ByteStringparameter name to look up -
-> RequestHTTP request -
-> Maybe [ByteString]
Looks up the value(s) for the given named parameter. Parameters initially - come from the request's query string and any decoded POST body (if the - request's Content-Type is application/x-www-form-urlencoded). Parameter - values can be modified within handlers using rqModifyParams. -
rqModifyParams :: (Params -> Params) -> Request -> RequestSource
Modifies the parameters mapping (which is a Map ByteString ByteString) in - a Request using the given function. -
rqSetParamSource
:: ByteStringparameter name -
-> [ByteString]parameter values -
-> Requestrequest -
-> Request
Writes a key-value pair to the parameters mapping within the given request. -
emptyResponse :: ResponseSource
An empty Response. -
setResponseBodySource
:: forall a. Enumerator anew response body - enumerator -
-> Responseresponse to modify -
-> Response
Sets an HTTP response body to the given Enumerator value. -
setResponseStatusSource
:: IntHTTP response integer code -
-> ByteStringHTTP response explanation -
-> ResponseResponse to be modified -
-> Response
Sets the HTTP response status. -
modifyResponseBody :: (forall a. Enumerator a -> Enumerator a) -> Response -> ResponseSource
Modifies a response body. -
setContentType :: ByteString -> Response -> ResponseSource
Sets the Content-Type in the Response headers. -
addCookieSource
:: Cookiecookie value -
-> Responseresponse to modify -
-> Response
Adds an HTTP Cookie to the Response headers. -
setContentLength :: Int -> Response -> ResponseSource

A note here: if you want to set the Content-Length for the response, - Snap forces you to do it with this function rather than by setting it in the - headers; the Content-Length in the headers will be ignored. -

The reason for this is that Snap needs to look up the value of - Content-Length for each request, and looking the string value up in the - headers and parsing the number out of the text will be too expensive. -

If you don't set a content length in your response, HTTP keep-alive will be - disabled for HTTP/1.0 clients, forcing a Connection: close. For HTTP/1.1 - clients, Snap will switch to the chunked transfer encoding if - Content-Length is not specified. -

clearContentLength :: Response -> ResponseSource
Removes any Content-Length set in the Response. -
formatHttpTime :: CTime -> IO ByteStringSource
Converts a CTime into an HTTP timestamp. -
parseHttpTime :: ByteString -> IO CTimeSource
Converts an HTTP timestamp into a CTime. -
parseToCompletion :: Parser a -> ByteString -> Maybe aSource
pUrlEscaped :: Parser ByteStringSource
urlDecode :: ByteString -> Maybe ByteStringSource
Decodes an URL-escaped string (see - http://tools.ietf.org/html/rfc2396.html#section-2.4) -
urlEncode :: ByteString -> ByteStringSource
URL-escapes a string (see - http://tools.ietf.org/html/rfc2396.html#section-2.4) -
hexd :: Word8 -> BuilderSource
finish :: Result a -> Result aSource
fromStr :: String -> ByteStringSource
toStr :: ByteString -> StringSource
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.1/snap-core/Snap-Internal-Iteratee-Debug.html b/static/docs/0.2.1/snap-core/Snap-Internal-Iteratee-Debug.html deleted file mode 100644 index ef5a523..0000000 --- a/static/docs/0.2.1/snap-core/Snap-Internal-Iteratee-Debug.html +++ /dev/null @@ -1,129 +0,0 @@ - - -Snap.Internal.Iteratee.Debug
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Snap.Internal.Iteratee.Debug
Description

An internal Snap module for debugging iteratees. -

N.B. this is an internal interface, please don't write user code that - depends on it. -

Documentation
debugIteratee :: Iteratee IO ()Source
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.1/snap-core/Snap-Iteratee.html b/static/docs/0.2.1/snap-core/Snap-Iteratee.html deleted file mode 100644 index c53c916..0000000 --- a/static/docs/0.2.1/snap-core/Snap-Iteratee.html +++ /dev/null @@ -1,971 +0,0 @@ - - -Snap.Iteratee
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Snap.Iteratee
Contents
Convenience aliases around types from Data.Iteratee -
Re-export types and functions from Data.Iteratee -
Helper functions -
Enumerators -
Conversion to/from WrappedByteString -
Iteratee utilities -
Description

Snap Framework type aliases and utilities for iteratees. Note that as a - convenience, this module also exports everything from Data.Iteratee in the - iteratee library. -

WARNING: Note that all of these types are scheduled to change in the - darcs head version of the iteratee library; John Lato et al. are working - on a much improved iteratee formulation. -

Synopsis
type Stream = StreamG WrappedByteString Word8
type IterV m = IterGV WrappedByteString Word8 m
type Iteratee m = IterateeG WrappedByteString Word8 m
type Enumerator m a = Iteratee m a -> m (Iteratee m a)
module Data.Iteratee
enumBS :: Monad m => ByteString -> Enumerator m a
enumLBS :: Monad m => ByteString -> Enumerator m a
enumFile :: FilePath -> Iteratee IO a -> IO (Iteratee IO a)
fromWrap :: WrappedByteString Word8 -> ByteString
toWrap :: ByteString -> WrappedByteString Word8
takeExactly :: (StreamChunk s el, Monad m) => Int -> EnumeratorN s el s el m a
takeNoMoreThan :: (StreamChunk s el, Monad m) => Int -> EnumeratorN s el s el m a
countBytes :: Monad m => Iteratee m a -> Iteratee m (a, Int)
bufferIteratee :: Monad m => Enumerator m a
Convenience aliases around types from Data.Iteratee -
type Stream = StreamG WrappedByteString Word8Source
type IterV m = IterGV WrappedByteString Word8 mSource
type Iteratee m = IterateeG WrappedByteString Word8 mSource
type Enumerator m a = Iteratee m a -> m (Iteratee m a)Source
Re-export types and functions from Data.Iteratee -
module Data.Iteratee
Helper functions -
Enumerators -
enumBS :: Monad m => ByteString -> Enumerator m aSource
Enumerates a strict bytestring. -
enumLBS :: Monad m => ByteString -> Enumerator m aSource
Enumerates a lazy bytestring. -
enumFile :: FilePath -> Iteratee IO a -> IO (Iteratee IO a)Source
Conversion to/from WrappedByteString -
fromWrap :: WrappedByteString Word8 -> ByteStringSource
Converts a wrapped bytestring to a lazy bytestring. -
toWrap :: ByteString -> WrappedByteString Word8Source
Converts a lazy bytestring to a wrapped bytestring. -
Iteratee utilities -
takeExactly :: (StreamChunk s el, Monad m) => Int -> EnumeratorN s el s el m aSource
Reads n elements from a stream and applies the given iteratee to - the stream of the read elements. Reads exactly n elements, and if - the stream is short propagates an error. -
takeNoMoreThan :: (StreamChunk s el, Monad m) => Int -> EnumeratorN s el s el m aSource
Reads up to n elements from a stream and applies the given iteratee to the - stream of the read elements. If more than n elements are read, propagates an - error. -
countBytes :: Monad m => Iteratee m a -> Iteratee m (a, Int)Source
Wraps an Iteratee, counting the number of bytes consumed by it. -
bufferIteratee :: Monad m => Enumerator m aSource

Buffers an iteratee. -

Our enumerators produce a lot of little strings; rather than spending all - our time doing kernel context switches for 4-byte write() calls, we buffer - the iteratee to send 2KB at a time. -

Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.1/snap-core/Snap-Types.html b/static/docs/0.2.1/snap-core/Snap-Types.html deleted file mode 100644 index b4542ee..0000000 --- a/static/docs/0.2.1/snap-core/Snap-Types.html +++ /dev/null @@ -1,5944 +0,0 @@ - - -Snap.Types
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Snap.Types
Contents
The Snap Monad -
Functions for control flow and early termination -
Routing -
Access to state -
Logging -
Grabbing request bodies -
HTTP Datatypes and Functions -
Headers -
Requests -
Responses -
Response I/O -
Iteratee -
HTTP utilities -
Description
This module contains the core type definitions, class instances, and functions -for HTTP as well as the Snap monad, which is used for web handlers. -
Synopsis
data Snap a
runSnap :: Snap a -> (ByteString -> IO ()) -> Request -> Iteratee IO (Request, Response)
data NoHandlerException = NoHandlerException
finishWith :: Response -> Snap ()
pass :: Snap a
method :: Method -> Snap a -> Snap a
path :: ByteString -> Snap a -> Snap a
dir :: ByteString -> Snap a -> Snap a
ifTop :: Snap a -> Snap a
route :: [(ByteString, Snap a)] -> Snap a
routeLocal :: [(ByteString, Snap a)] -> Snap a
getRequest :: Snap Request
getResponse :: Snap Response
putRequest :: Request -> Snap ()
putResponse :: Response -> Snap ()
modifyRequest :: (Request -> Request) -> Snap ()
modifyResponse :: (Response -> Response) -> Snap ()
localRequest :: (Request -> Request) -> Snap a -> Snap a
withRequest :: (Request -> Snap a) -> Snap a
withResponse :: (Response -> Snap a) -> Snap a
logError :: ByteString -> Snap ()
runRequestBody :: Iteratee IO a -> Snap a
getRequestBody :: Snap ByteString
unsafeDetachRequestBody :: Snap (Enumerator a)
data Request
data Response
type Headers = Map CIByteString [ByteString]
class HasHeaders a where
updateHeaders :: (Headers -> Headers) -> a -> a
headers :: a -> Headers
type Params = Map ByteString [ByteString]
data Method
= GET
| HEAD
| POST
| PUT
| DELETE
| TRACE
| OPTIONS
| CONNECT
data Cookie = Cookie {
cookieName :: !ByteString
cookieValue :: !ByteString
cookieExpires :: !(Maybe UTCTime)
cookieDomain :: !(Maybe ByteString)
cookiePath :: !(Maybe ByteString)
}
type HttpVersion = (Int, Int)
addHeader :: HasHeaders a => CIByteString -> ByteString -> a -> a
setHeader :: HasHeaders a => CIByteString -> ByteString -> a -> a
getHeader :: HasHeaders a => CIByteString -> a -> Maybe ByteString
rqServerName :: Request -> ByteString
rqServerPort :: Request -> Int
rqRemoteAddr :: Request -> ByteString
rqRemotePort :: Request -> Int
rqLocalAddr :: Request -> ByteString
rqLocalHostname :: Request -> ByteString
rqIsSecure :: Request -> Bool
rqContentLength :: Request -> Maybe Int
rqMethod :: Request -> Method
rqVersion :: Request -> HttpVersion
rqCookies :: Request -> [Cookie]
rqPathInfo :: Request -> ByteString
rqContextPath :: Request -> ByteString
rqURI :: Request -> ByteString
rqQueryString :: Request -> ByteString
rqParams :: Request -> Params
rqParam :: ByteString -> Request -> Maybe [ByteString]
getParam :: ByteString -> Snap (Maybe ByteString)
rqModifyParams :: (Params -> Params) -> Request -> Request
rqSetParam :: ByteString -> [ByteString] -> Request -> Request
emptyResponse :: Response
setResponseStatus :: Int -> ByteString -> Response -> Response
rspStatus :: Response -> Int
rspStatusReason :: Response -> ByteString
setContentType :: ByteString -> Response -> Response
addCookie :: Cookie -> Response -> Response
setContentLength :: Int -> Response -> Response
clearContentLength :: Response -> Response
setResponseBody :: (forall a. Enumerator a) -> Response -> Response
modifyResponseBody :: (forall a. Enumerator a -> Enumerator a) -> Response -> Response
addToOutput :: (forall a. Enumerator a) -> Snap ()
writeBS :: ByteString -> Snap ()
writeLazyText :: Text -> Snap ()
writeText :: Text -> Snap ()
writeLBS :: ByteString -> Snap ()
sendFile :: FilePath -> Snap ()
type Enumerator a = Enumerator IO a
formatHttpTime :: CTime -> IO ByteString
parseHttpTime :: ByteString -> IO CTime
urlEncode :: ByteString -> ByteString
urlDecode :: ByteString -> Maybe ByteString
The Snap Monad -
data Snap a Source

Snap is the Monad that user web handlers run in. Snap gives you: -

1. stateful access to fetch or modify an HTTP Request -

2. stateful access to fetch or modify an HTTP Response -

3. failure / Alternative / MonadPlus semantics: a Snap handler can - choose not to handle a given request, using empty or its synonym pass, - and you can try alternative handlers with the <|> operator: -

 a :: Snap String
- a = pass
-
- b :: Snap String
- b = return "foo"
-
- c :: Snap String
- c = a <|> b             -- try running a, if it fails then try b
-

4. convenience functions (writeBS, writeLBS, writeText, writeLazyText, - addToOutput) for writing output to the Response: -

 a :: (forall a . Enumerator a) -> Snap ()
- a someEnumerator = do
-     writeBS "I'm a strict bytestring"
-     writeLBS "I'm a lazy bytestring"
-     addToOutput someEnumerator
-

5. early termination: if you call finishWith: -

 a :: Snap ()
- a = do
-   modifyResponse $ setResponseStatus 500 "Internal Server Error"
-   writeBS "500 error"
-   r <- getResponse
-   finishWith r
-

then any subsequent processing will be skipped and supplied Response value - will be returned from runSnap as-is. -

6. access to the IO monad through a MonadIO instance: -

 a :: Snap ()
- a = liftIO fireTheMissiles
-
show/hide Instances
runSnap :: Snap a -> (ByteString -> IO ()) -> Request -> Iteratee IO (Request, Response)Source
Runs a Snap monad action in the 'Iteratee IO' monad. -
data NoHandlerException Source
This exception is thrown if the handler you supply to runSnap fails. -
Constructors
NoHandlerException
show/hide Instances
Functions for control flow and early termination -
finishWith :: Response -> Snap ()Source
Short-circuits a Snap monad action early, storing the given - Response value in its state. -
pass :: Snap aSource
Fails out of a Snap monad action. This is used to indicate - that you choose not to handle the given request within the given - handler. -
Routing -
method :: Method -> Snap a -> Snap aSource
Runs a Snap monad action only if the request's HTTP method matches - the given method. -
pathSource
:: ByteStringpath to match against -
-> Snap ahandler to run -
-> Snap a
Runs a Snap monad action only for requests where rqPathInfo is exactly - equal to the given string. If the path matches, locally sets rqContextPath - to the old value of rqPathInfo, sets rqPathInfo="", and runs the given - handler. -
dirSource
:: ByteStringpath component to match -
-> Snap ahandler to run -
-> Snap a

Runs a Snap monad action only when the rqPathInfo of the request - starts with the given path. For example, -

 dir "foo" handler
-

Will fail if rqPathInfo is not "/foo" or "/foo/...", and will - add "foo/" to the handler's local rqContextPath. -

ifTop :: Snap a -> Snap aSource
Runs a Snap monad action only when rqPathInfo is empty. -
route :: [(ByteString, Snap a)] -> Snap aSource

A web handler which, given a mapping from URL entry points to web - handlers, efficiently routes requests to the correct handler. -

The URL entry points are given as relative paths, for example: -

 route [ ("foo/bar/quux", fooBarQuux) ]
-

If the URI of the incoming request is -

 /foo/bar/quux
-

or -

 /foo/bar/quux/...anything...
-

then the request will be routed to "fooBarQuux", with rqContextPath - set to "/foo/bar/quux/" and rqPathInfo set to - "...anything...". -

A path component within an URL entry point beginning with a colon (":") - is treated as a variable capture; the corresponding path component within - the request URI will be entered into the rqParams parameters mapping with - the given name. For instance, if the routes were: -

 route [ ("foo/:bar/baz", fooBazHandler) ]
-

Then a request for "/foo/saskatchewan/baz" would be routed to - fooBazHandler with a mapping for: -

 "bar" => "saskatchewan"
-

in its parameters table. -

Longer paths are matched first, and specific routes are matched before - captures. That is, if given routes: -

 [ ("a", h1), ("a/b", h2), ("a/:x", h3) ]
-

a request for "/a/b" will go to h2, "/a/s" for any s will go - to h3, and "/a" will go to h1. -

The following example matches "/article" to an article index, - "/login" to a login, and "/article/..." to an article renderer. -

 route [ ("article",     renderIndex)
-       , ("article/:id", renderArticle)
-       , ("login",       method POST doLogin) ]
-
routeLocal :: [(ByteString, Snap a)] -> Snap aSource
The routeLocal function is the same as route, except it doesn't change - the request's context path. This is useful if you want to route to a - particular handler but you want that handler to receive the rqPathInfo as - it is. -
Access to state -
getRequest :: Snap RequestSource
Grabs the Request object out of the Snap monad. -
getResponse :: Snap ResponseSource
Grabs the Response object out of the Snap monad. -
putRequest :: Request -> Snap ()Source
Puts a new Request object into the Snap monad. -
putResponse :: Response -> Snap ()Source
Puts a new Response object into the Snap monad. -
modifyRequest :: (Request -> Request) -> Snap ()Source
Modifies the Request object stored in a Snap monad. -
modifyResponse :: (Response -> Response) -> Snap ()Source
Modifes the Response object stored in a Snap monad. -
localRequest :: (Request -> Request) -> Snap a -> Snap aSource
Runs a Snap action with a locally-modified Request state - object. The Request object in the Snap monad state after the call - to localRequest will be unchanged. -
withRequest :: (Request -> Snap a) -> Snap aSource
Fetches the Request from state and hands it to the given action. -
withResponse :: (Response -> Snap a) -> Snap aSource
Fetches the Response from state and hands it to the given action. -
Logging -
logError :: ByteString -> Snap ()Source
Log an error message in the Snap monad -
Grabbing request bodies -
runRequestBody :: Iteratee IO a -> Snap aSource
Sends the request body through an iteratee (data consumer) and - returns the result. -
getRequestBody :: Snap ByteStringSource
Returns the request body as a bytestring. -
unsafeDetachRequestBody :: Snap (Enumerator a)Source

Detaches the request body's Enumerator from the Request and - returns it. You would want to use this if you needed to send the - HTTP request body (transformed or otherwise) through to the output - in O(1) space. (Examples: transcoding, "echo", etc) -

Normally Snap is careful to ensure that the request body is fully - consumed after your web handler runs; this function is marked - "unsafe" because it breaks this guarantee and leaves the - responsibility up to you. If you don't fully consume the - Enumerator you get here, the next HTTP request in the pipeline - (if any) will misparse. Be careful with exception handlers. -

HTTP Datatypes and Functions -
HTTP-related datatypes: Request, Response, Cookie, etc. -
data Request Source
Contains all of the information about an incoming HTTP request. -
show/hide Instances
data Response Source
Represents an HTTP response. -
show/hide Instances
type Headers = Map CIByteString [ByteString]Source
A type alias for a case-insensitive key-value mapping. -
class HasHeaders a whereSource
A typeclass for datatypes which contain HTTP headers. -
Methods
updateHeaders :: (Headers -> Headers) -> a -> aSource
Modify the datatype's headers. -
headers :: a -> HeadersSource
Retrieve the headers from a datatype that has headers. -
show/hide Instances
type Params = Map ByteString [ByteString]Source
A type alias for the HTTP parameters mapping. Each parameter - key maps to a list of ByteString values; if a parameter is specified - multiple times (e.g.: "GET /foo?param=bar1&param=bar2"), looking up - "param" in the mapping will give you ["bar1", "bar2"]. -
data Method Source
Enumerates the HTTP method values (see - http://tools.ietf.org/html/rfc2068.html#section-5.1.1). -
Constructors
GET
HEAD
POST
PUT
DELETE
TRACE
OPTIONS
CONNECT
show/hide Instances
data Cookie Source
A datatype representing an HTTP cookie. -
Constructors
Cookie
cookieName :: !ByteStringThe name of the cookie. -
cookieValue :: !ByteStringThe cookie's string value. -
cookieExpires :: !(Maybe UTCTime)The cookie's expiration value, if it has one. -
cookieDomain :: !(Maybe ByteString)The cookie's "domain" value, if it has one. -
cookiePath :: !(Maybe ByteString)The cookie path. -
show/hide Instances
type HttpVersion = (Int, Int)Source
Headers -
addHeader :: HasHeaders a => CIByteString -> ByteString -> a -> aSource
Adds a header key-value-pair to the HasHeaders datatype. If a header with - the same name already exists, the new value is appended to the headers list. -
setHeader :: HasHeaders a => CIByteString -> ByteString -> a -> aSource
Sets a header key-value-pair in a HasHeaders datatype. If a header with - the same name already exists, it is overwritten with the new value. -
getHeader :: HasHeaders a => CIByteString -> a -> Maybe ByteStringSource
Gets a header value out of a HasHeaders datatype. If many headers came - in with the same name, they will be catenated together. -
Requests -
rqServerName :: Request -> ByteStringSource
The server name of the request, as it came in from the request's - Host: header. -
rqServerPort :: Request -> IntSource
Returns the port number the HTTP server is listening on. -
rqRemoteAddr :: Request -> ByteStringSource
The remote IP address. -
rqRemotePort :: Request -> IntSource
The remote TCP port number. -
rqLocalAddr :: Request -> ByteStringSource
The local IP address for this request. -
rqLocalHostname :: Request -> ByteStringSource
Returns the HTTP server's idea of its local hostname. -
rqIsSecure :: Request -> BoolSource
Returns True if this is an HTTPS session (currently always - False). -
rqContentLength :: Request -> Maybe IntSource
Returns the Content-Length of the HTTP request body. -
rqMethod :: Request -> MethodSource
Returns the HTTP request method. -
rqVersion :: Request -> HttpVersionSource
Returns the HTTP version used by the client. -
rqCookies :: Request -> [Cookie]Source
Returns a list of the cookies that came in from the HTTP request - headers. -
rqPathInfo :: Request -> ByteStringSource
Handlers can (will be; --ed) be hung on a URI "entry point"; - this is called the "context path". If a handler is hung on the - context path "/foo/", and you request "/foo/bar", the value - of rqPathInfo will be "bar". -
rqContextPath :: Request -> ByteStringSource
The "context path" of the request; catenating rqContextPath, and - rqPathInfo should get you back to the original rqURI. The - rqContextPath always begins and ends with a slash ("/") - character, and represents the path (relative to your - component/snaplet) you took to get to your handler. -
rqURI :: Request -> ByteStringSource
Returns the URI requested by the client. -
rqQueryString :: Request -> ByteStringSource
Returns the HTTP query string for this Request. -
rqParams :: Request -> ParamsSource
Returns the Params mapping for this Request. "Parameters" are - automatically decoded from the query string and POST body and - entered into this mapping. -
rqParamSource
:: ByteStringparameter name to look up -
-> RequestHTTP request -
-> Maybe [ByteString]
Looks up the value(s) for the given named parameter. Parameters initially - come from the request's query string and any decoded POST body (if the - request's Content-Type is application/x-www-form-urlencoded). Parameter - values can be modified within handlers using rqModifyParams. -
getParamSource
:: ByteStringparameter name to look up -
-> Snap (Maybe ByteString)

See rqParam. Looks up a value for the given named parameter in the - Request. If more than one value was entered for the given parameter name, - getParam gloms the values together with: -

    intercalate " "
rqModifyParams :: (Params -> Params) -> Request -> RequestSource
Modifies the parameters mapping (which is a Map ByteString ByteString) in - a Request using the given function. -
rqSetParamSource
:: ByteStringparameter name -
-> [ByteString]parameter values -
-> Requestrequest -
-> Request
Writes a key-value pair to the parameters mapping within the given request. -
Responses -
emptyResponse :: ResponseSource
An empty Response. -
setResponseStatusSource
:: IntHTTP response integer code -
-> ByteStringHTTP response explanation -
-> ResponseResponse to be modified -
-> Response
Sets the HTTP response status. -
rspStatus :: Response -> IntSource
Returns the HTTP status code. -
rspStatusReason :: Response -> ByteStringSource
Returns the HTTP status explanation string. -
setContentType :: ByteString -> Response -> ResponseSource
Sets the Content-Type in the Response headers. -
addCookieSource
:: Cookiecookie value -
-> Responseresponse to modify -
-> Response
Adds an HTTP Cookie to the Response headers. -
setContentLength :: Int -> Response -> ResponseSource

A note here: if you want to set the Content-Length for the response, - Snap forces you to do it with this function rather than by setting it in the - headers; the Content-Length in the headers will be ignored. -

The reason for this is that Snap needs to look up the value of - Content-Length for each request, and looking the string value up in the - headers and parsing the number out of the text will be too expensive. -

If you don't set a content length in your response, HTTP keep-alive will be - disabled for HTTP/1.0 clients, forcing a Connection: close. For HTTP/1.1 - clients, Snap will switch to the chunked transfer encoding if - Content-Length is not specified. -

clearContentLength :: Response -> ResponseSource
Removes any Content-Length set in the Response. -
Response I/O -
setResponseBodySource
:: forall a. Enumerator anew response body - enumerator -
-> Responseresponse to modify -
-> Response
Sets an HTTP response body to the given Enumerator value. -
modifyResponseBody :: (forall a. Enumerator a -> Enumerator a) -> Response -> ResponseSource
Modifies a response body. -
addToOutputSource
:: forall a. Enumerator aoutput to add -
-> Snap ()
Adds the output from the given enumerator to the Response - stored in the Snap monad state. -
writeBS :: ByteString -> Snap ()Source
Adds the given strict ByteString to the body of the Response stored in - the Snap monad state. -
writeLazyText :: Text -> Snap ()Source
Adds the given lazy Text to the body of the Response stored in the - Snap monad state. -
writeText :: Text -> Snap ()Source
Adds the given strict Text to the body of the Response stored in the - Snap monad state. -
writeLBS :: ByteString -> Snap ()Source
Adds the given lazy ByteString to the body of the Response stored in - the Snap monad state. -
sendFile :: FilePath -> Snap ()Source

Sets the output to be the contents of the specified file. -

Calling sendFile will overwrite any output queued to be sent in the - Response. If the response body is not modified after the call to - sendFile, Snap will use the efficient sendfile() system call on - platforms that support it. -

If the response body is modified (using modifyResponseBody), the file will - be read using mmap(). -

Iteratee -
type Enumerator a = Enumerator IO aSource
HTTP utilities -
formatHttpTime :: CTime -> IO ByteStringSource
Converts a CTime into an HTTP timestamp. -
parseHttpTime :: ByteString -> IO CTimeSource
Converts an HTTP timestamp into a CTime. -
urlEncode :: ByteString -> ByteStringSource
URL-escapes a string (see - http://tools.ietf.org/html/rfc2396.html#section-2.4) -
urlDecode :: ByteString -> Maybe ByteStringSource
Decodes an URL-escaped string (see - http://tools.ietf.org/html/rfc2396.html#section-2.4) -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.1/snap-core/Snap-Util-FileServe.html b/static/docs/0.2.1/snap-core/Snap-Util-FileServe.html deleted file mode 100644 index 868d046..0000000 --- a/static/docs/0.2.1/snap-core/Snap-Util-FileServe.html +++ /dev/null @@ -1,651 +0,0 @@ - - -Snap.Util.FileServe
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Snap.Util.FileServe
Description
Contains web handlers to serve files from a directory. -
Synopsis
getSafePath :: Snap FilePath
fileServe :: FilePath -> Snap ()
fileServe' :: MimeMap -> FilePath -> Snap ()
fileServeSingle :: FilePath -> Snap ()
fileServeSingle' :: ByteString -> FilePath -> Snap ()
defaultMimeTypes :: MimeMap
type MimeMap = Map FilePath ByteString
Documentation
getSafePath :: Snap FilePathSource
Gets a path from the Request using rqPathInfo and makes sure it is - safe to use for opening files. A path is safe if it is a relative path - and has no .. elements to escape the intended directory structure. -
fileServeSource
:: FilePathroot directory -
-> Snap ()

Serves files out of the given directory. The relative path given in - rqPathInfo is searched for the given file, and the file is served with the - appropriate mime type if it is found. Absolute paths and ".." are prohibited - to prevent files from being served from outside the sandbox. -

Uses defaultMimeTypes to determine the Content-Type based on the file's - extension. -

fileServe'Source
:: MimeMapMIME type mapping -
-> FilePathroot directory -
-> Snap ()
Same as fileServe, with control over the MIME mapping used. -
fileServeSingleSource
:: FilePathpath to file -
-> Snap ()
Serves a single file specified by a full or relative path. The - path restrictions on fileServe don't apply to this function since - the path is not being supplied by the user. -
fileServeSingle'Source
:: ByteStringMIME type mapping -
-> FilePathpath to file -
-> Snap ()
Same as fileServeSingle, with control over the MIME mapping used. -
defaultMimeTypes :: MimeMapSource

The default set of mime type mappings we use when serving files. Its - value: -

 Map.fromList [
-   ( ".asc"     , "text/plain"                        ),
-   ( ".asf"     , "video/x-ms-asf"                    ),
-   ( ".asx"     , "video/x-ms-asf"                    ),
-   ( ".avi"     , "video/x-msvideo"                   ),
-   ( ".bz2"     , "application/x-bzip"                ),
-   ( ".c"       , "text/plain"                        ),
-   ( ".class"   , "application/octet-stream"          ),
-   ( ".conf"    , "text/plain"                        ),
-   ( ".cpp"     , "text/plain"                        ),
-   ( ".css"     , "text/css"                          ),
-   ( ".cxx"     , "text/plain"                        ),
-   ( ".dtd"     , "text/xml"                          ),
-   ( ".dvi"     , "application/x-dvi"                 ),
-   ( ".gif"     , "image/gif"                         ),
-   ( ".gz"      , "application/x-gzip"                ),
-   ( ".hs"      , "text/plain"                        ),
-   ( ".htm"     , "text/html"                         ),
-   ( ".html"    , "text/html"                         ),
-   ( ".jar"     , "application/x-java-archive"        ),
-   ( ".jpeg"    , "image/jpeg"                        ),
-   ( ".jpg"     , "image/jpeg"                        ),
-   ( ".js"      , "text/javascript"                   ),
-   ( ".log"     , "text/plain"                        ),
-   ( ".m3u"     , "audio/x-mpegurl"                   ),
-   ( ".mov"     , "video/quicktime"                   ),
-   ( ".mp3"     , "audio/mpeg"                        ),
-   ( ".mpeg"    , "video/mpeg"                        ),
-   ( ".mpg"     , "video/mpeg"                        ),
-   ( ".ogg"     , "application/ogg"                   ),
-   ( ".pac"     , "application/x-ns-proxy-autoconfig" ),
-   ( ".pdf"     , "application/pdf"                   ),
-   ( ".png"     , "image/png"                         ),
-   ( ".ps"      , "application/postscript"            ),
-   ( ".qt"      , "video/quicktime"                   ),
-   ( ".sig"     , "application/pgp-signature"         ),
-   ( ".spl"     , "application/futuresplash"          ),
-   ( ".swf"     , "application/x-shockwave-flash"     ),
-   ( ".tar"     , "application/x-tar"                 ),
-   ( ".tar.bz2" , "application/x-bzip-compressed-tar" ),
-   ( ".tar.gz"  , "application/x-tgz"                 ),
-   ( ".tbz"     , "application/x-bzip-compressed-tar" ),
-   ( ".text"    , "text/plain"                        ),
-   ( ".tgz"     , "application/x-tgz"                 ),
-   ( ".torrent" , "application/x-bittorrent"          ),
-   ( ".txt"     , "text/plain"                        ),
-   ( ".wav"     , "audio/x-wav"                       ),
-   ( ".wax"     , "audio/x-ms-wax"                    ),
-   ( ".wma"     , "audio/x-ms-wma"                    ),
-   ( ".wmv"     , "video/x-ms-wmv"                    ),
-   ( ".xbm"     , "image/x-xbitmap"                   ),
-   ( ".xml"     , "text/xml"                          ),
-   ( ".xpm"     , "image/x-xpixmap"                   ),
-   ( ".xwd"     , "image/x-xwindowdump"               ),
-   ( ".zip"     , "application/zip"                   ) ]
-
type MimeMap = Map FilePath ByteStringSource
A type alias for MIME type -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.1/snap-core/Snap-Util-GZip.html b/static/docs/0.2.1/snap-core/Snap-Util-GZip.html deleted file mode 100644 index 112e361..0000000 --- a/static/docs/0.2.1/snap-core/Snap-Util-GZip.html +++ /dev/null @@ -1,328 +0,0 @@ - - -Snap.Util.GZip
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Snap.Util.GZip
Synopsis
withCompression :: Snap a -> Snap ()
withCompression' :: Set ByteString -> Snap a -> Snap ()
Documentation
withCompressionSource
:: Snap athe web handler to run -
-> Snap ()

Runs a Snap web handler with compression if available. -

If the client has indicated support for gzip or compress in its - Accept-Encoding header, and the Content-Type in the response is one of - the following types: -

  • application/x-javascript
  • text/css
  • text/html
  • text/javascript
  • text/plain
  • text/xml
  • application/x-font-truetype

Then the given handler's output stream will be compressed, - Content-Encoding will be set in the output headers, and the - Content-Length will be cleared if it was set. (We can't process the stream - in O(1) space if the length is known beforehand.) -

The wrapped handler will be run to completion, and then the Response - that's contained within the Snap monad state will be passed to - finishWith to prevent further processing. -

withCompression'Source
:: Set ByteStringset of compressible MIME types -
-> Snap athe web handler to run -
-> Snap ()
The same as withCompression, with control over which MIME types to - compress. -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.1/snap-core/doc-index-62.html b/static/docs/0.2.1/snap-core/doc-index-62.html deleted file mode 100644 index 19389f1..0000000 --- a/static/docs/0.2.1/snap-core/doc-index-62.html +++ /dev/null @@ -1,144 +0,0 @@ - - -snap-core-0.2.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (>)
>.
diff --git a/static/docs/0.2.1/snap-core/doc-index-A.html b/static/docs/0.2.1/snap-core/doc-index-A.html deleted file mode 100644 index 5babfd3..0000000 --- a/static/docs/0.2.1/snap-core/doc-index-A.html +++ /dev/null @@ -1,166 +0,0 @@ - - -snap-core-0.2.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (A)
addCookie
addHeader
addToOutput
diff --git a/static/docs/0.2.1/snap-core/doc-index-B.html b/static/docs/0.2.1/snap-core/doc-index-B.html deleted file mode 100644 index 0756541..0000000 --- a/static/docs/0.2.1/snap-core/doc-index-B.html +++ /dev/null @@ -1,152 +0,0 @@ - - -snap-core-0.2.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (B)
break
bufferIteratee
diff --git a/static/docs/0.2.1/snap-core/doc-index-C.html b/static/docs/0.2.1/snap-core/doc-index-C.html deleted file mode 100644 index 47e71aa..0000000 --- a/static/docs/0.2.1/snap-core/doc-index-C.html +++ /dev/null @@ -1,302 +0,0 @@ - - -snap-core-0.2.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (C)
checkErr
checkIfDone
Chunk
CIByteString
ciToLower
clearContentLength
CONNECT
Cont
convStream
Cookie
1 (Type/Class)
2 (Data Constructor)
cookieDomain
cookieExpires
cookieName
cookiePath
cookieValue
countBytes
c_format_http_time
c_parse_http_time
diff --git a/static/docs/0.2.1/snap-core/doc-index-D.html b/static/docs/0.2.1/snap-core/doc-index-D.html deleted file mode 100644 index 1d0c115..0000000 --- a/static/docs/0.2.1/snap-core/doc-index-D.html +++ /dev/null @@ -1,206 +0,0 @@ - - -snap-core-0.2.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (D)
debug
debugErrno
debugIteratee
defaultMimeTypes
DELETE
dir
Done
drop
dropWhile
diff --git a/static/docs/0.2.1/snap-core/doc-index-E.html b/static/docs/0.2.1/snap-core/doc-index-E.html deleted file mode 100644 index 6bc4af2..0000000 --- a/static/docs/0.2.1/snap-core/doc-index-E.html +++ /dev/null @@ -1,292 +0,0 @@ - - -snap-core-0.2.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (E)
emptyResponse
Endian
endianRead2
endianRead3
endianRead4
Enum
enumBS
enumEof
Enumerator
1 (Type/Class)
2 (Type/Class)
EnumeratorGM
EnumeratorGMM
EnumeratorN
enumErr
enumFile
enumLBS
enumPair
enumPure1Chunk
enumPureNChunk
EOF
Err
ErrMsg
diff --git a/static/docs/0.2.1/snap-core/doc-index-F.html b/static/docs/0.2.1/snap-core/doc-index-F.html deleted file mode 100644 index 08a731e..0000000 --- a/static/docs/0.2.1/snap-core/doc-index-F.html +++ /dev/null @@ -1,254 +0,0 @@ - - -snap-core-0.2.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (F)
fileDriver
fileDriverRandom
FileOffset
fileServe
fileServe'
fileServeSingle
fileServeSingle'
filter
finish
finishWith
foldl
foldl'
foldl1
formatHttpTime
fromStr
fromWrap
diff --git a/static/docs/0.2.1/snap-core/doc-index-G.html b/static/docs/0.2.1/snap-core/doc-index-G.html deleted file mode 100644 index 20c0ae0..0000000 --- a/static/docs/0.2.1/snap-core/doc-index-G.html +++ /dev/null @@ -1,206 +0,0 @@ - - -snap-core-0.2.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (G)
GET
getHeader
getHeaders
getParam
getRequest
getRequestBody
getResponse
getSafePath
diff --git a/static/docs/0.2.1/snap-core/doc-index-H.html b/static/docs/0.2.1/snap-core/doc-index-H.html deleted file mode 100644 index 518a5fb..0000000 --- a/static/docs/0.2.1/snap-core/doc-index-H.html +++ /dev/null @@ -1,208 +0,0 @@ - - -snap-core-0.2.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (H)
HasHeaders
HEAD
head
Headers
headers
heads
hexd
HttpVersion
diff --git a/static/docs/0.2.1/snap-core/doc-index-I.html b/static/docs/0.2.1/snap-core/doc-index-I.html deleted file mode 100644 index f67c1da..0000000 --- a/static/docs/0.2.1/snap-core/doc-index-I.html +++ /dev/null @@ -1,196 +0,0 @@ - - -snap-core-0.2.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (I)
identity
ifTop
isFinished
Iteratee
IterateeG
1 (Data Constructor)
2 (Type/Class)
IterGV
IterV
diff --git a/static/docs/0.2.1/snap-core/doc-index-J.html b/static/docs/0.2.1/snap-core/doc-index-J.html deleted file mode 100644 index f503aa7..0000000 --- a/static/docs/0.2.1/snap-core/doc-index-J.html +++ /dev/null @@ -1,150 +0,0 @@ - - -snap-core-0.2.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (J)
joinI
joinIM
diff --git a/static/docs/0.2.1/snap-core/doc-index-L.html b/static/docs/0.2.1/snap-core/doc-index-L.html deleted file mode 100644 index d8ed397..0000000 --- a/static/docs/0.2.1/snap-core/doc-index-L.html +++ /dev/null @@ -1,196 +0,0 @@ - - -snap-core-0.2.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (L)
length
liftI
liftInner
localRequest
logError
LooseMap
looseMap
looseMapStream
LSB
diff --git a/static/docs/0.2.1/snap-core/doc-index-M.html b/static/docs/0.2.1/snap-core/doc-index-M.html deleted file mode 100644 index d80d852..0000000 --- a/static/docs/0.2.1/snap-core/doc-index-M.html +++ /dev/null @@ -1,202 +0,0 @@ - - -snap-core-0.2.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (M)
mapStream
Method
method
MimeMap
modifyRequest
modifyResponse
modifyResponseBody
MSB
diff --git a/static/docs/0.2.1/snap-core/doc-index-N.html b/static/docs/0.2.1/snap-core/doc-index-N.html deleted file mode 100644 index eadedb8..0000000 --- a/static/docs/0.2.1/snap-core/doc-index-N.html +++ /dev/null @@ -1,158 +0,0 @@ - - -snap-core-0.2.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (N)
NoHandlerException
1 (Type/Class)
2 (Data Constructor)
diff --git a/static/docs/0.2.1/snap-core/doc-index-O.html b/static/docs/0.2.1/snap-core/doc-index-O.html deleted file mode 100644 index de5eaa7..0000000 --- a/static/docs/0.2.1/snap-core/doc-index-O.html +++ /dev/null @@ -1,148 +0,0 @@ - - -snap-core-0.2.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (O)
OPTIONS
diff --git a/static/docs/0.2.1/snap-core/doc-index-P.html b/static/docs/0.2.1/snap-core/doc-index-P.html deleted file mode 100644 index 06e35af..0000000 --- a/static/docs/0.2.1/snap-core/doc-index-P.html +++ /dev/null @@ -1,238 +0,0 @@ - - -snap-core-0.2.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (P)
Params
parseHttpTime
parseToCompletion
pass
path
peek
POST
product
pUrlEscaped
PUT
putRequest
putResponse
diff --git a/static/docs/0.2.1/snap-core/doc-index-R.html b/static/docs/0.2.1/snap-core/doc-index-R.html deleted file mode 100644 index 01a9ba3..0000000 --- a/static/docs/0.2.1/snap-core/doc-index-R.html +++ /dev/null @@ -1,530 +0,0 @@ - - -snap-core-0.2.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (R)
Request
1 (Type/Class)
2 (Data Constructor)
Response
1 (Type/Class)
2 (Data Constructor)
ResponseBody
rigidMapStream
route
routeLocal
rqBody
rqContentLength
rqContextPath
rqCookies
rqHeaders
rqIsSecure
rqLocalAddr
rqLocalHostname
rqLocalPort
rqMethod
rqModifyParams
rqParam
rqParams
rqPathInfo
rqQueryString
rqRemoteAddr
rqRemotePort
rqServerName
rqServerPort
rqSetParam
rqSnapletPath
rqURI
rqVersion
rspBody
rspBodyMap
rspBodyToEnum
rspContentLength
rspHeaders
rspHttpVersion
rspStatus
rspStatusReason
run
runIter
runRequestBody
runSnap
diff --git a/static/docs/0.2.1/snap-core/doc-index-S.html b/static/docs/0.2.1/snap-core/doc-index-S.html deleted file mode 100644 index 468a2ec..0000000 --- a/static/docs/0.2.1/snap-core/doc-index-S.html +++ /dev/null @@ -1,296 +0,0 @@ - - -snap-core-0.2.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (S)
Seek
seek
SendFile
sendFile
setContentLength
setContentType
setEOF
setHeader
setResponseBody
setResponseStatus
set_c_locale
skipToEof
Snap
SomeEnumerator
1 (Type/Class)
2 (Data Constructor)
Stream
stream2list
stream2stream
StreamG
sum
diff --git a/static/docs/0.2.1/snap-core/doc-index-T.html b/static/docs/0.2.1/snap-core/doc-index-T.html deleted file mode 100644 index 4a81ea1..0000000 --- a/static/docs/0.2.1/snap-core/doc-index-T.html +++ /dev/null @@ -1,206 +0,0 @@ - - -snap-core-0.2.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (T)
take
takeExactly
takeNoMoreThan
takeR
throwErr
toCI
toStr
toWrap
TRACE
diff --git a/static/docs/0.2.1/snap-core/doc-index-U.html b/static/docs/0.2.1/snap-core/doc-index-U.html deleted file mode 100644 index 180318f..0000000 --- a/static/docs/0.2.1/snap-core/doc-index-U.html +++ /dev/null @@ -1,184 +0,0 @@ - - -snap-core-0.2.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (U)
unCI
unsafeDetachRequestBody
updateHeaders
urlDecode
urlEncode
diff --git a/static/docs/0.2.1/snap-core/doc-index-W.html b/static/docs/0.2.1/snap-core/doc-index-W.html deleted file mode 100644 index 0514814..0000000 --- a/static/docs/0.2.1/snap-core/doc-index-W.html +++ /dev/null @@ -1,202 +0,0 @@ - - -snap-core-0.2.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (W)
withCompression
withCompression'
withRequest
withResponse
writeBS
writeLazyText
writeLBS
writeText
diff --git a/static/docs/0.2.1/snap-core/doc-index.html b/static/docs/0.2.1/snap-core/doc-index.html deleted file mode 100644 index ffd90d5..0000000 --- a/static/docs/0.2.1/snap-core/doc-index.html +++ /dev/null @@ -1,134 +0,0 @@ - - -snap-core-0.2.1: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)ContentsIndex
Index
ABCDEFGHIJLMNOPRSTUW>
diff --git a/static/docs/0.2.1/snap-core/fonts/DroidSerif-Bold.eot b/static/docs/0.2.1/snap-core/fonts/DroidSerif-Bold.eot deleted file mode 100644 index 01b9e1f..0000000 Binary files a/static/docs/0.2.1/snap-core/fonts/DroidSerif-Bold.eot and /dev/null differ diff --git a/static/docs/0.2.1/snap-core/fonts/DroidSerif-Bold.svg b/static/docs/0.2.1/snap-core/fonts/DroidSerif-Bold.svg deleted file mode 100644 index 1f7f2d2..0000000 --- a/static/docs/0.2.1/snap-core/fonts/DroidSerif-Bold.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.2.1/snap-core/fonts/DroidSerif-Bold.ttf b/static/docs/0.2.1/snap-core/fonts/DroidSerif-Bold.ttf deleted file mode 100644 index da0ea11..0000000 Binary files a/static/docs/0.2.1/snap-core/fonts/DroidSerif-Bold.ttf and /dev/null differ diff --git a/static/docs/0.2.1/snap-core/fonts/DroidSerif-Bold.woff b/static/docs/0.2.1/snap-core/fonts/DroidSerif-Bold.woff deleted file mode 100644 index 91549cd..0000000 Binary files a/static/docs/0.2.1/snap-core/fonts/DroidSerif-Bold.woff and /dev/null differ diff --git a/static/docs/0.2.1/snap-core/fonts/DroidSerif-BoldItalic.eot b/static/docs/0.2.1/snap-core/fonts/DroidSerif-BoldItalic.eot deleted file mode 100644 index 47dd0a0..0000000 Binary files a/static/docs/0.2.1/snap-core/fonts/DroidSerif-BoldItalic.eot and /dev/null differ diff --git a/static/docs/0.2.1/snap-core/fonts/DroidSerif-BoldItalic.svg b/static/docs/0.2.1/snap-core/fonts/DroidSerif-BoldItalic.svg deleted file mode 100644 index 1a57dbb..0000000 --- a/static/docs/0.2.1/snap-core/fonts/DroidSerif-BoldItalic.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.2.1/snap-core/fonts/DroidSerif-BoldItalic.ttf b/static/docs/0.2.1/snap-core/fonts/DroidSerif-BoldItalic.ttf deleted file mode 100644 index 8be3fb4..0000000 Binary files a/static/docs/0.2.1/snap-core/fonts/DroidSerif-BoldItalic.ttf and /dev/null differ diff --git a/static/docs/0.2.1/snap-core/fonts/DroidSerif-BoldItalic.woff b/static/docs/0.2.1/snap-core/fonts/DroidSerif-BoldItalic.woff deleted file mode 100644 index 6d5fa3d..0000000 Binary files a/static/docs/0.2.1/snap-core/fonts/DroidSerif-BoldItalic.woff and /dev/null differ diff --git a/static/docs/0.2.1/snap-core/fonts/DroidSerif-Italic.eot b/static/docs/0.2.1/snap-core/fonts/DroidSerif-Italic.eot deleted file mode 100644 index 2d4850c..0000000 Binary files a/static/docs/0.2.1/snap-core/fonts/DroidSerif-Italic.eot and /dev/null differ diff --git a/static/docs/0.2.1/snap-core/fonts/DroidSerif-Italic.svg b/static/docs/0.2.1/snap-core/fonts/DroidSerif-Italic.svg deleted file mode 100644 index 356c374..0000000 --- a/static/docs/0.2.1/snap-core/fonts/DroidSerif-Italic.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.2.1/snap-core/fonts/DroidSerif-Italic.ttf b/static/docs/0.2.1/snap-core/fonts/DroidSerif-Italic.ttf deleted file mode 100644 index 3719dc2..0000000 Binary files a/static/docs/0.2.1/snap-core/fonts/DroidSerif-Italic.ttf and /dev/null differ diff --git a/static/docs/0.2.1/snap-core/fonts/DroidSerif-Italic.woff b/static/docs/0.2.1/snap-core/fonts/DroidSerif-Italic.woff deleted file mode 100644 index b64436f..0000000 Binary files a/static/docs/0.2.1/snap-core/fonts/DroidSerif-Italic.woff and /dev/null differ diff --git a/static/docs/0.2.1/snap-core/fonts/DroidSerif-Regular.eot b/static/docs/0.2.1/snap-core/fonts/DroidSerif-Regular.eot deleted file mode 100644 index 0d17523..0000000 Binary files a/static/docs/0.2.1/snap-core/fonts/DroidSerif-Regular.eot and /dev/null differ diff --git a/static/docs/0.2.1/snap-core/fonts/DroidSerif-Regular.svg b/static/docs/0.2.1/snap-core/fonts/DroidSerif-Regular.svg deleted file mode 100644 index b9b65fb..0000000 --- a/static/docs/0.2.1/snap-core/fonts/DroidSerif-Regular.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.2.1/snap-core/fonts/DroidSerif-Regular.ttf b/static/docs/0.2.1/snap-core/fonts/DroidSerif-Regular.ttf deleted file mode 100644 index 066dcaa..0000000 Binary files a/static/docs/0.2.1/snap-core/fonts/DroidSerif-Regular.ttf and /dev/null differ diff --git a/static/docs/0.2.1/snap-core/fonts/DroidSerif-Regular.woff b/static/docs/0.2.1/snap-core/fonts/DroidSerif-Regular.woff deleted file mode 100644 index cfd3d67..0000000 Binary files a/static/docs/0.2.1/snap-core/fonts/DroidSerif-Regular.woff and /dev/null differ diff --git a/static/docs/0.2.1/snap-core/frames.html b/static/docs/0.2.1/snap-core/frames.html deleted file mode 100644 index 9e904fc..0000000 --- a/static/docs/0.2.1/snap-core/frames.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/static/docs/0.2.1/snap-core/haddock-util.js b/static/docs/0.2.1/snap-core/haddock-util.js deleted file mode 100644 index 364081f..0000000 --- a/static/docs/0.2.1/snap-core/haddock-util.js +++ /dev/null @@ -1,139 +0,0 @@ -// Haddock JavaScript utilities -function toggle(button,id) -{ - var n = document.getElementById(id).style; - if (n.display == "none") - { - button.src = "minus.gif"; - n.display = "block"; - } - else - { - button.src = "plus.gif"; - n.display = "none"; - } -} - - -var max_results = 75; // 50 is not enough to search for map in the base libraries -var shown_range = null; -var last_search = null; - -function quick_search() -{ - perform_search(false); -} - -function full_search() -{ - perform_search(true); -} - - -function perform_search(full) -{ - var text = document.getElementById("searchbox").value.toLowerCase(); - if (text == last_search && !full) return; - last_search = text; - - var table = document.getElementById("indexlist"); - var status = document.getElementById("searchmsg"); - var children = table.firstChild.childNodes; - - // first figure out the first node with the prefix - var first = bisect(-1); - var last = (first == -1 ? -1 : bisect(1)); - - if (first == -1) - { - table.className = ""; - status.innerHTML = "No results found, displaying all"; - } - else if (first == 0 && last == children.length - 1) - { - table.className = ""; - status.innerHTML = ""; - } - else if (last - first >= max_results && !full) - { - table.className = ""; - status.innerHTML = "More than " + max_results + ", press Search to display"; - } - else - { - // decide what you need to clear/show - if (shown_range) - setclass(shown_range[0], shown_range[1], "indexrow"); - setclass(first, last, "indexshow"); - shown_range = [first, last]; - table.className = "indexsearch"; - status.innerHTML = ""; - } - - - function setclass(first, last, status) - { - for (var i = first; i <= last; i++) - { - children[i].className = status; - } - } - - - // do a binary search, treating 0 as ... - // return either -1 (no 0's found) or location of most far match - function bisect(dir) - { - var first = 0, finish = children.length - 1; - var mid, success = false; - - while (finish - first > 3) - { - mid = Math.floor((finish + first) / 2); - - var i = checkitem(mid); - if (i == 0) i = dir; - if (i == -1) - finish = mid; - else - first = mid; - } - var a = (dir == 1 ? first : finish); - var b = (dir == 1 ? finish : first); - for (var i = b; i != a - dir; i -= dir) - { - if (checkitem(i) == 0) return i; - } - return -1; - } - - - // from an index, decide what the result is - // 0 = match, -1 is lower, 1 is higher - function checkitem(i) - { - var s = getitem(i).toLowerCase().substr(0, text.length); - if (s == text) return 0; - else return (s > text ? -1 : 1); - } - - - // from an index, get its string - // this abstracts over alternates - function getitem(i) - { - for ( ; i >= 0; i--) - { - var s = children[i].firstChild.firstChild.data; - if (s.indexOf(' ') == -1) - return s; - } - return ""; // should never be reached - } -} - -function setSynopsis(filename) { - if (parent.window.synopsis) { - parent.window.synopsis.location = filename; - } -} diff --git a/static/docs/0.2.1/snap-core/haddock.css b/static/docs/0.2.1/snap-core/haddock.css deleted file mode 100644 index fe050fe..0000000 --- a/static/docs/0.2.1/snap-core/haddock.css +++ /dev/null @@ -1,478 +0,0 @@ -/* -------- Global things --------- */ - -@font-face { - font-family: 'DroidSerif'; - src: url('fonts/DroidSerif-Regular.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Regular.woff') format('woff'), - url('fonts/DroidSerif-Regular.ttf') format('truetype'), - url('fonts/DroidSerif-Regular.svg#DroidSerif') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - font-style: italic; - src: url('fonts/DroidSerif-Italic.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Italic.woff') format('woff'), - url('fonts/DroidSerif-Italic.ttf') format('truetype'), - url('fonts/DroidSerif-Italic.svg#DroidSerif-Italic') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - font-weight: bold; - src: url('fonts/DroidSerif-Bold.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Bold.woff') format('woff'), - url('fonts/DroidSerif-Bold.ttf') format('truetype'), - url('fonts/DroidSerif-Bold.svg#DroidSerif-Bold') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - src: url('fonts/DroidSerif-BoldItalic.eot'); - font-weight: bold; - font-style: italic; - src: local('Droid Serif'), - url('fonts/DroidSerif-BoldItalic.woff') format('woff'), - url('fonts/DroidSerif-BoldItalic.ttf') format('truetype'), - url('fonts/DroidSerif-BoldItalic.svg#DroidSerif-BoldItalic') format('svg'); -} - - - -HTML { - background-color: #f0f3ff; - width: 100%; -} - -BODY { - -moz-border-radius:5px; - -webkit-border-radius:5px; - width: 50em; - margin: 2em auto; - padding: 0; - background-color: #ffffff; - color: #000000; - font-size: 110%; - font-family: DroidSerif, Georgia, serif; - } - -A:link { color: #5200A3; text-decoration: none } -A:visited { color: #5200A3; text-decoration: none } -A:hover { color: #5200A3; text-decoration: none; border-bottom:#5200A3 dashed 1px; } - -TABLE.vanilla { - width: 100%; - border-width: 0px; - /* I can't seem to specify cellspacing or cellpadding properly using CSS... */ -} - -DL { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - letter-spacing: -0.01em; - margin: 0; -} - -.vanilla .vanilla dl { font-size: 80%; } -.vanilla .vanilla dl dl { padding-left: 0; font-size: 95%; } - -TD.section1, TD.section2, TD.section3, TD.section4, TD.doc, DL { - padding: 0 30px 0 34px; -} - -TABLE.vanilla2 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - border-width: 0px; -} - -/* font is a little too small in MSIE */ -TT, PRE, CODE { - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - font-size: 90%; -} - -LI P { margin: 0pt } - -P { margin-top: 0; margin-bottom: 0.75em; } - -TD { - border-width: 0px; -} - -TABLE.narrow { - border-width: 0px; -} - -TD.s8 { height: 0; margin:0; padding: 0 } -TD.s15 { height: 20px; } - -SPAN.keyword { text-decoration: underline; } - -/* Resize the buttom image to match the text size */ -IMG.coll { width : 0.75em; height: 0.75em; margin-bottom: 0; margin-right: 0.5em } - -/* --------- Contents page ---------- */ - -DIV.node { - padding-left: 3em; -} - -DIV.cnode { - padding-left: 1.75em; -} - -SPAN.pkg { - position: absolute; - left: 50em; -} - -/* --------- Documentation elements ---------- */ - -TD FONT { font-weight: bold; letter-spacing: -0.02em; } - -TD.children { - padding-left: 25px; - } - -TD.synopsis { - padding: 2px; - background-color: #f0f0f0; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - } - -TD.decl { - padding: 4px 8px; - background-color: #FAFAFA; - border-bottom: #F2F2F2 solid 1px; - border-top: #FCFCFC solid 1px; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - vertical-align: top; - } - -TD.decl TD.decl { - font-size: 100%; - padding: 4px 0; - border: 0; -} - -TD.topdecl { - padding: 20px 30px 0.5ex 30px; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; -; - vertical-align: top; -} - -.vanilla .vanilla .vanilla .topdecl { - padding-left: 0; - padding-right: 0; -} - -.vanilla .vanilla .vanilla { - padding-left: 30px; -} - -.decl .vanilla { - padding-left: 0px !important; -} - -.body .vanilla .body { - padding-left: 0; - padding-right: 0; -} - -.body .vanilla .body .decl { - padding-left: 12px; -} - -.body .vanilla .body div .vanilla .decl { - padding-left: 12px; -} - -TABLE.declbar { - background-color: #f0f0f0; - border-spacing: 0px; - border-bottom:1px solid #d7d7df; - border-right:1px solid #d7d7df; - border-top:1px solid #f4f4f9; - border-left:1px solid #f4f4f9; - padding: 4px; - } - -TD.declname { - width: 100%; - padding-right: 4px; - } - -TD.declbut { - padding-left: 8px; - padding-right: 5px; - border-left-width: 1px; - border-left-color: #000099; - border-left-style: solid; - white-space: nowrap; - font-size: x-small; - } - -/* - arg is just like decl, except that wrapping is not allowed. It is - used for function and constructor arguments which have a text box - to the right, where if wrapping is allowed the text box squashes up - the declaration by wrapping it. -*/ -TD.arg { - padding: 2px 12px; - background-color: #f0f0f0; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - vertical-align: top; - white-space: nowrap; - } - -TD.recfield { padding-left: 20px } - -TD.doc { - padding-left: 38px; - font-size: 95%; - line-height: 1.66; - } - -TD.ndoc { - font-size: 95%; - line-height: 1.66; - padding: 2px 4px 2px 8px; - } - -TD.rdoc { - padding: 2px; - padding-left: 30px; - width: 100%; - font-size: 80%; - font-style: italic; - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - } - -TD.body { - padding: 0 30px; - } - -TD.pkg { - width: 100%; - padding-left: 30px -} - -TABLE.indexsearch TR.indexrow { - display: none; -} -TABLE.indexsearch TR.indexshow { - display: table-row; -} - -TD.indexentry { - vertical-align: top; - padding: 0 30px - } - -TD.indexannot { - vertical-align: top; - padding-left: 20px; - white-space: nowrap - } - -TD.indexlinks { - width: 100% - } - -/* ------- Section Headings ------- */ - -TD.section1, TD.section2, TD.section3, TD.section4, TD.section5 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; -} - -TD.section1 { - padding-top: 14px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 140% - } - -TD.section2 { - padding-top: 4px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 120% - } - -TD.section3 { - padding-top: 5px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 105% - } - -TD.section4 { - font-weight: bold; - padding-top: 12px; - padding-bottom: 4px; - letter-spacing: -0.02em; - font-size: 90% - } - -/* -------------- The title bar at the top of the page */ - -TD.infohead { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - font-weight: bold; - padding: 0 30px; - text-align: left; -} - -TD.infoval { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - padding: 0 30px; - text-align: left; -} - -TD.topbar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - background-color: #3465a4; - padding: 5px; - -moz-border-radius-topleft:5px; - -moz-border-radius-topright:5px; - -webkit-border-radius-topleft:5px; - -webkit-border-radius-topright:5px; -} - -TD.title { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - padding-left: 30px; - letter-spacing: -0.02em; - font-weight: bold; - width: 100% - } - -TD.topbut { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - padding-left: 5px; - padding-right: 5px; - border-left-width: 1px; - border-left-color: #ffffff; - border-left-style: solid; - letter-spacing: -0.02em; - font-weight: bold; - white-space: nowrap; - } - -TD.topbut A:link { - color: #ffffff - } - -TD.topbut A:visited { - color: #ffff00 - } - -TD.topbut A:hover { - background-color: #C9D3DE; - } - -TD.topbut:hover { - background-color: #C9D3DE; - } - -TD.modulebar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #141B24; - background-color: #C9D3DE; - padding: 5px; - border-top-width: 1px; - border-top-color: #ffffff; - border-top-style: solid; - -moz-border-radius-bottomleft:5px; - -moz-border-radius-bottomright:5px; - -webkit-border-radius-bottomleft:5px; - -webkit-border-radius-bottomright:5px; - - } - -/* --------- The page footer --------- */ - -TD.botbar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - -moz-border-radius:5px; - -webkit-border-radius:5px; - background-color: #3465a4; - color: #ffffff; - padding: 5px - } -TD.botbar A:link { - color: #ffffff; - text-decoration: underline - } -TD.botbar A:visited { - color: #ffff00 - } -TD.botbar A:hover { - background-color: #6060ff - } - -/* --------- Mini Synopsis for Frame View --------- */ - -.outer { - margin: 0 0; - padding: 0 0; -} - -.mini-synopsis { - padding: 0.25em 0.25em; -} - -.mini-synopsis H1 { font-size: 120%; } -.mini-synopsis H2 { font-size: 107%; } -.mini-synopsis H3 { font-size: 100%; } -.mini-synopsis H1, .mini-synopsis H2, .mini-synopsis H3 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - margin-top: 0.5em; - margin-bottom: 0.25em; - padding: 0 0; - font-weight: bold; letter-spacing: -0.02em; -} - -.mini-synopsis H1 { border-bottom: 1px solid #ccc; } - -.mini-topbar { - font-size: 120%; - background: #0077dd; - padding: 0.25em; -} - - diff --git a/static/docs/0.2.1/snap-core/haskell_icon.gif b/static/docs/0.2.1/snap-core/haskell_icon.gif deleted file mode 100644 index cb2a815..0000000 Binary files a/static/docs/0.2.1/snap-core/haskell_icon.gif and /dev/null differ diff --git a/static/docs/0.2.1/snap-core/index-frames.html b/static/docs/0.2.1/snap-core/index-frames.html deleted file mode 100644 index 898c406..0000000 --- a/static/docs/0.2.1/snap-core/index-frames.html +++ /dev/null @@ -1,43 +0,0 @@ - - -snap-core-0.2.1: Snap: A Haskell Web Framework (Core)

Data.CIByteString
Snap.Internal.Debug
Snap.Internal.Http.Types
Snap.Internal.Iteratee.Debug
Snap.Iteratee
Snap.Types
Snap.Util.FileServe
Snap.Util.GZip

diff --git a/static/docs/0.2.1/snap-core/index.html b/static/docs/0.2.1/snap-core/index.html deleted file mode 100644 index 9ff39c6..0000000 --- a/static/docs/0.2.1/snap-core/index.html +++ /dev/null @@ -1,300 +0,0 @@ - - -snap-core-0.2.1: Snap: A Haskell Web Framework (Core)
 snap-core-0.2.1: Snap: A Haskell Web Framework (Core)ContentsIndex
snap-core-0.2.1: Snap: A Haskell Web Framework (Core)

This is the first developer prerelease of the Snap framework. Snap is a -simple and fast web development framework and server written in Haskell. For -more information or to download the latest version, you can visit the Snap -project website at http://snapframework.com/. -

This library contains the core definitions and types for the Snap framework, -including: -

1. Primitive types and functions for HTTP (requests, responses, cookies, -post/query parameters, etc) -

2. Type aliases and helper functions for Iteratee I/O -

3. A monad for programming web handlers called "Snap", inspired by -happstack's (http://happstack.com/index.html), which allows: -

  • Stateful access to the HTTP request and response objects -
  • Monadic failure (i.e. MonadPlus/Alternative instances) for declining -to handle requests and chaining handlers together -
  • Early termination of the computation if you know early what you want -to return and want to prevent further monadic processing -

Quick start: The Snap monad and HTTP definitions are in Snap.Types, -some iteratee utilities are in Snap.Iteratee. -

Higher-level facilities for building web applications (like user/session -management, component interfaces, data modeling, etc.) are planned but not -yet implemented, so this release will mostly be of interest for those who: -

  • need a fast and minimal HTTP API at roughly the same level of abstraction -as Java servlets, or -
  • are interested in contributing to the Snap Framework project. -
Modules
show/hideData
Data.CIByteString
show/hideSnap
show/hideInternal
Snap.Internal.Debug
show/hideHttp
Snap.Internal.Http.Types
show/hideIteratee
Snap.Internal.Iteratee.Debug
Snap.Iteratee
Snap.Types
show/hideUtil
Snap.Util.FileServe
Snap.Util.GZip
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.1/snap-core/mini_Data-CIByteString.html b/static/docs/0.2.1/snap-core/mini_Data-CIByteString.html deleted file mode 100644 index d9be8f2..0000000 --- a/static/docs/0.2.1/snap-core/mini_Data-CIByteString.html +++ /dev/null @@ -1,39 +0,0 @@ - - -Data.CIByteString
Data.CIByteString
diff --git a/static/docs/0.2.1/snap-core/mini_Snap-Internal-Debug.html b/static/docs/0.2.1/snap-core/mini_Snap-Internal-Debug.html deleted file mode 100644 index 9f5123e..0000000 --- a/static/docs/0.2.1/snap-core/mini_Snap-Internal-Debug.html +++ /dev/null @@ -1,29 +0,0 @@ - - -Snap.Internal.Debug
Snap.Internal.Debug
diff --git a/static/docs/0.2.1/snap-core/mini_Snap-Internal-Http-Types.html b/static/docs/0.2.1/snap-core/mini_Snap-Internal-Http-Types.html deleted file mode 100644 index ce244b6..0000000 --- a/static/docs/0.2.1/snap-core/mini_Snap-Internal-Http-Types.html +++ /dev/null @@ -1,201 +0,0 @@ - - -Snap.Internal.Http.Types diff --git a/static/docs/0.2.1/snap-core/mini_Snap-Internal-Iteratee-Debug.html b/static/docs/0.2.1/snap-core/mini_Snap-Internal-Iteratee-Debug.html deleted file mode 100644 index c622c16..0000000 --- a/static/docs/0.2.1/snap-core/mini_Snap-Internal-Iteratee-Debug.html +++ /dev/null @@ -1,25 +0,0 @@ - - -Snap.Internal.Iteratee.Debug
Snap.Internal.Iteratee.Debug
diff --git a/static/docs/0.2.1/snap-core/mini_Snap-Iteratee.html b/static/docs/0.2.1/snap-core/mini_Snap-Iteratee.html deleted file mode 100644 index bf606a7..0000000 --- a/static/docs/0.2.1/snap-core/mini_Snap-Iteratee.html +++ /dev/null @@ -1,107 +0,0 @@ - - -Snap.Iteratee
Snap.Iteratee

Convenience aliases around types from Data.Iteratee -

type Stream
type IterV m
type Iteratee m
type Enumerator m a

Re-export types and functions from Data.Iteratee -

Helper functions -

Enumerators -

Conversion to/from WrappedByteString -

Iteratee utilities -

diff --git a/static/docs/0.2.1/snap-core/mini_Snap-Types.html b/static/docs/0.2.1/snap-core/mini_Snap-Types.html deleted file mode 100644 index 8fcdf2d..0000000 --- a/static/docs/0.2.1/snap-core/mini_Snap-Types.html +++ /dev/null @@ -1,386 +0,0 @@ - - -Snap.Types diff --git a/static/docs/0.2.1/snap-core/mini_Snap-Util-FileServe.html b/static/docs/0.2.1/snap-core/mini_Snap-Util-FileServe.html deleted file mode 100644 index 0ea73e5..0000000 --- a/static/docs/0.2.1/snap-core/mini_Snap-Util-FileServe.html +++ /dev/null @@ -1,51 +0,0 @@ - - -Snap.Util.FileServe diff --git a/static/docs/0.2.1/snap-core/mini_Snap-Util-GZip.html b/static/docs/0.2.1/snap-core/mini_Snap-Util-GZip.html deleted file mode 100644 index 93f3163..0000000 --- a/static/docs/0.2.1/snap-core/mini_Snap-Util-GZip.html +++ /dev/null @@ -1,29 +0,0 @@ - - -Snap.Util.GZip diff --git a/static/docs/0.2.1/snap-core/minus.gif b/static/docs/0.2.1/snap-core/minus.gif deleted file mode 100644 index 1deac2f..0000000 Binary files a/static/docs/0.2.1/snap-core/minus.gif and /dev/null differ diff --git a/static/docs/0.2.1/snap-core/plus.gif b/static/docs/0.2.1/snap-core/plus.gif deleted file mode 100644 index 2d15c14..0000000 Binary files a/static/docs/0.2.1/snap-core/plus.gif and /dev/null differ diff --git a/static/docs/0.2.1/snap-core/snap-core.haddock b/static/docs/0.2.1/snap-core/snap-core.haddock deleted file mode 100644 index 39dde90..0000000 Binary files a/static/docs/0.2.1/snap-core/snap-core.haddock and /dev/null differ diff --git a/static/docs/0.2.1/snap-core/src/Data-CIByteString.html b/static/docs/0.2.1/snap-core/src/Data-CIByteString.html deleted file mode 100644 index b69eba5..0000000 --- a/static/docs/0.2.1/snap-core/src/Data-CIByteString.html +++ /dev/null @@ -1,70 +0,0 @@ - - - - -src/Data/CIByteString.hs - - - -
{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE OverloadedStrings #-}
-
--- | "Data.CIByteString" is a module containing 'CIByteString', a wrapper for
--- 'ByteString' which provides case-insensitive (ASCII-wise) 'Ord' and 'Eq'
--- instances.
---
--- 'CIByteString' also has an 'IsString' instance, so if you use the
--- \"OverloadedStrings\" LANGUAGE pragma you can write case-insensitive string
--- literals, e.g.:
---
--- @
--- \> let a = \"Foo\" in
---   putStrLn $ (show $ unCI a) ++ \"==\\\"FoO\\\" is \" ++ show (a == \"FoO\")
--- \"Foo\"==\"FoO\" is True
--- @
-
-module Data.CIByteString
- ( CIByteString
- , toCI
- , unCI
- , ciToLower
- ) where
-
--- for IsString instance
-import           Data.ByteString.Char8 ()
-import           Data.ByteString (ByteString)
-import           Data.ByteString.Internal (c2w, w2c)
-import qualified Data.ByteString as S
-import           Data.Char
-import           Data.String
-
-
--- | A case-insensitive newtype wrapper for 'ByteString'
-data CIByteString = CIByteString { unCI        :: !ByteString
-                                 , _lowercased :: !ByteString }
-
-toCI :: ByteString -> CIByteString
-toCI s = CIByteString s t
-  where
-    t = lowercase s
-
-ciToLower :: CIByteString -> ByteString
-ciToLower = _lowercased
-
-instance Show CIByteString where
-    show (CIByteString s _) = show s
-
-lowercase :: ByteString -> ByteString
-lowercase = S.map (c2w . toLower . w2c)
-
-instance Eq CIByteString where
-    (CIByteString _ a) == (CIByteString _ b) = a == b
-    (CIByteString _ a) /= (CIByteString _ b) = a /= b
-
-instance Ord CIByteString where
-    (CIByteString _ a) <= (CIByteString _ b) = a <= b
-
-instance IsString CIByteString where
-    fromString = toCI . fromString
-
- diff --git a/static/docs/0.2.1/snap-core/src/Snap-Internal-Debug.html b/static/docs/0.2.1/snap-core/src/Snap-Internal-Debug.html deleted file mode 100644 index c295589..0000000 --- a/static/docs/0.2.1/snap-core/src/Snap-Internal-Debug.html +++ /dev/null @@ -1,86 +0,0 @@ - - - - -src/Snap/Internal/Debug.hs - - - -
-- | An internal Snap module for (optionally) printing debugging
--- messages. Normally 'debug' does nothing, but you can pass \"-fdebug\" to
--- @cabal install@ to build a @snap-core@ which debugs to stderr.
---
--- /N.B./ this is an internal interface, please don't write external code that
--- depends on it.
-
-{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE CPP #-}
-
-module Snap.Internal.Debug where
-
-import           Control.Monad.Trans
-
-#ifdef DEBUG_TEST
-
-debug :: (MonadIO m) => String -> m ()
-debug !s = return $ s `seq` ()
-{-# INLINE debug #-}
-
-debugErrno :: (MonadIO m) => String -> m ()
-debugErrno !s = return $ s `seq` ()
-
-#elif defined(DEBUG)
-
-------------------------------------------------------------------------------
-import           Control.Concurrent
-import           Data.List
-import           Data.Maybe
-import           Foreign.C.Error
-import           System.IO
-import           System.IO.Unsafe
-import           Text.Printf
-------------------------------------------------------------------------------
-
-
-------------------------------------------------------------------------------
-_debugMVar :: MVar ()
-_debugMVar = unsafePerformIO $ newMVar ()
-
-
-------------------------------------------------------------------------------
-debug :: (MonadIO m) => String -> m ()
-debug s = liftIO $ withMVar _debugMVar $ \_ -> do
-              tid <- myThreadId
-              hPutStrLn stderr $ s' tid
-              hFlush stderr
-  where
-    chop x = let y = fromMaybe x $ stripPrefix "ThreadId " x
-             in printf "%8s" y
-
-    s' t   = "[" ++ chop (show t) ++ "] " ++ s
-
-{-# INLINE debug #-}
-
-
-------------------------------------------------------------------------------
-debugErrno :: (MonadIO m) => String -> m ()
-debugErrno loc = liftIO $ do
-    err <- getErrno
-    let ex = errnoToIOError loc err Nothing Nothing
-    debug $ show ex
-------------------------------------------------------------------------------
-
-#else
-
-------------------------------------------------------------------------------
-debug :: (MonadIO m) => String -> m ()
-debug _ = return ()
-{-# INLINE debug #-}
-
-debugErrno :: (MonadIO m) => String -> m ()
-debugErrno _ = return ()
-------------------------------------------------------------------------------
-
-#endif
-
- diff --git a/static/docs/0.2.1/snap-core/src/Snap-Internal-Http-Types.html b/static/docs/0.2.1/snap-core/src/Snap-Internal-Http-Types.html deleted file mode 100644 index 44d3120..0000000 --- a/static/docs/0.2.1/snap-core/src/Snap-Internal-Http-Types.html +++ /dev/null @@ -1,648 +0,0 @@ - - - - -src/Snap/Internal/Http/Types.hs - - - -
-- | An internal Snap module containing HTTP types.
---
--- /N.B./ this is an internal interface, please don't write user code that
--- depends on it. Most of these declarations (except for the
--- unsafe/encapsulation-breaking ones) are re-exported from "Snap.Types".
-
-{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE EmptyDataDecls #-}
-{-# LANGUAGE ForeignFunctionInterface #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RankNTypes #-}
-{-# LANGUAGE TypeSynonymInstances #-}
-
-module Snap.Internal.Http.Types where
-
-
-------------------------------------------------------------------------------
-import           Control.Applicative hiding (empty)
-import           Control.Monad (liftM, when)
-import qualified Data.Attoparsec as Atto
-import           Data.Attoparsec hiding (many, Result(..))
-import           Data.Bits
-import           Data.ByteString (ByteString)
-import           Data.ByteString.Internal (c2w,w2c)
-import qualified Data.ByteString.Nums.Careless.Hex as Cvt
-import qualified Data.ByteString as S
-import           Data.Char
-import           Data.DList (DList)
-import qualified Data.DList as DL
-import           Data.IORef
-import           Data.Map (Map)
-import qualified Data.Map as Map
-import           Data.Monoid
-import           Data.Serialize.Builder
-import           Data.Time.Clock
-import           Data.Time.Format
-import           Data.Word
-import           Foreign hiding (new)
-import           Foreign.C.String
-import           Foreign.C.Types
-import           Prelude hiding (take)
-import           System.Locale (defaultTimeLocale)
-
-------------------------------------------------------------------------------
-import           Data.CIByteString
-import qualified Snap.Iteratee as I
-
-
-------------------------------------------------------------------------------
-foreign import ccall unsafe "set_c_locale"
-        set_c_locale :: IO ()
-
-
-------------------------------------------------------------------------------
-foreign import ccall unsafe "c_parse_http_time"
-        c_parse_http_time :: CString -> IO CTime
-
-
-------------------------------------------------------------------------------
-foreign import ccall unsafe "c_format_http_time"
-        c_format_http_time :: CTime -> CString -> IO ()
-
-------------------------------------------------------------------------------
-type Enumerator a = I.Enumerator IO a
-
-------------------------------------------------------------------------------
--- | A type alias for a case-insensitive key-value mapping.
-type Headers = Map CIByteString [ByteString]
-
-
-------------------------------------------------------------------------------
--- | A typeclass for datatypes which contain HTTP headers.
-class HasHeaders a where
-
-    -- | Modify the datatype's headers.
-    updateHeaders :: (Headers -> Headers) -> a -> a
-
-    -- | Retrieve the headers from a datatype that has headers.
-    headers       :: a -> Headers
-
-
-------------------------------------------------------------------------------
--- | Adds a header key-value-pair to the 'HasHeaders' datatype. If a header with
--- the same name already exists, the new value is appended to the headers list.
-addHeader :: (HasHeaders a) => CIByteString -> ByteString -> a -> a
-addHeader k v = updateHeaders $ Map.insertWith' (++) k [v]
-
-
-------------------------------------------------------------------------------
--- | Sets a header key-value-pair in a 'HasHeaders' datatype. If a header with
--- the same name already exists, it is overwritten with the new value.
-setHeader :: (HasHeaders a) => CIByteString -> ByteString -> a -> a
-setHeader k v = updateHeaders $ Map.insert k [v]
-
-
-------------------------------------------------------------------------------
--- | Gets all of the values for a given header.
-getHeaders :: (HasHeaders a) => CIByteString -> a -> Maybe [ByteString]
-getHeaders k a = Map.lookup k $ headers a
-
-
-------------------------------------------------------------------------------
--- | Gets a header value out of a 'HasHeaders' datatype. If many headers came
--- in with the same name, they will be catenated together.
-getHeader :: (HasHeaders a) => CIByteString -> a -> Maybe ByteString
-getHeader k a = liftM (S.intercalate " ") (Map.lookup k $ headers a)
-
-
-------------------------------------------------------------------------------
--- | Enumerates the HTTP method values (see
--- <http://tools.ietf.org/html/rfc2068.html#section-5.1.1>).
-data Method  = GET | HEAD | POST | PUT | DELETE | TRACE | OPTIONS | CONNECT
-               deriving(Show,Read,Ord,Eq)
-
-
-------------------------------------------------------------------------------
-type HttpVersion = (Int,Int)
-
-
-------------------------------------------------------------------------------
--- | A datatype representing an HTTP cookie.
-data Cookie = Cookie {
-      -- | The name of the cookie.
-      cookieName    :: !ByteString
-
-      -- | The cookie's string value.
-    , cookieValue   :: !ByteString
-
-      -- | The cookie's expiration value, if it has one.
-    , cookieExpires :: !(Maybe UTCTime)
-
-      -- | The cookie's \"domain\" value, if it has one.
-    , cookieDomain  :: !(Maybe ByteString)
-
-      -- | The cookie path.
-    , cookiePath    :: !(Maybe ByteString)
-} deriving (Eq, Show)
-
-
-------------------------------------------------------------------------------
--- | A type alias for the HTTP parameters mapping. Each parameter
--- key maps to a list of ByteString values; if a parameter is specified
--- multiple times (e.g.: \"@GET /foo?param=bar1&param=bar2@\"), looking up
--- \"@param@\" in the mapping will give you @[\"bar1\", \"bar2\"]@.
-type Params = Map ByteString [ByteString]
-
-
-------------------------------------------------------------------------------
--- request type
-------------------------------------------------------------------------------
-
-data SomeEnumerator = SomeEnumerator (forall a . Enumerator a)
-
-
-------------------------------------------------------------------------------
--- | Contains all of the information about an incoming HTTP request.
-data Request = Request
-    { -- | The server name of the request, as it came in from the request's
-      -- @Host:@ header.
-      rqServerName     :: !ByteString
-
-      -- | Returns the port number the HTTP server is listening on.
-    , rqServerPort     :: !Int
-
-      -- | The remote IP address.
-    , rqRemoteAddr     :: !ByteString
-
-      -- | The remote TCP port number.
-    , rqRemotePort     :: !Int
-
-      -- | The local IP address for this request.
-    , rqLocalAddr      :: !ByteString
-
-      -- | Returns the port number the HTTP server is listening on.
-    , rqLocalPort      :: !Int
-
-      -- | Returns the HTTP server's idea of its local hostname.
-    , rqLocalHostname  :: !ByteString
-
-      -- | Returns @True@ if this is an @HTTPS@ session (currently always
-      -- @False@).
-    , rqIsSecure       :: !Bool
-    , rqHeaders        :: Headers
-    , rqBody           :: IORef SomeEnumerator
-
-      -- | Returns the @Content-Length@ of the HTTP request body.
-    , rqContentLength  :: !(Maybe Int)
-
-      -- | Returns the HTTP request method.
-    , rqMethod         :: !Method
-
-      -- | Returns the HTTP version used by the client.
-    , rqVersion        :: !HttpVersion
-
-      -- | Returns a list of the cookies that came in from the HTTP request
-      -- headers.
-    , rqCookies        :: [Cookie]
-
-
-      -- | We'll be doing web components (or \"snaplets\") for version 0.2. The
-      -- \"snaplet path\" refers to the place on the URL where your containing
-      -- snaplet is hung. The value of 'rqSnapletPath' is either @\"\"@ (at the
-      -- top-level context) or is a path beginning with a slash, but not ending
-      -- with one.
-      --
-      -- An identity is that:
-      --
-      -- > rqURI r == 'S.concat' [ rqSnapletPath r
-      -- >                       , rqContextPath r
-      -- >                       , rqPathInfo r ]
-      --
-      -- note that until we introduce snaplets in v0.2, 'rqSnapletPath' will be
-      -- \"\"
-    , rqSnapletPath    :: !ByteString
-
-      -- | Handlers can (/will be; --ed/) be hung on a @URI@ \"entry point\";
-      -- this is called the \"context path\". If a handler is hung on the
-      -- context path @\"\/foo\/\"@, and you request @\"\/foo\/bar\"@, the value
-      -- of 'rqPathInfo' will be @\"bar\"@.
-    , rqPathInfo       :: !ByteString
-
-      -- | The \"context path\" of the request; catenating 'rqContextPath', and
-      -- 'rqPathInfo' should get you back to the original 'rqURI'. The
-      -- 'rqContextPath' always begins and ends with a slash (@\"\/\"@)
-      -- character, and represents the path (relative to your
-      -- component\/snaplet) you took to get to your handler.
-    , rqContextPath    :: !ByteString
-
-      -- | Returns the @URI@ requested by the client.
-    , rqURI            :: !ByteString
-
-      -- | Returns the HTTP query string for this 'Request'.
-    , rqQueryString    :: !ByteString
-
-      -- | Returns the 'Params' mapping for this 'Request'. \"Parameters\" are
-      -- automatically decoded from the query string and @POST@ body and
-      -- entered into this mapping.
-    , rqParams         :: Params
-    }
-
-
-------------------------------------------------------------------------------
-instance Show Request where
-  show r = concat [ "Request <\n"
-                  , body
-                  , ">" ]
-    where
-      body = concat $ map (("    "++) . (++ "\n")) [
-                      sname
-                    , remote
-                    , local
-                    , beginheaders
-                    , hdrs
-                    , endheaders
-                    , contentlength
-                    , method
-                    , version
-                    , cookies
-                    , pathinfo
-                    , contextpath
-                    , snapletpath
-                    , uri
-                    , params
-                    ]
-
-      sname         = concat [ "server-name: ", toStr $ rqServerName r ]
-      remote        = concat [ "remote: "
-                             , toStr $ rqRemoteAddr r
-                             , ":"
-                             , show (rqRemotePort r)
-                             ]
-      local         = concat [ "local: "
-                             , toStr $ rqLocalAddr r
-                             , ":"
-                             , show $ rqServerPort r
-                             ]
-      beginheaders  = "Headers:\n      ========================================"
-      endheaders    = "  ========================================"
-      hdrs          = "      " ++ show (rqHeaders r)
-      contentlength = concat [ "content-length: "
-                             , show $ rqContentLength r
-                             ]
-      method        = concat [ "method: "
-                             , show $ rqMethod r
-                             ]
-      version       = concat [ "version: "
-                             , show $ rqVersion r
-                             ]
-      cookies       = concat [ "cookies:\n"
-                             , "      ========================================\n"
-                             , "      " ++ (show $ rqCookies r)
-                             , "\n      ========================================"
-                             ]
-      pathinfo      = concat [ "pathinfo: ", toStr $ rqPathInfo r ]
-      contextpath   = concat [ "contextpath: ", toStr $ rqContextPath r ]
-      snapletpath   = concat [ "snapletpath: ", toStr $ rqSnapletPath r ]
-      uri           = concat [ "URI: ", toStr $ rqURI r ]
-      params        = concat [ "params:\n"
-                             , "      ========================================\n"
-                             , "      " ++ (show $ rqParams r)
-                             , "\n      ========================================"
-                             ]
-
-
-------------------------------------------------------------------------------
-instance HasHeaders Request where
-    headers           = rqHeaders
-    updateHeaders f r = r { rqHeaders = f (rqHeaders r) }
-
-
-------------------------------------------------------------------------------
-instance HasHeaders Headers where
-    headers       = id
-    updateHeaders = id
-
-------------------------------------------------------------------------------
--- response type
-------------------------------------------------------------------------------
-
-data ResponseBody = Enum (forall a . Enumerator a) -- ^ output body is enumerator
-                  | SendFile FilePath              -- ^ output body is sendfile()
-
-
-------------------------------------------------------------------------------
-rspBodyMap :: (forall a . Enumerator a -> Enumerator a)
-           -> ResponseBody
-           -> ResponseBody
-rspBodyMap f b      = Enum $ f $ rspBodyToEnum b
-
-
-------------------------------------------------------------------------------
-rspBodyToEnum :: ResponseBody -> Enumerator a
-rspBodyToEnum (Enum e) = e
-rspBodyToEnum (SendFile fp) = I.enumFile fp
-
-
-------------------------------------------------------------------------------
--- | Represents an HTTP response.
-data Response = Response
-    { rspHeaders       :: Headers
-    , rspHttpVersion   :: !HttpVersion
-
-      -- | We will need to inspect the content length no matter what, and
-      --   looking up \"content-length\" in the headers and parsing the number
-      --   out of the text will be too expensive.
-    , rspContentLength :: !(Maybe Int)
-    , rspBody          :: ResponseBody
-
-      -- | Returns the HTTP status code.
-    , rspStatus        :: !Int
-
-      -- | Returns the HTTP status explanation string.
-    , rspStatusReason  :: !ByteString
-    }
-
-
-------------------------------------------------------------------------------
-instance Show Response where
-  show r = concat [ "Response <\n"
-                  , body
-                  , ">" ]
-    where
-      body = concat $ map (("    "++) . (++ "\n")) [
-                         hdrs
-                       , version
-                       , status
-                       , reason
-                       ]
-
-      hdrs    = concat [ "headers:\n"
-                       , "      ==============================\n      "
-                       , show $ rspHeaders r
-                       , "\n      ==============================" ]
-
-      version = concat [ "version: ", show $ rspHttpVersion r ]
-      status  = concat [ "status: ", show $ rspStatus r ]
-      reason  = concat [ "reason: ", toStr $ rspStatusReason r ]
-
-
-------------------------------------------------------------------------------
-instance HasHeaders Response where
-    headers = rspHeaders
-    updateHeaders f r = r { rspHeaders = f (rspHeaders r) }
-
-
-------------------------------------------------------------------------------
--- | Looks up the value(s) for the given named parameter. Parameters initially
--- come from the request's query string and any decoded POST body (if the
--- request's @Content-Type@ is @application\/x-www-form-urlencoded@). Parameter
--- values can be modified within handlers using "rqModifyParams".
-rqParam :: ByteString           -- ^ parameter name to look up
-        -> Request              -- ^ HTTP request
-        -> Maybe [ByteString]
-rqParam k rq = Map.lookup k $ rqParams rq
-{-# INLINE rqParam #-}
-
-
-------------------------------------------------------------------------------
--- | Modifies the parameters mapping (which is a @Map ByteString ByteString@) in
--- a 'Request' using the given function.
-rqModifyParams :: (Params -> Params) -> Request -> Request
-rqModifyParams f r = r { rqParams = p }
-  where
-    p = f $ rqParams r
-{-# INLINE rqModifyParams #-}
-
-
-------------------------------------------------------------------------------
--- | Writes a key-value pair to the parameters mapping within the given request.
-rqSetParam :: ByteString        -- ^ parameter name
-           -> [ByteString]      -- ^ parameter values
-           -> Request           -- ^ request
-           -> Request
-rqSetParam k v = rqModifyParams $ Map.insert k v
-{-# INLINE rqSetParam #-}
-
-------------------------------------------------------------------------------
--- responses
-------------------------------------------------------------------------------
-
--- | An empty 'Response'.
-emptyResponse       :: Response
-emptyResponse       = Response Map.empty (1,1) Nothing (Enum return) 200 "OK"
-
-
-------------------------------------------------------------------------------
--- | Sets an HTTP response body to the given 'Enumerator' value.
-setResponseBody     :: (forall a . Enumerator a)  -- ^ new response body
-                                                  -- enumerator
-                    -> Response                   -- ^ response to modify
-                    -> Response
-setResponseBody e r = r { rspBody = Enum e }
-{-# INLINE setResponseBody #-}
-
-
-------------------------------------------------------------------------------
--- | Sets the HTTP response status.
-setResponseStatus   :: Int        -- ^ HTTP response integer code
-                    -> ByteString -- ^ HTTP response explanation
-                    -> Response   -- ^ Response to be modified
-                    -> Response
-setResponseStatus s reason r = r { rspStatus=s, rspStatusReason=reason }
-{-# INLINE setResponseStatus #-}
-
-
-------------------------------------------------------------------------------
--- | Modifies a response body.
-modifyResponseBody  :: (forall a . Enumerator a -> Enumerator a)
-                    -> Response
-                    -> Response
-modifyResponseBody f r = r { rspBody = rspBodyMap f (rspBody r) }
-{-# INLINE modifyResponseBody #-}
-
-
-------------------------------------------------------------------------------
--- | Sets the @Content-Type@ in the 'Response' headers.
-setContentType      :: ByteString -> Response -> Response
-setContentType = setHeader "Content-Type"
-{-# INLINE setContentType #-}
-
-
-------------------------------------------------------------------------------
--- | Adds an HTTP 'Cookie' to the 'Response' headers.
-addCookie :: Cookie            -- ^ cookie value
-          -> Response          -- ^ response to modify
-          -> Response
-addCookie (Cookie k v mbExpTime mbDomain mbPath) = updateHeaders f
-  where
-    f       = Map.insertWith' (++) "Set-Cookie" [cookie]
-    cookie  = S.concat [k, "=", v, path, exptime, domain]
-    path    = maybe "" (S.append "; path=") mbPath
-    domain  = maybe "" (S.append "; domain=") mbDomain
-    exptime = maybe "" (S.append "; expires=" . fmt) mbExpTime
-    fmt     = fromStr . formatTime defaultTimeLocale "%a, %d-%b-%Y %H:%M:%S GMT"
-
-
-------------------------------------------------------------------------------
--- | A note here: if you want to set the @Content-Length@ for the response,
--- Snap forces you to do it with this function rather than by setting it in the
--- headers; the @Content-Length@ in the headers will be ignored.
---
--- The reason for this is that Snap needs to look up the value of
--- @Content-Length@ for each request, and looking the string value up in the
--- headers and parsing the number out of the text will be too expensive.
---
--- If you don't set a content length in your response, HTTP keep-alive will be
--- disabled for HTTP\/1.0 clients, forcing a @Connection: close@. For HTTP\/1.1
--- clients, Snap will switch to the chunked transfer encoding if
--- @Content-Length@ is not specified.
-setContentLength    :: Int -> Response -> Response
-setContentLength l r = r { rspContentLength = Just l }
-{-# INLINE setContentLength #-}
-
-
-------------------------------------------------------------------------------
--- | Removes any @Content-Length@ set in the 'Response'.
-clearContentLength :: Response -> Response
-clearContentLength r = r { rspContentLength = Nothing }
-{-# INLINE clearContentLength #-}
-
-
-------------------------------------------------------------------------------
--- HTTP dates
-
-{-
--- | Converts a 'ClockTime' into an HTTP timestamp.
-formatHttpTime :: UTCTime -> ByteString
-formatHttpTime = fromStr . formatTime defaultTimeLocale "%a, %d %b %Y %X GMT"
-
--- | Converts an HTTP timestamp into a 'UTCTime'.
-parseHttpTime :: ByteString -> Maybe UTCTime
-parseHttpTime s' =
-    parseTime defaultTimeLocale "%a, %d %b %Y %H:%M:%S GMT" s
-  where
-    s = toStr s'
--}
-
--- | Converts a 'CTime' into an HTTP timestamp.
-formatHttpTime :: CTime -> IO ByteString
-formatHttpTime t = allocaBytes 40 $ \ptr -> do
-    c_format_http_time t ptr
-    S.packCString ptr
-
-
-------------------------------------------------------------------------------
--- | Converts an HTTP timestamp into a 'CTime'.
-parseHttpTime :: ByteString -> IO CTime
-parseHttpTime s = S.useAsCString s $ \ptr ->
-    c_parse_http_time ptr
-
-
-------------------------------------------------------------------------------
--- URL ENCODING
-------------------------------------------------------------------------------
-
-parseToCompletion :: Parser a -> ByteString -> Maybe a
-parseToCompletion p s = toResult $ finish r
-  where
-    r = parse p s
-
-    toResult (Atto.Done _ c) = Just c
-    toResult _               = Nothing
-
-
-------------------------------------------------------------------------------
-pUrlEscaped :: Parser ByteString
-pUrlEscaped = do
-    sq <- nextChunk DL.empty
-    return $ S.concat $ DL.toList sq
-
-  where
-    nextChunk :: DList ByteString -> Parser (DList ByteString)
-    nextChunk s = (endOfInput *> pure s) <|> do
-        c <- anyWord8
-        case w2c c of
-          '+' -> plusSpace s
-          '%' -> percentEncoded s
-          _   -> unEncoded c s
-
-    percentEncoded :: DList ByteString -> Parser (DList ByteString)
-    percentEncoded l = do
-        hx <- take 2
-        when (S.length hx /= 2 ||
-               (not $ S.all (isHexDigit . w2c) hx)) $
-             fail "bad hex in url"
-          
-        let code = (Cvt.hex hx) :: Word8
-        nextChunk $ DL.snoc l (S.singleton code)
-
-    unEncoded :: Word8 -> DList ByteString -> Parser (DList ByteString)
-    unEncoded c l' = do
-        let l = DL.snoc l' (S.singleton c)
-        bs <- takeTill (flip elem (map c2w "%+"))
-        if S.null bs
-          then nextChunk l
-          else nextChunk $ DL.snoc l bs
-
-    plusSpace :: DList ByteString -> Parser (DList ByteString)
-    plusSpace l = nextChunk (DL.snoc l (S.singleton $ c2w ' '))
-
-
-------------------------------------------------------------------------------
--- | Decodes an URL-escaped string (see
--- <http://tools.ietf.org/html/rfc2396.html#section-2.4>)
-urlDecode :: ByteString -> Maybe ByteString
-urlDecode = parseToCompletion pUrlEscaped
-
-
-------------------------------------------------------------------------------
--- "...Only alphanumerics [0-9a-zA-Z], the special characters "$-_.+!*'(),"
--- [not including the quotes - ed], and reserved characters used for their
--- reserved purposes may be used unencoded within a URL."
-
--- | URL-escapes a string (see
--- <http://tools.ietf.org/html/rfc2396.html#section-2.4>)
-urlEncode :: ByteString -> ByteString
-urlEncode = toByteString . S.foldl' f empty
-  where
-    f b c =
-        if c == c2w ' '
-          then b `mappend` singleton (c2w '+')
-          else if isKosher c
-                 then b `mappend` singleton c
-                 else b `mappend` hexd c
-
-    isKosher w = any ($ c) [ isAlphaNum
-                           , flip elem ['$', '-', '.', '!', '*'
-                                       , '\'', '(', ')', ',' ]]
-      where
-        c = w2c w
-
-
-------------------------------------------------------------------------------
-hexd :: Word8 -> Builder
-hexd c = singleton (c2w '%') `mappend` singleton hi `mappend` singleton low
-  where
-    d   = c2w . intToDigit
-    low = d $ fromEnum $ c .&. 0xf
-    hi  = d $ fromEnum $ (c .&. 0xf0) `shift` (-4)
-
-
-------------------------------------------------------------------------------
-finish :: Atto.Result a -> Atto.Result a
-finish (Atto.Partial f) = flip feed "" $ f ""
-finish x                = x
-
-
-------------------------------------------------------------------------------
--- local definitions
-fromStr :: String -> ByteString
-fromStr = S.pack . map c2w
-{-# INLINE fromStr #-}
-
-------------------------------------------------------------------------------
--- private helper functions
-toStr :: ByteString -> String
-toStr = map w2c . S.unpack
-
-
- diff --git a/static/docs/0.2.1/snap-core/src/Snap-Internal-Iteratee-Debug.html b/static/docs/0.2.1/snap-core/src/Snap-Internal-Iteratee-Debug.html deleted file mode 100644 index 972fc9d..0000000 --- a/static/docs/0.2.1/snap-core/src/Snap-Internal-Iteratee-Debug.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - -src/Snap/Internal/Iteratee/Debug.hs - - - -
-- | An internal Snap module for debugging iteratees.
---
--- /N.B./ this is an internal interface, please don't write user code that
--- depends on it.
-
-{-# OPTIONS_GHC -fno-warn-orphans #-}
-{-# LANGUAGE FlexibleInstances #-}
-
-module Snap.Internal.Iteratee.Debug ( debugIteratee ) where
-
-------------------------------------------------------------------------------
-import           Data.Iteratee.WrappedByteString
-import           Data.Word (Word8)
-import           System.IO
-------------------------------------------------------------------------------
-import           Snap.Iteratee
-------------------------------------------------------------------------------
-
-
-------------------------------------------------------------------------------
-instance Show (WrappedByteString Word8) where
-    show (WrapBS s) = show s
-
-
-------------------------------------------------------------------------------
-debugIteratee :: Iteratee IO ()
-debugIteratee = IterateeG f
-  where
-    f c@(EOF _) = do
-        putStrLn $ "got chunk: " ++ show c
-        hFlush stdout
-        return (Done () c)
-
-    f c@(Chunk _) = do
-        putStrLn $ "got chunk: " ++ show c
-        hFlush stdout
-        return $ Cont debugIteratee Nothing
-
- diff --git a/static/docs/0.2.1/snap-core/src/Snap-Internal-Routing.html b/static/docs/0.2.1/snap-core/src/Snap-Internal-Routing.html deleted file mode 100644 index 63cffe2..0000000 --- a/static/docs/0.2.1/snap-core/src/Snap-Internal-Routing.html +++ /dev/null @@ -1,191 +0,0 @@ - - - - -src/Snap/Internal/Routing.hs - - - -
module Snap.Internal.Routing where
-
-
-------------------------------------------------------------------------------
-import           Control.Applicative ((<|>))
-import           Data.ByteString (ByteString)
-import           Data.ByteString.Internal (c2w)
-import qualified Data.ByteString as B
-import           Data.Monoid
-import qualified Data.Map as Map
-
-------------------------------------------------------------------------------
-import           Snap.Internal.Http.Types
-import           Snap.Internal.Types
-
-
-------------------------------------------------------------------------------
-{-|
-
-The internal data type you use to build a routing tree.  Matching is
-done unambiguously.
-
-'Capture' and 'Dir' routes can have a "fallback" route:
-
-  - For 'Capture', the fallback is routed when there is nothing to capture
-  - For 'Dir', the fallback is routed when we can't find a route in its map
-
-Fallback routes are stacked: i.e. for a route like:
-
-> Dir [("foo", Capture "bar" (Action bar) NoRoute)] baz
-
-visiting the URI foo/ will result in the "bar" capture being empty and
-triggering its fallback. It's NoRoute, so we go to the nearest parent
-fallback and try that, which is the baz action.
-
--}
-data Route a = Action (Snap a)                        -- wraps a 'Snap' action
-             | Capture ByteString (Route a) (Route a) -- captures the dir in a param
-             | Dir (Map.Map ByteString (Route a)) (Route a)  -- match on a dir
-             | NoRoute
-
-
-------------------------------------------------------------------------------
-instance Monoid (Route a) where
-    mempty = NoRoute
-
-    -- Unions two routes, favoring the right-hand side
-    mappend NoRoute r = r
-
-    mappend l@(Action _) r = case r of
-      (Action _)        -> r
-      (Capture p r' fb) -> Capture p r' (mappend fb l)
-      (Dir _ _)         -> mappend (Dir Map.empty l) r
-      NoRoute           -> l
-
-    mappend l@(Capture p r' fb) r = case r of
-      (Action _)           -> Capture p r' (mappend fb r)
-      (Capture p' r'' fb')
-               | p == p'   -> Capture p (mappend r' r'') (mappend fb fb')
-               | otherwise -> r
-      (Dir rm fb')         -> Dir rm (mappend fb' l)
-      NoRoute              -> l
-
-    mappend l@(Dir rm fb) r = case r of
-      (Action _)      -> Dir rm (mappend fb r)
-      (Capture _ _ _) -> Dir rm (mappend fb r)
-      (Dir rm' fb')   -> Dir (Map.unionWith mappend rm rm') (mappend fb fb')
-      NoRoute         -> l
-
-
-------------------------------------------------------------------------------
--- | A web handler which, given a mapping from URL entry points to web
--- handlers, efficiently routes requests to the correct handler.
---
--- The URL entry points are given as relative paths, for example:
---
--- > route [ ("foo/bar/quux", fooBarQuux) ]
---
--- If the URI of the incoming request is
---
--- > /foo/bar/quux
---
--- or
---
--- > /foo/bar/quux/...anything...
---
--- then the request will be routed to \"@fooBarQuux@\", with 'rqContextPath'
--- set to \"@\/foo\/bar\/quux\/@\" and 'rqPathInfo' set to
--- \"@...anything...@\".
---
--- A path component within an URL entry point beginning with a colon (\"@:@\")
--- is treated as a /variable capture/; the corresponding path component within
--- the request URI will be entered into the 'rqParams' parameters mapping with
--- the given name. For instance, if the routes were:
---
--- > route [ ("foo/:bar/baz", fooBazHandler) ]
---
--- Then a request for \"@\/foo\/saskatchewan\/baz@\" would be routed to
--- @fooBazHandler@ with a mapping for:
---
--- > "bar" => "saskatchewan"
---
--- in its parameters table.
---
--- Longer paths are matched first, and specific routes are matched before
--- captures. That is, if given routes:
---
--- > [ ("a", h1), ("a/b", h2), ("a/:x", h3) ]
---
--- a request for \"@\/a\/b@\" will go to @h2@, \"@\/a\/s@\" for any /s/ will go
--- to @h3@, and \"@\/a@\" will go to @h1@.
---
--- The following example matches \"@\/article@\" to an article index,
--- \"@\/login@\" to a login, and \"@\/article\/...@\" to an article renderer.
---
--- > route [ ("article",     renderIndex)
--- >       , ("article/:id", renderArticle)
--- >       , ("login",       method POST doLogin) ]
---
-route :: [(ByteString, Snap a)] -> Snap a
-route rts = route' (return ()) rts' []
-  where
-    rts' = mconcat (map pRoute rts)
-
-
-------------------------------------------------------------------------------
--- | The 'routeLocal' function is the same as 'route', except it doesn't change
--- the request's context path. This is useful if you want to route to a
--- particular handler but you want that handler to receive the 'rqPathInfo' as
--- it is.
-routeLocal :: [(ByteString, Snap a)] -> Snap a
-routeLocal rts' = do
-    req    <- getRequest
-    let ctx = rqContextPath req
-    let p   = rqPathInfo req
-    let md  = modifyRequest $ \r -> r {rqContextPath=ctx, rqPathInfo=p}
-
-    route' md rts []   <|>   (md >> pass)
-
-  where
-    rts = mconcat (map pRoute rts')
-
-          
-------------------------------------------------------------------------------
-pRoute :: (ByteString, Snap a) -> Route a
-pRoute (r, a) = foldr f (Action a) hier
-  where
-    hier   = filter (not . B.null) $ B.splitWith (== (c2w '/')) r
-    f s rt = if B.head s == c2w ':'
-        then Capture (B.tail s) rt NoRoute
-        else Dir (Map.fromList [(s, rt)]) NoRoute
-
-
-------------------------------------------------------------------------------
-route' :: Snap ()               -- ^ an action to be run before any user
-                                -- handler
-       -> Route a               -- ^ currently active routing table
-       -> [Route a]             -- ^ list of fallback routing tables in case
-                                -- the current table fails
-       -> Snap a
-route' pre (Action action) _ = pre >> action
-
-route' pre (Capture param rt fb) fbs = do
-    cwd <- getRequest >>= return . B.takeWhile (/= (c2w '/')) . rqPathInfo
-    if B.null cwd
-      then route' pre fb fbs
-      else do localRequest (updateContextPath (B.length cwd) . (f cwd)) $
-                           route' pre rt (fb:fbs)
-  where
-    f v req = req { rqParams = Map.insertWith (++) param [v] (rqParams req) }
-
-route' pre (Dir rtm fb) fbs = do
-    cwd <- getRequest >>= return . B.takeWhile (/= (c2w '/')) . rqPathInfo
-    case Map.lookup cwd rtm of
-      Just rt -> do
-          localRequest (updateContextPath (B.length cwd)) $
-                       route' pre rt (fb:fbs)
-      Nothing -> route' pre fb fbs
-
-route' _ NoRoute       []   = pass
-route' pre NoRoute (fb:fbs) = route' pre fb fbs
-
- diff --git a/static/docs/0.2.1/snap-core/src/Snap-Internal-Types.html b/static/docs/0.2.1/snap-core/src/Snap-Internal-Types.html deleted file mode 100644 index 1ec95c1..0000000 --- a/static/docs/0.2.1/snap-core/src/Snap-Internal-Types.html +++ /dev/null @@ -1,544 +0,0 @@ - - - - -src/Snap/Internal/Types.hs - - - -
{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE EmptyDataDecls #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RankNTypes #-}
-
-module Snap.Internal.Types where
-
-------------------------------------------------------------------------------
-import           Control.Applicative
-import           Control.Exception (throwIO, ErrorCall(..))
-import           Control.Monad.CatchIO
-import           Control.Monad.State.Strict
-import           Data.ByteString.Char8 (ByteString)
-import qualified Data.ByteString.Char8 as S
-import qualified Data.ByteString.Lazy.Char8 as L
-import           Data.IORef
-import qualified Data.Iteratee as Iter
-import           Data.Maybe
-import qualified Data.Text as T
-import qualified Data.Text.Encoding as T
-import qualified Data.Text.Lazy as LT
-import qualified Data.Text.Lazy.Encoding as LT
-
-import           Data.Typeable
-
-------------------------------------------------------------------------------
-import           Snap.Iteratee hiding (Enumerator)
-import           Snap.Internal.Http.Types
-
-
-------------------------------------------------------------------------------
--- The Snap Monad
-------------------------------------------------------------------------------
-
-{-|
-
-'Snap' is the 'Monad' that user web handlers run in. 'Snap' gives you:
-
-1. stateful access to fetch or modify an HTTP 'Request'
-
-2. stateful access to fetch or modify an HTTP 'Response'
-
-3. failure \/ 'Alternative' \/ 'MonadPlus' semantics: a 'Snap' handler can
-   choose not to handle a given request, using 'empty' or its synonym 'pass',
-   and you can try alternative handlers with the '<|>' operator:
-
-   > a :: Snap String
-   > a = pass
-   >
-   > b :: Snap String
-   > b = return "foo"
-   >
-   > c :: Snap String
-   > c = a <|> b             -- try running a, if it fails then try b
-
-4. convenience functions ('writeBS', 'writeLBS', 'writeText', 'writeLazyText',
-   'addToOutput') for writing output to the 'Response':
-
-   > a :: (forall a . Enumerator a) -> Snap ()
-   > a someEnumerator = do
-   >     writeBS "I'm a strict bytestring"
-   >     writeLBS "I'm a lazy bytestring"
-   >     addToOutput someEnumerator
-
-5. early termination: if you call 'finishWith':
-
-   > a :: Snap ()
-   > a = do
-   >   modifyResponse $ setResponseStatus 500 "Internal Server Error"
-   >   writeBS "500 error"
-   >   r <- getResponse
-   >   finishWith r
-
-   then any subsequent processing will be skipped and supplied 'Response' value
-   will be returned from 'runSnap' as-is.
-
-6. access to the 'IO' monad through a 'MonadIO' instance:
-
-   > a :: Snap ()
-   > a = liftIO fireTheMissiles
--}
-
-
-------------------------------------------------------------------------------
-newtype Snap a = Snap {
-      unSnap :: StateT SnapState (Iteratee IO) (Maybe (Either Response a))
-}
-
-
-------------------------------------------------------------------------------
-data SnapState = SnapState
-    { _snapRequest  :: Request
-    , _snapResponse :: Response
-    , _snapLogError :: ByteString -> IO () }
-
-
-------------------------------------------------------------------------------
-instance Monad Snap where
-    (Snap m) >>= f =
-        Snap $ do
-            eth <- m
-            maybe (return Nothing)
-                  (either (return . Just . Left)
-                          (unSnap . f))
-                  eth
-
-    return = Snap . return . Just . Right
-    fail   = const $ Snap $ return Nothing
-
-
-------------------------------------------------------------------------------
-instance MonadIO Snap where
-    liftIO m = Snap $ liftM (Just . Right) $ liftIO m
-
-
-------------------------------------------------------------------------------
-instance MonadCatchIO Snap where
-    catch (Snap m) handler = Snap $ do
-        x <- try m
-        case x of
-          (Left e)  -> let (Snap z) = handler e in z
-          (Right y) -> return y
-
-    block (Snap m) = Snap $ block m
-    unblock (Snap m) = Snap $ unblock m
-
-
-------------------------------------------------------------------------------
-instance MonadPlus Snap where
-    mzero = Snap $ return Nothing
-
-    a `mplus` b =
-        Snap $ do
-            mb <- unSnap a
-            if isJust mb then return mb else unSnap b
-
-
-------------------------------------------------------------------------------
-instance Functor Snap where
-    fmap = liftM
-
-
-------------------------------------------------------------------------------
-instance Applicative Snap where
-    pure  = return
-    (<*>) = ap
-
-
-------------------------------------------------------------------------------
-instance Alternative Snap where
-    empty = mzero
-    (<|>) = mplus
-
-
-------------------------------------------------------------------------------
-liftIter :: Iteratee IO a -> Snap a
-liftIter i = Snap (lift i >>= return . Just . Right)
-
-
-------------------------------------------------------------------------------
--- | Sends the request body through an iteratee (data consumer) and
--- returns the result.
-runRequestBody :: Iteratee IO a -> Snap a
-runRequestBody iter = do
-    req  <- getRequest
-    senum <- liftIO $ readIORef $ rqBody req
-    let (SomeEnumerator enum) = senum
-
-    -- make sure the iteratee consumes all of the output
-    let iter' = iter >>= (\a -> Iter.skipToEof >> return a)
-
-    -- run the iteratee
-    result <- liftIter $ Iter.joinIM $ enum iter'
-
-    -- stuff a new dummy enumerator into the request, so you can only try to
-    -- read the request body from the socket once
-    liftIO $ writeIORef (rqBody req)
-                        (SomeEnumerator $ return . Iter.joinI . Iter.take 0 )
-
-    return result
-
-
-------------------------------------------------------------------------------
--- | Returns the request body as a bytestring.
-getRequestBody :: Snap L.ByteString
-getRequestBody = liftM fromWrap $ runRequestBody stream2stream
-{-# INLINE getRequestBody #-}
-
-
-------------------------------------------------------------------------------
--- | Detaches the request body's 'Enumerator' from the 'Request' and
--- returns it. You would want to use this if you needed to send the
--- HTTP request body (transformed or otherwise) through to the output
--- in O(1) space. (Examples: transcoding, \"echo\", etc)
--- 
--- Normally Snap is careful to ensure that the request body is fully
--- consumed after your web handler runs; this function is marked
--- \"unsafe\" because it breaks this guarantee and leaves the
--- responsibility up to you. If you don't fully consume the
--- 'Enumerator' you get here, the next HTTP request in the pipeline
--- (if any) will misparse. Be careful with exception handlers.
-unsafeDetachRequestBody :: Snap (Enumerator a)
-unsafeDetachRequestBody = do
-    req <- getRequest
-    let ioref = rqBody req
-    senum <- liftIO $ readIORef ioref
-    let (SomeEnumerator enum) = senum
-    liftIO $ writeIORef ioref
-               (SomeEnumerator $ return . Iter.joinI . Iter.take 0)
-    return enum
-
-
-------------------------------------------------------------------------------
--- | Short-circuits a 'Snap' monad action early, storing the given
--- 'Response' value in its state.
-finishWith :: Response -> Snap ()
-finishWith = Snap . return . Just . Left
-{-# INLINE finishWith #-}
-
-
-------------------------------------------------------------------------------
--- | Fails out of a 'Snap' monad action.  This is used to indicate
--- that you choose not to handle the given request within the given
--- handler.
-pass :: Snap a
-pass = empty
-
-
-------------------------------------------------------------------------------
--- | Runs a 'Snap' monad action only if the request's HTTP method matches
--- the given method.
-method :: Method -> Snap a -> Snap a
-method m action = do
-    req <- getRequest
-    unless (rqMethod req == m) pass
-    action
-{-# INLINE method #-}
-
-
-------------------------------------------------------------------------------
--- Appends n bytes of the path info to the context path with a
--- trailing slash.
-updateContextPath :: Int -> Request -> Request
-updateContextPath n req | n > 0     = req { rqContextPath = ctx
-                                          , rqPathInfo    = pinfo }
-                        | otherwise = req
-  where
-    ctx'  = S.take n (rqPathInfo req)
-    ctx   = S.concat [rqContextPath req, ctx', "/"]
-    pinfo = S.drop (n+1) (rqPathInfo req)
-
-
-------------------------------------------------------------------------------
--- Runs a 'Snap' monad action only if the 'rqPathInfo' matches the given
--- predicate.
-pathWith :: (ByteString -> ByteString -> Bool)
-         -> ByteString
-         -> Snap a
-         -> Snap a
-pathWith c p action = do
-    req <- getRequest
-    unless (c p (rqPathInfo req)) pass
-    localRequest (updateContextPath $ S.length p) action
-
-
-------------------------------------------------------------------------------
--- | Runs a 'Snap' monad action only when the 'rqPathInfo' of the request
--- starts with the given path. For example,
---
--- > dir "foo" handler
---
--- Will fail if 'rqPathInfo' is not \"@\/foo@\" or \"@\/foo\/...@\", and will
--- add @\"foo\/\"@ to the handler's local 'rqContextPath'.
-dir :: ByteString  -- ^ path component to match
-    -> Snap a      -- ^ handler to run
-    -> Snap a
-dir = pathWith f
-  where
-    f dr pinfo = dr == x
-      where
-        (x,_) = S.break (=='/') pinfo
-{-# INLINE dir #-}
-
-
-------------------------------------------------------------------------------
--- | Runs a 'Snap' monad action only for requests where 'rqPathInfo' is exactly
--- equal to the given string. If the path matches, locally sets 'rqContextPath'
--- to the old value of 'rqPathInfo', sets 'rqPathInfo'=\"\", and runs the given
--- handler.
-path :: ByteString  -- ^ path to match against
-     -> Snap a      -- ^ handler to run
-     -> Snap a
-path = pathWith (==)
-{-# INLINE path #-}
-
-
-------------------------------------------------------------------------------
--- | Runs a 'Snap' monad action only when 'rqPathInfo' is empty.
-ifTop :: Snap a -> Snap a
-ifTop = path ""
-{-# INLINE ifTop #-}
-
-
-------------------------------------------------------------------------------
--- | Local Snap version of 'get'.
-sget :: Snap SnapState
-sget = Snap $ liftM (Just . Right) get
-{-# INLINE sget #-}
-
-
-------------------------------------------------------------------------------
--- | Local Snap monad version of 'modify'.
-smodify :: (SnapState -> SnapState) -> Snap ()
-smodify f = Snap $ modify f >> return (Just $ Right ())
-{-# INLINE smodify #-}
-
-
-------------------------------------------------------------------------------
--- | Grabs the 'Request' object out of the 'Snap' monad.
-getRequest :: Snap Request
-getRequest = liftM _snapRequest sget
-{-# INLINE getRequest #-}
-
-
-------------------------------------------------------------------------------
--- | Grabs the 'Response' object out of the 'Snap' monad.
-getResponse :: Snap Response
-getResponse = liftM _snapResponse sget
-{-# INLINE getResponse #-}
-
-
-------------------------------------------------------------------------------
--- | Puts a new 'Response' object into the 'Snap' monad.
-putResponse :: Response -> Snap ()
-putResponse r = smodify $ \ss -> ss { _snapResponse = r }
-{-# INLINE putResponse #-}
-
-
-------------------------------------------------------------------------------
--- | Puts a new 'Request' object into the 'Snap' monad.
-putRequest :: Request -> Snap ()
-putRequest r = smodify $ \ss -> ss { _snapRequest = r }
-{-# INLINE putRequest #-}
-
-
-------------------------------------------------------------------------------
--- | Modifies the 'Request' object stored in a 'Snap' monad.
-modifyRequest :: (Request -> Request) -> Snap ()
-modifyRequest f = smodify $ \ss -> ss { _snapRequest = f $ _snapRequest ss }
-{-# INLINE modifyRequest #-}
-
-
-------------------------------------------------------------------------------
--- | Modifes the 'Response' object stored in a 'Snap' monad.
-modifyResponse :: (Response -> Response) -> Snap () 
-modifyResponse f = smodify $ \ss -> ss { _snapResponse = f $ _snapResponse ss }
-{-# INLINE modifyResponse #-}
-
-
-------------------------------------------------------------------------------
--- | Log an error message in the 'Snap' monad
-logError :: ByteString -> Snap ()
-logError s = Snap $ gets _snapLogError >>= (\l -> liftIO $ l s)
-                                       >>  return (Just $ Right ())
-{-# INLINE logError #-}
-
-
-------------------------------------------------------------------------------
--- | Adds the output from the given enumerator to the 'Response'
--- stored in the 'Snap' monad state.
-addToOutput :: (forall a . Enumerator a)   -- ^ output to add
-            -> Snap ()
-addToOutput enum = modifyResponse $ modifyResponseBody (>. enum)
-
-
-------------------------------------------------------------------------------
--- | Adds the given strict 'ByteString' to the body of the 'Response' stored in
--- the 'Snap' monad state.
-writeBS :: ByteString -> Snap ()
-writeBS s = addToOutput $ enumBS s
-
-
-------------------------------------------------------------------------------
--- | Adds the given lazy 'L.ByteString' to the body of the 'Response' stored in
--- the 'Snap' monad state.
-writeLBS :: L.ByteString -> Snap ()
-writeLBS s = addToOutput $ enumLBS s
-
-
-------------------------------------------------------------------------------
--- | Adds the given strict 'T.Text' to the body of the 'Response' stored in the
--- 'Snap' monad state.
-writeText :: T.Text -> Snap ()
-writeText s = writeBS $ T.encodeUtf8 s
-
-
-------------------------------------------------------------------------------
--- | Adds the given lazy 'LT.Text' to the body of the 'Response' stored in the
--- 'Snap' monad state.
-writeLazyText :: LT.Text -> Snap ()
-writeLazyText s = writeLBS $ LT.encodeUtf8 s
-
-
-------------------------------------------------------------------------------
--- | Sets the output to be the contents of the specified file.
---
--- Calling 'sendFile' will overwrite any output queued to be sent in the
--- 'Response'. If the response body is not modified after the call to
--- 'sendFile', Snap will use the efficient @sendfile()@ system call on
--- platforms that support it.
---
--- If the response body is modified (using 'modifyResponseBody'), the file will
--- be read using @mmap()@.
-sendFile :: FilePath -> Snap ()
-sendFile f = modifyResponse $ \r -> r { rspBody = SendFile f }
-
-
-------------------------------------------------------------------------------
--- | Runs a 'Snap' action with a locally-modified 'Request' state
--- object. The 'Request' object in the Snap monad state after the call
--- to localRequest will be unchanged.
-localRequest :: (Request -> Request) -> Snap a -> Snap a
-localRequest f m = do
-    req <- getRequest
-
-    runAct req <|> (putRequest req >> pass)
-
-  where
-    runAct req = do
-        modifyRequest f
-        result <- m
-        putRequest req
-        return result
-{-# INLINE localRequest #-}
-
-
-------------------------------------------------------------------------------
--- | Fetches the 'Request' from state and hands it to the given action.
-withRequest :: (Request -> Snap a) -> Snap a
-withRequest = (getRequest >>=)
-{-# INLINE withRequest #-}
-
-
-------------------------------------------------------------------------------
--- | Fetches the 'Response' from state and hands it to the given action.
-withResponse :: (Response -> Snap a) -> Snap a
-withResponse = (getResponse >>=)
-{-# INLINE withResponse #-}
-
-
-------------------------------------------------------------------------------
--- | This exception is thrown if the handler you supply to 'runSnap' fails.
-data NoHandlerException = NoHandlerException
-   deriving (Eq, Typeable)
-
-
-------------------------------------------------------------------------------
-instance Show NoHandlerException where
-    show NoHandlerException = "No handler for request"
-
-
-------------------------------------------------------------------------------
-instance Exception NoHandlerException
-
-
-------------------------------------------------------------------------------
--- | Runs a 'Snap' monad action in the 'Iteratee IO' monad.
-runSnap :: Snap a
-        -> (ByteString -> IO ())
-        -> Request
-        -> Iteratee IO (Request,Response)
-runSnap (Snap m) logerr req = do
-    (r, ss') <- runStateT m ss
-
-    e <- maybe (return $ Left fourohfour)
-               return
-               r
-
-    -- is this a case of early termination?
-    let resp = case e of 
-                 Left x  -> x
-                 Right _ -> _snapResponse ss'
-
-    return (_snapRequest ss', resp)
-
-  where
-    fourohfour = setContentLength 3 $
-                 setResponseStatus 404 "Not Found" $
-                 modifyResponseBody (>. enumBS "404") $
-                 emptyResponse
-
-    dresp = emptyResponse { rspHttpVersion = rqVersion req }
-
-    ss = SnapState req dresp logerr
-{-# INLINE runSnap #-}
-
-
-------------------------------------------------------------------------------
-evalSnap :: Snap a
-         -> (ByteString -> IO ())
-         -> Request
-         -> Iteratee IO a
-evalSnap (Snap m) logerr req = do
-    (r, _) <- runStateT m ss
-
-    e <- maybe (liftIO $ throwIO NoHandlerException)
-               return
-               r
-
-    -- is this a case of early termination?
-    case e of 
-      Left _  -> liftIO $ throwIO $ ErrorCall "no value"
-      Right x -> return x
-  where
-    dresp = emptyResponse { rspHttpVersion = rqVersion req }
-    ss = SnapState req dresp logerr
-{-# INLINE evalSnap #-}
-
-
-
-------------------------------------------------------------------------------
--- | See 'rqParam'. Looks up a value for the given named parameter in the
--- 'Request'. If more than one value was entered for the given parameter name,
--- 'getParam' gloms the values together with:
---
--- @    'S.intercalate' \" \"@
---
-getParam :: ByteString          -- ^ parameter name to look up
-         -> Snap (Maybe ByteString)
-getParam k = do
-    rq <- getRequest
-    return $ liftM (S.intercalate " ") $ rqParam k rq
-
-
-
- diff --git a/static/docs/0.2.1/snap-core/src/Snap-Iteratee.html b/static/docs/0.2.1/snap-core/src/Snap-Iteratee.html deleted file mode 100644 index 0aecc98..0000000 --- a/static/docs/0.2.1/snap-core/src/Snap-Iteratee.html +++ /dev/null @@ -1,267 +0,0 @@ - - - - -src/Snap/Iteratee.hs - - - -
{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE TypeSynonymInstances #-}
-
--- | Snap Framework type aliases and utilities for iteratees. Note that as a
--- convenience, this module also exports everything from @Data.Iteratee@ in the
--- @iteratee@ library.
---
--- /WARNING/: Note that all of these types are scheduled to change in the
--- @darcs@ head version of the @iteratee@ library; John Lato et al. are working
--- on a much improved iteratee formulation.
-
-module Snap.Iteratee
-  ( -- * Convenience aliases around types from @Data.Iteratee@
-    Stream
-  , IterV
-  , Iteratee
-  , Enumerator
-
-    -- * Re-export types and functions from @Data.Iteratee@
-  , module Data.Iteratee
-
-    -- * Helper functions
-
-    -- ** Enumerators
-  , enumBS
-  , enumLBS
-  , enumFile
-
-    -- ** Conversion to/from 'WrappedByteString'
-  , fromWrap
-  , toWrap
-
-    -- ** Iteratee utilities
-  , takeExactly
-  , takeNoMoreThan
-  , countBytes
-  , bufferIteratee
-  ) where
-
-------------------------------------------------------------------------------
-import           Control.Exception (SomeException)
-import           Control.Monad
-import           Control.Monad.CatchIO
-import           Data.ByteString (ByteString)
-import qualified Data.ByteString as S
-import qualified Data.ByteString.Lazy as L
-import           Data.Iteratee
-import qualified Data.Iteratee.Base.StreamChunk as SC
-import           Data.Iteratee.WrappedByteString
-import           Data.Monoid (mappend)
-import           Data.Word (Word8)
-import           Prelude hiding (catch,drop)
-import           System.IO.Posix.MMap
-import qualified Data.DList as D
-------------------------------------------------------------------------------
-
-type Stream         = StreamG WrappedByteString Word8
-type IterV      m   = IterGV WrappedByteString Word8 m
-type Iteratee   m   = IterateeG WrappedByteString Word8 m
-type Enumerator m a = Iteratee m a -> m (Iteratee m a)
-
-
-------------------------------------------------------------------------------
-instance (Functor m, MonadCatchIO m) =>
-         MonadCatchIO (IterateeG s el m) where
-    --catch  :: Exception  e => m a -> (e -> m a) -> m a
-    catch m handler = IterateeG $ \str -> do
-        ee <- try $ runIter m str
-        case ee of 
-          (Left e)  -> runIter (handler e) str
-          (Right v) -> return v
-
-    --block :: m a -> m a        
-    block m = IterateeG $ \str -> block $ runIter m str
-    unblock m = IterateeG $ \str -> unblock $ runIter m str
-
-
-------------------------------------------------------------------------------
--- | Wraps an 'Iteratee', counting the number of bytes consumed by it.
-countBytes :: (Monad m) => Iteratee m a -> Iteratee m (a, Int)
-countBytes = go 0
-  where
-    go !n iter = IterateeG $ f n iter
-
-    f !n !iter ch@(Chunk ws) = do
-        iterv <- runIter iter ch
-        case iterv of
-          Done x rest -> let !n' = n + m - len rest
-                         in return $! Done (x, n') rest
-          Cont i err  -> return $ Cont ((go $! n + m) i) err
-      where
-        m = S.length $ unWrap ws
-
-        len (EOF _) = 0
-        len (Chunk s) = S.length $ unWrap s
-
-    f !n !iter stream = do
-        iterv <- runIter iter stream
-        case iterv of
-          Done x rest -> return $ Done (x, n) rest
-          Cont i err  -> return $ Cont (go n i) err
-
-
-------------------------------------------------------------------------------
--- | Buffers an iteratee.
---
--- Our enumerators produce a lot of little strings; rather than spending all
--- our time doing kernel context switches for 4-byte write() calls, we buffer
--- the iteratee to send 2KB at a time.
-bufferIteratee :: (Monad m) => Enumerator m a
-bufferIteratee = return . go (D.empty,0)
-  where
-    blocksize = 2048
-
-    --go :: (DList ByteString, Int) -> Iteratee m a -> Iteratee m a
-    go (!dl,!n) iter = IterateeG $! f (dl,n) iter
-
-    --f :: (DList ByteString, Int) -> Iteratee m a -> Stream -> m (IterV m a)
-    f _      !iter ch@(EOF (Just _)) = runIter iter ch
-    f (!dl,_) !iter ch@(EOF Nothing) = do
-        iterv <- runIter iter $ Chunk big
-        case iterv of
-          Done x rest     -> return $ Done x rest
-          Cont i (Just e) -> return $ Cont i (Just e)
-          Cont i Nothing  -> runIter i ch
-      where
-        big = toWrap $ L.fromChunks [S.concat $ D.toList dl]
-        
-    f (!dl,!n) iter (Chunk ws) =
-        if n' > blocksize
-           then do
-               iterv <- runIter iter (Chunk big)
-               case iterv of
-                  Done x rest     -> return $ Done x rest
-                  Cont i (Just e) -> return $ Cont i (Just e)
-                  Cont i Nothing  -> return $ Cont (go (D.empty,0) i) Nothing
-           else return $ Cont (go (dl',n') iter) Nothing
-      where
-        s   = S.concat $ L.toChunks $ fromWrap ws
-        m   = S.length s
-        n'  = n+m
-        dl' = D.snoc dl s
-        big = toWrap $ L.fromChunks [S.concat $ D.toList dl']
-        
-
-------------------------------------------------------------------------------
--- | Enumerates a strict bytestring.
-enumBS :: (Monad m) => ByteString -> Enumerator m a
-enumBS bs = enumPure1Chunk $ WrapBS bs
-{-# INLINE enumBS #-}
-
-
-------------------------------------------------------------------------------
--- | Enumerates a lazy bytestring.
-enumLBS :: (Monad m) => L.ByteString -> Enumerator m a
-enumLBS lbs iter = foldM k iter enums
-  where
-    enums = map (enumPure1Chunk . WrapBS) $ L.toChunks lbs
-    k i e = e i
-
-
-------------------------------------------------------------------------------
--- | Converts a lazy bytestring to a wrapped bytestring.
-toWrap :: L.ByteString -> WrappedByteString Word8
-toWrap = WrapBS . S.concat . L.toChunks
-{-# INLINE toWrap #-}
-
-
-------------------------------------------------------------------------------
--- | Converts a wrapped bytestring to a lazy bytestring.
-fromWrap :: WrappedByteString Word8 -> L.ByteString
-fromWrap = L.fromChunks . (:[]) . unWrap
-{-# INLINE fromWrap #-}
-
-
-------------------------------------------------------------------------------
--- | Reads n elements from a stream and applies the given iteratee to
--- the stream of the read elements. Reads exactly n elements, and if
--- the stream is short propagates an error.
-takeExactly :: (SC.StreamChunk s el, Monad m) =>
-               Int ->
-               EnumeratorN s el s el m a
-takeExactly 0 iter = return iter
-takeExactly n' iter =
-    if n' < 0
-      then takeExactly 0 iter
-      else IterateeG (step n')
-  where
-  step n chk@(Chunk str)
-    | SC.null str = return $ Cont (takeExactly n iter) Nothing
-    | SC.length str < n = liftM (flip Cont Nothing) inner
-      where inner = liftM (check (n - SC.length str)) (runIter iter chk)
-  step n (Chunk str) = done (Chunk s1) (Chunk s2)
-    where (s1, s2) = SC.splitAt n str
-  step _n (EOF (Just e))    = return $ Cont undefined (Just e)
-  step _n (EOF Nothing)     = return $ Cont undefined (Just (Err "short write"))
-  check n (Done x _)        = drop n >> return (return x)
-  check n (Cont x Nothing)  = takeExactly n x
-  check n (Cont _ (Just e)) = drop n >> throwErr e
-  done s1 s2 = liftM (flip Done s2) (runIter iter s1 >>= checkIfDone return)
-
-
-------------------------------------------------------------------------------
--- | Reads up to n elements from a stream and applies the given iteratee to the
--- stream of the read elements. If more than n elements are read, propagates an
--- error.
-takeNoMoreThan :: (SC.StreamChunk s el, Monad m) =>
-                  Int ->
-                  EnumeratorN s el s el m a
-takeNoMoreThan n' iter =
-    if n' < 0
-      then takeNoMoreThan 0 iter
-      else IterateeG (step n')
-  where
-    step n chk@(Chunk str)
-      | SC.null str = return $ Cont (takeNoMoreThan n iter) Nothing
-      | SC.length str < n = liftM (flip Cont Nothing) inner
-      | otherwise = done (Chunk s1) (Chunk s2)
-          where inner    = liftM (check (n - SC.length str)) (runIter iter chk)
-                (s1, s2) = SC.splitAt n str
-
-    step _n (EOF (Just e))    = return $ Cont undefined (Just e)
-    step _n chk@(EOF Nothing) = do
-        v  <- runIter iter chk
-
-        case v of
-          (Done x s)        -> return $ Done (return x) s
-          (Cont _ (Just e)) -> return $ Cont undefined (Just e)
-          (Cont _ Nothing)  -> return $ Cont (throwErr $ Err "premature EOF") Nothing
-
-    check _ v@(Done _ _)      = return $ liftI v
-    check n (Cont x Nothing)  = takeNoMoreThan n x
-    check _ (Cont _ (Just e)) = throwErr e
-
-    done _ (EOF _) = error "impossible"
-    done s1 s2@(Chunk s2') = do
-        v <- runIter iter s1
-        case v of
-          (Done x s')       -> return $ Done (return x) (s' `mappend` s2)
-          (Cont _ (Just e)) -> return $ Cont undefined (Just e)
-          (Cont i Nothing)  ->
-              if SC.null s2'
-                then return $ Cont (takeNoMoreThan 0 i) Nothing
-                else return $ Cont undefined (Just $ Err "too many bytes")
-
-
-------------------------------------------------------------------------------
-enumFile :: FilePath -> Iteratee IO a -> IO (Iteratee IO a)
-enumFile fp iter = do
-    es <- (try $
-           liftM WrapBS $
-           unsafeMMapFile fp) :: IO (Either SomeException (WrappedByteString Word8))
-    
-    case es of
-      (Left e)  -> return $ throwErr $ Err $ "IO error" ++ show e
-      (Right s) -> liftM liftI $ runIter iter $ Chunk s
-
- diff --git a/static/docs/0.2.1/snap-core/src/Snap-Types.html b/static/docs/0.2.1/snap-core/src/Snap-Types.html deleted file mode 100644 index ecbe5f0..0000000 --- a/static/docs/0.2.1/snap-core/src/Snap-Types.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - -src/Snap/Types.hs - - - -
{-|
-
-This module contains the core type definitions, class instances, and functions
-for HTTP as well as the 'Snap' monad, which is used for web handlers.
-
--}
-module Snap.Types
-  ( 
-    -- * The Snap Monad
-    Snap
-  , runSnap
-  , NoHandlerException(..)
-
-    -- ** Functions for control flow and early termination
-  , finishWith
-  , pass
-
-    -- ** Routing
-  , method
-  , path
-  , dir
-  , ifTop
-  , route
-  , routeLocal
-
-    -- ** Access to state
-  , getRequest
-  , getResponse
-  , putRequest
-  , putResponse
-  , modifyRequest
-  , modifyResponse
-  , localRequest
-  , withRequest
-  , withResponse
-
-    -- ** Logging
-  , logError
-
-    -- ** Grabbing request bodies
-  , runRequestBody
-  , getRequestBody
-  , unsafeDetachRequestBody
-    -- * HTTP Datatypes and Functions
-    -- $httpDoc
-    --
-  , Request
-  , Response
-  , Headers
-  , HasHeaders(..)
-  , Params
-  , Method(..)
-  , Cookie(..)
-  , HttpVersion
-
-    -- ** Headers
-  , addHeader
-  , setHeader
-  , getHeader
-
-    -- ** Requests
-  , rqServerName
-  , rqServerPort
-  , rqRemoteAddr
-  , rqRemotePort
-  , rqLocalAddr
-  , rqLocalHostname
-  , rqIsSecure
-  , rqContentLength
-  , rqMethod
-  , rqVersion
-  , rqCookies
-  , rqPathInfo
-  , rqContextPath
-  , rqURI
-  , rqQueryString
-  , rqParams
-  , rqParam
-  , getParam
-  , rqModifyParams
-  , rqSetParam
-
-    -- ** Responses
-  , emptyResponse
-  , setResponseStatus
-  , rspStatus
-  , rspStatusReason
-  , setContentType
-  , addCookie
-  , setContentLength
-  , clearContentLength
-
-    -- *** Response I/O
-  , setResponseBody
-  , modifyResponseBody
-  , addToOutput
-  , writeBS
-  , writeLazyText
-  , writeText
-  , writeLBS
-  , sendFile
-
-    -- * Iteratee
-  , Enumerator
-
-    -- * HTTP utilities
-  , formatHttpTime
-  , parseHttpTime 
-  , urlEncode
-  , urlDecode
-  ) where
-
-------------------------------------------------------------------------------
-import           Snap.Internal.Http.Types
-import           Snap.Internal.Routing
-import           Snap.Internal.Types
-------------------------------------------------------------------------------
-
--- $httpDoc
--- HTTP-related datatypes: 'Request', 'Response', 'Cookie', etc.
-
- diff --git a/static/docs/0.2.1/snap-core/src/Snap-Util-FileServe.html b/static/docs/0.2.1/snap-core/src/Snap-Util-FileServe.html deleted file mode 100644 index 38c9a3f..0000000 --- a/static/docs/0.2.1/snap-core/src/Snap-Util-FileServe.html +++ /dev/null @@ -1,273 +0,0 @@ - - - - -src/Snap/Util/FileServe.hs - - - -
{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
--- | Contains web handlers to serve files from a directory.
-module Snap.Util.FileServe
-(
-  getSafePath
-, fileServe
-, fileServe'
-, fileServeSingle
-, fileServeSingle'
-, defaultMimeTypes
-, MimeMap
-) where
-
-------------------------------------------------------------------------------
-import           Control.Monad
-import           Control.Monad.Trans
-import qualified Data.ByteString.Char8 as S
-import           Data.ByteString.Char8 (ByteString)
-import           Data.Map (Map)
-import qualified Data.Map as Map
-import           Data.Maybe (fromMaybe)
-import           System.Directory
-import           System.FilePath
-import           System.Posix.Files
-
-------------------------------------------------------------------------------
-import           Snap.Types
-
-
-------------------------------------------------------------------------------
--- | A type alias for MIME type 
-type MimeMap = Map FilePath ByteString
-
-
-------------------------------------------------------------------------------
--- | The default set of mime type mappings we use when serving files. Its
--- value:
---
--- > Map.fromList [
--- >   ( ".asc"     , "text/plain"                        ),
--- >   ( ".asf"     , "video/x-ms-asf"                    ),
--- >   ( ".asx"     , "video/x-ms-asf"                    ),
--- >   ( ".avi"     , "video/x-msvideo"                   ),
--- >   ( ".bz2"     , "application/x-bzip"                ),
--- >   ( ".c"       , "text/plain"                        ),
--- >   ( ".class"   , "application/octet-stream"          ),
--- >   ( ".conf"    , "text/plain"                        ),
--- >   ( ".cpp"     , "text/plain"                        ),
--- >   ( ".css"     , "text/css"                          ),
--- >   ( ".cxx"     , "text/plain"                        ),
--- >   ( ".dtd"     , "text/xml"                          ),
--- >   ( ".dvi"     , "application/x-dvi"                 ),
--- >   ( ".gif"     , "image/gif"                         ),
--- >   ( ".gz"      , "application/x-gzip"                ),
--- >   ( ".hs"      , "text/plain"                        ),
--- >   ( ".htm"     , "text/html"                         ),
--- >   ( ".html"    , "text/html"                         ),
--- >   ( ".jar"     , "application/x-java-archive"        ),
--- >   ( ".jpeg"    , "image/jpeg"                        ),
--- >   ( ".jpg"     , "image/jpeg"                        ),
--- >   ( ".js"      , "text/javascript"                   ),
--- >   ( ".log"     , "text/plain"                        ),
--- >   ( ".m3u"     , "audio/x-mpegurl"                   ),
--- >   ( ".mov"     , "video/quicktime"                   ),
--- >   ( ".mp3"     , "audio/mpeg"                        ),
--- >   ( ".mpeg"    , "video/mpeg"                        ),
--- >   ( ".mpg"     , "video/mpeg"                        ),
--- >   ( ".ogg"     , "application/ogg"                   ),
--- >   ( ".pac"     , "application/x-ns-proxy-autoconfig" ),
--- >   ( ".pdf"     , "application/pdf"                   ),
--- >   ( ".png"     , "image/png"                         ),
--- >   ( ".ps"      , "application/postscript"            ),
--- >   ( ".qt"      , "video/quicktime"                   ),
--- >   ( ".sig"     , "application/pgp-signature"         ),
--- >   ( ".spl"     , "application/futuresplash"          ),
--- >   ( ".swf"     , "application/x-shockwave-flash"     ),
--- >   ( ".tar"     , "application/x-tar"                 ),
--- >   ( ".tar.bz2" , "application/x-bzip-compressed-tar" ),
--- >   ( ".tar.gz"  , "application/x-tgz"                 ),
--- >   ( ".tbz"     , "application/x-bzip-compressed-tar" ),
--- >   ( ".text"    , "text/plain"                        ),
--- >   ( ".tgz"     , "application/x-tgz"                 ),
--- >   ( ".torrent" , "application/x-bittorrent"          ),
--- >   ( ".txt"     , "text/plain"                        ),
--- >   ( ".wav"     , "audio/x-wav"                       ),
--- >   ( ".wax"     , "audio/x-ms-wax"                    ),
--- >   ( ".wma"     , "audio/x-ms-wma"                    ),
--- >   ( ".wmv"     , "video/x-ms-wmv"                    ),
--- >   ( ".xbm"     , "image/x-xbitmap"                   ),
--- >   ( ".xml"     , "text/xml"                          ),
--- >   ( ".xpm"     , "image/x-xpixmap"                   ),
--- >   ( ".xwd"     , "image/x-xwindowdump"               ),
--- >   ( ".zip"     , "application/zip"                   ) ]
---
-defaultMimeTypes :: MimeMap
-defaultMimeTypes = Map.fromList [
-  ( ".asc"     , "text/plain"                        ),
-  ( ".asf"     , "video/x-ms-asf"                    ),
-  ( ".asx"     , "video/x-ms-asf"                    ),
-  ( ".avi"     , "video/x-msvideo"                   ),
-  ( ".bz2"     , "application/x-bzip"                ),
-  ( ".c"       , "text/plain"                        ),
-  ( ".class"   , "application/octet-stream"          ),
-  ( ".conf"    , "text/plain"                        ),
-  ( ".cpp"     , "text/plain"                        ),
-  ( ".css"     , "text/css"                          ),
-  ( ".cxx"     , "text/plain"                        ),
-  ( ".dtd"     , "text/xml"                          ),
-  ( ".dvi"     , "application/x-dvi"                 ),
-  ( ".gif"     , "image/gif"                         ),
-  ( ".gz"      , "application/x-gzip"                ),
-  ( ".hs"      , "text/plain"                        ),
-  ( ".htm"     , "text/html"                         ),
-  ( ".html"    , "text/html"                         ),
-  ( ".jar"     , "application/x-java-archive"        ),
-  ( ".jpeg"    , "image/jpeg"                        ),
-  ( ".jpg"     , "image/jpeg"                        ),
-  ( ".js"      , "text/javascript"                   ),
-  ( ".log"     , "text/plain"                        ),
-  ( ".m3u"     , "audio/x-mpegurl"                   ),
-  ( ".mov"     , "video/quicktime"                   ),
-  ( ".mp3"     , "audio/mpeg"                        ),
-  ( ".mpeg"    , "video/mpeg"                        ),
-  ( ".mpg"     , "video/mpeg"                        ),
-  ( ".ogg"     , "application/ogg"                   ),
-  ( ".pac"     , "application/x-ns-proxy-autoconfig" ),
-  ( ".pdf"     , "application/pdf"                   ),
-  ( ".png"     , "image/png"                         ),
-  ( ".ps"      , "application/postscript"            ),
-  ( ".qt"      , "video/quicktime"                   ),
-  ( ".sig"     , "application/pgp-signature"         ),
-  ( ".spl"     , "application/futuresplash"          ),
-  ( ".swf"     , "application/x-shockwave-flash"     ),
-  ( ".tar"     , "application/x-tar"                 ),
-  ( ".tar.bz2" , "application/x-bzip-compressed-tar" ),
-  ( ".tar.gz"  , "application/x-tgz"                 ),
-  ( ".tbz"     , "application/x-bzip-compressed-tar" ),
-  ( ".text"    , "text/plain"                        ),
-  ( ".tgz"     , "application/x-tgz"                 ),
-  ( ".torrent" , "application/x-bittorrent"          ),
-  ( ".ttf"     , "application/x-font-truetype"       ),
-  ( ".txt"     , "text/plain"                        ),
-  ( ".wav"     , "audio/x-wav"                       ),
-  ( ".wax"     , "audio/x-ms-wax"                    ),
-  ( ".wma"     , "audio/x-ms-wma"                    ),
-  ( ".wmv"     , "video/x-ms-wmv"                    ),
-  ( ".xbm"     , "image/x-xbitmap"                   ),
-  ( ".xml"     , "text/xml"                          ),
-  ( ".xpm"     , "image/x-xpixmap"                   ),
-  ( ".xwd"     , "image/x-xwindowdump"               ),
-  ( ".zip"     , "application/zip"                   ) ]
-
-------------------------------------------------------------------------------
--- | Gets a path from the 'Request' using 'rqPathInfo' and makes sure it is
--- safe to use for opening files.  A path is safe if it is a relative path
--- and has no ".." elements to escape the intended directory structure.
-getSafePath :: Snap FilePath
-getSafePath = do
-    req <- getRequest
-    let p = S.unpack $ rqPathInfo req
-
-    -- check that we don't have any sneaky .. paths
-    let dirs = splitDirectories p
-    when (elem ".." dirs) pass
-    return p
-
-
-------------------------------------------------------------------------------
--- | Serves files out of the given directory. The relative path given in
--- 'rqPathInfo' is searched for the given file, and the file is served with the
--- appropriate mime type if it is found. Absolute paths and \"@..@\" are prohibited
--- to prevent files from being served from outside the sandbox.
---
--- Uses 'defaultMimeTypes' to determine the @Content-Type@ based on the file's
--- extension.
-fileServe :: FilePath  -- ^ root directory
-          -> Snap ()
-fileServe = fileServe' defaultMimeTypes
-{-# INLINE fileServe #-}
-
-
-------------------------------------------------------------------------------
--- | Same as 'fileServe', with control over the MIME mapping used.
-fileServe' :: MimeMap           -- ^ MIME type mapping
-           -> FilePath          -- ^ root directory
-           -> Snap ()
-fileServe' mm root = do
-    sp <- getSafePath
-    let fp   = root </> sp
-
-    -- check that the file exists
-    liftIO (doesFileExist fp) >>= flip unless pass
-
-    let fn   = takeFileName fp
-    let mime = fileType mm fn
-    fileServeSingle' mime fp
-{-# INLINE fileServe' #-}
-
-
-------------------------------------------------------------------------------
--- | Serves a single file specified by a full or relative path.  The
--- path restrictions on fileServe don't apply to this function since
--- the path is not being supplied by the user.
-fileServeSingle :: FilePath          -- ^ path to file
-                -> Snap ()
-fileServeSingle fp =
-    fileServeSingle' (fileType defaultMimeTypes (takeFileName fp)) fp
-{-# INLINE fileServeSingle #-}
-
-
-------------------------------------------------------------------------------
--- | Same as 'fileServeSingle', with control over the MIME mapping used.
-fileServeSingle' :: ByteString        -- ^ MIME type mapping
-                 -> FilePath          -- ^ path to file
-                 -> Snap ()
-fileServeSingle' mime fp = do
-    req <- getRequest
-    
-    let mbH = getHeader "if-modified-since" req
-    mbIfModified <- liftIO $ case mbH of
-                               Nothing  -> return Nothing
-                               (Just s) -> liftM Just $ parseHttpTime s
-
-    -- check modification time and bug out early if the file is not modified.
-    filestat <- liftIO $ getFileStatus fp
-    let mt = modificationTime filestat
-    maybe (return ()) (chkModificationTime mt) mbIfModified
-
-    let sz = fromEnum $ fileSize filestat
-    lm <- liftIO $ formatHttpTime mt
-
-    modifyResponse $ setHeader "Last-Modified" lm
-                   . setContentType mime
-                   . setContentLength sz
-    sendFile fp
-
-  where
-    --------------------------------------------------------------------------
-    chkModificationTime mt lt = when (mt <= lt) notModified
-
-    --------------------------------------------------------------------------
-    notModified = finishWith $
-                  setResponseStatus 304 "Not Modified" emptyResponse
-
-
-------------------------------------------------------------------------------
-fileType :: MimeMap -> FilePath -> ByteString
-fileType mm f =
-    if null ext
-      then defaultMimeType
-      else fromMaybe (fileType mm (drop 1 ext))
-                     mbe
-
-  where
-    ext             = takeExtensions f
-    mbe             = Map.lookup ext mm
-
-
-------------------------------------------------------------------------------
-defaultMimeType :: ByteString
-defaultMimeType = "application/octet-stream"
-
- diff --git a/static/docs/0.2.1/snap-core/src/Snap-Util-GZip.html b/static/docs/0.2.1/snap-core/src/Snap-Util-GZip.html deleted file mode 100644 index 6119f1d..0000000 --- a/static/docs/0.2.1/snap-core/src/Snap-Util-GZip.html +++ /dev/null @@ -1,341 +0,0 @@ - - - - -src/Snap/Util/GZip.hs - - - -
{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE ExistentialQuantification #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module Snap.Util.GZip
-( withCompression
-, withCompression' ) where
-
-import qualified Codec.Compression.GZip as GZip
-import qualified Codec.Compression.Zlib as Zlib
-import           Control.Concurrent
-import           Control.Applicative hiding (many)
-import           Control.Exception
-import           Control.Monad
-import           Control.Monad.Trans
-import           Data.Attoparsec.Char8 hiding (Done)
-import qualified Data.Attoparsec.Char8 as Atto
-import qualified Data.ByteString.Lazy.Char8 as L
-import           Data.ByteString.Char8 (ByteString)
-import           Data.Iteratee.WrappedByteString
-import           Data.Maybe
-import qualified Data.Set as Set
-import           Data.Set (Set)
-import           Data.Typeable
-import           Prelude hiding (catch, takeWhile)
-
-------------------------------------------------------------------------------
-import           Snap.Internal.Debug
-import           Snap.Iteratee hiding (Enumerator)
-import           Snap.Types
-
-
-------------------------------------------------------------------------------
--- | Runs a 'Snap' web handler with compression if available.
---
--- If the client has indicated support for @gzip@ or @compress@ in its
--- @Accept-Encoding@ header, and the @Content-Type@ in the response is one of
--- the following types:
---
---   * @application/x-javascript@
---
---   * @text/css@
---
---   * @text/html@
---
---   * @text/javascript@
---
---   * @text/plain@
---
---   * @text/xml@
---
---   * @application/x-font-truetype@
---
--- Then the given handler's output stream will be compressed,
--- @Content-Encoding@ will be set in the output headers, and the
--- @Content-Length@ will be cleared if it was set. (We can't process the stream
--- in O(1) space if the length is known beforehand.)
---
--- The wrapped handler will be run to completion, and then the 'Response'
--- that's contained within the 'Snap' monad state will be passed to
--- 'finishWith' to prevent further processing.
---
-withCompression :: Snap a   -- ^ the web handler to run
-                -> Snap ()
-withCompression = withCompression' compressibleMimeTypes
-
-
-------------------------------------------------------------------------------
--- | The same as 'withCompression', with control over which MIME types to
--- compress.
-withCompression' :: Set ByteString
-                    -- ^ set of compressible MIME types
-                 -> Snap a
-                    -- ^ the web handler to run
-                 -> Snap ()
-withCompression' mimeTable action = do
-    _    <- action
-    resp <- getResponse
-
-    -- If a content-encoding is already set, do nothing. This prevents
-    -- "withCompression $ withCompression m" from ruining your day.
-    if isJust $ getHeader "Content-Encoding" resp
-       then return ()
-       else do
-           let mbCt = getHeader "Content-Type" resp
-
-           debug $ "withCompression', content-type is " ++ show mbCt
-
-           case mbCt of
-             (Just ct) -> if Set.member ct mimeTable
-                             then chkAcceptEncoding
-                             else return ()
-             _         -> return ()
-
-
-    getResponse >>= finishWith
-
-  where
-    chkAcceptEncoding :: Snap ()
-    chkAcceptEncoding = do
-        req <- getRequest
-        debug $ "checking accept-encoding"
-        let mbAcc = getHeader "Accept-Encoding" req
-        debug $ "accept-encoding is " ++ show mbAcc
-        let s = fromMaybe "" mbAcc
-
-        types <- liftIO $ parseAcceptEncoding s
-
-        chooseType types
-
-
-    chooseType []               = return ()
-    chooseType ("gzip":_)       = gzipCompression
-    chooseType ("compress":_)   = compressCompression
-    chooseType ("x-gzip":_)     = gzipCompression
-    chooseType ("x-compress":_) = compressCompression
-    chooseType (_:xs)           = chooseType xs
-
-
-------------------------------------------------------------------------------
--- private following
-------------------------------------------------------------------------------
-
-
-------------------------------------------------------------------------------
-compressibleMimeTypes :: Set ByteString
-compressibleMimeTypes = Set.fromList [ "application/x-font-truetype"
-                                     , "application/x-javascript"
-                                     , "text/css"
-                                     , "text/html"
-                                     , "text/javascript"
-                                     , "text/plain"
-                                     , "text/xml" ]
-
-
-
-
-------------------------------------------------------------------------------
-gzipCompression :: Snap ()
-gzipCompression = modifyResponse f
-  where
-    f = setHeader "Content-Encoding" "gzip" .
-        clearContentLength .
-        modifyResponseBody gcompress
-
-
-------------------------------------------------------------------------------
-compressCompression :: Snap ()
-compressCompression = modifyResponse f
-  where
-    f = setHeader "Content-Encoding" "compress" .
-        clearContentLength .
-        modifyResponseBody ccompress
-
-
-------------------------------------------------------------------------------
-gcompress :: forall a . Enumerator a -> Enumerator a
-gcompress = compressEnumerator GZip.compress
-
-
-------------------------------------------------------------------------------
-ccompress :: forall a . Enumerator a -> Enumerator a
-ccompress = compressEnumerator Zlib.compress
-
-
-------------------------------------------------------------------------------
-compressEnumerator :: forall a .
-                      (L.ByteString -> L.ByteString)
-                   -> Enumerator a
-                   -> Enumerator a
-compressEnumerator compFunc enum iteratee = do
-    writeEnd <- newChan
-    readEnd  <- newChan
-    tid      <- forkIO $ threadProc readEnd writeEnd
-
-    enum (IterateeG $ f readEnd writeEnd tid iteratee)
-
-  where
-    --------------------------------------------------------------------------
-    streamFinished :: Stream -> Bool
-    streamFinished (EOF _)   = True
-    streamFinished (Chunk _) = False
-
-
-    --------------------------------------------------------------------------
-    consumeSomeOutput :: Chan Stream
-                      -> Iteratee IO a
-                      -> IO (Iteratee IO a)
-    consumeSomeOutput writeEnd iter = do
-        e <- isEmptyChan writeEnd
-        if e
-          then return iter
-          else do
-            ch <- readChan writeEnd
-
-            iter' <- liftM liftI $ runIter iter ch
-            if (streamFinished ch)
-               then return iter'
-               else consumeSomeOutput writeEnd iter'
-
-
-    --------------------------------------------------------------------------
-    consumeRest :: Chan Stream
-                -> Iteratee IO a
-                -> IO (IterV IO a)
-    consumeRest writeEnd iter = do
-        ch <- readChan writeEnd
-
-        iv <- runIter iter ch
-        if (streamFinished ch)
-           then return iv
-           else consumeRest writeEnd $ liftI iv
-
-
-    --------------------------------------------------------------------------
-    f readEnd writeEnd tid i (EOF Nothing) = do
-        writeChan readEnd Nothing
-        x <- consumeRest writeEnd i
-        killThread tid
-        return x
-
-    f _ _ tid i ch@(EOF (Just _)) = do
-        x <- runIter i ch
-        killThread tid
-        return x
-
-    f readEnd writeEnd tid i (Chunk s') = do
-        let s = unWrap s'
-        writeChan readEnd $ Just s
-        i' <- consumeSomeOutput writeEnd i
-        return $ Cont (IterateeG $ f readEnd writeEnd tid i') Nothing
-
-
-    --------------------------------------------------------------------------
-    threadProc :: Chan (Maybe ByteString)
-               -> Chan Stream
-               -> IO ()
-    threadProc readEnd writeEnd = do
-        stream <- getChanContents readEnd
-        let bs = L.fromChunks $ streamToChunks stream
-
-        let output = L.toChunks $ compFunc bs
-        let runIt = do
-            mapM_ (writeChan writeEnd . toChunk) output
-            writeChan writeEnd $ EOF Nothing
-
-        runIt `catch` \(e::SomeException) ->
-            writeChan writeEnd $ EOF (Just $ Err $ show e)
-
-
-    --------------------------------------------------------------------------
-    streamToChunks []            = []
-    streamToChunks (Nothing:_)   = []
-    streamToChunks ((Just x):xs) = x:(streamToChunks xs)
-
-
-    --------------------------------------------------------------------------
-    toChunk = Chunk . WrapBS
-
-
-------------------------------------------------------------------------------
-fullyParse :: ByteString -> Parser a -> Either String a
-fullyParse s p =
-    case r' of
-      (Fail _ _ e)    -> Left e
-      (Partial _)     -> Left "parse failed"
-      (Atto.Done _ x) -> Right x
-  where
-    r  = parse p s
-    r' = feed r ""
-
-
-------------------------------------------------------------------------------
--- We're not gonna bother with quality values; we'll do gzip or compress in
--- that order.
-acceptParser :: Parser [ByteString]
-acceptParser = do
-    xs <- option [] $ (:[]) <$> encoding
-    ys <- many (char ',' *> encoding)
-    endOfInput
-    return $ xs ++ ys
-  where
-    encoding = skipSpace *> c <* skipSpace
-
-    c = do
-        x <- coding
-        option () qvalue
-        return x
-
-    qvalue = do
-        skipSpace
-        char ';'
-        skipSpace
-        char 'q'
-        skipSpace
-        char '='
-        float
-        return ()
-
-    coding = string "*" <|> takeWhile isCodingChar
-
-    isCodingChar c = isAlpha_ascii c || c == '-'
-
-    float = takeWhile isDigit >>
-            option () (char '.' >> takeWhile isDigit >> pure ())
-
-
-------------------------------------------------------------------------------
-data BadAcceptEncodingException = BadAcceptEncodingException
-   deriving (Typeable)
-
-
-------------------------------------------------------------------------------
-instance Show BadAcceptEncodingException where
-    show BadAcceptEncodingException = "bad 'accept-encoding' header"
-
-
-------------------------------------------------------------------------------
-instance Exception BadAcceptEncodingException
-
-
-------------------------------------------------------------------------------
-parseAcceptEncoding :: ByteString -> IO [ByteString]
-parseAcceptEncoding s =
-    case r of
-      Left _ -> throwIO BadAcceptEncodingException
-      Right x -> return x
-  where
-    r = fullyParse s acceptParser
-
-
- diff --git a/static/docs/0.2.1/snap-core/src/hscolour.css b/static/docs/0.2.1/snap-core/src/hscolour.css deleted file mode 100644 index 150e4d0..0000000 --- a/static/docs/0.2.1/snap-core/src/hscolour.css +++ /dev/null @@ -1,15 +0,0 @@ -body { font-size: 90%; } - -pre, code, body { - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; -} - -.hs-keyglyph, .hs-layout {color: #5200A3;} -.hs-keyword {color: #3465a4; font-weight: bold;} -.hs-comment, .hs-comment a {color: #579; } -.hs-str, .hs-chr {color: #141B24;} -.hs-keyword, .hs-conid, .hs-varid, .hs-conop, .hs-varop, .hs-num, .hs-cpp, .hs-sel, .hs-definition {} diff --git a/static/docs/0.2.1/snap-server/Snap-Http-Server-Config.html b/static/docs/0.2.1/snap-server/Snap-Http-Server-Config.html deleted file mode 100644 index 42ca9f0..0000000 --- a/static/docs/0.2.1/snap-server/Snap-Http-Server-Config.html +++ /dev/null @@ -1,263 +0,0 @@ - - -Snap.Http.Server.Config
 snap-server-0.2.1: A fast, iteratee-based, epoll-enabled web server for the Snap FrameworkContentsIndex
Snap.Http.Server.Config
Documentation
data Config
Constructors
Config
localHostname :: !ByteString
bindAddress :: !ByteString
listenPort :: !Int
accessLog :: !(Maybe FilePath)
errorLog :: !(Maybe FilePath)
show/hide Instances
readConfigFromCmdLineArgs
:: Stringapplication description, e.g. - "Foo applet v0.2" -
-> IO Config
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.1/snap-server/Snap-Http-Server.html b/static/docs/0.2.1/snap-server/Snap-Http-Server.html deleted file mode 100644 index 0a1070b..0000000 --- a/static/docs/0.2.1/snap-server/Snap-Http-Server.html +++ /dev/null @@ -1,231 +0,0 @@ - - -Snap.Http.Server
 snap-server-0.2.1: A fast, iteratee-based, epoll-enabled web server for the Snap FrameworkContentsIndex
Snap.Http.Server
Description
The Snap HTTP server is a high performance, epoll-enabled, iteratee-based - web server library written in Haskell. Together with the snap-core library - upon which it depends, it provides a clean and efficient Haskell programming - interface to the HTTP protocol. -
Synopsis
httpServe :: ByteString -> Int -> ByteString -> Maybe FilePath -> Maybe FilePath -> Snap () -> IO ()
Documentation
httpServe
:: ByteStringbind address, or "*" for all -
-> Intport to bind to -
-> ByteStringlocal hostname (server name) -
-> Maybe FilePathpath to the (optional) access log -
-> Maybe FilePathpath to the (optional) error log -
-> Snap ()handler procedure -
-> IO ()
Starts serving HTTP requests on the given port using the given handler. - This function never returns; to shut down the HTTP server, kill the - controlling thread. -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.1/snap-server/System-FastLogger.html b/static/docs/0.2.1/snap-server/System-FastLogger.html deleted file mode 100644 index 1adb108..0000000 --- a/static/docs/0.2.1/snap-server/System-FastLogger.html +++ /dev/null @@ -1,446 +0,0 @@ - - -System.FastLogger
 snap-server-0.2.1: A fast, iteratee-based, epoll-enabled web server for the Snap FrameworkContentsIndex
System.FastLogger
Synopsis
data Logger
timestampedLogEntry :: ByteString -> IO ByteString
combinedLogEntry :: ByteString -> Maybe ByteString -> ByteString -> Int -> Maybe Int -> Maybe ByteString -> ByteString -> IO ByteString
newLogger :: FilePath -> IO Logger
logMsg :: Logger -> ByteString -> IO ()
stopLogger :: Logger -> IO ()
Documentation
data Logger
Holds the state for a logger. -
timestampedLogEntry :: ByteString -> IO ByteString
Prepares a log message with the time prepended. -
combinedLogEntry
:: ByteStringremote host -
-> Maybe ByteStringremote user -
-> ByteStringrequest line (up to you to ensure - there are no quotes in here) -
-> Intstatus code -
-> Maybe Intnum bytes sent -
-> Maybe ByteStringreferer (up to you to ensure - there are no quotes in here) -
-> ByteStringuser agent (up to you to ensure - there are no quotes in here) -
-> IO ByteString
Prepares a log message in "combined" format. -
newLogger :: FilePath -> IO Logger
Creates a new logger, logging to the given file. If the file argument is - "-", then log to stdout; if it's "stderr" then we log to stderr, - otherwise we log to a regular file in append mode. The file is closed and - re-opened every 15 minutes to facilitate external log rotation. -
logMsg :: Logger -> ByteString -> IO ()
Sends out a log message verbatim with a newline appended. Note: - if you want a fancy log message you'll have to format it yourself - (or use combinedLogEntry). -
stopLogger :: Logger -> IO ()
Kills a logger thread, causing any unwritten contents to be - flushed out to disk -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.1/snap-server/doc-index.html b/static/docs/0.2.1/snap-server/doc-index.html deleted file mode 100644 index 1f8023d..0000000 --- a/static/docs/0.2.1/snap-server/doc-index.html +++ /dev/null @@ -1,168 +0,0 @@ - - -snap-server-0.2.1: A fast, iteratee-based, epoll-enabled web server for the Snap Framework (Index)
 snap-server-0.2.1: A fast, iteratee-based, epoll-enabled web server for the Snap FrameworkContentsIndex
accessLog
bindAddress
combinedLogEntry
Config
1 (Type/Class)
2 (Data Constructor)
errorLog
httpServe
listenPort
localHostname
Logger
logMsg
newLogger
readConfigFromCmdLineArgs
stopLogger
timestampedLogEntry
diff --git a/static/docs/0.2.1/snap-server/fonts/DroidSerif-Bold.eot b/static/docs/0.2.1/snap-server/fonts/DroidSerif-Bold.eot deleted file mode 100644 index 01b9e1f..0000000 Binary files a/static/docs/0.2.1/snap-server/fonts/DroidSerif-Bold.eot and /dev/null differ diff --git a/static/docs/0.2.1/snap-server/fonts/DroidSerif-Bold.svg b/static/docs/0.2.1/snap-server/fonts/DroidSerif-Bold.svg deleted file mode 100644 index 1f7f2d2..0000000 --- a/static/docs/0.2.1/snap-server/fonts/DroidSerif-Bold.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.2.1/snap-server/fonts/DroidSerif-Bold.ttf b/static/docs/0.2.1/snap-server/fonts/DroidSerif-Bold.ttf deleted file mode 100644 index da0ea11..0000000 Binary files a/static/docs/0.2.1/snap-server/fonts/DroidSerif-Bold.ttf and /dev/null differ diff --git a/static/docs/0.2.1/snap-server/fonts/DroidSerif-Bold.woff b/static/docs/0.2.1/snap-server/fonts/DroidSerif-Bold.woff deleted file mode 100644 index 91549cd..0000000 Binary files a/static/docs/0.2.1/snap-server/fonts/DroidSerif-Bold.woff and /dev/null differ diff --git a/static/docs/0.2.1/snap-server/fonts/DroidSerif-BoldItalic.eot b/static/docs/0.2.1/snap-server/fonts/DroidSerif-BoldItalic.eot deleted file mode 100644 index 47dd0a0..0000000 Binary files a/static/docs/0.2.1/snap-server/fonts/DroidSerif-BoldItalic.eot and /dev/null differ diff --git a/static/docs/0.2.1/snap-server/fonts/DroidSerif-BoldItalic.svg b/static/docs/0.2.1/snap-server/fonts/DroidSerif-BoldItalic.svg deleted file mode 100644 index 1a57dbb..0000000 --- a/static/docs/0.2.1/snap-server/fonts/DroidSerif-BoldItalic.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.2.1/snap-server/fonts/DroidSerif-BoldItalic.ttf b/static/docs/0.2.1/snap-server/fonts/DroidSerif-BoldItalic.ttf deleted file mode 100644 index 8be3fb4..0000000 Binary files a/static/docs/0.2.1/snap-server/fonts/DroidSerif-BoldItalic.ttf and /dev/null differ diff --git a/static/docs/0.2.1/snap-server/fonts/DroidSerif-BoldItalic.woff b/static/docs/0.2.1/snap-server/fonts/DroidSerif-BoldItalic.woff deleted file mode 100644 index 6d5fa3d..0000000 Binary files a/static/docs/0.2.1/snap-server/fonts/DroidSerif-BoldItalic.woff and /dev/null differ diff --git a/static/docs/0.2.1/snap-server/fonts/DroidSerif-Italic.eot b/static/docs/0.2.1/snap-server/fonts/DroidSerif-Italic.eot deleted file mode 100644 index 2d4850c..0000000 Binary files a/static/docs/0.2.1/snap-server/fonts/DroidSerif-Italic.eot and /dev/null differ diff --git a/static/docs/0.2.1/snap-server/fonts/DroidSerif-Italic.svg b/static/docs/0.2.1/snap-server/fonts/DroidSerif-Italic.svg deleted file mode 100644 index 356c374..0000000 --- a/static/docs/0.2.1/snap-server/fonts/DroidSerif-Italic.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.2.1/snap-server/fonts/DroidSerif-Italic.ttf b/static/docs/0.2.1/snap-server/fonts/DroidSerif-Italic.ttf deleted file mode 100644 index 3719dc2..0000000 Binary files a/static/docs/0.2.1/snap-server/fonts/DroidSerif-Italic.ttf and /dev/null differ diff --git a/static/docs/0.2.1/snap-server/fonts/DroidSerif-Italic.woff b/static/docs/0.2.1/snap-server/fonts/DroidSerif-Italic.woff deleted file mode 100644 index b64436f..0000000 Binary files a/static/docs/0.2.1/snap-server/fonts/DroidSerif-Italic.woff and /dev/null differ diff --git a/static/docs/0.2.1/snap-server/fonts/DroidSerif-Regular.eot b/static/docs/0.2.1/snap-server/fonts/DroidSerif-Regular.eot deleted file mode 100644 index 0d17523..0000000 Binary files a/static/docs/0.2.1/snap-server/fonts/DroidSerif-Regular.eot and /dev/null differ diff --git a/static/docs/0.2.1/snap-server/fonts/DroidSerif-Regular.svg b/static/docs/0.2.1/snap-server/fonts/DroidSerif-Regular.svg deleted file mode 100644 index b9b65fb..0000000 --- a/static/docs/0.2.1/snap-server/fonts/DroidSerif-Regular.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.2.1/snap-server/fonts/DroidSerif-Regular.ttf b/static/docs/0.2.1/snap-server/fonts/DroidSerif-Regular.ttf deleted file mode 100644 index 066dcaa..0000000 Binary files a/static/docs/0.2.1/snap-server/fonts/DroidSerif-Regular.ttf and /dev/null differ diff --git a/static/docs/0.2.1/snap-server/fonts/DroidSerif-Regular.woff b/static/docs/0.2.1/snap-server/fonts/DroidSerif-Regular.woff deleted file mode 100644 index cfd3d67..0000000 Binary files a/static/docs/0.2.1/snap-server/fonts/DroidSerif-Regular.woff and /dev/null differ diff --git a/static/docs/0.2.1/snap-server/frames.html b/static/docs/0.2.1/snap-server/frames.html deleted file mode 100644 index 9e904fc..0000000 --- a/static/docs/0.2.1/snap-server/frames.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/static/docs/0.2.1/snap-server/haddock-util.js b/static/docs/0.2.1/snap-server/haddock-util.js deleted file mode 100644 index 364081f..0000000 --- a/static/docs/0.2.1/snap-server/haddock-util.js +++ /dev/null @@ -1,139 +0,0 @@ -// Haddock JavaScript utilities -function toggle(button,id) -{ - var n = document.getElementById(id).style; - if (n.display == "none") - { - button.src = "minus.gif"; - n.display = "block"; - } - else - { - button.src = "plus.gif"; - n.display = "none"; - } -} - - -var max_results = 75; // 50 is not enough to search for map in the base libraries -var shown_range = null; -var last_search = null; - -function quick_search() -{ - perform_search(false); -} - -function full_search() -{ - perform_search(true); -} - - -function perform_search(full) -{ - var text = document.getElementById("searchbox").value.toLowerCase(); - if (text == last_search && !full) return; - last_search = text; - - var table = document.getElementById("indexlist"); - var status = document.getElementById("searchmsg"); - var children = table.firstChild.childNodes; - - // first figure out the first node with the prefix - var first = bisect(-1); - var last = (first == -1 ? -1 : bisect(1)); - - if (first == -1) - { - table.className = ""; - status.innerHTML = "No results found, displaying all"; - } - else if (first == 0 && last == children.length - 1) - { - table.className = ""; - status.innerHTML = ""; - } - else if (last - first >= max_results && !full) - { - table.className = ""; - status.innerHTML = "More than " + max_results + ", press Search to display"; - } - else - { - // decide what you need to clear/show - if (shown_range) - setclass(shown_range[0], shown_range[1], "indexrow"); - setclass(first, last, "indexshow"); - shown_range = [first, last]; - table.className = "indexsearch"; - status.innerHTML = ""; - } - - - function setclass(first, last, status) - { - for (var i = first; i <= last; i++) - { - children[i].className = status; - } - } - - - // do a binary search, treating 0 as ... - // return either -1 (no 0's found) or location of most far match - function bisect(dir) - { - var first = 0, finish = children.length - 1; - var mid, success = false; - - while (finish - first > 3) - { - mid = Math.floor((finish + first) / 2); - - var i = checkitem(mid); - if (i == 0) i = dir; - if (i == -1) - finish = mid; - else - first = mid; - } - var a = (dir == 1 ? first : finish); - var b = (dir == 1 ? finish : first); - for (var i = b; i != a - dir; i -= dir) - { - if (checkitem(i) == 0) return i; - } - return -1; - } - - - // from an index, decide what the result is - // 0 = match, -1 is lower, 1 is higher - function checkitem(i) - { - var s = getitem(i).toLowerCase().substr(0, text.length); - if (s == text) return 0; - else return (s > text ? -1 : 1); - } - - - // from an index, get its string - // this abstracts over alternates - function getitem(i) - { - for ( ; i >= 0; i--) - { - var s = children[i].firstChild.firstChild.data; - if (s.indexOf(' ') == -1) - return s; - } - return ""; // should never be reached - } -} - -function setSynopsis(filename) { - if (parent.window.synopsis) { - parent.window.synopsis.location = filename; - } -} diff --git a/static/docs/0.2.1/snap-server/haddock.css b/static/docs/0.2.1/snap-server/haddock.css deleted file mode 100644 index 35a078d..0000000 --- a/static/docs/0.2.1/snap-server/haddock.css +++ /dev/null @@ -1,297 +0,0 @@ -/* -------- Global things --------- */ - -BODY { - background-color: #ffffff; - color: #000000; - font-family: sans-serif; - padding: 0 0; - } - -A:link { color: #0000e0; text-decoration: none } -A:visited { color: #0000a0; text-decoration: none } -A:hover { background-color: #e0e0ff; text-decoration: none } - -TABLE.vanilla { - width: 100%; - border-width: 0px; - /* I can't seem to specify cellspacing or cellpadding properly using CSS... */ -} - -TABLE.vanilla2 { - border-width: 0px; -} - -/* font is a little too small in MSIE */ -TT { font-size: 100%; } -PRE { font-size: 100%; } - -LI P { margin: 0pt } - -TD { - border-width: 0px; -} - -TABLE.narrow { - border-width: 0px; -} - -TD.s8 { height: 8px; } -TD.s15 { height: 15px; } - -SPAN.keyword { text-decoration: underline; } - -/* Resize the buttom image to match the text size */ -IMG.coll { width : 0.75em; height: 0.75em; margin-bottom: 0; margin-right: 0.5em } - -/* --------- Contents page ---------- */ - -DIV.node { - padding-left: 3em; -} - -DIV.cnode { - padding-left: 1.75em; -} - -SPAN.pkg { - position: absolute; - left: 50em; -} - -/* --------- Documentation elements ---------- */ - -TD.children { - padding-left: 25px; - } - -TD.synopsis { - padding: 2px; - background-color: #f0f0f0; - font-family: monospace - } - -TD.decl { - padding: 2px; - background-color: #f0f0f0; - font-family: monospace; - vertical-align: top; - } - -TD.topdecl { - padding: 2px; - background-color: #f0f0f0; - font-family: monospace; - vertical-align: top; -} - -TABLE.declbar { - border-spacing: 0px; - } - -TD.declname { - width: 100%; - } - -TD.declbut { - padding-left: 5px; - padding-right: 5px; - border-left-width: 1px; - border-left-color: #000099; - border-left-style: solid; - white-space: nowrap; - font-size: small; - } - -/* - arg is just like decl, except that wrapping is not allowed. It is - used for function and constructor arguments which have a text box - to the right, where if wrapping is allowed the text box squashes up - the declaration by wrapping it. -*/ -TD.arg { - padding: 2px; - background-color: #f0f0f0; - font-family: monospace; - vertical-align: top; - white-space: nowrap; - } - -TD.recfield { padding-left: 20px } - -TD.doc { - padding-top: 2px; - padding-left: 10px; - } - -TD.ndoc { - padding: 2px; - } - -TD.rdoc { - padding: 2px; - padding-left: 10px; - width: 100%; - } - -TD.body { - padding-left: 10px - } - -TD.pkg { - width: 100%; - padding-left: 10px -} - -TABLE.indexsearch TR.indexrow { - display: none; -} -TABLE.indexsearch TR.indexshow { - display: table-row; -} - -TD.indexentry { - vertical-align: top; - padding-right: 10px - } - -TD.indexannot { - vertical-align: top; - padding-left: 20px; - white-space: nowrap - } - -TD.indexlinks { - width: 100% - } - -/* ------- Section Headings ------- */ - -TD.section1 { - padding-top: 15px; - font-weight: bold; - font-size: 150% - } - -TD.section2 { - padding-top: 10px; - font-weight: bold; - font-size: 130% - } - -TD.section3 { - padding-top: 5px; - font-weight: bold; - font-size: 110% - } - -TD.section4 { - font-weight: bold; - font-size: 100% - } - -/* -------------- The title bar at the top of the page */ - -TD.infohead { - color: #ffffff; - font-weight: bold; - padding-right: 10px; - text-align: left; -} - -TD.infoval { - color: #ffffff; - padding-right: 10px; - text-align: left; -} - -TD.topbar { - background-color: #000099; - padding: 5px; -} - -TD.title { - color: #ffffff; - padding-left: 10px; - width: 100% - } - -TD.topbut { - padding-left: 5px; - padding-right: 5px; - border-left-width: 1px; - border-left-color: #ffffff; - border-left-style: solid; - white-space: nowrap; - } - -TD.topbut A:link { - color: #ffffff - } - -TD.topbut A:visited { - color: #ffff00 - } - -TD.topbut A:hover { - background-color: #6060ff; - } - -TD.topbut:hover { - background-color: #6060ff - } - -TD.modulebar { - background-color: #0077dd; - padding: 5px; - border-top-width: 1px; - border-top-color: #ffffff; - border-top-style: solid; - } - -/* --------- The page footer --------- */ - -TD.botbar { - background-color: #000099; - color: #ffffff; - padding: 5px - } -TD.botbar A:link { - color: #ffffff; - text-decoration: underline - } -TD.botbar A:visited { - color: #ffff00 - } -TD.botbar A:hover { - background-color: #6060ff - } - -/* --------- Mini Synopsis for Frame View --------- */ - -.outer { - margin: 0 0; - padding: 0 0; -} - -.mini-synopsis { - padding: 0.25em 0.25em; -} - -.mini-synopsis H1 { font-size: 130%; } -.mini-synopsis H2 { font-size: 110%; } -.mini-synopsis H3 { font-size: 100%; } -.mini-synopsis H1, .mini-synopsis H2, .mini-synopsis H3 { - margin-top: 0.5em; - margin-bottom: 0.25em; - padding: 0 0; -} - -.mini-synopsis H1 { border-bottom: 1px solid #ccc; } - -.mini-topbar { - font-size: 130%; - background: #0077dd; - padding: 0.25em; -} - - diff --git a/static/docs/0.2.1/snap-server/haskell_icon.gif b/static/docs/0.2.1/snap-server/haskell_icon.gif deleted file mode 100644 index cb2a815..0000000 Binary files a/static/docs/0.2.1/snap-server/haskell_icon.gif and /dev/null differ diff --git a/static/docs/0.2.1/snap-server/index-frames.html b/static/docs/0.2.1/snap-server/index-frames.html deleted file mode 100644 index 2d91d04..0000000 --- a/static/docs/0.2.1/snap-server/index-frames.html +++ /dev/null @@ -1,28 +0,0 @@ - - -snap-server-0.2.1: A fast, iteratee-based, epoll-enabled web server for the Snap Framework

Snap.Http.Server
Snap.Http.Server.Config
System.FastLogger

diff --git a/static/docs/0.2.1/snap-server/index.html b/static/docs/0.2.1/snap-server/index.html deleted file mode 100644 index 275fb2b..0000000 --- a/static/docs/0.2.1/snap-server/index.html +++ /dev/null @@ -1,178 +0,0 @@ - - -snap-server-0.2.1: A fast, iteratee-based, epoll-enabled web server for the Snap Framework
 snap-server-0.2.1: A fast, iteratee-based, epoll-enabled web server for the Snap FrameworkContentsIndex
snap-server-0.2.1: A fast, iteratee-based, epoll-enabled web server for the Snap Framework

This is the first developer prerelease of the Snap framework. Snap is a -simple and fast web development framework and server written in Haskell. For -more information or to download the latest version, you can visit the Snap -project website at http://snapframework.com/. -

The Snap HTTP server is a high performance, epoll-enabled, iteratee-based web -server library written in Haskell. Together with the snap-core library upon -which it depends, it provides a clean and efficient Haskell programming -interface to the HTTP protocol. -

Higher-level facilities for building web applications (like user/session -management, component interfaces, data modeling, etc.) are planned but not -yet implemented, so this release will mostly be of interest for those who: -

  • need a fast and minimal HTTP API at roughly the same level of abstraction -as Java servlets, or -
  • are interested in contributing to the Snap Framework project. -
Modules
show/hideSnap
show/hideHttp
show/hideSnap.Http.Server
Snap.Http.Server.Config
show/hideSystem
System.FastLogger
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.1/snap-server/mini_Snap-Http-Server-Config.html b/static/docs/0.2.1/snap-server/mini_Snap-Http-Server-Config.html deleted file mode 100644 index c4ec20a..0000000 --- a/static/docs/0.2.1/snap-server/mini_Snap-Http-Server-Config.html +++ /dev/null @@ -1,31 +0,0 @@ - - -Snap.Http.Server.Config
Snap.Http.Server.Config
diff --git a/static/docs/0.2.1/snap-server/mini_Snap-Http-Server.html b/static/docs/0.2.1/snap-server/mini_Snap-Http-Server.html deleted file mode 100644 index 3841177..0000000 --- a/static/docs/0.2.1/snap-server/mini_Snap-Http-Server.html +++ /dev/null @@ -1,25 +0,0 @@ - - -Snap.Http.Server
Snap.Http.Server
diff --git a/static/docs/0.2.1/snap-server/mini_System-FastLogger.html b/static/docs/0.2.1/snap-server/mini_System-FastLogger.html deleted file mode 100644 index 891c97c..0000000 --- a/static/docs/0.2.1/snap-server/mini_System-FastLogger.html +++ /dev/null @@ -1,47 +0,0 @@ - - -System.FastLogger diff --git a/static/docs/0.2.1/snap-server/minus.gif b/static/docs/0.2.1/snap-server/minus.gif deleted file mode 100644 index 1deac2f..0000000 Binary files a/static/docs/0.2.1/snap-server/minus.gif and /dev/null differ diff --git a/static/docs/0.2.1/snap-server/plus.gif b/static/docs/0.2.1/snap-server/plus.gif deleted file mode 100644 index 2d15c14..0000000 Binary files a/static/docs/0.2.1/snap-server/plus.gif and /dev/null differ diff --git a/static/docs/0.2.1/snap-server/snap-server.haddock b/static/docs/0.2.1/snap-server/snap-server.haddock deleted file mode 100644 index 715e3fa..0000000 Binary files a/static/docs/0.2.1/snap-server/snap-server.haddock and /dev/null differ diff --git a/static/docs/0.2.4/heist/Text-Templating-Heist-Splices-Apply.html b/static/docs/0.2.4/heist/Text-Templating-Heist-Splices-Apply.html deleted file mode 100644 index dcb2054..0000000 --- a/static/docs/0.2.4/heist/Text-Templating-Heist-Splices-Apply.html +++ /dev/null @@ -1,225 +0,0 @@ - - -Text.Templating.Heist.Splices.Apply
 heist-0.1.3: An xhtml templating systemSource codeContentsIndex
Text.Templating.Heist.Splices.Apply
Synopsis
applyTag :: ByteString
applyAttr :: ByteString
applyImpl :: Monad m => Splice m
Documentation
applyTag :: ByteStringSource
Default name for the apply splice. -
applyAttr :: ByteStringSource
Default attribute name for the apply tag. -
applyImpl :: Monad m => Splice mSource
Implementation of the apply splice. -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.4/heist/Text-Templating-Heist-Splices-Bind.html b/static/docs/0.2.4/heist/Text-Templating-Heist-Splices-Bind.html deleted file mode 100644 index d5afbc1..0000000 --- a/static/docs/0.2.4/heist/Text-Templating-Heist-Splices-Bind.html +++ /dev/null @@ -1,225 +0,0 @@ - - -Text.Templating.Heist.Splices.Bind
 heist-0.1.3: An xhtml templating systemSource codeContentsIndex
Text.Templating.Heist.Splices.Bind
Synopsis
bindTag :: ByteString
bindAttr :: ByteString
bindImpl :: Monad m => Splice m
Documentation
bindTag :: ByteStringSource
Default name for the bind splice. -
bindAttr :: ByteStringSource
Default attribute name for the bind tag. -
bindImpl :: Monad m => Splice mSource
Implementation of the bind splice. -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.4/heist/Text-Templating-Heist-Splices-Ignore.html b/static/docs/0.2.4/heist/Text-Templating-Heist-Splices-Ignore.html deleted file mode 100644 index 004720f..0000000 --- a/static/docs/0.2.4/heist/Text-Templating-Heist-Splices-Ignore.html +++ /dev/null @@ -1,183 +0,0 @@ - - -Text.Templating.Heist.Splices.Ignore
 heist-0.1.3: An xhtml templating systemSource codeContentsIndex
Text.Templating.Heist.Splices.Ignore
Synopsis
ignoreTag :: ByteString
ignoreImpl :: Monad m => Splice m
Documentation
ignoreTag :: ByteStringSource
Default name for the ignore splice. -
ignoreImpl :: Monad m => Splice mSource
The ignore tag and everything it surrounds disappears in the - rendered output. -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.4/heist/Text-Templating-Heist-Splices-Markdown.html b/static/docs/0.2.4/heist/Text-Templating-Heist-Splices-Markdown.html deleted file mode 100644 index 41f7c38..0000000 --- a/static/docs/0.2.4/heist/Text-Templating-Heist-Splices-Markdown.html +++ /dev/null @@ -1,592 +0,0 @@ - - -Text.Templating.Heist.Splices.Markdown
 heist-0.1.3: An xhtml templating systemSource codeContentsIndex
Text.Templating.Heist.Splices.Markdown
Synopsis
data PandocMissingException = PandocMissingException
data MarkdownException = MarkdownException ByteString
markdownTag :: ByteString
markdownSplice :: MonadIO m => Splice m
pandoc :: FilePath -> FilePath -> IO ByteString
pandocBS :: FilePath -> ByteString -> IO ByteString
readProcessWithExitCode' :: FilePath -> [String] -> ByteString -> IO (ExitCode, ByteString, ByteString)
Documentation
data PandocMissingException Source
Constructors
PandocMissingException
show/hide Instances
data MarkdownException Source
Constructors
MarkdownException ByteString
show/hide Instances
markdownTag :: ByteStringSource
Default name for the markdown splice. -
markdownSplice :: MonadIO m => Splice mSource
Implementation of the markdown splice. -
pandoc :: FilePath -> FilePath -> IO ByteStringSource
pandocBS :: FilePath -> ByteString -> IO ByteStringSource
readProcessWithExitCode'Source
:: FilePathcommand to run -
-> [String]any arguments -
-> ByteStringstandard input -
-> IO (ExitCode, ByteString, ByteString)exitcode, stdout, stderr -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.4/heist/Text-Templating-Heist-Splices-Static.html b/static/docs/0.2.4/heist/Text-Templating-Heist-Splices-Static.html deleted file mode 100644 index cd666d3..0000000 --- a/static/docs/0.2.4/heist/Text-Templating-Heist-Splices-Static.html +++ /dev/null @@ -1,253 +0,0 @@ - - -Text.Templating.Heist.Splices.Static
 heist-0.1.3: An xhtml templating systemSource codeContentsIndex
Text.Templating.Heist.Splices.Static
Synopsis
data StaticTagState
bindStaticTag :: MonadIO m => TemplateState m -> IO (TemplateState m, StaticTagState)
clearStaticTagCache :: StaticTagState -> IO ()
Documentation
data StaticTagState Source
State for storing static tag information -
bindStaticTag :: MonadIO m => TemplateState m -> IO (TemplateState m, StaticTagState)Source
Modifies a TemplateState to include a static tag. -
clearStaticTagCache :: StaticTagState -> IO ()Source
Clears the static tag state. -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.4/heist/Text-Templating-Heist-Splices.html b/static/docs/0.2.4/heist/Text-Templating-Heist-Splices.html deleted file mode 100644 index c882f02..0000000 --- a/static/docs/0.2.4/heist/Text-Templating-Heist-Splices.html +++ /dev/null @@ -1,132 +0,0 @@ - - -Text.Templating.Heist.Splices
 heist-0.1.3: An xhtml templating systemSource codeContentsIndex
Text.Templating.Heist.Splices
Documentation
module Text.Templating.Heist.Splices.Apply
module Text.Templating.Heist.Splices.Bind
module Text.Templating.Heist.Splices.Ignore
module Text.Templating.Heist.Splices.Markdown
module Text.Templating.Heist.Splices.Static
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.4/heist/Text-Templating-Heist.html b/static/docs/0.2.4/heist/Text-Templating-Heist.html deleted file mode 100644 index b4722f9..0000000 --- a/static/docs/0.2.4/heist/Text-Templating-Heist.html +++ /dev/null @@ -1,2315 +0,0 @@ - - -Text.Templating.Heist
 heist-0.1.3: An xhtml templating systemSource codeContentsIndex
Text.Templating.Heist
Contents
Types -
Functions and declarations on TemplateState values -
Hook functions -
TemplateMonad functions -
Functions for running splices and templates -
Misc functions -
Description

This module contains the core definitions for the Heist template system. -

The Heist template system is based on XML/xhtml. It allows you to build - custom XML-based markup languages. With Heist you can define your own - domain-specific XML tags implemented with Haskell and use them in your - templates. -

The most important concept in Heist is the Splice. Splices can be thought - of as functions that transform a node into a list of nodes. Heist then - substitutes the resulting list of nodes into your template in place of the - input node. Splice is implemented as a type synonym type Splice m = - TemplateMonad m [Node], and TemplateMonad has a function getParamNode - that lets you get the input node. -

Suppose you have a place on your page where you want to display a link with - the text "Logout username" if the user is currently logged in or a link to - the login page if no user is logged in. Assume you have a function - getUser :: MyAppMonad (Maybe ByteString) that gets the current user. - You can implement this functionality with a Splice as follows: -

- import Text.XML.Expat.Tree
-
- link :: ByteString -> ByteString -> Node
- link target text = X.Element "a" [("href", target)] [X.Text text]
- 
- loginLink :: Node
- loginLink = link "/login" "Login"
- 
- logoutLink :: ByteString -> Node
- logoutLink user = link "/logout" (B.append "Logout " user)
- 
- loginLogoutSplice :: Splice MyAppMonad
- loginLogoutSplice = do
-     user <- lift getUser
-     return $ [maybe loginLink logoutLink user]
-
-

Next, you need to bind that splice to an XML tag. Heist stores information - about splices and templates in the TemplateState data structure. The - following code demonstrates how this splice would be used. -

 mySplices = [ ("loginLogout", loginLogoutSplice) ]
- 
- main = do
-     ets <- loadTemplates "templates" $
-            foldr (uncurry bindSplice) emptyTemplateState mySplices
-     let ts = either error id ets
-     t <- runMyAppMonad $ renderTemplate ts "index"
-     print $ maybe "Page not found" id t
-

Here we build up our TemplateState by starting with emptyTemplateState and - applying bindSplice for all the splices we want to add. Then we pass this - to loadTemplates our final TemplateState wrapped in an Either to handle - errors. Then we use this TemplateState to render our templates. -

Synopsis
type Node = Node ByteString ByteString
type Splice m = TemplateMonad m Template
type Template = [Node]
data TemplateMonad m a
data TemplateState m
addTemplate :: Monad m => ByteString -> Template -> TemplateState m -> TemplateState m
emptyTemplateState :: MonadIO m => TemplateState m
bindSplice :: Monad m => ByteString -> Splice m -> TemplateState m -> TemplateState m
lookupSplice :: Monad m => ByteString -> TemplateState m -> Maybe (Splice m)
setTemplates :: Monad m => TemplateMap -> TemplateState m -> TemplateState m
loadTemplates :: Monad m => FilePath -> TemplateState m -> IO (Either String (TemplateState m))
addOnLoadHook :: Monad m => (Template -> IO Template) -> TemplateState m -> TemplateState m
addPreRunHook :: Monad m => (Template -> m Template) -> TemplateState m -> TemplateState m
addPostRunHook :: Monad m => (Template -> m Template) -> TemplateState m -> TemplateState m
stopRecursion :: Monad m => TemplateMonad m ()
getParamNode :: Monad m => TemplateMonad m Node
runNodeList :: Monad m => [Node] -> Splice m
getContext :: Monad m => TemplateMonad m TPath
runTemplate :: Monad m => TemplateState m -> ByteString -> m (Maybe [Node])
evalTemplate :: Monad m => ByteString -> TemplateMonad m (Maybe [Node])
callTemplate :: Monad m => ByteString -> [(ByteString, ByteString)] -> TemplateMonad m (Maybe Template)
renderTemplate :: Monad m => TemplateState m -> ByteString -> m (Maybe ByteString)
bindStrings :: Monad m => [(ByteString, ByteString)] -> TemplateState m -> TemplateState m
runSplice :: Monad m => TemplateState m -> Node -> Splice m -> m [Node]
runRawTemplate :: Monad m => TemplateState m -> Template -> m [Node]
getDoc :: String -> IO (Either String Template)
bindStaticTag :: MonadIO m => TemplateState m -> IO (TemplateState m, StaticTagState)
heistExpatOptions :: ParserOptions ByteString ByteString
htmlEntityLookupTable :: Map ByteString ByteString
Types -
type Node = Node ByteString ByteStringSource
Heist templates are XML documents. The hexpat library is polymorphic over - the type of strings, so here we define a Node alias to fix the string - types of the tag names and tag bodies to ByteString. -
type Splice m = TemplateMonad m TemplateSource
A Splice is a TemplateMonad computation that returns [Node]. -
type Template = [Node]Source
A Template is a forest of XML nodes. -
data TemplateMonad m a Source
TemplateMonad is a monad transformer that gives you access to the Node - being processed (using the MonadReader instance) as well as holding the - TemplateState that contains splice and template mappings (accessible - using the MonadState instance. -
show/hide Instances
data TemplateState m Source

Holds all the state information needed for template processing: -

  • a collection of named templates. If you use the <apply - template="foo"> tag to include another template by name, "foo" - is looked up in here. -
  • the mapping from tag names to Splices. -
  • a flag to control whether we will recurse during splice processing. -

We'll illustrate the recursion flag with a small example template: -

 <foo>
-   <bar>
-     ...
-   </bar>
- </foo>
-

Assume that "foo" is bound to a splice procedure. Running the foo - splice will result in a list of nodes L; if the recursion flag is on we - will recursively scan L for splices, otherwise L will be included in the - output verbatim. -

show/hide Instances
Functions and declarations on TemplateState values -
addTemplate :: Monad m => ByteString -> Template -> TemplateState m -> TemplateState mSource
Adds a template to the template state. -
emptyTemplateState :: MonadIO m => TemplateState mSource
An empty template state, with Heist's default splices (<bind> and - <apply>) mapped. -
bindSpliceSource
:: Monad m
=> ByteStringtag name -
-> Splice msplice action -
-> TemplateState msource state -
-> TemplateState m
Bind a new splice declaration to a tag name within a TemplateState. -
lookupSplice :: Monad m => ByteString -> TemplateState m -> Maybe (Splice m)Source
Convenience function for looking up a splice. -
setTemplates :: Monad m => TemplateMap -> TemplateState m -> TemplateState mSource
Sets the templateMap in a TemplateState. -
loadTemplates :: Monad m => FilePath -> TemplateState m -> IO (Either String (TemplateState m))Source
Traverses the specified directory structure and builds a - TemplateState by loading all the files with a .tpl extension. -
Hook functions -

Heist hooks allow you to modify templates when they are loaded and before - and after they are run. Every time you call one of the addAbcHook - functions the hook is added to onto the processing pipeline. The hooks - processes the template in the order that they were added to the - TemplateState. -

The pre-run and post-run hooks are run before and after every template is - run/rendered. You should be careful what code you put in these hooks - because it can significantly affect the performance of your site. -

addOnLoadHook :: Monad m => (Template -> IO Template) -> TemplateState m -> TemplateState mSource
Adds an on-load hook to a TemplateState. -
addPreRunHook :: Monad m => (Template -> m Template) -> TemplateState m -> TemplateState mSource
Adds a pre-run hook to a TemplateState. -
addPostRunHook :: Monad m => (Template -> m Template) -> TemplateState m -> TemplateState mSource
Adds a post-run hook to a TemplateState. -
TemplateMonad functions -
stopRecursion :: Monad m => TemplateMonad m ()Source
Stops the recursive processing of splices. -
getParamNode :: Monad m => TemplateMonad m NodeSource
Gets the node currently being processed. -
runNodeList :: Monad m => [Node] -> Splice mSource
Performs splice processing on a list of nodes. -
getContext :: Monad m => TemplateMonad m TPathSource
Gets the current context -
Functions for running splices and templates -
runTemplate :: Monad m => TemplateState m -> ByteString -> m (Maybe [Node])Source
Looks up a template name in the supplied TemplateState and runs - it in the underlying monad. -
evalTemplate :: Monad m => ByteString -> TemplateMonad m (Maybe [Node])Source
Looks up a template name evaluates it. Same as runTemplate except it - runs in TemplateMonad instead of m. -
callTemplateSource
:: Monad m
=> ByteStringThe name of the template -
-> [(ByteString, ByteString)]Association list of - (name,value) parameter pairs -
-> TemplateMonad m (Maybe Template)
Renders a template with the specified parameters. This is the function - to use when you want to call a template and pass in parameters from code. -
renderTemplate :: Monad m => TemplateState m -> ByteString -> m (Maybe ByteString)Source
Renders a template from the specified TemplateState. -
bindStrings :: Monad m => [(ByteString, ByteString)] -> TemplateState m -> TemplateState mSource
Binds a list of constant string splices -
Misc functions -
runSpliceSource
:: Monad m
=> TemplateState mThe initial template state -
-> NodeThe splice's input node -
-> Splice mThe splice -
-> m [Node]
Runs a splice in the underlying monad. Splices require two - parameters, the template state, and an input node. -
runRawTemplate :: Monad m => TemplateState m -> Template -> m [Node]Source
Runs a template in the underlying monad. Similar to runSplice - except that templates don't require a Node as a parameter. -
getDoc :: String -> IO (Either String Template)Source
Reads an XML document from disk. -
bindStaticTag :: MonadIO m => TemplateState m -> IO (TemplateState m, StaticTagState)Source
Modifies a TemplateState to include a static tag. -
heistExpatOptions :: ParserOptions ByteString ByteStringSource
htmlEntityLookupTable :: Map ByteString ByteStringSource
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.4/heist/doc-index.html b/static/docs/0.2.4/heist/doc-index.html deleted file mode 100644 index bbbe85c..0000000 --- a/static/docs/0.2.4/heist/doc-index.html +++ /dev/null @@ -1,438 +0,0 @@ - - -heist-0.1.3: An xhtml templating system (Index)
 heist-0.1.3: An xhtml templating systemContentsIndex
addOnLoadHook
addPostRunHook
addPreRunHook
addTemplate
applyAttr
applyImpl
applyTag
bindAttr
bindImpl
bindSplice
bindStaticTag
bindStrings
bindTag
callTemplate
clearStaticTagCache
emptyTemplateState
evalTemplate
getContext
getDoc
getParamNode
heistExpatOptions
htmlEntityLookupTable
ignoreImpl
ignoreTag
loadTemplates
lookupSplice
MarkdownException
1 (Type/Class)
2 (Data Constructor)
markdownSplice
markdownTag
Node
pandoc
pandocBS
PandocMissingException
1 (Type/Class)
2 (Data Constructor)
readProcessWithExitCode'
renderTemplate
runNodeList
runRawTemplate
runSplice
runTemplate
setTemplates
Splice
StaticTagState
stopRecursion
Template
TemplateMonad
TemplateState
diff --git a/static/docs/0.2.4/heist/fonts/DroidSerif-Bold.eot b/static/docs/0.2.4/heist/fonts/DroidSerif-Bold.eot deleted file mode 100644 index 01b9e1f..0000000 Binary files a/static/docs/0.2.4/heist/fonts/DroidSerif-Bold.eot and /dev/null differ diff --git a/static/docs/0.2.4/heist/fonts/DroidSerif-Bold.svg b/static/docs/0.2.4/heist/fonts/DroidSerif-Bold.svg deleted file mode 100644 index 1f7f2d2..0000000 --- a/static/docs/0.2.4/heist/fonts/DroidSerif-Bold.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.2.4/heist/fonts/DroidSerif-Bold.ttf b/static/docs/0.2.4/heist/fonts/DroidSerif-Bold.ttf deleted file mode 100644 index da0ea11..0000000 Binary files a/static/docs/0.2.4/heist/fonts/DroidSerif-Bold.ttf and /dev/null differ diff --git a/static/docs/0.2.4/heist/fonts/DroidSerif-Bold.woff b/static/docs/0.2.4/heist/fonts/DroidSerif-Bold.woff deleted file mode 100644 index 91549cd..0000000 Binary files a/static/docs/0.2.4/heist/fonts/DroidSerif-Bold.woff and /dev/null differ diff --git a/static/docs/0.2.4/heist/fonts/DroidSerif-BoldItalic.eot b/static/docs/0.2.4/heist/fonts/DroidSerif-BoldItalic.eot deleted file mode 100644 index 47dd0a0..0000000 Binary files a/static/docs/0.2.4/heist/fonts/DroidSerif-BoldItalic.eot and /dev/null differ diff --git a/static/docs/0.2.4/heist/fonts/DroidSerif-BoldItalic.svg b/static/docs/0.2.4/heist/fonts/DroidSerif-BoldItalic.svg deleted file mode 100644 index 1a57dbb..0000000 --- a/static/docs/0.2.4/heist/fonts/DroidSerif-BoldItalic.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.2.4/heist/fonts/DroidSerif-BoldItalic.ttf b/static/docs/0.2.4/heist/fonts/DroidSerif-BoldItalic.ttf deleted file mode 100644 index 8be3fb4..0000000 Binary files a/static/docs/0.2.4/heist/fonts/DroidSerif-BoldItalic.ttf and /dev/null differ diff --git a/static/docs/0.2.4/heist/fonts/DroidSerif-BoldItalic.woff b/static/docs/0.2.4/heist/fonts/DroidSerif-BoldItalic.woff deleted file mode 100644 index 6d5fa3d..0000000 Binary files a/static/docs/0.2.4/heist/fonts/DroidSerif-BoldItalic.woff and /dev/null differ diff --git a/static/docs/0.2.4/heist/fonts/DroidSerif-Italic.eot b/static/docs/0.2.4/heist/fonts/DroidSerif-Italic.eot deleted file mode 100644 index 2d4850c..0000000 Binary files a/static/docs/0.2.4/heist/fonts/DroidSerif-Italic.eot and /dev/null differ diff --git a/static/docs/0.2.4/heist/fonts/DroidSerif-Italic.svg b/static/docs/0.2.4/heist/fonts/DroidSerif-Italic.svg deleted file mode 100644 index 356c374..0000000 --- a/static/docs/0.2.4/heist/fonts/DroidSerif-Italic.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.2.4/heist/fonts/DroidSerif-Italic.ttf b/static/docs/0.2.4/heist/fonts/DroidSerif-Italic.ttf deleted file mode 100644 index 3719dc2..0000000 Binary files a/static/docs/0.2.4/heist/fonts/DroidSerif-Italic.ttf and /dev/null differ diff --git a/static/docs/0.2.4/heist/fonts/DroidSerif-Italic.woff b/static/docs/0.2.4/heist/fonts/DroidSerif-Italic.woff deleted file mode 100644 index b64436f..0000000 Binary files a/static/docs/0.2.4/heist/fonts/DroidSerif-Italic.woff and /dev/null differ diff --git a/static/docs/0.2.4/heist/fonts/DroidSerif-Regular.eot b/static/docs/0.2.4/heist/fonts/DroidSerif-Regular.eot deleted file mode 100644 index 0d17523..0000000 Binary files a/static/docs/0.2.4/heist/fonts/DroidSerif-Regular.eot and /dev/null differ diff --git a/static/docs/0.2.4/heist/fonts/DroidSerif-Regular.svg b/static/docs/0.2.4/heist/fonts/DroidSerif-Regular.svg deleted file mode 100644 index b9b65fb..0000000 --- a/static/docs/0.2.4/heist/fonts/DroidSerif-Regular.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.2.4/heist/fonts/DroidSerif-Regular.ttf b/static/docs/0.2.4/heist/fonts/DroidSerif-Regular.ttf deleted file mode 100644 index 066dcaa..0000000 Binary files a/static/docs/0.2.4/heist/fonts/DroidSerif-Regular.ttf and /dev/null differ diff --git a/static/docs/0.2.4/heist/fonts/DroidSerif-Regular.woff b/static/docs/0.2.4/heist/fonts/DroidSerif-Regular.woff deleted file mode 100644 index cfd3d67..0000000 Binary files a/static/docs/0.2.4/heist/fonts/DroidSerif-Regular.woff and /dev/null differ diff --git a/static/docs/0.2.4/heist/frames.html b/static/docs/0.2.4/heist/frames.html deleted file mode 100644 index 9e904fc..0000000 --- a/static/docs/0.2.4/heist/frames.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/static/docs/0.2.4/heist/haddock-util.js b/static/docs/0.2.4/heist/haddock-util.js deleted file mode 100644 index 364081f..0000000 --- a/static/docs/0.2.4/heist/haddock-util.js +++ /dev/null @@ -1,139 +0,0 @@ -// Haddock JavaScript utilities -function toggle(button,id) -{ - var n = document.getElementById(id).style; - if (n.display == "none") - { - button.src = "minus.gif"; - n.display = "block"; - } - else - { - button.src = "plus.gif"; - n.display = "none"; - } -} - - -var max_results = 75; // 50 is not enough to search for map in the base libraries -var shown_range = null; -var last_search = null; - -function quick_search() -{ - perform_search(false); -} - -function full_search() -{ - perform_search(true); -} - - -function perform_search(full) -{ - var text = document.getElementById("searchbox").value.toLowerCase(); - if (text == last_search && !full) return; - last_search = text; - - var table = document.getElementById("indexlist"); - var status = document.getElementById("searchmsg"); - var children = table.firstChild.childNodes; - - // first figure out the first node with the prefix - var first = bisect(-1); - var last = (first == -1 ? -1 : bisect(1)); - - if (first == -1) - { - table.className = ""; - status.innerHTML = "No results found, displaying all"; - } - else if (first == 0 && last == children.length - 1) - { - table.className = ""; - status.innerHTML = ""; - } - else if (last - first >= max_results && !full) - { - table.className = ""; - status.innerHTML = "More than " + max_results + ", press Search to display"; - } - else - { - // decide what you need to clear/show - if (shown_range) - setclass(shown_range[0], shown_range[1], "indexrow"); - setclass(first, last, "indexshow"); - shown_range = [first, last]; - table.className = "indexsearch"; - status.innerHTML = ""; - } - - - function setclass(first, last, status) - { - for (var i = first; i <= last; i++) - { - children[i].className = status; - } - } - - - // do a binary search, treating 0 as ... - // return either -1 (no 0's found) or location of most far match - function bisect(dir) - { - var first = 0, finish = children.length - 1; - var mid, success = false; - - while (finish - first > 3) - { - mid = Math.floor((finish + first) / 2); - - var i = checkitem(mid); - if (i == 0) i = dir; - if (i == -1) - finish = mid; - else - first = mid; - } - var a = (dir == 1 ? first : finish); - var b = (dir == 1 ? finish : first); - for (var i = b; i != a - dir; i -= dir) - { - if (checkitem(i) == 0) return i; - } - return -1; - } - - - // from an index, decide what the result is - // 0 = match, -1 is lower, 1 is higher - function checkitem(i) - { - var s = getitem(i).toLowerCase().substr(0, text.length); - if (s == text) return 0; - else return (s > text ? -1 : 1); - } - - - // from an index, get its string - // this abstracts over alternates - function getitem(i) - { - for ( ; i >= 0; i--) - { - var s = children[i].firstChild.firstChild.data; - if (s.indexOf(' ') == -1) - return s; - } - return ""; // should never be reached - } -} - -function setSynopsis(filename) { - if (parent.window.synopsis) { - parent.window.synopsis.location = filename; - } -} diff --git a/static/docs/0.2.4/heist/haddock.css b/static/docs/0.2.4/heist/haddock.css deleted file mode 100644 index fe050fe..0000000 --- a/static/docs/0.2.4/heist/haddock.css +++ /dev/null @@ -1,478 +0,0 @@ -/* -------- Global things --------- */ - -@font-face { - font-family: 'DroidSerif'; - src: url('fonts/DroidSerif-Regular.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Regular.woff') format('woff'), - url('fonts/DroidSerif-Regular.ttf') format('truetype'), - url('fonts/DroidSerif-Regular.svg#DroidSerif') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - font-style: italic; - src: url('fonts/DroidSerif-Italic.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Italic.woff') format('woff'), - url('fonts/DroidSerif-Italic.ttf') format('truetype'), - url('fonts/DroidSerif-Italic.svg#DroidSerif-Italic') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - font-weight: bold; - src: url('fonts/DroidSerif-Bold.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Bold.woff') format('woff'), - url('fonts/DroidSerif-Bold.ttf') format('truetype'), - url('fonts/DroidSerif-Bold.svg#DroidSerif-Bold') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - src: url('fonts/DroidSerif-BoldItalic.eot'); - font-weight: bold; - font-style: italic; - src: local('Droid Serif'), - url('fonts/DroidSerif-BoldItalic.woff') format('woff'), - url('fonts/DroidSerif-BoldItalic.ttf') format('truetype'), - url('fonts/DroidSerif-BoldItalic.svg#DroidSerif-BoldItalic') format('svg'); -} - - - -HTML { - background-color: #f0f3ff; - width: 100%; -} - -BODY { - -moz-border-radius:5px; - -webkit-border-radius:5px; - width: 50em; - margin: 2em auto; - padding: 0; - background-color: #ffffff; - color: #000000; - font-size: 110%; - font-family: DroidSerif, Georgia, serif; - } - -A:link { color: #5200A3; text-decoration: none } -A:visited { color: #5200A3; text-decoration: none } -A:hover { color: #5200A3; text-decoration: none; border-bottom:#5200A3 dashed 1px; } - -TABLE.vanilla { - width: 100%; - border-width: 0px; - /* I can't seem to specify cellspacing or cellpadding properly using CSS... */ -} - -DL { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - letter-spacing: -0.01em; - margin: 0; -} - -.vanilla .vanilla dl { font-size: 80%; } -.vanilla .vanilla dl dl { padding-left: 0; font-size: 95%; } - -TD.section1, TD.section2, TD.section3, TD.section4, TD.doc, DL { - padding: 0 30px 0 34px; -} - -TABLE.vanilla2 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - border-width: 0px; -} - -/* font is a little too small in MSIE */ -TT, PRE, CODE { - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - font-size: 90%; -} - -LI P { margin: 0pt } - -P { margin-top: 0; margin-bottom: 0.75em; } - -TD { - border-width: 0px; -} - -TABLE.narrow { - border-width: 0px; -} - -TD.s8 { height: 0; margin:0; padding: 0 } -TD.s15 { height: 20px; } - -SPAN.keyword { text-decoration: underline; } - -/* Resize the buttom image to match the text size */ -IMG.coll { width : 0.75em; height: 0.75em; margin-bottom: 0; margin-right: 0.5em } - -/* --------- Contents page ---------- */ - -DIV.node { - padding-left: 3em; -} - -DIV.cnode { - padding-left: 1.75em; -} - -SPAN.pkg { - position: absolute; - left: 50em; -} - -/* --------- Documentation elements ---------- */ - -TD FONT { font-weight: bold; letter-spacing: -0.02em; } - -TD.children { - padding-left: 25px; - } - -TD.synopsis { - padding: 2px; - background-color: #f0f0f0; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - } - -TD.decl { - padding: 4px 8px; - background-color: #FAFAFA; - border-bottom: #F2F2F2 solid 1px; - border-top: #FCFCFC solid 1px; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - vertical-align: top; - } - -TD.decl TD.decl { - font-size: 100%; - padding: 4px 0; - border: 0; -} - -TD.topdecl { - padding: 20px 30px 0.5ex 30px; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; -; - vertical-align: top; -} - -.vanilla .vanilla .vanilla .topdecl { - padding-left: 0; - padding-right: 0; -} - -.vanilla .vanilla .vanilla { - padding-left: 30px; -} - -.decl .vanilla { - padding-left: 0px !important; -} - -.body .vanilla .body { - padding-left: 0; - padding-right: 0; -} - -.body .vanilla .body .decl { - padding-left: 12px; -} - -.body .vanilla .body div .vanilla .decl { - padding-left: 12px; -} - -TABLE.declbar { - background-color: #f0f0f0; - border-spacing: 0px; - border-bottom:1px solid #d7d7df; - border-right:1px solid #d7d7df; - border-top:1px solid #f4f4f9; - border-left:1px solid #f4f4f9; - padding: 4px; - } - -TD.declname { - width: 100%; - padding-right: 4px; - } - -TD.declbut { - padding-left: 8px; - padding-right: 5px; - border-left-width: 1px; - border-left-color: #000099; - border-left-style: solid; - white-space: nowrap; - font-size: x-small; - } - -/* - arg is just like decl, except that wrapping is not allowed. It is - used for function and constructor arguments which have a text box - to the right, where if wrapping is allowed the text box squashes up - the declaration by wrapping it. -*/ -TD.arg { - padding: 2px 12px; - background-color: #f0f0f0; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - vertical-align: top; - white-space: nowrap; - } - -TD.recfield { padding-left: 20px } - -TD.doc { - padding-left: 38px; - font-size: 95%; - line-height: 1.66; - } - -TD.ndoc { - font-size: 95%; - line-height: 1.66; - padding: 2px 4px 2px 8px; - } - -TD.rdoc { - padding: 2px; - padding-left: 30px; - width: 100%; - font-size: 80%; - font-style: italic; - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - } - -TD.body { - padding: 0 30px; - } - -TD.pkg { - width: 100%; - padding-left: 30px -} - -TABLE.indexsearch TR.indexrow { - display: none; -} -TABLE.indexsearch TR.indexshow { - display: table-row; -} - -TD.indexentry { - vertical-align: top; - padding: 0 30px - } - -TD.indexannot { - vertical-align: top; - padding-left: 20px; - white-space: nowrap - } - -TD.indexlinks { - width: 100% - } - -/* ------- Section Headings ------- */ - -TD.section1, TD.section2, TD.section3, TD.section4, TD.section5 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; -} - -TD.section1 { - padding-top: 14px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 140% - } - -TD.section2 { - padding-top: 4px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 120% - } - -TD.section3 { - padding-top: 5px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 105% - } - -TD.section4 { - font-weight: bold; - padding-top: 12px; - padding-bottom: 4px; - letter-spacing: -0.02em; - font-size: 90% - } - -/* -------------- The title bar at the top of the page */ - -TD.infohead { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - font-weight: bold; - padding: 0 30px; - text-align: left; -} - -TD.infoval { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - padding: 0 30px; - text-align: left; -} - -TD.topbar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - background-color: #3465a4; - padding: 5px; - -moz-border-radius-topleft:5px; - -moz-border-radius-topright:5px; - -webkit-border-radius-topleft:5px; - -webkit-border-radius-topright:5px; -} - -TD.title { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - padding-left: 30px; - letter-spacing: -0.02em; - font-weight: bold; - width: 100% - } - -TD.topbut { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - padding-left: 5px; - padding-right: 5px; - border-left-width: 1px; - border-left-color: #ffffff; - border-left-style: solid; - letter-spacing: -0.02em; - font-weight: bold; - white-space: nowrap; - } - -TD.topbut A:link { - color: #ffffff - } - -TD.topbut A:visited { - color: #ffff00 - } - -TD.topbut A:hover { - background-color: #C9D3DE; - } - -TD.topbut:hover { - background-color: #C9D3DE; - } - -TD.modulebar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #141B24; - background-color: #C9D3DE; - padding: 5px; - border-top-width: 1px; - border-top-color: #ffffff; - border-top-style: solid; - -moz-border-radius-bottomleft:5px; - -moz-border-radius-bottomright:5px; - -webkit-border-radius-bottomleft:5px; - -webkit-border-radius-bottomright:5px; - - } - -/* --------- The page footer --------- */ - -TD.botbar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - -moz-border-radius:5px; - -webkit-border-radius:5px; - background-color: #3465a4; - color: #ffffff; - padding: 5px - } -TD.botbar A:link { - color: #ffffff; - text-decoration: underline - } -TD.botbar A:visited { - color: #ffff00 - } -TD.botbar A:hover { - background-color: #6060ff - } - -/* --------- Mini Synopsis for Frame View --------- */ - -.outer { - margin: 0 0; - padding: 0 0; -} - -.mini-synopsis { - padding: 0.25em 0.25em; -} - -.mini-synopsis H1 { font-size: 120%; } -.mini-synopsis H2 { font-size: 107%; } -.mini-synopsis H3 { font-size: 100%; } -.mini-synopsis H1, .mini-synopsis H2, .mini-synopsis H3 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - margin-top: 0.5em; - margin-bottom: 0.25em; - padding: 0 0; - font-weight: bold; letter-spacing: -0.02em; -} - -.mini-synopsis H1 { border-bottom: 1px solid #ccc; } - -.mini-topbar { - font-size: 120%; - background: #0077dd; - padding: 0.25em; -} - - diff --git a/static/docs/0.2.4/heist/haskell_icon.gif b/static/docs/0.2.4/heist/haskell_icon.gif deleted file mode 100644 index cb2a815..0000000 Binary files a/static/docs/0.2.4/heist/haskell_icon.gif and /dev/null differ diff --git a/static/docs/0.2.4/heist/heist.haddock b/static/docs/0.2.4/heist/heist.haddock deleted file mode 100644 index 2650bf0..0000000 Binary files a/static/docs/0.2.4/heist/heist.haddock and /dev/null differ diff --git a/static/docs/0.2.4/heist/index-frames.html b/static/docs/0.2.4/heist/index-frames.html deleted file mode 100644 index d4d5a50..0000000 --- a/static/docs/0.2.4/heist/index-frames.html +++ /dev/null @@ -1,40 +0,0 @@ - - -heist-0.1.3: An xhtml templating system

Text.Templating.Heist
Text.Templating.Heist.Splices
Text.Templating.Heist.Splices.Apply
Text.Templating.Heist.Splices.Bind
Text.Templating.Heist.Splices.Ignore
Text.Templating.Heist.Splices.Markdown
Text.Templating.Heist.Splices.Static

diff --git a/static/docs/0.2.4/heist/index.html b/static/docs/0.2.4/heist/index.html deleted file mode 100644 index 7032804..0000000 --- a/static/docs/0.2.4/heist/index.html +++ /dev/null @@ -1,181 +0,0 @@ - - -heist-0.1.3: An xhtml templating system
 heist-0.1.3: An xhtml templating systemContentsIndex
heist-0.1.3: An xhtml templating system
An xhtml templating system -
Modules
show/hideText
show/hideTemplating
show/hideText.Templating.Heist
show/hideText.Templating.Heist.Splices
Text.Templating.Heist.Splices.Apply
Text.Templating.Heist.Splices.Bind
Text.Templating.Heist.Splices.Ignore
Text.Templating.Heist.Splices.Markdown
Text.Templating.Heist.Splices.Static
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.4/heist/mini_Text-Templating-Heist-Splices-Apply.html b/static/docs/0.2.4/heist/mini_Text-Templating-Heist-Splices-Apply.html deleted file mode 100644 index b3a2987..0000000 --- a/static/docs/0.2.4/heist/mini_Text-Templating-Heist-Splices-Apply.html +++ /dev/null @@ -1,33 +0,0 @@ - - -Text.Templating.Heist.Splices.Apply
Text.Templating.Heist.Splices.Apply
diff --git a/static/docs/0.2.4/heist/mini_Text-Templating-Heist-Splices-Bind.html b/static/docs/0.2.4/heist/mini_Text-Templating-Heist-Splices-Bind.html deleted file mode 100644 index 347bf97..0000000 --- a/static/docs/0.2.4/heist/mini_Text-Templating-Heist-Splices-Bind.html +++ /dev/null @@ -1,33 +0,0 @@ - - -Text.Templating.Heist.Splices.Bind
Text.Templating.Heist.Splices.Bind
diff --git a/static/docs/0.2.4/heist/mini_Text-Templating-Heist-Splices-Ignore.html b/static/docs/0.2.4/heist/mini_Text-Templating-Heist-Splices-Ignore.html deleted file mode 100644 index cf11fd3..0000000 --- a/static/docs/0.2.4/heist/mini_Text-Templating-Heist-Splices-Ignore.html +++ /dev/null @@ -1,29 +0,0 @@ - - -Text.Templating.Heist.Splices.Ignore
Text.Templating.Heist.Splices.Ignore
diff --git a/static/docs/0.2.4/heist/mini_Text-Templating-Heist-Splices-Markdown.html b/static/docs/0.2.4/heist/mini_Text-Templating-Heist-Splices-Markdown.html deleted file mode 100644 index 70738c6..0000000 --- a/static/docs/0.2.4/heist/mini_Text-Templating-Heist-Splices-Markdown.html +++ /dev/null @@ -1,53 +0,0 @@ - - -Text.Templating.Heist.Splices.Markdown diff --git a/static/docs/0.2.4/heist/mini_Text-Templating-Heist-Splices-Static.html b/static/docs/0.2.4/heist/mini_Text-Templating-Heist-Splices-Static.html deleted file mode 100644 index 482ea55..0000000 --- a/static/docs/0.2.4/heist/mini_Text-Templating-Heist-Splices-Static.html +++ /dev/null @@ -1,35 +0,0 @@ - - -Text.Templating.Heist.Splices.Static
Text.Templating.Heist.Splices.Static
diff --git a/static/docs/0.2.4/heist/mini_Text-Templating-Heist-Splices.html b/static/docs/0.2.4/heist/mini_Text-Templating-Heist-Splices.html deleted file mode 100644 index f3e9a96..0000000 --- a/static/docs/0.2.4/heist/mini_Text-Templating-Heist-Splices.html +++ /dev/null @@ -1,21 +0,0 @@ - - -Text.Templating.Heist.Splices
Text.Templating.Heist.Splices
diff --git a/static/docs/0.2.4/heist/mini_Text-Templating-Heist.html b/static/docs/0.2.4/heist/mini_Text-Templating-Heist.html deleted file mode 100644 index d0342ea..0000000 --- a/static/docs/0.2.4/heist/mini_Text-Templating-Heist.html +++ /dev/null @@ -1,165 +0,0 @@ - - -Text.Templating.Heist
Text.Templating.Heist

Types -

type Node
type Splice m
type Template
data TemplateMonad m a

Functions and declarations on TemplateState values -

Hook functions -

TemplateMonad functions -

Functions for running splices and templates -

Misc functions -

diff --git a/static/docs/0.2.4/heist/minus.gif b/static/docs/0.2.4/heist/minus.gif deleted file mode 100644 index 1deac2f..0000000 Binary files a/static/docs/0.2.4/heist/minus.gif and /dev/null differ diff --git a/static/docs/0.2.4/heist/plus.gif b/static/docs/0.2.4/heist/plus.gif deleted file mode 100644 index 2d15c14..0000000 Binary files a/static/docs/0.2.4/heist/plus.gif and /dev/null differ diff --git a/static/docs/0.2.4/heist/src/Text-Templating-Heist-Constants.html b/static/docs/0.2.4/heist/src/Text-Templating-Heist-Constants.html deleted file mode 100644 index 1f8683a..0000000 --- a/static/docs/0.2.4/heist/src/Text-Templating-Heist-Constants.html +++ /dev/null @@ -1,265 +0,0 @@ - - - - -src/Text/Templating/Heist/Constants.hs - - - -
{-# LANGUAGE OverloadedStrings #-}
-module Text.Templating.Heist.Constants where
-
-import           Data.ByteString.Char8 (ByteString)
-import qualified Data.Map as Map
-import           Data.Map (Map)
-
-htmlEntityLookupTable :: Map ByteString ByteString
-htmlEntityLookupTable = Map.fromList [
-                         ("acute"      , "\xc2\xb4")
-                       , ("cedil"      , "\xc2\xb8")
-                       , ("circ"       , "\xcb\x86")
-                       , ("macr"       , "\xc2\xaf")
-                       , ("middot"     , "\xc2\xb7")
-                       , ("tilde"      , "\xcb\x9c")
-                       , ("uml"        , "\xc2\xa8")
-                       , ("Aacute"     , "\xc3\x81")
-                       , ("aacute"     , "\xc3\xa1")
-                       , ("Acirc"      , "\xc3\x82")
-                       , ("acirc"      , "\xc3\xa2")
-                       , ("AElig"      , "\xc3\x86")
-                       , ("aelig"      , "\xc3\xa6")
-                       , ("Agrave"     , "\xc3\x80")
-                       , ("agrave"     , "\xc3\xa0")
-                       , ("Aring"      , "\xc3\x85")
-                       , ("aring"      , "\xc3\xa5")
-                       , ("Atilde"     , "\xc3\x83")
-                       , ("atilde"     , "\xc3\xa3")
-                       , ("Auml"       , "\xc3\x84")
-                       , ("auml"       , "\xc3\xa4")
-                       , ("Ccedil"     , "\xc3\x87")
-                       , ("ccedil"     , "\xc3\xa7")
-                       , ("Eacute"     , "\xc3\x89")
-                       , ("eacute"     , "\xc3\xa9")
-                       , ("Ecirc"      , "\xc3\x8a")
-                       , ("ecirc"      , "\xc3\xaa")
-                       , ("Egrave"     , "\xc3\x88")
-                       , ("egrave"     , "\xc3\xa8")
-                       , ("ETH"        , "\xc3\x90")
-                       , ("eth"        , "\xc3\xb0")
-                       , ("Euml"       , "\xc3\x8b")
-                       , ("euml"       , "\xc3\xab")
-                       , ("Iacute"     , "\xc3\x8d")
-                       , ("iacute"     , "\xc3\xad")
-                       , ("Icirc"      , "\xc3\x8e")
-                       , ("icirc"      , "\xc3\xae")
-                       , ("Igrave"     , "\xc3\x8c")
-                       , ("igrave"     , "\xc3\xac")
-                       , ("Iuml"       , "\xc3\x8f")
-                       , ("iuml"       , "\xc3\xaf")
-                       , ("Ntilde"     , "\xc3\x91")
-                       , ("ntilde"     , "\xc3\xb1")
-                       , ("Oacute"     , "\xc3\x93")
-                       , ("oacute"     , "\xc3\xb3")
-                       , ("Ocirc"      , "\xc3\x94")
-                       , ("ocirc"      , "\xc3\xb4")
-                       , ("OElig"      , "\xc5\x92")
-                       , ("oelig"      , "\xc5\x93")
-                       , ("Ograve"     , "\xc3\x92")
-                       , ("ograve"     , "\xc3\xb2")
-                       , ("Oslash"     , "\xc3\x98")
-                       , ("oslash"     , "\xc3\xb8")
-                       , ("Otilde"     , "\xc3\x95")
-                       , ("otilde"     , "\xc3\xb5")
-                       , ("Ouml"       , "\xc3\x96")
-                       , ("ouml"       , "\xc3\xb6")
-                       , ("Scaron"     , "\xc5\xa0")
-                       , ("scaron"     , "\xc5\xa1")
-                       , ("szlig"      , "\xc3\x9f")
-                       , ("THORN"      , "\xc3\x9e")
-                       , ("thorn"      , "\xc3\xbe")
-                       , ("Uacute"     , "\xc3\x9a")
-                       , ("uacute"     , "\xc3\xba")
-                       , ("Ucirc"      , "\xc3\x9b")
-                       , ("ucirc"      , "\xc3\xbb")
-                       , ("Ugrave"     , "\xc3\x99")
-                       , ("ugrave"     , "\xc3\xb9")
-                       , ("Uuml"       , "\xc3\x9c")
-                       , ("uuml"       , "\xc3\xbc")
-                       , ("Yacute"     , "\xc3\x9d")
-                       , ("yacute"     , "\xc3\xbd")
-                       , ("yuml"       , "\xc3\xbf")
-                       , ("Yuml"       , "\xc5\xb8")
-                       , ("cent"       , "\xc2\xa2")
-                       , ("curren"     , "\xc2\xa4")
-                       , ("euro"       , "\xe2\x82\xac")
-                       , ("pound"      , "\xc2\xa3")
-                       , ("yen"        , "\xc2\xa5")
-                       , ("brvbar"     , "\xc2\xa6")
-                       , ("bull"       , "\xe2\x80\xa2")
-                       , ("copy"       , "\xc2\xa9")
-                       , ("dagger"     , "\xe2\x80\xa0")
-                       , ("Dagger"     , "\xe2\x80\xa1")
-                       , ("frasl"      , "\xe2\x81\x84")
-                       , ("hellip"     , "\xe2\x80\xa6")
-                       , ("iexcl"      , "\xc2\xa1")
-                       , ("image"      , "\xe2\x84\x91")
-                       , ("iquest"     , "\xc2\xbf")
-                       , ("mdash"      , "\xe2\x80\x94")
-                       , ("ndash"      , "\xe2\x80\x93")
-                       , ("not"        , "\xc2\xac")
-                       , ("oline"      , "\xe2\x80\xbe")
-                       , ("ordf"       , "\xc2\xaa")
-                       , ("ordm"       , "\xc2\xba")
-                       , ("para"       , "\xc2\xb6")
-                       , ("permil"     , "\xe2\x80\xb0")
-                       , ("prime"      , "\xe2\x80\xb2")
-                       , ("Prime"      , "\xe2\x80\xb3")
-                       , ("real"       , "\xe2\x84\x9c")
-                       , ("reg"        , "\xc2\xae")
-                       , ("sect"       , "\xc2\xa7")
-                       , ("shy"        , "\173")
-                       , ("sup1"       , "\xc2\xb9")
-                       , ("trade"      , "\xe2\x84\xa2")
-                       , ("weierp"     , "\xe2\x84\x98")
-                       , ("bdquo"      , "\xe2\x80\x9e")
-                       , ("laquo"      , "\xc2\xab")
-                       , ("ldquo"      , "\xe2\x80\x9c")
-                       , ("lsaquo"     , "\xe2\x80\xb9")
-                       , ("lsquo"      , "\xe2\x80\x98")
-                       , ("raquo"      , "\xc2\xbb")
-                       , ("rdquo"      , "\xe2\x80\x9d")
-                       , ("rsaquo"     , "\xe2\x80\xba")
-                       , ("rsquo"      , "\xe2\x80\x99")
-                       , ("sbquo"      , "\xe2\x80\x9a")
-                       , ("emsp"       , "\xe2\x80\x83")
-                       , ("ensp"       , "\xe2\x80\x82")
-                       , ("nbsp"       , "\x20")
-                       , ("thinsp"     , "\xe2\x80\x89")
-                       , ("zwj"        , "\xe2\x80\x8d")
-                       , ("zwnj"       , "\xe2\x80\x8c")
-                       , ("deg"        , "\xc2\xb0")
-                       , ("divide"     , "\xc3\xb7")
-                       , ("frac12"     , "\xc2\xbd")
-                       , ("frac14"     , "\xc2\xbc")
-                       , ("frac34"     , "\xc2\xbe")
-                       , ("ge"         , "\xe2\x89\xa5")
-                       , ("le"         , "\xe2\x89\xa4")
-                       , ("minus"      , "\xe2\x88\x92")
-                       , ("sup2"       , "\xc2\xb2")
-                       , ("sup3"       , "\xc2\xb3")
-                       , ("times"      , "\xc3\x97")
-                       , ("alefsym"    , "\xe2\x84\xb5")
-                       , ("and"        , "\xe2\x88\xa7")
-                       , ("ang"        , "\xe2\x88\xa0")
-                       , ("asymp"      , "\xe2\x89\x88")
-                       , ("cap"        , "\xe2\x88\xa9")
-                       , ("cong"       , "\xe2\x89\x85")
-                       , ("cup"        , "\xe2\x88\xaa")
-                       , ("empty"      , "\xe2\x88\x85")
-                       , ("equiv"      , "\xe2\x89\xa1")
-                       , ("exist"      , "\xe2\x88\x83")
-                       , ("fnof"       , "\xc6\x92")
-                       , ("forall"     , "\xe2\x88\x80")
-                       , ("infin"      , "\xe2\x88\x9e")
-                       , ("int"        , "\xe2\x88\xab")
-                       , ("isin"       , "\xe2\x88\x88")
-                       , ("lang"       , "\xe3\x80\x88")
-                       , ("lceil"      , "\xe2\x8c\x88")
-                       , ("lfloor"     , "\xe2\x8c\x8a")
-                       , ("lowast"     , "\xe2\x88\x97")
-                       , ("micro"      , "\xc2\xb5")
-                       , ("nabla"      , "\xe2\x88\x87")
-                       , ("ne"         , "\xe2\x89\xa0")
-                       , ("ni"         , "\xe2\x88\x8b")
-                       , ("notin"      , "\xe2\x88\x89")
-                       , ("nsub"       , "\xe2\x8a\x84")
-                       , ("oplus"      , "\xe2\x8a\x95")
-                       , ("or"         , "\xe2\x88\xa8")
-                       , ("otimes"     , "\xe2\x8a\x97")
-                       , ("part"       , "\xe2\x88\x82")
-                       , ("perp"       , "\xe2\x8a\xa5")
-                       , ("plusmn"     , "\xc2\xb1")
-                       , ("prod"       , "\xe2\x88\x8f")
-                       , ("prop"       , "\xe2\x88\x9d")
-                       , ("radic"      , "\xe2\x88\x9a")
-                       , ("rang"       , "\xe3\x80\x89")
-                       , ("rceil"      , "\xe2\x8c\x89")
-                       , ("rfloor"     , "\xe2\x8c\x8b")
-                       , ("sdot"       , "\xe2\x8b\x85")
-                       , ("sim"        , "\xe2\x88\xbc")
-                       , ("sub"        , "\xe2\x8a\x82")
-                       , ("sube"       , "\xe2\x8a\x86")
-                       , ("sum"        , "\xe2\x88\x91")
-                       , ("sup"        , "\xe2\x8a\x83")
-                       , ("supe"       , "\xe2\x8a\x87")
-                       , ("there4"     , "\xe2\x88\xb4")
-                       , ("Alpha"      , "\xce\x91")
-                       , ("alpha"      , "\xce\xb1")
-                       , ("Beta"       , "\xce\x92")
-                       , ("beta"       , "\xce\xb2")
-                       , ("Chi"        , "\xce\xa7")
-                       , ("chi"        , "\xcf\x87")
-                       , ("Delta"      , "\xce\x94")
-                       , ("delta"      , "\xce\xb4")
-                       , ("Epsilon"    , "\xce\x95")
-                       , ("epsilon"    , "\xce\xb5")
-                       , ("Eta"        , "\xce\x97")
-                       , ("eta"        , "\xce\xb7")
-                       , ("Gamma"      , "\xce\x93")
-                       , ("gamma"      , "\xce\xb3")
-                       , ("Iota"       , "\xce\x99")
-                       , ("iota"       , "\xce\xb9")
-                       , ("Kappa"      , "\xce\x9a")
-                       , ("kappa"      , "\xce\xba")
-                       , ("Lambda"     , "\xce\x9b")
-                       , ("lambda"     , "\xce\xbb")
-                       , ("Mu"         , "\xce\x9c")
-                       , ("mu"         , "\xce\xbc")
-                       , ("Nu"         , "\xce\x9d")
-                       , ("nu"         , "\xce\xbd")
-                       , ("Omega"      , "\xce\xa9")
-                       , ("omega"      , "\xcf\x89")
-                       , ("Omicron"    , "\xce\x9f")
-                       , ("omicron"    , "\xce\xbf")
-                       , ("Phi"        , "\xce\xa6")
-                       , ("phi"        , "\xcf\x86")
-                       , ("Pi"         , "\xce\xa0")
-                       , ("pi"         , "\xcf\x80")
-                       , ("piv"        , "\xcf\x96")
-                       , ("Psi"        , "\xce\xa8")
-                       , ("psi"        , "\xcf\x88")
-                       , ("Rho"        , "\xce\xa1")
-                       , ("rho"        , "\xcf\x81")
-                       , ("Sigma"      , "\xce\xa3")
-                       , ("sigma"      , "\xcf\x83")
-                       , ("sigmaf"     , "\xcf\x82")
-                       , ("Tau"        , "\xce\xa4")
-                       , ("tau"        , "\xcf\x84")
-                       , ("Theta"      , "\xce\x98")
-                       , ("theta"      , "\xce\xb8")
-                       , ("thetasym"   , "\xcf\x91")
-                       , ("upsih"      , "\xcf\x92")
-                       , ("Upsilon"    , "\xce\xa5")
-                       , ("upsilon"    , "\xcf\x85")
-                       , ("Xi"         , "\xce\x9e")
-                       , ("xi"         , "\xce\xbe")
-                       , ("Zeta"       , "\xce\x96")
-                       , ("zeta"       , "\xce\xb6")
-                       , ("crarr"      , "\xe2\x86\xb5")
-                       , ("darr"       , "\xe2\x86\x93")
-                       , ("dArr"       , "\xe2\x87\x93")
-                       , ("harr"       , "\xe2\x86\x94")
-                       , ("hArr"       , "\xe2\x87\x94")
-                       , ("larr"       , "\xe2\x86\x90")
-                       , ("lArr"       , "\xe2\x87\x90")
-                       , ("rarr"       , "\xe2\x86\x92")
-                       , ("rArr"       , "\xe2\x87\x92")
-                       , ("uarr"       , "\xe2\x86\x91")
-                       , ("uArr"       , "\xe2\x87\x91")
-                       , ("clubs"      , "\xe2\x99\xa3")
-                       , ("diams"      , "\xe2\x99\xa6")
-                       , ("hearts"     , "\xe2\x99\xa5")
-                       , ("spades"     , "\xe2\x99\xa0")
-                       , ("loz"        , "\xe2\x97\x8a") ]
-
- diff --git a/static/docs/0.2.4/heist/src/Text-Templating-Heist-Internal.html b/static/docs/0.2.4/heist/src/Text-Templating-Heist-Internal.html deleted file mode 100644 index 2546209..0000000 --- a/static/docs/0.2.4/heist/src/Text-Templating-Heist-Internal.html +++ /dev/null @@ -1,524 +0,0 @@ - - - - -src/Text/Templating/Heist/Internal.hs - - - -
{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-
-module Text.Templating.Heist.Internal where
-
-------------------------------------------------------------------------------
-import           Control.Exception (SomeException)
-import           Control.Monad.CatchIO
-import           Control.Monad.RWS.Strict
-import           Data.ByteString.Char8 (ByteString)
-import qualified Data.ByteString.Char8 as B
-import qualified Data.ByteString.Lazy as L
-import           Data.Either
-import qualified Data.Foldable as F
-import           Data.List
-import qualified Data.Map as Map
-import           Data.Map (Map)
-import           Data.Typeable
-import           Prelude hiding (catch)
-import           System.Directory.Tree hiding (name)
-import           Text.XML.Expat.Format
-import qualified Text.XML.Expat.Tree as X
-
-------------------------------------------------------------------------------
-import           Text.Templating.Heist.Constants
-
-------------------------------------------------------------------------------
--- Types
-------------------------------------------------------------------------------
-
--- | Heist templates are XML documents. The hexpat library is polymorphic over
--- the type of strings, so here we define a 'Node' alias to fix the string
--- types of the tag names and tag bodies to 'ByteString'.
-type Node = X.Node ByteString ByteString
-
-
-------------------------------------------------------------------------------
--- | A 'Template' is a forest of XML nodes.
-type Template = [Node]
-
-
-------------------------------------------------------------------------------
--- | Reversed list of directories
-type TPath = [ByteString]
-
-
-------------------------------------------------------------------------------
-type TemplateMap = Map TPath Template
-
-
-------------------------------------------------------------------------------
--- | Holds all the state information needed for template processing:
---
---     * a collection of named templates. If you use the @\<apply
---       template=\"foo\"\>@ tag to include another template by name, @\"foo\"@
---       is looked up in here.
---
---     * the mapping from tag names to 'Splice's.
---
---     * a flag to control whether we will recurse during splice processing.
---
--- We'll illustrate the recursion flag with a small example template:
---
---   > <foo>
---   >   <bar>
---   >     ...
---   >   </bar>
---   > </foo>
---
--- Assume that @\"foo\"@ is bound to a splice procedure. Running the @foo@
--- splice will result in a list of nodes @L@; if the recursion flag is on we
--- will recursively scan @L@ for splices, otherwise @L@ will be included in the
--- output verbatim.
-data TemplateState m = TemplateState {
-    -- | A mapping of splice names to splice actions
-      _spliceMap      :: SpliceMap m
-    -- | A mapping of template names to templates
-    , _templateMap    :: TemplateMap
-    -- | A flag to control splice recursion
-    , _recurse        :: Bool
-    , _curContext     :: TPath
-    , _recursionDepth :: Int
-    , _onLoadHook     :: Template -> IO Template
-    , _preRunHook     :: Template -> m Template
-    , _postRunHook    :: Template -> m Template
-}
-
-
-------------------------------------------------------------------------------
-instance Eq (TemplateState m) where
-    a == b = (_recurse a == _recurse b) &&
-             (_templateMap a == _templateMap b) &&
-             (_curContext a == _curContext b)
-
-
-------------------------------------------------------------------------------
--- | 'TemplateMonad' is a monad transformer that gives you access to the 'Node'
---   being processed (using the 'MonadReader' instance) as well as holding the
---   'TemplateState' that contains splice and template mappings (accessible
---   using the 'MonadState' instance.
-newtype TemplateMonad m a = TemplateMonad (RWST Node () (TemplateState m) m a)
-  deriving ( Monad
-           , MonadIO
-           , MonadCatchIO
-           , MonadReader Node
-           , MonadState (TemplateState m) )
-
-
-------------------------------------------------------------------------------
-instance (Monad m) => Monoid (TemplateState m) where
-    mempty = TemplateState Map.empty Map.empty True [] 0
-                           return return return
-
-    (TemplateState s1 t1 r1 _ d1 o1 b1 a1) `mappend`
-        (TemplateState s2 t2 r2 c2 d2 o2 b2 a2) =
-        TemplateState s t r c2 d (o1 >=> o2) (b1 >=> b2) (a1 >=> a2)
-      where
-        s = s1 `mappend` s2
-        t = t1 `mappend` t2
-        r = r1 && r2
-        d = max d1 d2
-
-
-------------------------------------------------------------------------------
-instance MonadTrans TemplateMonad where
-  lift = TemplateMonad . lift
-
-------------------------------------------------------------------------------
-instance (Typeable1 m, Typeable a) => Typeable (TemplateMonad m a) where
-    typeOf _ = mkTyConApp tCon [mRep, aRep]
-      where
-        tCon = mkTyCon "TemplateMonad"
-        maRep = typeOf (undefined :: m a)
-        (mCon, [aRep]) = splitTyConApp maRep
-        mRep = mkTyConApp mCon []
-
-
-------------------------------------------------------------------------------
--- | A Splice is a TemplateMonad computation that returns [Node].
-type Splice m = TemplateMonad m Template
-
-
-------------------------------------------------------------------------------
--- | SpliceMap associates a name and a Splice.
-type SpliceMap m = Map ByteString (Splice m)
-
-
-------------------------------------------------------------------------------
--- TemplateState functions
-------------------------------------------------------------------------------
-
-
-------------------------------------------------------------------------------
--- | Adds an on-load hook to a `TemplateState`.
-addOnLoadHook :: (Monad m) =>
-                 (Template -> IO Template)
-              -> TemplateState m
-              -> TemplateState m
-addOnLoadHook hook ts = ts { _onLoadHook = _onLoadHook ts >=> hook }
-
-
-------------------------------------------------------------------------------
--- | Adds a pre-run hook to a `TemplateState`.
-addPreRunHook :: (Monad m) =>
-                 (Template -> m Template)
-              -> TemplateState m
-              -> TemplateState m
-addPreRunHook hook ts = ts { _preRunHook = _preRunHook ts >=> hook }
-
-
-------------------------------------------------------------------------------
--- | Adds a post-run hook to a `TemplateState`.
-addPostRunHook :: (Monad m) =>
-                  (Template -> m Template)
-               -> TemplateState m
-               -> TemplateState m
-addPostRunHook hook ts = ts { _postRunHook = _postRunHook ts >=> hook }
-
-
-------------------------------------------------------------------------------
--- | Bind a new splice declaration to a tag name within a 'TemplateState'.
-bindSplice :: Monad m =>
-              ByteString        -- ^ tag name
-           -> Splice m          -- ^ splice action
-           -> TemplateState m   -- ^ source state
-           -> TemplateState m
-bindSplice n v ts = ts {_spliceMap = Map.insert n v (_spliceMap ts)}
-
-
-------------------------------------------------------------------------------
--- | Convenience function for looking up a splice.
-lookupSplice :: Monad m =>
-                ByteString
-             -> TemplateState m
-             -> Maybe (Splice m)
-lookupSplice nm ts = Map.lookup nm $ _spliceMap ts
-
-
-------------------------------------------------------------------------------
--- | Converts a path into an array of the elements in reverse order.  If the
--- path is absolute, we need to remove the leading slash so the split doesn't
--- leave @\"\"@ as the last element of the TPath.
---
--- FIXME @\"..\"@ currently doesn't work in paths, the solution is non-trivial
-splitPaths :: ByteString -> TPath
-splitPaths p = if B.null p then [] else (reverse $ B.split '/' path)
-  where
-    path = if B.head p == '/' then B.tail p else p
-
-
-------------------------------------------------------------------------------
--- | Does a single template lookup without cascading up.
-singleLookup :: TemplateMap
-             -> TPath
-             -> ByteString
-             -> Maybe (Template, TPath)
-singleLookup tm path name = fmap (\a -> (a,path)) $ Map.lookup (name:path) tm
-
-
-------------------------------------------------------------------------------
--- | Searches for a template by looking in the full path then backing up into each
--- of the parent directories until the template is found.
-traversePath :: TemplateMap
-             -> TPath
-             -> ByteString
-             -> Maybe (Template, TPath)
-traversePath tm [] name = fmap (\a -> (a,[])) (Map.lookup [name] tm)
-traversePath tm path name =
-    singleLookup tm path name `mplus`
-    traversePath tm (tail path) name
-
-
-------------------------------------------------------------------------------
--- | Convenience function for looking up a template.
-lookupTemplate :: Monad m =>
-                  ByteString
-               -> TemplateState m
-               -> Maybe (Template, TPath)
-lookupTemplate nameStr ts = 
-    f (_templateMap ts) path name
-  where (name:p) = case splitPaths nameStr of
-                       [] -> [""]
-                       ps -> ps
-        path = p ++ (_curContext ts)
-        f = if '/' `B.elem` nameStr
-                then singleLookup
-                else traversePath
-
-
-------------------------------------------------------------------------------
--- | Sets the templateMap in a TemplateState.
-setTemplates :: Monad m => TemplateMap -> TemplateState m -> TemplateState m
-setTemplates m ts = ts { _templateMap = m }
-
-
-------------------------------------------------------------------------------
--- | Adds a template to the template state.
-insertTemplate :: Monad m =>
-               TPath
-            -> Template
-            -> TemplateState m
-            -> TemplateState m
-insertTemplate p t st =
-    setTemplates (Map.insert p t (_templateMap st)) st
-
-
-------------------------------------------------------------------------------
--- | Adds a template to the template state.
-addTemplate :: Monad m =>
-               ByteString
-            -> Template
-            -> TemplateState m
-            -> TemplateState m
-addTemplate n t st = insertTemplate (splitPaths n) t st
-
-
-------------------------------------------------------------------------------
--- | Gets the node currently being processed.
-getParamNode :: Monad m => TemplateMonad m Node
-getParamNode = ask
-
-
-------------------------------------------------------------------------------
--- | Stops the recursive processing of splices.
-stopRecursion :: Monad m => TemplateMonad m ()
-stopRecursion = modify (\st -> st { _recurse = False })
-
-
-------------------------------------------------------------------------------
--- | Sets the current context
-setContext :: Monad m => TPath -> TemplateMonad m ()
-setContext c = modify (\st -> st { _curContext = c })
-
-
-------------------------------------------------------------------------------
--- | Gets the current context
-getContext :: Monad m => TemplateMonad m TPath
-getContext = gets _curContext
-  
-
-------------------------------------------------------------------------------
--- | Performs splice processing on a list of nodes.
-runNodeList :: Monad m => [Node] -> Splice m
-runNodeList nodes = liftM concat $ sequence (map runNode nodes)
-
-
-------------------------------------------------------------------------------
--- | Performs splice processing on a single node.
-runNode :: Monad m => Node -> Splice m
-runNode n@(X.Text _)          = return [n]
-runNode n@(X.Element nm _ ch) = do
-    s <- liftM (lookupSplice nm) get
-    maybe runChildren (recurseSplice n) s
-
-  where
-    runChildren = do
-        newKids <- runNodeList ch
-        return [X.modifyChildren (const newKids) n]
-
-
-------------------------------------------------------------------------------
--- | The maximum recursion depth.  (Used to prevent infinite loops.)
-mAX_RECURSION_DEPTH :: Int
-mAX_RECURSION_DEPTH = 20
-
-
-------------------------------------------------------------------------------
--- | Checks the recursion flag and recurses accordingly.  Does not recurse
--- deeper than mAX_RECURSION_DEPTH to avoid infinite loops.
-recurseSplice :: Monad m => Node -> Splice m -> Splice m
-recurseSplice node splice = do
-    result <- local (const node) splice
-    ts' <- get
-    if _recurse ts' && _recursionDepth ts' < mAX_RECURSION_DEPTH
-        then do modify (\st -> st { _recursionDepth = _recursionDepth st + 1 })
-                res <- runNodeList result
-                put ts'
-                return res
-        else return result
-
-
-------------------------------------------------------------------------------
--- | Runs a splice in the underlying monad.  Splices require two
--- parameters, the template state, and an input node.
-runSplice :: Monad m =>
-             TemplateState m -- ^ The initial template state
-          -> Node            -- ^ The splice's input node
-          -> Splice m        -- ^ The splice
-          -> m [Node]
-runSplice ts node (TemplateMonad splice) = do
-    (result,_,_) <- runRWST splice node ts
-    return result
-
-
-------------------------------------------------------------------------------
--- | Runs a template in the underlying monad.  Similar to runSplice
--- except that templates don't require a Node as a parameter.
-runRawTemplate :: Monad m => TemplateState m -> Template -> m [Node]
-runRawTemplate ts template =
-    _preRunHook ts template >>=
-    runSplice ts (X.Text "") . runNodeList >>=
-    _postRunHook ts
-
-
-------------------------------------------------------------------------------
--- | Looks up a template name in the supplied 'TemplateState' and runs
--- it in the underlying monad.
-runTemplate :: Monad m
-            => TemplateState m
-            -> ByteString
-            -> m (Maybe [Node])
-runTemplate ts name =
-    maybe (return Nothing)
-          (\(t,ctx) ->
-              return . Just =<<
-              runRawTemplate (ts {_curContext = ctx}) t)
-          (lookupTemplate name ts)
-
-
-------------------------------------------------------------------------------
--- | Looks up a template name evaluates it.  Same as runTemplate except it
--- runs in TemplateMonad instead of m.
-evalTemplate :: Monad m
-            => ByteString
-            -> TemplateMonad m (Maybe [Node])
-evalTemplate name = do
-    ts <- get
-    lift $ runTemplate ts name
-
-
-------------------------------------------------------------------------------
--- | Binds a list of constant string splices
-bindStrings :: Monad m
-            => [(ByteString, ByteString)]
-            -> TemplateState m
-            -> TemplateState m
-bindStrings pairs ts = foldr add ts pairs
-  where
-    add (n,v) = bindSplice n (return [X.Text v])
-
-
-------------------------------------------------------------------------------
--- | Renders a template with the specified parameters.  This is the function
--- to use when you want to "call" a template and pass in parameters from code.
-callTemplate :: Monad m
-             => ByteString                 -- ^ The name of the template
-             -> [(ByteString, ByteString)] -- ^ Association list of
-                                           -- (name,value) parameter pairs
-             -> TemplateMonad m (Maybe Template)
-callTemplate name params = do
-    modify $ bindStrings params
-    evalTemplate name
-
-
-------------------------------------------------------------------------------
--- | Renders a template from the specified TemplateState.
-renderTemplate :: Monad m
-               => TemplateState m
-               -> ByteString
-               -> m (Maybe ByteString)
-renderTemplate ts name = do
-    ns <- runTemplate ts name
-    return $ (Just . formatList') =<< ns
-
-
-------------------------------------------------------------------------------
-heistExpatOptions :: X.ParserOptions ByteString ByteString
-heistExpatOptions =
-    X.defaultParserOptions {
-           X.parserEncoding = Just X.UTF8
-         , X.entityDecoder  = Just (\k -> Map.lookup k htmlEntityLookupTable)
-         }
-
-------------------------------------------------------------------------------
--- Template loading
-------------------------------------------------------------------------------
-
--- | Reads an XML document from disk.
-getDoc :: String -> IO (Either String Template)
-getDoc f = do
-    bs <- catch (liftM Right $ B.readFile f)
-                (\(e::SomeException) -> return $ Left $ show e)
-    let wrap b = "<snap:root>\n" `B.append` b `B.append` "\n</snap:root>"
-    return $ (mapRight X.getChildren .
-              mapLeft genErrorMsg .
-              X.parse' heistExpatOptions . wrap) =<< bs
-  where
-    genErrorMsg (X.XMLParseError str loc) = f ++ " " ++ locMsg loc ++ ": " ++ translate str
-    locMsg (X.XMLParseLocation line col _ _) =
-        "(line " ++ show (line-1) ++ ", col " ++ show col ++ ")"
-    translate "junk after document element" = "document must have a single root element"
-    translate s = s
-
-------------------------------------------------------------------------------
-mapLeft :: (a -> b) -> Either a c -> Either b c
-mapLeft g = either (Left . g) Right
-mapRight :: (b -> c) -> Either a b -> Either a c
-mapRight g = either Left (Right . g)
-
-
-------------------------------------------------------------------------------
--- | Loads a template with the specified path and filename.  The
--- template is only loaded if it has a ".tpl" extension.
-loadTemplate :: String -- ^ path of the template root
-             -> String -- ^ full file path (includes the template root)
-             -> IO [Either String (TPath, Template)] --TemplateMap
-loadTemplate templateRoot fname
-    | ".tpl" `isSuffixOf` fname = do
-        c <- getDoc fname
-        return [fmap (\t -> (splitPaths $ B.pack tName, t)) c]
-    | otherwise = return []
-  where -- tName is path relative to the template root directory
-        tName = drop ((length templateRoot)+1) $
-                -- We're only dropping the template root, not the whole path
-                take ((length fname) - 4) fname
-
-
-------------------------------------------------------------------------------
--- | Traverses the specified directory structure and builds a
--- TemplateState by loading all the files with a ".tpl" extension.
-loadTemplates :: Monad m => FilePath -> TemplateState m -> IO (Either String (TemplateState m))
-loadTemplates dir ts = do
-    d <- readDirectoryWith (loadTemplate dir) dir
-    let tlist = F.fold (free d)
-        errs = lefts tlist
-    case errs of
-        [] -> liftM Right $ foldM loadHook ts $ rights tlist
-        _  -> return $ Left $ unlines errs
-
-
-------------------------------------------------------------------------------
--- | Runs the onLoad hook on the template and returns the `TemplateState`
--- with the result inserted.
-loadHook :: Monad m => TemplateState m -> (TPath, Template) -> IO (TemplateState m)
-loadHook ts (tp, t) = do
-    t' <- _onLoadHook ts t
-    return $ insertTemplate tp t' ts
-
-
-------------------------------------------------------------------------------
--- These are here until we can get them into hexpat.
-------------------------------------------------------------------------------
-
-formatList :: (X.GenericXMLString tag, X.GenericXMLString text) =>
-              [X.Node tag text]
-           -> L.ByteString
-formatList nodes = foldl L.append L.empty $ map formatNode nodes
-
-formatList' :: (X.GenericXMLString tag, X.GenericXMLString text) =>
-               [X.Node tag text]
-            -> B.ByteString
-formatList' = B.concat . L.toChunks . formatList
-
-
- diff --git a/static/docs/0.2.4/heist/src/Text-Templating-Heist-Splices-Apply.html b/static/docs/0.2.4/heist/src/Text-Templating-Heist-Splices-Apply.html deleted file mode 100644 index 83efe53..0000000 --- a/static/docs/0.2.4/heist/src/Text-Templating-Heist-Splices-Apply.html +++ /dev/null @@ -1,57 +0,0 @@ - - - - -src/Text/Templating/Heist/Splices/Apply.hs - - - -
{-# LANGUAGE OverloadedStrings #-}
-
-module Text.Templating.Heist.Splices.Apply where
-
-------------------------------------------------------------------------------
-import           Control.Monad.RWS.Strict
-import           Data.ByteString.Char8 (ByteString)
-import qualified Data.ByteString.Char8 as B
-import qualified Text.XML.Expat.Tree as X
-
-------------------------------------------------------------------------------
-import           Text.Templating.Heist.Internal
-
-------------------------------------------------------------------------------
--- | Default name for the apply splice.
-applyTag :: ByteString
-applyTag = "apply"
-
-
-------------------------------------------------------------------------------
--- | Default attribute name for the apply tag.
-applyAttr :: ByteString
-applyAttr = "template"
-
-
-------------------------------------------------------------------------------
--- | Implementation of the apply splice.
-applyImpl :: Monad m => Splice m
-applyImpl = do
-    node <- getParamNode
-    case X.getAttribute node applyAttr of
-        Nothing   -> return [] -- TODO: error handling
-        Just attr -> do 
-            st <- get
-            processedChildren <- runNodeList $ X.getChildren node
-            modify (bindSplice "content" $ return processedChildren)
-            maybe (return []) -- TODO: error handling
-                  (\(t,ctx) -> do setContext ctx
-                                  result <- runNodeList t
-                                  put st
-                                  return result)
-                  (lookupTemplate attr (st {_curContext = nextCtx attr st}))
-  where nextCtx name st
-            | B.isPrefixOf "/" name = []
-            | otherwise             = _curContext st
-
-
-
- diff --git a/static/docs/0.2.4/heist/src/Text-Templating-Heist-Splices-Bind.html b/static/docs/0.2.4/heist/src/Text-Templating-Heist-Splices-Bind.html deleted file mode 100644 index 27c602f..0000000 --- a/static/docs/0.2.4/heist/src/Text-Templating-Heist-Splices-Bind.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - -src/Text/Templating/Heist/Splices/Bind.hs - - - -
{-# LANGUAGE OverloadedStrings #-}
-
-module Text.Templating.Heist.Splices.Bind where
-
-------------------------------------------------------------------------------
-import           Control.Monad.RWS.Strict
-import           Data.ByteString.Char8 (ByteString)
-import qualified Text.XML.Expat.Tree as X
-
-------------------------------------------------------------------------------
-import           Text.Templating.Heist.Internal
-
--- | Default name for the bind splice.
-bindTag :: ByteString
-bindTag = "bind"
-
-
-------------------------------------------------------------------------------
--- | Default attribute name for the bind tag.
-bindAttr :: ByteString
-bindAttr = "tag"
-
-
-------------------------------------------------------------------------------
--- | Implementation of the bind splice.
-bindImpl :: Monad m => Splice m
-bindImpl = do
-    node <- getParamNode
-    maybe (return ())
-          (add node)
-          (X.getAttribute node bindAttr)
-    return []
-
-  where
-    add node nm = modify $ bindSplice nm (return $ X.getChildren node)
-
-
-
- diff --git a/static/docs/0.2.4/heist/src/Text-Templating-Heist-Splices-Ignore.html b/static/docs/0.2.4/heist/src/Text-Templating-Heist-Splices-Ignore.html deleted file mode 100644 index 94cfc79..0000000 --- a/static/docs/0.2.4/heist/src/Text-Templating-Heist-Splices-Ignore.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - -src/Text/Templating/Heist/Splices/Ignore.hs - - - -
{-# LANGUAGE OverloadedStrings #-}
-
-module Text.Templating.Heist.Splices.Ignore where
-
-------------------------------------------------------------------------------
-import           Data.ByteString.Char8 (ByteString)
-
-------------------------------------------------------------------------------
-import           Text.Templating.Heist.Internal
-
-
-------------------------------------------------------------------------------
--- | Default name for the ignore splice.
-ignoreTag :: ByteString
-ignoreTag = "ignore"
-
-
-------------------------------------------------------------------------------
--- | The ignore tag and everything it surrounds disappears in the
--- rendered output.
-ignoreImpl :: Monad m => Splice m
-ignoreImpl = return []
-
-
-
- diff --git a/static/docs/0.2.4/heist/src/Text-Templating-Heist-Splices-Markdown.html b/static/docs/0.2.4/heist/src/Text-Templating-Heist-Splices-Markdown.html deleted file mode 100644 index fc4682c..0000000 --- a/static/docs/0.2.4/heist/src/Text-Templating-Heist-Splices-Markdown.html +++ /dev/null @@ -1,160 +0,0 @@ - - - - -src/Text/Templating/Heist/Splices/Markdown.hs - - - -
{-# LANGUAGE OverloadedStrings, DeriveDataTypeable #-}
-
-module Text.Templating.Heist.Splices.Markdown where
-
-import           Data.ByteString (ByteString)
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Char8 as BC
-import           Data.Maybe
-import           Control.Concurrent
-import           Control.Exception (throwIO)
-import           Control.Monad
-import           Control.Monad.CatchIO
-import           Control.Monad.Trans
-import           Data.Typeable
-import           Prelude hiding (catch)
-import           System.Directory
-import           System.Exit
-import           System.IO
-import           System.Process
-import           Text.Templating.Heist.Internal
-import           Text.XML.Expat.Tree hiding (Node)
-
-
-data PandocMissingException = PandocMissingException
-   deriving (Typeable)
-
-instance Show PandocMissingException where
-    show PandocMissingException =
-        "Cannot find the \"pandoc\" executable; is it on your $PATH?"
-
-instance Exception PandocMissingException
-
-
-data MarkdownException = MarkdownException ByteString
-   deriving (Typeable)
-
-instance Show MarkdownException where
-    show (MarkdownException e) =
-        "Markdown error: pandoc replied:\n\n" ++ BC.unpack e
-
-instance Exception MarkdownException
-
-
-------------------------------------------------------------------------------
--- | Default name for the markdown splice.
-markdownTag :: ByteString
-markdownTag = "markdown"
-
-------------------------------------------------------------------------------
--- | Implementation of the markdown splice.
-markdownSplice :: MonadIO m => Splice m
-markdownSplice = do
-    pdMD <- liftIO $ findExecutable "pandoc"
-
-    when (isNothing pdMD) $ liftIO $ throwIO PandocMissingException
-
-    tree <- getParamNode
-    markup <- liftIO $
-        case getAttribute tree "file" of
-            Just f  -> pandoc (fromJust pdMD) $ BC.unpack f
-            Nothing -> pandocBS (fromJust pdMD) $ textContent tree
-
-    let ee = parse' heistExpatOptions markup
-    case ee of
-      (Left e) -> throw $ MarkdownException
-                        $ BC.pack ("Error parsing markdown output: " ++ show e)
-      (Right n) -> return [n]
-
-
-pandoc :: FilePath -> FilePath -> IO ByteString
-pandoc pandocPath inputFile = do
-    (ex, sout, serr) <- readProcessWithExitCode' pandocPath args ""
-
-    when (isFail ex) $ throw $ MarkdownException serr
-    return $ BC.concat [ "<div class=\"markdown\">\n"
-                       , sout
-                       , "\n</div>" ]
-
-  where
-    isFail ExitSuccess = False
-    isFail _           = True
-
-    -- FIXME: hardcoded path
-    args = [ "-S", "--no-wrap", "templates/"++inputFile ]
-
-
-pandocBS :: FilePath -> ByteString -> IO ByteString
-pandocBS pandocPath s = do
-    -- using the crummy string functions for convenience here
-    (ex, sout, serr) <- readProcessWithExitCode' pandocPath args s
-
-    when (isFail ex) $ throw $ MarkdownException serr
-    return $ BC.concat [ "<div class=\"markdown\">\n"
-                       , sout
-                       , "\n</div>" ]
-
-  where
-    isFail ExitSuccess = False
-    isFail _           = True
-    args = [ "-S", "--no-wrap" ]
-
-
--- a version of readProcessWithExitCode that does I/O properly
-readProcessWithExitCode'
-    :: FilePath                 -- ^ command to run
-    -> [String]                 -- ^ any arguments
-    -> ByteString               -- ^ standard input
-    -> IO (ExitCode,ByteString,ByteString) -- ^ exitcode, stdout, stderr
-readProcessWithExitCode' cmd args input = do
-    (Just inh, Just outh, Just errh, pid) <-
-        createProcess (proc cmd args){ std_in  = CreatePipe,
-                                       std_out = CreatePipe,
-                                       std_err = CreatePipe }
-    outMVar <- newEmptyMVar
-
-    outM <- newEmptyMVar
-    errM <- newEmptyMVar
-
-    -- fork off a thread to start consuming stdout
-    forkIO $ do
-        out <- B.hGetContents outh
-        putMVar outM out
-        putMVar outMVar ()
-
-    -- fork off a thread to start consuming stderr
-    forkIO $ do
-        err  <- B.hGetContents errh
-        putMVar errM err
-        putMVar outMVar ()
-
-    -- now write and flush any input
-    when (not (B.null input)) $ do B.hPutStr inh input; hFlush inh
-    hClose inh -- done with stdin
-
-    -- wait on the output
-    takeMVar outMVar
-    takeMVar outMVar
-    hClose outh
-
-    -- wait on the process
-    ex <- waitForProcess pid
-
-    out <- readMVar outM
-    err <- readMVar errM
-
-    return (ex, out, err)
-
-
-
-
-
- diff --git a/static/docs/0.2.4/heist/src/Text-Templating-Heist-Splices-Static.html b/static/docs/0.2.4/heist/src/Text-Templating-Heist-Splices-Static.html deleted file mode 100644 index 734781d..0000000 --- a/static/docs/0.2.4/heist/src/Text-Templating-Heist-Splices-Static.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - -src/Text/Templating/Heist/Splices/Static.hs - - - -
{-# LANGUAGE OverloadedStrings #-}
-
-module Text.Templating.Heist.Splices.Static 
-  ( StaticTagState
-  , bindStaticTag
-  , clearStaticTagCache
-  ) where
-
-------------------------------------------------------------------------------
-import           Control.Concurrent
-import           Control.Monad
-import           Control.Monad.Trans
-import           Data.ByteString.Char8 (ByteString)
-import qualified Data.ByteString.Char8 as B
-import           Data.IORef
-import qualified Data.Map as Map
-import           Data.Map (Map)
-import           Data.Maybe
-import qualified Data.Set as Set
-import           System.Random
-import           Text.XML.Expat.Cursor
-import           Text.XML.Expat.Tree hiding (Node)
-
-
-------------------------------------------------------------------------------
-import           Text.Templating.Heist.Internal
-
-
-------------------------------------------------------------------------------
--- | State for storing static tag information
-newtype StaticTagState = STS (MVar (Map ByteString Template))
-
-
-------------------------------------------------------------------------------
--- | Clears the static tag state.
-clearStaticTagCache :: StaticTagState -> IO ()
-clearStaticTagCache (STS staticMVar) =
-    modifyMVar_ staticMVar (const $ return Map.empty)
-
-
-------------------------------------------------------------------------------
--- | The "static" splice ensures that its contents are evaluated once and then
--- cached.  The cached contents are returned every time the splice is
--- referenced.
-staticImpl :: (MonadIO m)
-           => StaticTagState
-           -> TemplateMonad m Template
-staticImpl (STS mv) = do
-    tree <- getParamNode
-    let i = fromJust $ getAttribute tree "id"
-
-    mp <- liftIO $ readMVar mv
-
-    (mp',ns) <- do
-                   let mbn = Map.lookup i mp
-                   case mbn of
-                       Nothing -> do
-                           nodes' <- runNodeList $ getChildren tree
-                           return $! (Map.insert i nodes' mp, nodes')
-                       (Just n) -> do
-                           stopRecursion
-                           return $! (mp,n)
-
-    liftIO $ modifyMVar_ mv (const $ return mp')
-
-    return ns
-
-
-------------------------------------------------------------------------------
--- | Modifies a TemplateState to include a "static" tag.
-bindStaticTag :: MonadIO m
-              => TemplateState m
-              -> IO (TemplateState m, StaticTagState)
-bindStaticTag ts = do
-    sr <- newIORef $ Set.empty
-    mv <- liftM STS $ newMVar Map.empty
-
-    return $ (addOnLoadHook (assignIds sr) $
-                bindSplice "static" (staticImpl mv) ts,
-              mv)
-
-  where
-    generateId :: IO Int
-    generateId = getStdRandom random
-
-    assignIds setref = mapM f
-        where
-          f node = g $ fromTree node
-
-          getId = do
-              i  <- liftM (B.pack . show) generateId
-              st <- readIORef setref
-              if Set.member i st
-                then getId
-                else do
-                    writeIORef setref $ Set.insert i st
-                    return i
-
-          g curs = do
-              let node = current curs
-              curs' <- if getName node == "static"
-                         then do
-                             i <- getId
-                             return $ modifyContent (setAttribute "id" i) curs
-                         else return curs
-              let mbc = nextDF curs'
-              maybe (return $ toTree curs') g mbc
-
-
-
-
-
- diff --git a/static/docs/0.2.4/heist/src/Text-Templating-Heist-Splices.html b/static/docs/0.2.4/heist/src/Text-Templating-Heist-Splices.html deleted file mode 100644 index 9919a2e..0000000 --- a/static/docs/0.2.4/heist/src/Text-Templating-Heist-Splices.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - -src/Text/Templating/Heist/Splices.hs - - - -
module Text.Templating.Heist.Splices
-  ( module Text.Templating.Heist.Splices.Apply
-  , module Text.Templating.Heist.Splices.Bind
-  , module Text.Templating.Heist.Splices.Ignore
-  , module Text.Templating.Heist.Splices.Markdown
-  , module Text.Templating.Heist.Splices.Static
-  ) where
-
-import Text.Templating.Heist.Splices.Apply
-import Text.Templating.Heist.Splices.Bind
-import Text.Templating.Heist.Splices.Ignore
-import Text.Templating.Heist.Splices.Markdown
-import Text.Templating.Heist.Splices.Static
-
-
- diff --git a/static/docs/0.2.4/heist/src/Text-Templating-Heist.html b/static/docs/0.2.4/heist/src/Text-Templating-Heist.html deleted file mode 100644 index d02f5a7..0000000 --- a/static/docs/0.2.4/heist/src/Text-Templating-Heist.html +++ /dev/null @@ -1,155 +0,0 @@ - - - - -src/Text/Templating/Heist.hs - - - -
{-# LANGUAGE OverloadedStrings, GeneralizedNewtypeDeriving #-}
-
-{-|
-
-  This module contains the core definitions for the Heist template system.
-
-  The Heist template system is based on XML\/xhtml.  It allows you to build
-  custom XML-based markup languages.  With Heist you can define your own
-  domain-specific XML tags implemented with Haskell and use them in your
-  templates.  
-
-  The most important concept in Heist is the 'Splice'.  Splices can be thought
-  of as functions that transform a node into a list of nodes.  Heist then
-  substitutes the resulting list of nodes into your template in place of the
-  input node.  'Splice' is implemented as a type synonym @type Splice m =
-  TemplateMonad m [Node]@, and 'TemplateMonad' has a function 'getParamNode'
-  that lets you get the input node.
-
-  Suppose you have a place on your page where you want to display a link with
-  the text \"Logout username\" if the user is currently logged in or a link to
-  the login page if no user is logged in.  Assume you have a function
-  @getUser :: MyAppMonad (Maybe ByteString)@ that gets the current user.
-  You can implement this functionality with a 'Splice' as follows:
-
-  >
-  > import Text.XML.Expat.Tree
-  >
-  > link :: ByteString -> ByteString -> Node
-  > link target text = X.Element "a" [("href", target)] [X.Text text]
-  > 
-  > loginLink :: Node
-  > loginLink = link "/login" "Login"
-  > 
-  > logoutLink :: ByteString -> Node
-  > logoutLink user = link "/logout" (B.append "Logout " user)
-  > 
-  > loginLogoutSplice :: Splice MyAppMonad
-  > loginLogoutSplice = do
-  >     user <- lift getUser
-  >     return $ [maybe loginLink logoutLink user]
-  >
-
-  Next, you need to bind that splice to an XML tag.  Heist stores information
-  about splices and templates in the 'TemplateState' data structure.  The
-  following code demonstrates how this splice would be used.
-
-  > mySplices = [ ("loginLogout", loginLogoutSplice) ]
-  > 
-  > main = do
-  >     ets <- loadTemplates "templates" $
-  >            foldr (uncurry bindSplice) emptyTemplateState mySplices
-  >     let ts = either error id ets
-  >     t <- runMyAppMonad $ renderTemplate ts "index"
-  >     print $ maybe "Page not found" id t
-
-  Here we build up our 'TemplateState' by starting with emptyTemplateState and
-  applying bindSplice for all the splices we want to add.  Then we pass this
-  to loadTemplates our final 'TemplateState' wrapped in an Either to handle
-  errors.  Then we use this 'TemplateState' to render our templates.
-
--}
-
-module Text.Templating.Heist
-  (
-    -- * Types
-    Node
-  , Splice
-  , Template
-  , TemplateMonad
-  , TemplateState
-
-    -- * Functions and declarations on TemplateState values
-  , addTemplate
-  , emptyTemplateState
-  , bindSplice
-  , lookupSplice
-  , setTemplates
-  , loadTemplates
-
-    -- * Hook functions
-    -- $hookDoc
-  , addOnLoadHook
-  , addPreRunHook
-  , addPostRunHook
-
-    -- * TemplateMonad functions
-  , stopRecursion
-  , getParamNode
-  , runNodeList
-  , getContext
-
-    -- * Functions for running splices and templates
-  , runTemplate
-  , evalTemplate
-  , callTemplate
-  , renderTemplate
-  , bindStrings
-
-    -- * Misc functions
-  , runSplice
-  , runRawTemplate
-  , getDoc
-  , bindStaticTag
-
-  , heistExpatOptions
-  , module Text.Templating.Heist.Constants
-  ) where
-
-import           Control.Monad.Trans
-import qualified Data.Map as Map
-import           Text.Templating.Heist.Internal
-import           Text.Templating.Heist.Constants
-import           Text.Templating.Heist.Splices
-
-
-------------------------------------------------------------------------------
--- | The default set of built-in splices.
-defaultSpliceMap :: MonadIO m => SpliceMap m
-defaultSpliceMap = Map.fromList
-    [(applyTag, applyImpl)
-    ,(bindTag, bindImpl)
-    ,(ignoreTag, ignoreImpl)
-    ,(markdownTag, markdownSplice)
-    ]
-
-
-------------------------------------------------------------------------------
--- | An empty template state, with Heist's default splices (@\<bind\>@ and
--- @\<apply\>@) mapped.
-emptyTemplateState :: MonadIO m => TemplateState m
-emptyTemplateState = TemplateState defaultSpliceMap Map.empty True [] 0
-                                   return return return
-
-
--- $hookDoc
--- Heist hooks allow you to modify templates when they are loaded and before
--- and after they are run.  Every time you call one of the addAbcHook
--- functions the hook is added to onto the processing pipeline.  The hooks
--- processes the template in the order that they were added to the
--- TemplateState.
---
--- The pre-run and post-run hooks are run before and after every template is
--- run/rendered.  You should be careful what code you put in these hooks
--- because it can significantly affect the performance of your site.
-
-
- diff --git a/static/docs/0.2.4/heist/src/hscolour.css b/static/docs/0.2.4/heist/src/hscolour.css deleted file mode 100644 index 150e4d0..0000000 --- a/static/docs/0.2.4/heist/src/hscolour.css +++ /dev/null @@ -1,15 +0,0 @@ -body { font-size: 90%; } - -pre, code, body { - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; -} - -.hs-keyglyph, .hs-layout {color: #5200A3;} -.hs-keyword {color: #3465a4; font-weight: bold;} -.hs-comment, .hs-comment a {color: #579; } -.hs-str, .hs-chr {color: #141B24;} -.hs-keyword, .hs-conid, .hs-varid, .hs-conop, .hs-varop, .hs-num, .hs-cpp, .hs-sel, .hs-definition {} diff --git a/static/docs/0.2.4/snap-core/Data-CIByteString.html b/static/docs/0.2.4/snap-core/Data-CIByteString.html deleted file mode 100644 index 7dd5821..0000000 --- a/static/docs/0.2.4/snap-core/Data-CIByteString.html +++ /dev/null @@ -1,366 +0,0 @@ - - -Data.CIByteString
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Data.CIByteString
Description

Data.CIByteString is a module containing CIByteString, a wrapper for - ByteString which provides case-insensitive (ASCII-wise) Ord and Eq - instances. -

CIByteString also has an IsString instance, so if you use the - "OverloadedStrings" LANGUAGE pragma you can write case-insensitive string - literals, e.g.: -

- > let a = "Foo" in
-   putStrLn $ (show $ unCI a) ++ "==\"FoO\" is " ++ show (a == "FoO")
- "Foo"=="FoO" is True
-
Synopsis
data CIByteString
toCI :: ByteString -> CIByteString
unCI :: CIByteString -> ByteString
ciToLower :: CIByteString -> ByteString
Documentation
data CIByteString Source
A case-insensitive newtype wrapper for ByteString -
show/hide Instances
toCI :: ByteString -> CIByteStringSource
unCI :: CIByteString -> ByteStringSource
ciToLower :: CIByteString -> ByteStringSource
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.4/snap-core/Snap-Internal-Debug.html b/static/docs/0.2.4/snap-core/Snap-Internal-Debug.html deleted file mode 100644 index 501fad8..0000000 --- a/static/docs/0.2.4/snap-core/Snap-Internal-Debug.html +++ /dev/null @@ -1,169 +0,0 @@ - - -Snap.Internal.Debug
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Snap.Internal.Debug
Description

An internal Snap module for (optionally) printing debugging - messages. Normally debug does nothing, but you can pass "-fdebug" to - cabal install to build a snap-core which debugs to stderr. -

N.B. this is an internal interface, please don't write external code that - depends on it. -

Documentation
debug :: MonadIO m => String -> m ()Source
debugErrno :: MonadIO m => String -> m ()Source
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.4/snap-core/Snap-Internal-Http-Types.html b/static/docs/0.2.4/snap-core/Snap-Internal-Http-Types.html deleted file mode 100644 index 4a042d8..0000000 --- a/static/docs/0.2.4/snap-core/Snap-Internal-Http-Types.html +++ /dev/null @@ -1,3959 +0,0 @@ - - -Snap.Internal.Http.Types
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Snap.Internal.Http.Types
Description

An internal Snap module containing HTTP types. -

N.B. this is an internal interface, please don't write user code that - depends on it. Most of these declarations (except for the - unsafe/encapsulation-breaking ones) are re-exported from Snap.Types. -

Synopsis
set_c_locale :: IO ()
c_parse_http_time :: CString -> IO CTime
c_format_http_time :: CTime -> CString -> IO ()
c_format_log_time :: CTime -> CString -> IO ()
type Enumerator a = Enumerator IO a
type Headers = Map CIByteString [ByteString]
class HasHeaders a where
updateHeaders :: (Headers -> Headers) -> a -> a
headers :: a -> Headers
addHeader :: HasHeaders a => CIByteString -> ByteString -> a -> a
setHeader :: HasHeaders a => CIByteString -> ByteString -> a -> a
getHeaders :: HasHeaders a => CIByteString -> a -> Maybe [ByteString]
getHeader :: HasHeaders a => CIByteString -> a -> Maybe ByteString
data Method
= GET
| HEAD
| POST
| PUT
| DELETE
| TRACE
| OPTIONS
| CONNECT
type HttpVersion = (Int, Int)
data Cookie = Cookie {
cookieName :: !ByteString
cookieValue :: !ByteString
cookieExpires :: !(Maybe UTCTime)
cookieDomain :: !(Maybe ByteString)
cookiePath :: !(Maybe ByteString)
}
type Params = Map ByteString [ByteString]
data SomeEnumerator = SomeEnumerator (forall a. Enumerator a)
data Request = Request {
rqServerName :: !ByteString
rqServerPort :: !Int
rqRemoteAddr :: !ByteString
rqRemotePort :: !Int
rqLocalAddr :: !ByteString
rqLocalPort :: !Int
rqLocalHostname :: !ByteString
rqIsSecure :: !Bool
rqHeaders :: Headers
rqBody :: IORef SomeEnumerator
rqContentLength :: !(Maybe Int)
rqMethod :: !Method
rqVersion :: !HttpVersion
rqCookies :: [Cookie]
rqSnapletPath :: !ByteString
rqPathInfo :: !ByteString
rqContextPath :: !ByteString
rqURI :: !ByteString
rqQueryString :: !ByteString
rqParams :: Params
}
data ResponseBody
= Enum (forall a. Enumerator a)
| SendFile FilePath
rspBodyMap :: (forall a. Enumerator a -> Enumerator a) -> ResponseBody -> ResponseBody
rspBodyToEnum :: ResponseBody -> Enumerator a
data Response = Response {
rspHeaders :: Headers
rspHttpVersion :: !HttpVersion
rspContentLength :: !(Maybe Int)
rspBody :: ResponseBody
rspStatus :: !Int
rspStatusReason :: !ByteString
}
rqParam :: ByteString -> Request -> Maybe [ByteString]
rqModifyParams :: (Params -> Params) -> Request -> Request
rqSetParam :: ByteString -> [ByteString] -> Request -> Request
emptyResponse :: Response
setResponseBody :: (forall a. Enumerator a) -> Response -> Response
setResponseStatus :: Int -> ByteString -> Response -> Response
modifyResponseBody :: (forall a. Enumerator a -> Enumerator a) -> Response -> Response
setContentType :: ByteString -> Response -> Response
addCookie :: Cookie -> Response -> Response
setContentLength :: Int -> Response -> Response
clearContentLength :: Response -> Response
formatHttpTime :: CTime -> IO ByteString
formatLogTime :: CTime -> IO ByteString
parseHttpTime :: ByteString -> IO CTime
parseToCompletion :: Parser a -> ByteString -> Maybe a
pUrlEscaped :: Parser ByteString
urlDecode :: ByteString -> Maybe ByteString
urlEncode :: ByteString -> ByteString
hexd :: Word8 -> Builder
finish :: Result a -> Result a
fromStr :: String -> ByteString
toStr :: ByteString -> String
Documentation
set_c_locale :: IO ()Source
c_parse_http_time :: CString -> IO CTimeSource
c_format_http_time :: CTime -> CString -> IO ()Source
c_format_log_time :: CTime -> CString -> IO ()Source
type Enumerator a = Enumerator IO aSource
type Headers = Map CIByteString [ByteString]Source
A type alias for a case-insensitive key-value mapping. -
class HasHeaders a whereSource
A typeclass for datatypes which contain HTTP headers. -
Methods
updateHeaders :: (Headers -> Headers) -> a -> aSource
Modify the datatype's headers. -
headers :: a -> HeadersSource
Retrieve the headers from a datatype that has headers. -
show/hide Instances
addHeader :: HasHeaders a => CIByteString -> ByteString -> a -> aSource
Adds a header key-value-pair to the HasHeaders datatype. If a header with - the same name already exists, the new value is appended to the headers list. -
setHeader :: HasHeaders a => CIByteString -> ByteString -> a -> aSource
Sets a header key-value-pair in a HasHeaders datatype. If a header with - the same name already exists, it is overwritten with the new value. -
getHeaders :: HasHeaders a => CIByteString -> a -> Maybe [ByteString]Source
Gets all of the values for a given header. -
getHeader :: HasHeaders a => CIByteString -> a -> Maybe ByteStringSource
Gets a header value out of a HasHeaders datatype. If many headers came - in with the same name, they will be catenated together. -
data Method Source
Enumerates the HTTP method values (see - http://tools.ietf.org/html/rfc2068.html#section-5.1.1). -
Constructors
GET
HEAD
POST
PUT
DELETE
TRACE
OPTIONS
CONNECT
show/hide Instances
type HttpVersion = (Int, Int)Source
data Cookie Source
A datatype representing an HTTP cookie. -
Constructors
Cookie
cookieName :: !ByteStringThe name of the cookie. -
cookieValue :: !ByteStringThe cookie's string value. -
cookieExpires :: !(Maybe UTCTime)The cookie's expiration value, if it has one. -
cookieDomain :: !(Maybe ByteString)The cookie's "domain" value, if it has one. -
cookiePath :: !(Maybe ByteString)The cookie path. -
show/hide Instances
type Params = Map ByteString [ByteString]Source
A type alias for the HTTP parameters mapping. Each parameter - key maps to a list of ByteString values; if a parameter is specified - multiple times (e.g.: "GET /foo?param=bar1&param=bar2"), looking up - "param" in the mapping will give you ["bar1", "bar2"]. -
data SomeEnumerator Source
Constructors
SomeEnumerator (forall a. Enumerator a)
data Request Source
Contains all of the information about an incoming HTTP request. -
Constructors
Request
rqServerName :: !ByteStringThe server name of the request, as it came in from the request's - Host: header. -
rqServerPort :: !IntReturns the port number the HTTP server is listening on. -
rqRemoteAddr :: !ByteStringThe remote IP address. -
rqRemotePort :: !IntThe remote TCP port number. -
rqLocalAddr :: !ByteStringThe local IP address for this request. -
rqLocalPort :: !IntReturns the port number the HTTP server is listening on. -
rqLocalHostname :: !ByteStringReturns the HTTP server's idea of its local hostname. -
rqIsSecure :: !BoolReturns True if this is an HTTPS session (currently always - False). -
rqHeaders :: Headers
rqBody :: IORef SomeEnumerator
rqContentLength :: !(Maybe Int)Returns the Content-Length of the HTTP request body. -
rqMethod :: !MethodReturns the HTTP request method. -
rqVersion :: !HttpVersionReturns the HTTP version used by the client. -
rqCookies :: [Cookie]Returns a list of the cookies that came in from the HTTP request - headers. -
rqSnapletPath :: !ByteString

We'll be doing web components (or "snaplets") for version 0.2. The - "snaplet path" refers to the place on the URL where your containing - snaplet is hung. The value of rqSnapletPath is either "" (at the - top-level context) or is a path beginning with a slash, but not ending - with one. -

An identity is that: -

 rqURI r == 'S.concat' [ rqSnapletPath r
-                       , rqContextPath r
-                       , rqPathInfo r ]
-

note that until we introduce snaplets in v0.2, rqSnapletPath will be - "" -

rqPathInfo :: !ByteStringHandlers can (will be; --ed) be hung on a URI "entry point"; - this is called the "context path". If a handler is hung on the - context path "/foo/", and you request "/foo/bar", the value - of rqPathInfo will be "bar". -
rqContextPath :: !ByteStringThe "context path" of the request; catenating rqContextPath, and - rqPathInfo should get you back to the original rqURI. The - rqContextPath always begins and ends with a slash ("/") - character, and represents the path (relative to your - component/snaplet) you took to get to your handler. -
rqURI :: !ByteStringReturns the URI requested by the client. -
rqQueryString :: !ByteStringReturns the HTTP query string for this Request. -
rqParams :: ParamsReturns the Params mapping for this Request. "Parameters" are - automatically decoded from the query string and POST body and - entered into this mapping. -
show/hide Instances
data ResponseBody Source
Constructors
Enum (forall a. Enumerator a)output body is enumerator -
SendFile FilePathoutput body is sendfile() -
rspBodyMap :: (forall a. Enumerator a -> Enumerator a) -> ResponseBody -> ResponseBodySource
rspBodyToEnum :: ResponseBody -> Enumerator aSource
data Response Source
Represents an HTTP response. -
Constructors
Response
rspHeaders :: Headers
rspHttpVersion :: !HttpVersion
rspContentLength :: !(Maybe Int)We will need to inspect the content length no matter what, and - looking up "content-length" in the headers and parsing the number - out of the text will be too expensive. -
rspBody :: ResponseBody
rspStatus :: !IntReturns the HTTP status code. -
rspStatusReason :: !ByteStringReturns the HTTP status explanation string. -
show/hide Instances
rqParamSource
:: ByteStringparameter name to look up -
-> RequestHTTP request -
-> Maybe [ByteString]
Looks up the value(s) for the given named parameter. Parameters initially - come from the request's query string and any decoded POST body (if the - request's Content-Type is application/x-www-form-urlencoded). Parameter - values can be modified within handlers using rqModifyParams. -
rqModifyParams :: (Params -> Params) -> Request -> RequestSource
Modifies the parameters mapping (which is a Map ByteString ByteString) in - a Request using the given function. -
rqSetParamSource
:: ByteStringparameter name -
-> [ByteString]parameter values -
-> Requestrequest -
-> Request
Writes a key-value pair to the parameters mapping within the given request. -
emptyResponse :: ResponseSource
An empty Response. -
setResponseBodySource
:: forall a. Enumerator anew response body - enumerator -
-> Responseresponse to modify -
-> Response
Sets an HTTP response body to the given Enumerator value. -
setResponseStatusSource
:: IntHTTP response integer code -
-> ByteStringHTTP response explanation -
-> ResponseResponse to be modified -
-> Response
Sets the HTTP response status. -
modifyResponseBody :: (forall a. Enumerator a -> Enumerator a) -> Response -> ResponseSource
Modifies a response body. -
setContentType :: ByteString -> Response -> ResponseSource
Sets the Content-Type in the Response headers. -
addCookieSource
:: Cookiecookie value -
-> Responseresponse to modify -
-> Response
Adds an HTTP Cookie to the Response headers. -
setContentLength :: Int -> Response -> ResponseSource

A note here: if you want to set the Content-Length for the response, - Snap forces you to do it with this function rather than by setting it in the - headers; the Content-Length in the headers will be ignored. -

The reason for this is that Snap needs to look up the value of - Content-Length for each request, and looking the string value up in the - headers and parsing the number out of the text will be too expensive. -

If you don't set a content length in your response, HTTP keep-alive will be - disabled for HTTP/1.0 clients, forcing a Connection: close. For HTTP/1.1 - clients, Snap will switch to the chunked transfer encoding if - Content-Length is not specified. -

clearContentLength :: Response -> ResponseSource
Removes any Content-Length set in the Response. -
formatHttpTime :: CTime -> IO ByteStringSource
Converts a CTime into an HTTP timestamp. -
formatLogTime :: CTime -> IO ByteStringSource
Converts a CTime into common log entry format. -
parseHttpTime :: ByteString -> IO CTimeSource
Converts an HTTP timestamp into a CTime. -
parseToCompletion :: Parser a -> ByteString -> Maybe aSource
pUrlEscaped :: Parser ByteStringSource
urlDecode :: ByteString -> Maybe ByteStringSource
Decodes an URL-escaped string (see - http://tools.ietf.org/html/rfc2396.html#section-2.4) -
urlEncode :: ByteString -> ByteStringSource
URL-escapes a string (see - http://tools.ietf.org/html/rfc2396.html#section-2.4) -
hexd :: Word8 -> BuilderSource
finish :: Result a -> Result aSource
fromStr :: String -> ByteStringSource
toStr :: ByteString -> StringSource
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.4/snap-core/Snap-Internal-Iteratee-Debug.html b/static/docs/0.2.4/snap-core/Snap-Internal-Iteratee-Debug.html deleted file mode 100644 index 7e83697..0000000 --- a/static/docs/0.2.4/snap-core/Snap-Internal-Iteratee-Debug.html +++ /dev/null @@ -1,129 +0,0 @@ - - -Snap.Internal.Iteratee.Debug
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Snap.Internal.Iteratee.Debug
Description

An internal Snap module for debugging iteratees. -

N.B. this is an internal interface, please don't write user code that - depends on it. -

Documentation
debugIteratee :: Iteratee IO ()Source
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.4/snap-core/Snap-Iteratee.html b/static/docs/0.2.4/snap-core/Snap-Iteratee.html deleted file mode 100644 index f3d5693..0000000 --- a/static/docs/0.2.4/snap-core/Snap-Iteratee.html +++ /dev/null @@ -1,1205 +0,0 @@ - - -Snap.Iteratee
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Snap.Iteratee
Contents
Convenience aliases around types from Data.Iteratee -
Re-export types and functions from Data.Iteratee -
Helper functions -
Enumerators -
Conversion to/from WrappedByteString -
Iteratee utilities -
Description

Snap Framework type aliases and utilities for iteratees. Note that as a - convenience, this module also exports everything from Data.Iteratee in the - iteratee library. -

WARNING: Note that all of these types are scheduled to change in the - darcs head version of the iteratee library; John Lato et al. are working - on a much improved iteratee formulation. -

Synopsis
type Stream = StreamG WrappedByteString Word8
type IterV m = IterGV WrappedByteString Word8 m
type Iteratee m = IterateeG WrappedByteString Word8 m
type Enumerator m a = Iteratee m a -> m (Iteratee m a)
module Data.Iteratee
enumBS :: Monad m => ByteString -> Enumerator m a
enumLBS :: Monad m => ByteString -> Enumerator m a
enumFile :: FilePath -> Iteratee IO a -> IO (Iteratee IO a)
fromWrap :: WrappedByteString Word8 -> ByteString
toWrap :: ByteString -> WrappedByteString Word8
takeExactly :: (StreamChunk s el, Monad m) => Int -> EnumeratorN s el s el m a
takeNoMoreThan :: (StreamChunk s el, Monad m) => Int -> EnumeratorN s el s el m a
countBytes :: Monad m => Iteratee m a -> Iteratee m (a, Int)
bufferIteratee :: Monad m => Enumerator m a
mkIterateeBuffer :: IO (ForeignPtr CChar)
unsafeBufferIterateeWithBuffer :: ForeignPtr CChar -> Iteratee IO a -> IO (Iteratee IO a, IORef Bool)
unsafeBufferIteratee :: Iteratee IO a -> IO (Iteratee IO a, IORef Bool)
Convenience aliases around types from Data.Iteratee -
type Stream = StreamG WrappedByteString Word8Source
type IterV m = IterGV WrappedByteString Word8 mSource
type Iteratee m = IterateeG WrappedByteString Word8 mSource
type Enumerator m a = Iteratee m a -> m (Iteratee m a)Source
Re-export types and functions from Data.Iteratee -
module Data.Iteratee
Helper functions -
Enumerators -
enumBS :: Monad m => ByteString -> Enumerator m aSource
Enumerates a strict bytestring. -
enumLBS :: Monad m => ByteString -> Enumerator m aSource
Enumerates a lazy bytestring. -
enumFile :: FilePath -> Iteratee IO a -> IO (Iteratee IO a)Source
Conversion to/from WrappedByteString -
fromWrap :: WrappedByteString Word8 -> ByteStringSource
Converts a wrapped bytestring to a lazy bytestring. -
toWrap :: ByteString -> WrappedByteString Word8Source
Converts a lazy bytestring to a wrapped bytestring. -
Iteratee utilities -
takeExactly :: (StreamChunk s el, Monad m) => Int -> EnumeratorN s el s el m aSource
Reads n elements from a stream and applies the given iteratee to - the stream of the read elements. Reads exactly n elements, and if - the stream is short propagates an error. -
takeNoMoreThan :: (StreamChunk s el, Monad m) => Int -> EnumeratorN s el s el m aSource
Reads up to n elements from a stream and applies the given iteratee to the - stream of the read elements. If more than n elements are read, propagates an - error. -
countBytes :: Monad m => Iteratee m a -> Iteratee m (a, Int)Source
Wraps an Iteratee, counting the number of bytes consumed by it. -
bufferIteratee :: Monad m => Enumerator m aSource

Buffers an iteratee. -

Our enumerators produce a lot of little strings; rather than spending all - our time doing kernel context switches for 4-byte write() calls, we buffer - the iteratee to send 8KB at a time. -

mkIterateeBuffer :: IO (ForeignPtr CChar)Source
Creates a buffer to be passed into unsafeBufferIterateeWithBuffer. -
unsafeBufferIterateeWithBuffer :: ForeignPtr CChar -> Iteratee IO a -> IO (Iteratee IO a, IORef Bool)Source

Buffers an iteratee, "unsafely". Here we use a fixed binary buffer which - we'll re-use, meaning that if you hold on to any of the bytestring data - passed into your iteratee (instead of, let's say, shoving it right out a - socket) it'll get changed out from underneath you, breaking referential - transparency. Use with caution! -

This version accepts a buffer created by mkIterateeBuffer. -

The IORef returned can be set to True to cancel buffering. We added this - so that transfer-encoding: chunked (which needs its own buffer and therefore - doesn't need its output buffered) can switch the outer buffer off. -

unsafeBufferIteratee :: Iteratee IO a -> IO (Iteratee IO a, IORef Bool)Source

Buffers an iteratee, "unsafely". Here we use a fixed binary buffer which - we'll re-use, meaning that if you hold on to any of the bytestring data - passed into your iteratee (instead of, let's say, shoving it right out a - socket) it'll get changed out from underneath you, breaking referential - transparency. Use with caution! -

The IORef returned can be set to True to cancel buffering. We added this - so that transfer-encoding: chunked (which needs its own buffer and therefore - doesn't need its output buffered) can switch the outer buffer off. -

Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.4/snap-core/Snap-Types.html b/static/docs/0.2.4/snap-core/Snap-Types.html deleted file mode 100644 index 43f8838..0000000 --- a/static/docs/0.2.4/snap-core/Snap-Types.html +++ /dev/null @@ -1,5952 +0,0 @@ - - -Snap.Types
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Snap.Types
Contents
The Snap Monad -
Functions for control flow and early termination -
Routing -
Access to state -
Logging -
Grabbing request bodies -
HTTP Datatypes and Functions -
Headers -
Requests -
Responses -
Response I/O -
Iteratee -
HTTP utilities -
Description
This module contains the core type definitions, class instances, and functions -for HTTP as well as the Snap monad, which is used for web handlers. -
Synopsis
data Snap a
runSnap :: Snap a -> (ByteString -> IO ()) -> Request -> Iteratee IO (Request, Response)
data NoHandlerException = NoHandlerException
finishWith :: Response -> Snap ()
pass :: Snap a
method :: Method -> Snap a -> Snap a
path :: ByteString -> Snap a -> Snap a
dir :: ByteString -> Snap a -> Snap a
ifTop :: Snap a -> Snap a
route :: [(ByteString, Snap a)] -> Snap a
routeLocal :: [(ByteString, Snap a)] -> Snap a
getRequest :: Snap Request
getResponse :: Snap Response
putRequest :: Request -> Snap ()
putResponse :: Response -> Snap ()
modifyRequest :: (Request -> Request) -> Snap ()
modifyResponse :: (Response -> Response) -> Snap ()
localRequest :: (Request -> Request) -> Snap a -> Snap a
withRequest :: (Request -> Snap a) -> Snap a
withResponse :: (Response -> Snap a) -> Snap a
logError :: ByteString -> Snap ()
runRequestBody :: Iteratee IO a -> Snap a
getRequestBody :: Snap ByteString
unsafeDetachRequestBody :: Snap (Enumerator a)
data Request
data Response
type Headers = Map CIByteString [ByteString]
class HasHeaders a where
updateHeaders :: (Headers -> Headers) -> a -> a
headers :: a -> Headers
type Params = Map ByteString [ByteString]
data Method
= GET
| HEAD
| POST
| PUT
| DELETE
| TRACE
| OPTIONS
| CONNECT
data Cookie = Cookie {
cookieName :: !ByteString
cookieValue :: !ByteString
cookieExpires :: !(Maybe UTCTime)
cookieDomain :: !(Maybe ByteString)
cookiePath :: !(Maybe ByteString)
}
type HttpVersion = (Int, Int)
addHeader :: HasHeaders a => CIByteString -> ByteString -> a -> a
setHeader :: HasHeaders a => CIByteString -> ByteString -> a -> a
getHeader :: HasHeaders a => CIByteString -> a -> Maybe ByteString
rqServerName :: Request -> ByteString
rqServerPort :: Request -> Int
rqRemoteAddr :: Request -> ByteString
rqRemotePort :: Request -> Int
rqLocalAddr :: Request -> ByteString
rqLocalHostname :: Request -> ByteString
rqIsSecure :: Request -> Bool
rqContentLength :: Request -> Maybe Int
rqMethod :: Request -> Method
rqVersion :: Request -> HttpVersion
rqCookies :: Request -> [Cookie]
rqPathInfo :: Request -> ByteString
rqContextPath :: Request -> ByteString
rqURI :: Request -> ByteString
rqQueryString :: Request -> ByteString
rqParams :: Request -> Params
rqParam :: ByteString -> Request -> Maybe [ByteString]
getParam :: ByteString -> Snap (Maybe ByteString)
rqModifyParams :: (Params -> Params) -> Request -> Request
rqSetParam :: ByteString -> [ByteString] -> Request -> Request
emptyResponse :: Response
setResponseStatus :: Int -> ByteString -> Response -> Response
rspStatus :: Response -> Int
rspStatusReason :: Response -> ByteString
setContentType :: ByteString -> Response -> Response
addCookie :: Cookie -> Response -> Response
setContentLength :: Int -> Response -> Response
clearContentLength :: Response -> Response
setResponseBody :: (forall a. Enumerator a) -> Response -> Response
modifyResponseBody :: (forall a. Enumerator a -> Enumerator a) -> Response -> Response
addToOutput :: (forall a. Enumerator a) -> Snap ()
writeBS :: ByteString -> Snap ()
writeLazyText :: Text -> Snap ()
writeText :: Text -> Snap ()
writeLBS :: ByteString -> Snap ()
sendFile :: FilePath -> Snap ()
type Enumerator a = Enumerator IO a
formatHttpTime :: CTime -> IO ByteString
parseHttpTime :: ByteString -> IO CTime
urlEncode :: ByteString -> ByteString
urlDecode :: ByteString -> Maybe ByteString
The Snap Monad -
data Snap a Source

Snap is the Monad that user web handlers run in. Snap gives you: -

1. stateful access to fetch or modify an HTTP Request -

2. stateful access to fetch or modify an HTTP Response -

3. failure / Alternative / MonadPlus semantics: a Snap handler can - choose not to handle a given request, using empty or its synonym pass, - and you can try alternative handlers with the <|> operator: -

 a :: Snap String
- a = pass
-
- b :: Snap String
- b = return "foo"
-
- c :: Snap String
- c = a <|> b             -- try running a, if it fails then try b
-

4. convenience functions (writeBS, writeLBS, writeText, writeLazyText, - addToOutput) for writing output to the Response: -

 a :: (forall a . Enumerator a) -> Snap ()
- a someEnumerator = do
-     writeBS "I'm a strict bytestring"
-     writeLBS "I'm a lazy bytestring"
-     addToOutput someEnumerator
-

5. early termination: if you call finishWith: -

 a :: Snap ()
- a = do
-   modifyResponse $ setResponseStatus 500 "Internal Server Error"
-   writeBS "500 error"
-   r <- getResponse
-   finishWith r
-

then any subsequent processing will be skipped and supplied Response value - will be returned from runSnap as-is. -

6. access to the IO monad through a MonadIO instance: -

 a :: Snap ()
- a = liftIO fireTheMissiles
-
show/hide Instances
runSnap :: Snap a -> (ByteString -> IO ()) -> Request -> Iteratee IO (Request, Response)Source
Runs a Snap monad action in the 'Iteratee IO' monad. -
data NoHandlerException Source
This exception is thrown if the handler you supply to runSnap fails. -
Constructors
NoHandlerException
show/hide Instances
Functions for control flow and early termination -
finishWith :: Response -> Snap ()Source
Short-circuits a Snap monad action early, storing the given - Response value in its state. -
pass :: Snap aSource
Fails out of a Snap monad action. This is used to indicate - that you choose not to handle the given request within the given - handler. -
Routing -
method :: Method -> Snap a -> Snap aSource
Runs a Snap monad action only if the request's HTTP method matches - the given method. -
pathSource
:: ByteStringpath to match against -
-> Snap ahandler to run -
-> Snap a
Runs a Snap monad action only for requests where rqPathInfo is exactly - equal to the given string. If the path matches, locally sets rqContextPath - to the old value of rqPathInfo, sets rqPathInfo="", and runs the given - handler. -
dirSource
:: ByteStringpath component to match -
-> Snap ahandler to run -
-> Snap a

Runs a Snap monad action only when the rqPathInfo of the request - starts with the given path. For example, -

 dir "foo" handler
-

Will fail if rqPathInfo is not "/foo" or "/foo/...", and will - add "foo/" to the handler's local rqContextPath. -

ifTop :: Snap a -> Snap aSource
Runs a Snap monad action only when rqPathInfo is empty. -
route :: [(ByteString, Snap a)] -> Snap aSource

A web handler which, given a mapping from URL entry points to web - handlers, efficiently routes requests to the correct handler. -

The URL entry points are given as relative paths, for example: -

 route [ ("foo/bar/quux", fooBarQuux) ]
-

If the URI of the incoming request is -

 /foo/bar/quux
-

or -

 /foo/bar/quux/...anything...
-

then the request will be routed to "fooBarQuux", with rqContextPath - set to "/foo/bar/quux/" and rqPathInfo set to - "...anything...". -

A path component within an URL entry point beginning with a colon (":") - is treated as a variable capture; the corresponding path component within - the request URI will be entered into the rqParams parameters mapping with - the given name. For instance, if the routes were: -

 route [ ("foo/:bar/baz", fooBazHandler) ]
-

Then a request for "/foo/saskatchewan/baz" would be routed to - fooBazHandler with a mapping for: -

 "bar" => "saskatchewan"
-

in its parameters table. -

Longer paths are matched first, and specific routes are matched before - captures. That is, if given routes: -

 [ ("a", h1), ("a/b", h2), ("a/:x", h3) ]
-

a request for "/a/b" will go to h2, "/a/s" for any s will go - to h3, and "/a" will go to h1. -

The following example matches "/article" to an article index, - "/login" to a login, and "/article/..." to an article renderer. -

 route [ ("article",     renderIndex)
-       , ("article/:id", renderArticle)
-       , ("login",       method POST doLogin) ]
-
routeLocal :: [(ByteString, Snap a)] -> Snap aSource
The routeLocal function is the same as route, except it doesn't change - the request's context path. This is useful if you want to route to a - particular handler but you want that handler to receive the rqPathInfo as - it is. -
Access to state -
getRequest :: Snap RequestSource
Grabs the Request object out of the Snap monad. -
getResponse :: Snap ResponseSource
Grabs the Response object out of the Snap monad. -
putRequest :: Request -> Snap ()Source
Puts a new Request object into the Snap monad. -
putResponse :: Response -> Snap ()Source
Puts a new Response object into the Snap monad. -
modifyRequest :: (Request -> Request) -> Snap ()Source
Modifies the Request object stored in a Snap monad. -
modifyResponse :: (Response -> Response) -> Snap ()Source
Modifes the Response object stored in a Snap monad. -
localRequest :: (Request -> Request) -> Snap a -> Snap aSource
Runs a Snap action with a locally-modified Request state - object. The Request object in the Snap monad state after the call - to localRequest will be unchanged. -
withRequest :: (Request -> Snap a) -> Snap aSource
Fetches the Request from state and hands it to the given action. -
withResponse :: (Response -> Snap a) -> Snap aSource
Fetches the Response from state and hands it to the given action. -
Logging -
logError :: ByteString -> Snap ()Source
Log an error message in the Snap monad -
Grabbing request bodies -
runRequestBody :: Iteratee IO a -> Snap aSource
Sends the request body through an iteratee (data consumer) and - returns the result. -
getRequestBody :: Snap ByteStringSource
Returns the request body as a bytestring. -
unsafeDetachRequestBody :: Snap (Enumerator a)Source

Detaches the request body's Enumerator from the Request and - returns it. You would want to use this if you needed to send the - HTTP request body (transformed or otherwise) through to the output - in O(1) space. (Examples: transcoding, "echo", etc) -

Normally Snap is careful to ensure that the request body is fully - consumed after your web handler runs; this function is marked - "unsafe" because it breaks this guarantee and leaves the - responsibility up to you. If you don't fully consume the - Enumerator you get here, the next HTTP request in the pipeline - (if any) will misparse. Be careful with exception handlers. -

HTTP Datatypes and Functions -
HTTP-related datatypes: Request, Response, Cookie, etc. -
data Request Source
Contains all of the information about an incoming HTTP request. -
show/hide Instances
data Response Source
Represents an HTTP response. -
show/hide Instances
type Headers = Map CIByteString [ByteString]Source
A type alias for a case-insensitive key-value mapping. -
class HasHeaders a whereSource
A typeclass for datatypes which contain HTTP headers. -
Methods
updateHeaders :: (Headers -> Headers) -> a -> aSource
Modify the datatype's headers. -
headers :: a -> HeadersSource
Retrieve the headers from a datatype that has headers. -
show/hide Instances
type Params = Map ByteString [ByteString]Source
A type alias for the HTTP parameters mapping. Each parameter - key maps to a list of ByteString values; if a parameter is specified - multiple times (e.g.: "GET /foo?param=bar1&param=bar2"), looking up - "param" in the mapping will give you ["bar1", "bar2"]. -
data Method Source
Enumerates the HTTP method values (see - http://tools.ietf.org/html/rfc2068.html#section-5.1.1). -
Constructors
GET
HEAD
POST
PUT
DELETE
TRACE
OPTIONS
CONNECT
show/hide Instances
data Cookie Source
A datatype representing an HTTP cookie. -
Constructors
Cookie
cookieName :: !ByteStringThe name of the cookie. -
cookieValue :: !ByteStringThe cookie's string value. -
cookieExpires :: !(Maybe UTCTime)The cookie's expiration value, if it has one. -
cookieDomain :: !(Maybe ByteString)The cookie's "domain" value, if it has one. -
cookiePath :: !(Maybe ByteString)The cookie path. -
show/hide Instances
type HttpVersion = (Int, Int)Source
Headers -
addHeader :: HasHeaders a => CIByteString -> ByteString -> a -> aSource
Adds a header key-value-pair to the HasHeaders datatype. If a header with - the same name already exists, the new value is appended to the headers list. -
setHeader :: HasHeaders a => CIByteString -> ByteString -> a -> aSource
Sets a header key-value-pair in a HasHeaders datatype. If a header with - the same name already exists, it is overwritten with the new value. -
getHeader :: HasHeaders a => CIByteString -> a -> Maybe ByteStringSource
Gets a header value out of a HasHeaders datatype. If many headers came - in with the same name, they will be catenated together. -
Requests -
rqServerName :: Request -> ByteStringSource
The server name of the request, as it came in from the request's - Host: header. -
rqServerPort :: Request -> IntSource
Returns the port number the HTTP server is listening on. -
rqRemoteAddr :: Request -> ByteStringSource
The remote IP address. -
rqRemotePort :: Request -> IntSource
The remote TCP port number. -
rqLocalAddr :: Request -> ByteStringSource
The local IP address for this request. -
rqLocalHostname :: Request -> ByteStringSource
Returns the HTTP server's idea of its local hostname. -
rqIsSecure :: Request -> BoolSource
Returns True if this is an HTTPS session (currently always - False). -
rqContentLength :: Request -> Maybe IntSource
Returns the Content-Length of the HTTP request body. -
rqMethod :: Request -> MethodSource
Returns the HTTP request method. -
rqVersion :: Request -> HttpVersionSource
Returns the HTTP version used by the client. -
rqCookies :: Request -> [Cookie]Source
Returns a list of the cookies that came in from the HTTP request - headers. -
rqPathInfo :: Request -> ByteStringSource
Handlers can (will be; --ed) be hung on a URI "entry point"; - this is called the "context path". If a handler is hung on the - context path "/foo/", and you request "/foo/bar", the value - of rqPathInfo will be "bar". -
rqContextPath :: Request -> ByteStringSource
The "context path" of the request; catenating rqContextPath, and - rqPathInfo should get you back to the original rqURI. The - rqContextPath always begins and ends with a slash ("/") - character, and represents the path (relative to your - component/snaplet) you took to get to your handler. -
rqURI :: Request -> ByteStringSource
Returns the URI requested by the client. -
rqQueryString :: Request -> ByteStringSource
Returns the HTTP query string for this Request. -
rqParams :: Request -> ParamsSource
Returns the Params mapping for this Request. "Parameters" are - automatically decoded from the query string and POST body and - entered into this mapping. -
rqParamSource
:: ByteStringparameter name to look up -
-> RequestHTTP request -
-> Maybe [ByteString]
Looks up the value(s) for the given named parameter. Parameters initially - come from the request's query string and any decoded POST body (if the - request's Content-Type is application/x-www-form-urlencoded). Parameter - values can be modified within handlers using rqModifyParams. -
getParamSource
:: ByteStringparameter name to look up -
-> Snap (Maybe ByteString)

See rqParam. Looks up a value for the given named parameter in the - Request. If more than one value was entered for the given parameter name, - getParam gloms the values together with: -

    intercalate " "
rqModifyParams :: (Params -> Params) -> Request -> RequestSource
Modifies the parameters mapping (which is a Map ByteString ByteString) in - a Request using the given function. -
rqSetParamSource
:: ByteStringparameter name -
-> [ByteString]parameter values -
-> Requestrequest -
-> Request
Writes a key-value pair to the parameters mapping within the given request. -
Responses -
emptyResponse :: ResponseSource
An empty Response. -
setResponseStatusSource
:: IntHTTP response integer code -
-> ByteStringHTTP response explanation -
-> ResponseResponse to be modified -
-> Response
Sets the HTTP response status. -
rspStatus :: Response -> IntSource
Returns the HTTP status code. -
rspStatusReason :: Response -> ByteStringSource
Returns the HTTP status explanation string. -
setContentType :: ByteString -> Response -> ResponseSource
Sets the Content-Type in the Response headers. -
addCookieSource
:: Cookiecookie value -
-> Responseresponse to modify -
-> Response
Adds an HTTP Cookie to the Response headers. -
setContentLength :: Int -> Response -> ResponseSource

A note here: if you want to set the Content-Length for the response, - Snap forces you to do it with this function rather than by setting it in the - headers; the Content-Length in the headers will be ignored. -

The reason for this is that Snap needs to look up the value of - Content-Length for each request, and looking the string value up in the - headers and parsing the number out of the text will be too expensive. -

If you don't set a content length in your response, HTTP keep-alive will be - disabled for HTTP/1.0 clients, forcing a Connection: close. For HTTP/1.1 - clients, Snap will switch to the chunked transfer encoding if - Content-Length is not specified. -

clearContentLength :: Response -> ResponseSource
Removes any Content-Length set in the Response. -
Response I/O -
setResponseBodySource
:: forall a. Enumerator anew response body - enumerator -
-> Responseresponse to modify -
-> Response
Sets an HTTP response body to the given Enumerator value. -
modifyResponseBody :: (forall a. Enumerator a -> Enumerator a) -> Response -> ResponseSource
Modifies a response body. -
addToOutputSource
:: forall a. Enumerator aoutput to add -
-> Snap ()
Adds the output from the given enumerator to the Response - stored in the Snap monad state. -
writeBS :: ByteString -> Snap ()Source
Adds the given strict ByteString to the body of the Response stored in - the Snap monad state. -
writeLazyText :: Text -> Snap ()Source
Adds the given lazy Text to the body of the Response stored in the - Snap monad state. -
writeText :: Text -> Snap ()Source
Adds the given strict Text to the body of the Response stored in the - Snap monad state. -
writeLBS :: ByteString -> Snap ()Source
Adds the given lazy ByteString to the body of the Response stored in - the Snap monad state. -
sendFile :: FilePath -> Snap ()Source

Sets the output to be the contents of the specified file. -

Calling sendFile will overwrite any output queued to be sent in the - Response. If the response body is not modified after the call to - sendFile, Snap will use the efficient sendfile() system call on - platforms that support it. -

If the response body is modified (using modifyResponseBody), the file will - be read using mmap(). -

Iteratee -
type Enumerator a = Enumerator IO aSource
HTTP utilities -
formatHttpTime :: CTime -> IO ByteStringSource
Converts a CTime into an HTTP timestamp. -
parseHttpTime :: ByteString -> IO CTimeSource
Converts an HTTP timestamp into a CTime. -
urlEncode :: ByteString -> ByteStringSource
URL-escapes a string (see - http://tools.ietf.org/html/rfc2396.html#section-2.4) -
urlDecode :: ByteString -> Maybe ByteStringSource
Decodes an URL-escaped string (see - http://tools.ietf.org/html/rfc2396.html#section-2.4) -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.4/snap-core/Snap-Util-FileServe.html b/static/docs/0.2.4/snap-core/Snap-Util-FileServe.html deleted file mode 100644 index 6ec4da5..0000000 --- a/static/docs/0.2.4/snap-core/Snap-Util-FileServe.html +++ /dev/null @@ -1,651 +0,0 @@ - - -Snap.Util.FileServe
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Snap.Util.FileServe
Description
Contains web handlers to serve files from a directory. -
Synopsis
getSafePath :: Snap FilePath
fileServe :: FilePath -> Snap ()
fileServe' :: MimeMap -> FilePath -> Snap ()
fileServeSingle :: FilePath -> Snap ()
fileServeSingle' :: ByteString -> FilePath -> Snap ()
defaultMimeTypes :: MimeMap
type MimeMap = Map FilePath ByteString
Documentation
getSafePath :: Snap FilePathSource
Gets a path from the Request using rqPathInfo and makes sure it is - safe to use for opening files. A path is safe if it is a relative path - and has no .. elements to escape the intended directory structure. -
fileServeSource
:: FilePathroot directory -
-> Snap ()

Serves files out of the given directory. The relative path given in - rqPathInfo is searched for the given file, and the file is served with the - appropriate mime type if it is found. Absolute paths and ".." are prohibited - to prevent files from being served from outside the sandbox. -

Uses defaultMimeTypes to determine the Content-Type based on the file's - extension. -

fileServe'Source
:: MimeMapMIME type mapping -
-> FilePathroot directory -
-> Snap ()
Same as fileServe, with control over the MIME mapping used. -
fileServeSingleSource
:: FilePathpath to file -
-> Snap ()
Serves a single file specified by a full or relative path. The - path restrictions on fileServe don't apply to this function since - the path is not being supplied by the user. -
fileServeSingle'Source
:: ByteStringMIME type mapping -
-> FilePathpath to file -
-> Snap ()
Same as fileServeSingle, with control over the MIME mapping used. -
defaultMimeTypes :: MimeMapSource

The default set of mime type mappings we use when serving files. Its - value: -

 Map.fromList [
-   ( ".asc"     , "text/plain"                        ),
-   ( ".asf"     , "video/x-ms-asf"                    ),
-   ( ".asx"     , "video/x-ms-asf"                    ),
-   ( ".avi"     , "video/x-msvideo"                   ),
-   ( ".bz2"     , "application/x-bzip"                ),
-   ( ".c"       , "text/plain"                        ),
-   ( ".class"   , "application/octet-stream"          ),
-   ( ".conf"    , "text/plain"                        ),
-   ( ".cpp"     , "text/plain"                        ),
-   ( ".css"     , "text/css"                          ),
-   ( ".cxx"     , "text/plain"                        ),
-   ( ".dtd"     , "text/xml"                          ),
-   ( ".dvi"     , "application/x-dvi"                 ),
-   ( ".gif"     , "image/gif"                         ),
-   ( ".gz"      , "application/x-gzip"                ),
-   ( ".hs"      , "text/plain"                        ),
-   ( ".htm"     , "text/html"                         ),
-   ( ".html"    , "text/html"                         ),
-   ( ".jar"     , "application/x-java-archive"        ),
-   ( ".jpeg"    , "image/jpeg"                        ),
-   ( ".jpg"     , "image/jpeg"                        ),
-   ( ".js"      , "text/javascript"                   ),
-   ( ".log"     , "text/plain"                        ),
-   ( ".m3u"     , "audio/x-mpegurl"                   ),
-   ( ".mov"     , "video/quicktime"                   ),
-   ( ".mp3"     , "audio/mpeg"                        ),
-   ( ".mpeg"    , "video/mpeg"                        ),
-   ( ".mpg"     , "video/mpeg"                        ),
-   ( ".ogg"     , "application/ogg"                   ),
-   ( ".pac"     , "application/x-ns-proxy-autoconfig" ),
-   ( ".pdf"     , "application/pdf"                   ),
-   ( ".png"     , "image/png"                         ),
-   ( ".ps"      , "application/postscript"            ),
-   ( ".qt"      , "video/quicktime"                   ),
-   ( ".sig"     , "application/pgp-signature"         ),
-   ( ".spl"     , "application/futuresplash"          ),
-   ( ".swf"     , "application/x-shockwave-flash"     ),
-   ( ".tar"     , "application/x-tar"                 ),
-   ( ".tar.bz2" , "application/x-bzip-compressed-tar" ),
-   ( ".tar.gz"  , "application/x-tgz"                 ),
-   ( ".tbz"     , "application/x-bzip-compressed-tar" ),
-   ( ".text"    , "text/plain"                        ),
-   ( ".tgz"     , "application/x-tgz"                 ),
-   ( ".torrent" , "application/x-bittorrent"          ),
-   ( ".txt"     , "text/plain"                        ),
-   ( ".wav"     , "audio/x-wav"                       ),
-   ( ".wax"     , "audio/x-ms-wax"                    ),
-   ( ".wma"     , "audio/x-ms-wma"                    ),
-   ( ".wmv"     , "video/x-ms-wmv"                    ),
-   ( ".xbm"     , "image/x-xbitmap"                   ),
-   ( ".xml"     , "text/xml"                          ),
-   ( ".xpm"     , "image/x-xpixmap"                   ),
-   ( ".xwd"     , "image/x-xwindowdump"               ),
-   ( ".zip"     , "application/zip"                   ) ]
-
type MimeMap = Map FilePath ByteStringSource
A type alias for MIME type -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.4/snap-core/Snap-Util-GZip.html b/static/docs/0.2.4/snap-core/Snap-Util-GZip.html deleted file mode 100644 index 7587f1f..0000000 --- a/static/docs/0.2.4/snap-core/Snap-Util-GZip.html +++ /dev/null @@ -1,328 +0,0 @@ - - -Snap.Util.GZip
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)Source codeContentsIndex
Snap.Util.GZip
Synopsis
withCompression :: Snap a -> Snap ()
withCompression' :: Set ByteString -> Snap a -> Snap ()
Documentation
withCompressionSource
:: Snap athe web handler to run -
-> Snap ()

Runs a Snap web handler with compression if available. -

If the client has indicated support for gzip or compress in its - Accept-Encoding header, and the Content-Type in the response is one of - the following types: -

  • application/x-javascript
  • text/css
  • text/html
  • text/javascript
  • text/plain
  • text/xml
  • application/x-font-truetype

Then the given handler's output stream will be compressed, - Content-Encoding will be set in the output headers, and the - Content-Length will be cleared if it was set. (We can't process the stream - in O(1) space if the length is known beforehand.) -

The wrapped handler will be run to completion, and then the Response - that's contained within the Snap monad state will be passed to - finishWith to prevent further processing. -

withCompression'Source
:: Set ByteStringset of compressible MIME types -
-> Snap athe web handler to run -
-> Snap ()
The same as withCompression, with control over which MIME types to - compress. -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.4/snap-core/doc-index-62.html b/static/docs/0.2.4/snap-core/doc-index-62.html deleted file mode 100644 index 9a25e46..0000000 --- a/static/docs/0.2.4/snap-core/doc-index-62.html +++ /dev/null @@ -1,144 +0,0 @@ - - -snap-core-0.2.4: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (>)
>.
diff --git a/static/docs/0.2.4/snap-core/doc-index-A.html b/static/docs/0.2.4/snap-core/doc-index-A.html deleted file mode 100644 index dc74e9c..0000000 --- a/static/docs/0.2.4/snap-core/doc-index-A.html +++ /dev/null @@ -1,166 +0,0 @@ - - -snap-core-0.2.4: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (A)
addCookie
addHeader
addToOutput
diff --git a/static/docs/0.2.4/snap-core/doc-index-B.html b/static/docs/0.2.4/snap-core/doc-index-B.html deleted file mode 100644 index a35f40c..0000000 --- a/static/docs/0.2.4/snap-core/doc-index-B.html +++ /dev/null @@ -1,152 +0,0 @@ - - -snap-core-0.2.4: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (B)
break
bufferIteratee
diff --git a/static/docs/0.2.4/snap-core/doc-index-C.html b/static/docs/0.2.4/snap-core/doc-index-C.html deleted file mode 100644 index 629819a..0000000 --- a/static/docs/0.2.4/snap-core/doc-index-C.html +++ /dev/null @@ -1,310 +0,0 @@ - - -snap-core-0.2.4: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (C)
checkErr
checkIfDone
Chunk
CIByteString
ciToLower
clearContentLength
CONNECT
Cont
convStream
Cookie
1 (Type/Class)
2 (Data Constructor)
cookieDomain
cookieExpires
cookieName
cookiePath
cookieValue
countBytes
c_format_http_time
c_format_log_time
c_parse_http_time
diff --git a/static/docs/0.2.4/snap-core/doc-index-D.html b/static/docs/0.2.4/snap-core/doc-index-D.html deleted file mode 100644 index 702bab3..0000000 --- a/static/docs/0.2.4/snap-core/doc-index-D.html +++ /dev/null @@ -1,206 +0,0 @@ - - -snap-core-0.2.4: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (D)
debug
debugErrno
debugIteratee
defaultMimeTypes
DELETE
dir
Done
drop
dropWhile
diff --git a/static/docs/0.2.4/snap-core/doc-index-E.html b/static/docs/0.2.4/snap-core/doc-index-E.html deleted file mode 100644 index 8372114..0000000 --- a/static/docs/0.2.4/snap-core/doc-index-E.html +++ /dev/null @@ -1,292 +0,0 @@ - - -snap-core-0.2.4: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (E)
emptyResponse
Endian
endianRead2
endianRead3
endianRead4
Enum
enumBS
enumEof
Enumerator
1 (Type/Class)
2 (Type/Class)
EnumeratorGM
EnumeratorGMM
EnumeratorN
enumErr
enumFile
enumLBS
enumPair
enumPure1Chunk
enumPureNChunk
EOF
Err
ErrMsg
diff --git a/static/docs/0.2.4/snap-core/doc-index-F.html b/static/docs/0.2.4/snap-core/doc-index-F.html deleted file mode 100644 index 61d0373..0000000 --- a/static/docs/0.2.4/snap-core/doc-index-F.html +++ /dev/null @@ -1,262 +0,0 @@ - - -snap-core-0.2.4: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (F)
fileDriver
fileDriverRandom
FileOffset
fileServe
fileServe'
fileServeSingle
fileServeSingle'
filter
finish
finishWith
foldl
foldl'
foldl1
formatHttpTime
formatLogTime
fromStr
fromWrap
diff --git a/static/docs/0.2.4/snap-core/doc-index-G.html b/static/docs/0.2.4/snap-core/doc-index-G.html deleted file mode 100644 index 5d82f55..0000000 --- a/static/docs/0.2.4/snap-core/doc-index-G.html +++ /dev/null @@ -1,206 +0,0 @@ - - -snap-core-0.2.4: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (G)
GET
getHeader
getHeaders
getParam
getRequest
getRequestBody
getResponse
getSafePath
diff --git a/static/docs/0.2.4/snap-core/doc-index-H.html b/static/docs/0.2.4/snap-core/doc-index-H.html deleted file mode 100644 index 3401373..0000000 --- a/static/docs/0.2.4/snap-core/doc-index-H.html +++ /dev/null @@ -1,208 +0,0 @@ - - -snap-core-0.2.4: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (H)
HasHeaders
HEAD
head
Headers
headers
heads
hexd
HttpVersion
diff --git a/static/docs/0.2.4/snap-core/doc-index-I.html b/static/docs/0.2.4/snap-core/doc-index-I.html deleted file mode 100644 index 7771735..0000000 --- a/static/docs/0.2.4/snap-core/doc-index-I.html +++ /dev/null @@ -1,196 +0,0 @@ - - -snap-core-0.2.4: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (I)
identity
ifTop
isFinished
Iteratee
IterateeG
1 (Data Constructor)
2 (Type/Class)
IterGV
IterV
diff --git a/static/docs/0.2.4/snap-core/doc-index-J.html b/static/docs/0.2.4/snap-core/doc-index-J.html deleted file mode 100644 index 3d42fef..0000000 --- a/static/docs/0.2.4/snap-core/doc-index-J.html +++ /dev/null @@ -1,150 +0,0 @@ - - -snap-core-0.2.4: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (J)
joinI
joinIM
diff --git a/static/docs/0.2.4/snap-core/doc-index-L.html b/static/docs/0.2.4/snap-core/doc-index-L.html deleted file mode 100644 index 8e3ed32..0000000 --- a/static/docs/0.2.4/snap-core/doc-index-L.html +++ /dev/null @@ -1,196 +0,0 @@ - - -snap-core-0.2.4: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (L)
length
liftI
liftInner
localRequest
logError
LooseMap
looseMap
looseMapStream
LSB
diff --git a/static/docs/0.2.4/snap-core/doc-index-M.html b/static/docs/0.2.4/snap-core/doc-index-M.html deleted file mode 100644 index 1f8ba8d..0000000 --- a/static/docs/0.2.4/snap-core/doc-index-M.html +++ /dev/null @@ -1,210 +0,0 @@ - - -snap-core-0.2.4: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (M)
mapStream
Method
method
MimeMap
mkIterateeBuffer
modifyRequest
modifyResponse
modifyResponseBody
MSB
diff --git a/static/docs/0.2.4/snap-core/doc-index-N.html b/static/docs/0.2.4/snap-core/doc-index-N.html deleted file mode 100644 index 9380c05..0000000 --- a/static/docs/0.2.4/snap-core/doc-index-N.html +++ /dev/null @@ -1,158 +0,0 @@ - - -snap-core-0.2.4: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (N)
NoHandlerException
1 (Type/Class)
2 (Data Constructor)
diff --git a/static/docs/0.2.4/snap-core/doc-index-O.html b/static/docs/0.2.4/snap-core/doc-index-O.html deleted file mode 100644 index 501cc30..0000000 --- a/static/docs/0.2.4/snap-core/doc-index-O.html +++ /dev/null @@ -1,148 +0,0 @@ - - -snap-core-0.2.4: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (O)
OPTIONS
diff --git a/static/docs/0.2.4/snap-core/doc-index-P.html b/static/docs/0.2.4/snap-core/doc-index-P.html deleted file mode 100644 index 34d8bcd..0000000 --- a/static/docs/0.2.4/snap-core/doc-index-P.html +++ /dev/null @@ -1,238 +0,0 @@ - - -snap-core-0.2.4: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (P)
Params
parseHttpTime
parseToCompletion
pass
path
peek
POST
product
pUrlEscaped
PUT
putRequest
putResponse
diff --git a/static/docs/0.2.4/snap-core/doc-index-R.html b/static/docs/0.2.4/snap-core/doc-index-R.html deleted file mode 100644 index 034f306..0000000 --- a/static/docs/0.2.4/snap-core/doc-index-R.html +++ /dev/null @@ -1,530 +0,0 @@ - - -snap-core-0.2.4: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (R)
Request
1 (Type/Class)
2 (Data Constructor)
Response
1 (Type/Class)
2 (Data Constructor)
ResponseBody
rigidMapStream
route
routeLocal
rqBody
rqContentLength
rqContextPath
rqCookies
rqHeaders
rqIsSecure
rqLocalAddr
rqLocalHostname
rqLocalPort
rqMethod
rqModifyParams
rqParam
rqParams
rqPathInfo
rqQueryString
rqRemoteAddr
rqRemotePort
rqServerName
rqServerPort
rqSetParam
rqSnapletPath
rqURI
rqVersion
rspBody
rspBodyMap
rspBodyToEnum
rspContentLength
rspHeaders
rspHttpVersion
rspStatus
rspStatusReason
run
runIter
runRequestBody
runSnap
diff --git a/static/docs/0.2.4/snap-core/doc-index-S.html b/static/docs/0.2.4/snap-core/doc-index-S.html deleted file mode 100644 index 5a87952..0000000 --- a/static/docs/0.2.4/snap-core/doc-index-S.html +++ /dev/null @@ -1,296 +0,0 @@ - - -snap-core-0.2.4: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (S)
Seek
seek
SendFile
sendFile
setContentLength
setContentType
setEOF
setHeader
setResponseBody
setResponseStatus
set_c_locale
skipToEof
Snap
SomeEnumerator
1 (Type/Class)
2 (Data Constructor)
Stream
stream2list
stream2stream
StreamG
sum
diff --git a/static/docs/0.2.4/snap-core/doc-index-T.html b/static/docs/0.2.4/snap-core/doc-index-T.html deleted file mode 100644 index 777c76f..0000000 --- a/static/docs/0.2.4/snap-core/doc-index-T.html +++ /dev/null @@ -1,206 +0,0 @@ - - -snap-core-0.2.4: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (T)
take
takeExactly
takeNoMoreThan
takeR
throwErr
toCI
toStr
toWrap
TRACE
diff --git a/static/docs/0.2.4/snap-core/doc-index-U.html b/static/docs/0.2.4/snap-core/doc-index-U.html deleted file mode 100644 index ea4744f..0000000 --- a/static/docs/0.2.4/snap-core/doc-index-U.html +++ /dev/null @@ -1,200 +0,0 @@ - - -snap-core-0.2.4: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (U)
unCI
unsafeBufferIteratee
unsafeBufferIterateeWithBuffer
unsafeDetachRequestBody
updateHeaders
urlDecode
urlEncode
diff --git a/static/docs/0.2.4/snap-core/doc-index-W.html b/static/docs/0.2.4/snap-core/doc-index-W.html deleted file mode 100644 index ef5ae87..0000000 --- a/static/docs/0.2.4/snap-core/doc-index-W.html +++ /dev/null @@ -1,202 +0,0 @@ - - -snap-core-0.2.4: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)ContentsIndex
ABCDEFGHIJLMNOPRSTUW>
Index (W)
withCompression
withCompression'
withRequest
withResponse
writeBS
writeLazyText
writeLBS
writeText
diff --git a/static/docs/0.2.4/snap-core/doc-index.html b/static/docs/0.2.4/snap-core/doc-index.html deleted file mode 100644 index 545596a..0000000 --- a/static/docs/0.2.4/snap-core/doc-index.html +++ /dev/null @@ -1,134 +0,0 @@ - - -snap-core-0.2.4: Snap: A Haskell Web Framework (Core) (Index)
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)ContentsIndex
Index
ABCDEFGHIJLMNOPRSTUW>
diff --git a/static/docs/0.2.4/snap-core/fonts/DroidSerif-Bold.eot b/static/docs/0.2.4/snap-core/fonts/DroidSerif-Bold.eot deleted file mode 100644 index 01b9e1f..0000000 Binary files a/static/docs/0.2.4/snap-core/fonts/DroidSerif-Bold.eot and /dev/null differ diff --git a/static/docs/0.2.4/snap-core/fonts/DroidSerif-Bold.svg b/static/docs/0.2.4/snap-core/fonts/DroidSerif-Bold.svg deleted file mode 100644 index 1f7f2d2..0000000 --- a/static/docs/0.2.4/snap-core/fonts/DroidSerif-Bold.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.2.4/snap-core/fonts/DroidSerif-Bold.ttf b/static/docs/0.2.4/snap-core/fonts/DroidSerif-Bold.ttf deleted file mode 100644 index da0ea11..0000000 Binary files a/static/docs/0.2.4/snap-core/fonts/DroidSerif-Bold.ttf and /dev/null differ diff --git a/static/docs/0.2.4/snap-core/fonts/DroidSerif-Bold.woff b/static/docs/0.2.4/snap-core/fonts/DroidSerif-Bold.woff deleted file mode 100644 index 91549cd..0000000 Binary files a/static/docs/0.2.4/snap-core/fonts/DroidSerif-Bold.woff and /dev/null differ diff --git a/static/docs/0.2.4/snap-core/fonts/DroidSerif-BoldItalic.eot b/static/docs/0.2.4/snap-core/fonts/DroidSerif-BoldItalic.eot deleted file mode 100644 index 47dd0a0..0000000 Binary files a/static/docs/0.2.4/snap-core/fonts/DroidSerif-BoldItalic.eot and /dev/null differ diff --git a/static/docs/0.2.4/snap-core/fonts/DroidSerif-BoldItalic.svg b/static/docs/0.2.4/snap-core/fonts/DroidSerif-BoldItalic.svg deleted file mode 100644 index 1a57dbb..0000000 --- a/static/docs/0.2.4/snap-core/fonts/DroidSerif-BoldItalic.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.2.4/snap-core/fonts/DroidSerif-BoldItalic.ttf b/static/docs/0.2.4/snap-core/fonts/DroidSerif-BoldItalic.ttf deleted file mode 100644 index 8be3fb4..0000000 Binary files a/static/docs/0.2.4/snap-core/fonts/DroidSerif-BoldItalic.ttf and /dev/null differ diff --git a/static/docs/0.2.4/snap-core/fonts/DroidSerif-BoldItalic.woff b/static/docs/0.2.4/snap-core/fonts/DroidSerif-BoldItalic.woff deleted file mode 100644 index 6d5fa3d..0000000 Binary files a/static/docs/0.2.4/snap-core/fonts/DroidSerif-BoldItalic.woff and /dev/null differ diff --git a/static/docs/0.2.4/snap-core/fonts/DroidSerif-Italic.eot b/static/docs/0.2.4/snap-core/fonts/DroidSerif-Italic.eot deleted file mode 100644 index 2d4850c..0000000 Binary files a/static/docs/0.2.4/snap-core/fonts/DroidSerif-Italic.eot and /dev/null differ diff --git a/static/docs/0.2.4/snap-core/fonts/DroidSerif-Italic.svg b/static/docs/0.2.4/snap-core/fonts/DroidSerif-Italic.svg deleted file mode 100644 index 356c374..0000000 --- a/static/docs/0.2.4/snap-core/fonts/DroidSerif-Italic.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.2.4/snap-core/fonts/DroidSerif-Italic.ttf b/static/docs/0.2.4/snap-core/fonts/DroidSerif-Italic.ttf deleted file mode 100644 index 3719dc2..0000000 Binary files a/static/docs/0.2.4/snap-core/fonts/DroidSerif-Italic.ttf and /dev/null differ diff --git a/static/docs/0.2.4/snap-core/fonts/DroidSerif-Italic.woff b/static/docs/0.2.4/snap-core/fonts/DroidSerif-Italic.woff deleted file mode 100644 index b64436f..0000000 Binary files a/static/docs/0.2.4/snap-core/fonts/DroidSerif-Italic.woff and /dev/null differ diff --git a/static/docs/0.2.4/snap-core/fonts/DroidSerif-Regular.eot b/static/docs/0.2.4/snap-core/fonts/DroidSerif-Regular.eot deleted file mode 100644 index 0d17523..0000000 Binary files a/static/docs/0.2.4/snap-core/fonts/DroidSerif-Regular.eot and /dev/null differ diff --git a/static/docs/0.2.4/snap-core/fonts/DroidSerif-Regular.svg b/static/docs/0.2.4/snap-core/fonts/DroidSerif-Regular.svg deleted file mode 100644 index b9b65fb..0000000 --- a/static/docs/0.2.4/snap-core/fonts/DroidSerif-Regular.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.2.4/snap-core/fonts/DroidSerif-Regular.ttf b/static/docs/0.2.4/snap-core/fonts/DroidSerif-Regular.ttf deleted file mode 100644 index 066dcaa..0000000 Binary files a/static/docs/0.2.4/snap-core/fonts/DroidSerif-Regular.ttf and /dev/null differ diff --git a/static/docs/0.2.4/snap-core/fonts/DroidSerif-Regular.woff b/static/docs/0.2.4/snap-core/fonts/DroidSerif-Regular.woff deleted file mode 100644 index cfd3d67..0000000 Binary files a/static/docs/0.2.4/snap-core/fonts/DroidSerif-Regular.woff and /dev/null differ diff --git a/static/docs/0.2.4/snap-core/frames.html b/static/docs/0.2.4/snap-core/frames.html deleted file mode 100644 index 9e904fc..0000000 --- a/static/docs/0.2.4/snap-core/frames.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/static/docs/0.2.4/snap-core/haddock-util.js b/static/docs/0.2.4/snap-core/haddock-util.js deleted file mode 100644 index 364081f..0000000 --- a/static/docs/0.2.4/snap-core/haddock-util.js +++ /dev/null @@ -1,139 +0,0 @@ -// Haddock JavaScript utilities -function toggle(button,id) -{ - var n = document.getElementById(id).style; - if (n.display == "none") - { - button.src = "minus.gif"; - n.display = "block"; - } - else - { - button.src = "plus.gif"; - n.display = "none"; - } -} - - -var max_results = 75; // 50 is not enough to search for map in the base libraries -var shown_range = null; -var last_search = null; - -function quick_search() -{ - perform_search(false); -} - -function full_search() -{ - perform_search(true); -} - - -function perform_search(full) -{ - var text = document.getElementById("searchbox").value.toLowerCase(); - if (text == last_search && !full) return; - last_search = text; - - var table = document.getElementById("indexlist"); - var status = document.getElementById("searchmsg"); - var children = table.firstChild.childNodes; - - // first figure out the first node with the prefix - var first = bisect(-1); - var last = (first == -1 ? -1 : bisect(1)); - - if (first == -1) - { - table.className = ""; - status.innerHTML = "No results found, displaying all"; - } - else if (first == 0 && last == children.length - 1) - { - table.className = ""; - status.innerHTML = ""; - } - else if (last - first >= max_results && !full) - { - table.className = ""; - status.innerHTML = "More than " + max_results + ", press Search to display"; - } - else - { - // decide what you need to clear/show - if (shown_range) - setclass(shown_range[0], shown_range[1], "indexrow"); - setclass(first, last, "indexshow"); - shown_range = [first, last]; - table.className = "indexsearch"; - status.innerHTML = ""; - } - - - function setclass(first, last, status) - { - for (var i = first; i <= last; i++) - { - children[i].className = status; - } - } - - - // do a binary search, treating 0 as ... - // return either -1 (no 0's found) or location of most far match - function bisect(dir) - { - var first = 0, finish = children.length - 1; - var mid, success = false; - - while (finish - first > 3) - { - mid = Math.floor((finish + first) / 2); - - var i = checkitem(mid); - if (i == 0) i = dir; - if (i == -1) - finish = mid; - else - first = mid; - } - var a = (dir == 1 ? first : finish); - var b = (dir == 1 ? finish : first); - for (var i = b; i != a - dir; i -= dir) - { - if (checkitem(i) == 0) return i; - } - return -1; - } - - - // from an index, decide what the result is - // 0 = match, -1 is lower, 1 is higher - function checkitem(i) - { - var s = getitem(i).toLowerCase().substr(0, text.length); - if (s == text) return 0; - else return (s > text ? -1 : 1); - } - - - // from an index, get its string - // this abstracts over alternates - function getitem(i) - { - for ( ; i >= 0; i--) - { - var s = children[i].firstChild.firstChild.data; - if (s.indexOf(' ') == -1) - return s; - } - return ""; // should never be reached - } -} - -function setSynopsis(filename) { - if (parent.window.synopsis) { - parent.window.synopsis.location = filename; - } -} diff --git a/static/docs/0.2.4/snap-core/haddock.css b/static/docs/0.2.4/snap-core/haddock.css deleted file mode 100644 index fe050fe..0000000 --- a/static/docs/0.2.4/snap-core/haddock.css +++ /dev/null @@ -1,478 +0,0 @@ -/* -------- Global things --------- */ - -@font-face { - font-family: 'DroidSerif'; - src: url('fonts/DroidSerif-Regular.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Regular.woff') format('woff'), - url('fonts/DroidSerif-Regular.ttf') format('truetype'), - url('fonts/DroidSerif-Regular.svg#DroidSerif') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - font-style: italic; - src: url('fonts/DroidSerif-Italic.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Italic.woff') format('woff'), - url('fonts/DroidSerif-Italic.ttf') format('truetype'), - url('fonts/DroidSerif-Italic.svg#DroidSerif-Italic') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - font-weight: bold; - src: url('fonts/DroidSerif-Bold.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Bold.woff') format('woff'), - url('fonts/DroidSerif-Bold.ttf') format('truetype'), - url('fonts/DroidSerif-Bold.svg#DroidSerif-Bold') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - src: url('fonts/DroidSerif-BoldItalic.eot'); - font-weight: bold; - font-style: italic; - src: local('Droid Serif'), - url('fonts/DroidSerif-BoldItalic.woff') format('woff'), - url('fonts/DroidSerif-BoldItalic.ttf') format('truetype'), - url('fonts/DroidSerif-BoldItalic.svg#DroidSerif-BoldItalic') format('svg'); -} - - - -HTML { - background-color: #f0f3ff; - width: 100%; -} - -BODY { - -moz-border-radius:5px; - -webkit-border-radius:5px; - width: 50em; - margin: 2em auto; - padding: 0; - background-color: #ffffff; - color: #000000; - font-size: 110%; - font-family: DroidSerif, Georgia, serif; - } - -A:link { color: #5200A3; text-decoration: none } -A:visited { color: #5200A3; text-decoration: none } -A:hover { color: #5200A3; text-decoration: none; border-bottom:#5200A3 dashed 1px; } - -TABLE.vanilla { - width: 100%; - border-width: 0px; - /* I can't seem to specify cellspacing or cellpadding properly using CSS... */ -} - -DL { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - letter-spacing: -0.01em; - margin: 0; -} - -.vanilla .vanilla dl { font-size: 80%; } -.vanilla .vanilla dl dl { padding-left: 0; font-size: 95%; } - -TD.section1, TD.section2, TD.section3, TD.section4, TD.doc, DL { - padding: 0 30px 0 34px; -} - -TABLE.vanilla2 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - border-width: 0px; -} - -/* font is a little too small in MSIE */ -TT, PRE, CODE { - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - font-size: 90%; -} - -LI P { margin: 0pt } - -P { margin-top: 0; margin-bottom: 0.75em; } - -TD { - border-width: 0px; -} - -TABLE.narrow { - border-width: 0px; -} - -TD.s8 { height: 0; margin:0; padding: 0 } -TD.s15 { height: 20px; } - -SPAN.keyword { text-decoration: underline; } - -/* Resize the buttom image to match the text size */ -IMG.coll { width : 0.75em; height: 0.75em; margin-bottom: 0; margin-right: 0.5em } - -/* --------- Contents page ---------- */ - -DIV.node { - padding-left: 3em; -} - -DIV.cnode { - padding-left: 1.75em; -} - -SPAN.pkg { - position: absolute; - left: 50em; -} - -/* --------- Documentation elements ---------- */ - -TD FONT { font-weight: bold; letter-spacing: -0.02em; } - -TD.children { - padding-left: 25px; - } - -TD.synopsis { - padding: 2px; - background-color: #f0f0f0; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - } - -TD.decl { - padding: 4px 8px; - background-color: #FAFAFA; - border-bottom: #F2F2F2 solid 1px; - border-top: #FCFCFC solid 1px; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - vertical-align: top; - } - -TD.decl TD.decl { - font-size: 100%; - padding: 4px 0; - border: 0; -} - -TD.topdecl { - padding: 20px 30px 0.5ex 30px; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; -; - vertical-align: top; -} - -.vanilla .vanilla .vanilla .topdecl { - padding-left: 0; - padding-right: 0; -} - -.vanilla .vanilla .vanilla { - padding-left: 30px; -} - -.decl .vanilla { - padding-left: 0px !important; -} - -.body .vanilla .body { - padding-left: 0; - padding-right: 0; -} - -.body .vanilla .body .decl { - padding-left: 12px; -} - -.body .vanilla .body div .vanilla .decl { - padding-left: 12px; -} - -TABLE.declbar { - background-color: #f0f0f0; - border-spacing: 0px; - border-bottom:1px solid #d7d7df; - border-right:1px solid #d7d7df; - border-top:1px solid #f4f4f9; - border-left:1px solid #f4f4f9; - padding: 4px; - } - -TD.declname { - width: 100%; - padding-right: 4px; - } - -TD.declbut { - padding-left: 8px; - padding-right: 5px; - border-left-width: 1px; - border-left-color: #000099; - border-left-style: solid; - white-space: nowrap; - font-size: x-small; - } - -/* - arg is just like decl, except that wrapping is not allowed. It is - used for function and constructor arguments which have a text box - to the right, where if wrapping is allowed the text box squashes up - the declaration by wrapping it. -*/ -TD.arg { - padding: 2px 12px; - background-color: #f0f0f0; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - vertical-align: top; - white-space: nowrap; - } - -TD.recfield { padding-left: 20px } - -TD.doc { - padding-left: 38px; - font-size: 95%; - line-height: 1.66; - } - -TD.ndoc { - font-size: 95%; - line-height: 1.66; - padding: 2px 4px 2px 8px; - } - -TD.rdoc { - padding: 2px; - padding-left: 30px; - width: 100%; - font-size: 80%; - font-style: italic; - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - } - -TD.body { - padding: 0 30px; - } - -TD.pkg { - width: 100%; - padding-left: 30px -} - -TABLE.indexsearch TR.indexrow { - display: none; -} -TABLE.indexsearch TR.indexshow { - display: table-row; -} - -TD.indexentry { - vertical-align: top; - padding: 0 30px - } - -TD.indexannot { - vertical-align: top; - padding-left: 20px; - white-space: nowrap - } - -TD.indexlinks { - width: 100% - } - -/* ------- Section Headings ------- */ - -TD.section1, TD.section2, TD.section3, TD.section4, TD.section5 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; -} - -TD.section1 { - padding-top: 14px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 140% - } - -TD.section2 { - padding-top: 4px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 120% - } - -TD.section3 { - padding-top: 5px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 105% - } - -TD.section4 { - font-weight: bold; - padding-top: 12px; - padding-bottom: 4px; - letter-spacing: -0.02em; - font-size: 90% - } - -/* -------------- The title bar at the top of the page */ - -TD.infohead { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - font-weight: bold; - padding: 0 30px; - text-align: left; -} - -TD.infoval { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - padding: 0 30px; - text-align: left; -} - -TD.topbar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - background-color: #3465a4; - padding: 5px; - -moz-border-radius-topleft:5px; - -moz-border-radius-topright:5px; - -webkit-border-radius-topleft:5px; - -webkit-border-radius-topright:5px; -} - -TD.title { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - padding-left: 30px; - letter-spacing: -0.02em; - font-weight: bold; - width: 100% - } - -TD.topbut { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - padding-left: 5px; - padding-right: 5px; - border-left-width: 1px; - border-left-color: #ffffff; - border-left-style: solid; - letter-spacing: -0.02em; - font-weight: bold; - white-space: nowrap; - } - -TD.topbut A:link { - color: #ffffff - } - -TD.topbut A:visited { - color: #ffff00 - } - -TD.topbut A:hover { - background-color: #C9D3DE; - } - -TD.topbut:hover { - background-color: #C9D3DE; - } - -TD.modulebar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #141B24; - background-color: #C9D3DE; - padding: 5px; - border-top-width: 1px; - border-top-color: #ffffff; - border-top-style: solid; - -moz-border-radius-bottomleft:5px; - -moz-border-radius-bottomright:5px; - -webkit-border-radius-bottomleft:5px; - -webkit-border-radius-bottomright:5px; - - } - -/* --------- The page footer --------- */ - -TD.botbar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - -moz-border-radius:5px; - -webkit-border-radius:5px; - background-color: #3465a4; - color: #ffffff; - padding: 5px - } -TD.botbar A:link { - color: #ffffff; - text-decoration: underline - } -TD.botbar A:visited { - color: #ffff00 - } -TD.botbar A:hover { - background-color: #6060ff - } - -/* --------- Mini Synopsis for Frame View --------- */ - -.outer { - margin: 0 0; - padding: 0 0; -} - -.mini-synopsis { - padding: 0.25em 0.25em; -} - -.mini-synopsis H1 { font-size: 120%; } -.mini-synopsis H2 { font-size: 107%; } -.mini-synopsis H3 { font-size: 100%; } -.mini-synopsis H1, .mini-synopsis H2, .mini-synopsis H3 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - margin-top: 0.5em; - margin-bottom: 0.25em; - padding: 0 0; - font-weight: bold; letter-spacing: -0.02em; -} - -.mini-synopsis H1 { border-bottom: 1px solid #ccc; } - -.mini-topbar { - font-size: 120%; - background: #0077dd; - padding: 0.25em; -} - - diff --git a/static/docs/0.2.4/snap-core/haskell_icon.gif b/static/docs/0.2.4/snap-core/haskell_icon.gif deleted file mode 100644 index cb2a815..0000000 Binary files a/static/docs/0.2.4/snap-core/haskell_icon.gif and /dev/null differ diff --git a/static/docs/0.2.4/snap-core/index-frames.html b/static/docs/0.2.4/snap-core/index-frames.html deleted file mode 100644 index 38b58b5..0000000 --- a/static/docs/0.2.4/snap-core/index-frames.html +++ /dev/null @@ -1,43 +0,0 @@ - - -snap-core-0.2.4: Snap: A Haskell Web Framework (Core)

Data.CIByteString
Snap.Internal.Debug
Snap.Internal.Http.Types
Snap.Internal.Iteratee.Debug
Snap.Iteratee
Snap.Types
Snap.Util.FileServe
Snap.Util.GZip

diff --git a/static/docs/0.2.4/snap-core/index.html b/static/docs/0.2.4/snap-core/index.html deleted file mode 100644 index 688bfdc..0000000 --- a/static/docs/0.2.4/snap-core/index.html +++ /dev/null @@ -1,300 +0,0 @@ - - -snap-core-0.2.4: Snap: A Haskell Web Framework (Core)
 snap-core-0.2.4: Snap: A Haskell Web Framework (Core)ContentsIndex
snap-core-0.2.4: Snap: A Haskell Web Framework (Core)

This is the first developer prerelease of the Snap framework. Snap is a -simple and fast web development framework and server written in Haskell. For -more information or to download the latest version, you can visit the Snap -project website at http://snapframework.com/. -

This library contains the core definitions and types for the Snap framework, -including: -

1. Primitive types and functions for HTTP (requests, responses, cookies, -post/query parameters, etc) -

2. Type aliases and helper functions for Iteratee I/O -

3. A monad for programming web handlers called "Snap", inspired by -happstack's (http://happstack.com/index.html), which allows: -

  • Stateful access to the HTTP request and response objects -
  • Monadic failure (i.e. MonadPlus/Alternative instances) for declining -to handle requests and chaining handlers together -
  • Early termination of the computation if you know early what you want -to return and want to prevent further monadic processing -

Quick start: The Snap monad and HTTP definitions are in Snap.Types, -some iteratee utilities are in Snap.Iteratee. -

Higher-level facilities for building web applications (like user/session -management, component interfaces, data modeling, etc.) are planned but not -yet implemented, so this release will mostly be of interest for those who: -

  • need a fast and minimal HTTP API at roughly the same level of abstraction -as Java servlets, or -
  • are interested in contributing to the Snap Framework project. -
Modules
show/hideData
Data.CIByteString
show/hideSnap
show/hideInternal
Snap.Internal.Debug
show/hideHttp
Snap.Internal.Http.Types
show/hideIteratee
Snap.Internal.Iteratee.Debug
Snap.Iteratee
Snap.Types
show/hideUtil
Snap.Util.FileServe
Snap.Util.GZip
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.4/snap-core/mini_Data-CIByteString.html b/static/docs/0.2.4/snap-core/mini_Data-CIByteString.html deleted file mode 100644 index d9be8f2..0000000 --- a/static/docs/0.2.4/snap-core/mini_Data-CIByteString.html +++ /dev/null @@ -1,39 +0,0 @@ - - -Data.CIByteString
Data.CIByteString
diff --git a/static/docs/0.2.4/snap-core/mini_Snap-Internal-Debug.html b/static/docs/0.2.4/snap-core/mini_Snap-Internal-Debug.html deleted file mode 100644 index 9f5123e..0000000 --- a/static/docs/0.2.4/snap-core/mini_Snap-Internal-Debug.html +++ /dev/null @@ -1,29 +0,0 @@ - - -Snap.Internal.Debug
Snap.Internal.Debug
diff --git a/static/docs/0.2.4/snap-core/mini_Snap-Internal-Http-Types.html b/static/docs/0.2.4/snap-core/mini_Snap-Internal-Http-Types.html deleted file mode 100644 index f36e31d..0000000 --- a/static/docs/0.2.4/snap-core/mini_Snap-Internal-Http-Types.html +++ /dev/null @@ -1,207 +0,0 @@ - - -Snap.Internal.Http.Types diff --git a/static/docs/0.2.4/snap-core/mini_Snap-Internal-Iteratee-Debug.html b/static/docs/0.2.4/snap-core/mini_Snap-Internal-Iteratee-Debug.html deleted file mode 100644 index c622c16..0000000 --- a/static/docs/0.2.4/snap-core/mini_Snap-Internal-Iteratee-Debug.html +++ /dev/null @@ -1,25 +0,0 @@ - - -Snap.Internal.Iteratee.Debug
Snap.Internal.Iteratee.Debug
diff --git a/static/docs/0.2.4/snap-core/mini_Snap-Iteratee.html b/static/docs/0.2.4/snap-core/mini_Snap-Iteratee.html deleted file mode 100644 index c94546c..0000000 --- a/static/docs/0.2.4/snap-core/mini_Snap-Iteratee.html +++ /dev/null @@ -1,119 +0,0 @@ - - -Snap.Iteratee
Snap.Iteratee

Convenience aliases around types from Data.Iteratee -

type Stream
type IterV m
type Iteratee m
type Enumerator m a

Re-export types and functions from Data.Iteratee -

Helper functions -

Enumerators -

Conversion to/from WrappedByteString -

Iteratee utilities -

diff --git a/static/docs/0.2.4/snap-core/mini_Snap-Types.html b/static/docs/0.2.4/snap-core/mini_Snap-Types.html deleted file mode 100644 index 8fcdf2d..0000000 --- a/static/docs/0.2.4/snap-core/mini_Snap-Types.html +++ /dev/null @@ -1,386 +0,0 @@ - - -Snap.Types diff --git a/static/docs/0.2.4/snap-core/mini_Snap-Util-FileServe.html b/static/docs/0.2.4/snap-core/mini_Snap-Util-FileServe.html deleted file mode 100644 index 0ea73e5..0000000 --- a/static/docs/0.2.4/snap-core/mini_Snap-Util-FileServe.html +++ /dev/null @@ -1,51 +0,0 @@ - - -Snap.Util.FileServe diff --git a/static/docs/0.2.4/snap-core/mini_Snap-Util-GZip.html b/static/docs/0.2.4/snap-core/mini_Snap-Util-GZip.html deleted file mode 100644 index 93f3163..0000000 --- a/static/docs/0.2.4/snap-core/mini_Snap-Util-GZip.html +++ /dev/null @@ -1,29 +0,0 @@ - - -Snap.Util.GZip diff --git a/static/docs/0.2.4/snap-core/minus.gif b/static/docs/0.2.4/snap-core/minus.gif deleted file mode 100644 index 1deac2f..0000000 Binary files a/static/docs/0.2.4/snap-core/minus.gif and /dev/null differ diff --git a/static/docs/0.2.4/snap-core/plus.gif b/static/docs/0.2.4/snap-core/plus.gif deleted file mode 100644 index 2d15c14..0000000 Binary files a/static/docs/0.2.4/snap-core/plus.gif and /dev/null differ diff --git a/static/docs/0.2.4/snap-core/snap-core.haddock b/static/docs/0.2.4/snap-core/snap-core.haddock deleted file mode 100644 index 9ffcd94..0000000 Binary files a/static/docs/0.2.4/snap-core/snap-core.haddock and /dev/null differ diff --git a/static/docs/0.2.4/snap-core/src/Data-CIByteString.html b/static/docs/0.2.4/snap-core/src/Data-CIByteString.html deleted file mode 100644 index b69eba5..0000000 --- a/static/docs/0.2.4/snap-core/src/Data-CIByteString.html +++ /dev/null @@ -1,70 +0,0 @@ - - - - -src/Data/CIByteString.hs - - - -
{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE OverloadedStrings #-}
-
--- | "Data.CIByteString" is a module containing 'CIByteString', a wrapper for
--- 'ByteString' which provides case-insensitive (ASCII-wise) 'Ord' and 'Eq'
--- instances.
---
--- 'CIByteString' also has an 'IsString' instance, so if you use the
--- \"OverloadedStrings\" LANGUAGE pragma you can write case-insensitive string
--- literals, e.g.:
---
--- @
--- \> let a = \"Foo\" in
---   putStrLn $ (show $ unCI a) ++ \"==\\\"FoO\\\" is \" ++ show (a == \"FoO\")
--- \"Foo\"==\"FoO\" is True
--- @
-
-module Data.CIByteString
- ( CIByteString
- , toCI
- , unCI
- , ciToLower
- ) where
-
--- for IsString instance
-import           Data.ByteString.Char8 ()
-import           Data.ByteString (ByteString)
-import           Data.ByteString.Internal (c2w, w2c)
-import qualified Data.ByteString as S
-import           Data.Char
-import           Data.String
-
-
--- | A case-insensitive newtype wrapper for 'ByteString'
-data CIByteString = CIByteString { unCI        :: !ByteString
-                                 , _lowercased :: !ByteString }
-
-toCI :: ByteString -> CIByteString
-toCI s = CIByteString s t
-  where
-    t = lowercase s
-
-ciToLower :: CIByteString -> ByteString
-ciToLower = _lowercased
-
-instance Show CIByteString where
-    show (CIByteString s _) = show s
-
-lowercase :: ByteString -> ByteString
-lowercase = S.map (c2w . toLower . w2c)
-
-instance Eq CIByteString where
-    (CIByteString _ a) == (CIByteString _ b) = a == b
-    (CIByteString _ a) /= (CIByteString _ b) = a /= b
-
-instance Ord CIByteString where
-    (CIByteString _ a) <= (CIByteString _ b) = a <= b
-
-instance IsString CIByteString where
-    fromString = toCI . fromString
-
- diff --git a/static/docs/0.2.4/snap-core/src/Snap-Internal-Debug.html b/static/docs/0.2.4/snap-core/src/Snap-Internal-Debug.html deleted file mode 100644 index aafa21f..0000000 --- a/static/docs/0.2.4/snap-core/src/Snap-Internal-Debug.html +++ /dev/null @@ -1,86 +0,0 @@ - - - - -src/Snap/Internal/Debug.hs - - - -
-- | An internal Snap module for (optionally) printing debugging
--- messages. Normally 'debug' does nothing, but you can pass \"-fdebug\" to
--- @cabal install@ to build a @snap-core@ which debugs to stderr.
---
--- /N.B./ this is an internal interface, please don't write external code that
--- depends on it.
-
-{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE CPP #-}
-
-module Snap.Internal.Debug where
-
-import           Control.Monad.Trans
-
-#ifdef DEBUG_TEST
-
-debug :: (MonadIO m) => String -> m ()
-debug !s = return $ s `seq` ()
-{-# INLINE debug #-}
-
-debugErrno :: (MonadIO m) => String -> m ()
-debugErrno !s = return $ s `seq` ()
-
-#elif defined(DEBUG)
-
-------------------------------------------------------------------------------
-import           Control.Concurrent
-import           Data.List
-import           Data.Maybe
-import           Foreign.C.Error
-import           System.IO
-import           System.IO.Unsafe
-import           Text.Printf
-------------------------------------------------------------------------------
-
-
-------------------------------------------------------------------------------
-_debugMVar :: MVar ()
-_debugMVar = unsafePerformIO $ newMVar ()
-{-# NOINLINE _debugMVar #-}
-
-------------------------------------------------------------------------------
-debug :: (MonadIO m) => String -> m ()
-debug s = liftIO $ withMVar _debugMVar $ \_ -> do
-              tid <- myThreadId
-              hPutStrLn stderr $ s' tid
-              hFlush stderr
-  where
-    chop x = let y = fromMaybe x $ stripPrefix "ThreadId " x
-             in printf "%8s" y
-
-    s' t   = "[" ++ chop (show t) ++ "] " ++ s
-
-{-# INLINE debug #-}
-
-
-------------------------------------------------------------------------------
-debugErrno :: (MonadIO m) => String -> m ()
-debugErrno loc = liftIO $ do
-    err <- getErrno
-    let ex = errnoToIOError loc err Nothing Nothing
-    debug $ show ex
-------------------------------------------------------------------------------
-
-#else
-
-------------------------------------------------------------------------------
-debug :: (MonadIO m) => String -> m ()
-debug _ = return ()
-{-# INLINE debug #-}
-
-debugErrno :: (MonadIO m) => String -> m ()
-debugErrno _ = return ()
-------------------------------------------------------------------------------
-
-#endif
-
- diff --git a/static/docs/0.2.4/snap-core/src/Snap-Internal-Http-Types.html b/static/docs/0.2.4/snap-core/src/Snap-Internal-Http-Types.html deleted file mode 100644 index 32777ab..0000000 --- a/static/docs/0.2.4/snap-core/src/Snap-Internal-Http-Types.html +++ /dev/null @@ -1,693 +0,0 @@ - - - - -src/Snap/Internal/Http/Types.hs - - - -
-- | An internal Snap module containing HTTP types.
---
--- /N.B./ this is an internal interface, please don't write user code that
--- depends on it. Most of these declarations (except for the
--- unsafe/encapsulation-breaking ones) are re-exported from "Snap.Types".
-
-{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE CPP #-}
-{-# LANGUAGE EmptyDataDecls #-}
-{-# LANGUAGE ForeignFunctionInterface #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RankNTypes #-}
-{-# LANGUAGE TypeSynonymInstances #-}
-
-module Snap.Internal.Http.Types where
-
-
-------------------------------------------------------------------------------
-import           Control.Applicative hiding (empty)
-import           Control.Monad (liftM, when)
-import qualified Data.Attoparsec as Atto
-import           Data.Attoparsec hiding (many, Result(..))
-import           Data.Bits
-import           Data.ByteString (ByteString)
-import           Data.ByteString.Internal (c2w,w2c)
-import qualified Data.ByteString.Nums.Careless.Hex as Cvt
-import qualified Data.ByteString as S
-import qualified Data.ByteString.Unsafe as S
-import           Data.Char
-import           Data.DList (DList)
-import qualified Data.DList as DL
-import           Data.IORef
-import           Data.Map (Map)
-import qualified Data.Map as Map
-import           Data.Monoid
-import           Data.Serialize.Builder
-import           Data.Time.Clock
-import           Data.Time.Format
-import           Data.Word
-import           Foreign hiding (new)
-import           Foreign.C.Types
-import           Prelude hiding (take)
-import           System.Locale (defaultTimeLocale)
-
-
-#ifdef PORTABLE
-import           Data.Time.LocalTime
-import           Data.Time.Clock.POSIX
-#else
-import           Foreign.C.String
-#endif
-
-------------------------------------------------------------------------------
-import           Data.CIByteString
-import qualified Snap.Iteratee as I
-
-
-#ifndef PORTABLE
-
-------------------------------------------------------------------------------
--- foreign imports from cbits
-
-foreign import ccall unsafe "set_c_locale"
-        set_c_locale :: IO ()
-
-foreign import ccall unsafe "c_parse_http_time"
-        c_parse_http_time :: CString -> IO CTime
-
-foreign import ccall unsafe "c_format_http_time"
-        c_format_http_time :: CTime -> CString -> IO ()
-
-foreign import ccall unsafe "c_format_log_time"
-        c_format_log_time :: CTime -> CString -> IO ()
-
-#endif
-
-------------------------------------------------------------------------------
-type Enumerator a = I.Enumerator IO a
-
-------------------------------------------------------------------------------
--- | A type alias for a case-insensitive key-value mapping.
-type Headers = Map CIByteString [ByteString]
-
-
-------------------------------------------------------------------------------
--- | A typeclass for datatypes which contain HTTP headers.
-class HasHeaders a where
-
-    -- | Modify the datatype's headers.
-    updateHeaders :: (Headers -> Headers) -> a -> a
-
-    -- | Retrieve the headers from a datatype that has headers.
-    headers       :: a -> Headers
-
-
-------------------------------------------------------------------------------
--- | Adds a header key-value-pair to the 'HasHeaders' datatype. If a header with
--- the same name already exists, the new value is appended to the headers list.
-addHeader :: (HasHeaders a) => CIByteString -> ByteString -> a -> a
-addHeader k v = updateHeaders $ Map.insertWith' (++) k [v]
-
-
-------------------------------------------------------------------------------
--- | Sets a header key-value-pair in a 'HasHeaders' datatype. If a header with
--- the same name already exists, it is overwritten with the new value.
-setHeader :: (HasHeaders a) => CIByteString -> ByteString -> a -> a
-setHeader k v = updateHeaders $ Map.insert k [v]
-
-
-------------------------------------------------------------------------------
--- | Gets all of the values for a given header.
-getHeaders :: (HasHeaders a) => CIByteString -> a -> Maybe [ByteString]
-getHeaders k a = Map.lookup k $ headers a
-
-
-------------------------------------------------------------------------------
--- | Gets a header value out of a 'HasHeaders' datatype. If many headers came
--- in with the same name, they will be catenated together.
-getHeader :: (HasHeaders a) => CIByteString -> a -> Maybe ByteString
-getHeader k a = liftM (S.intercalate " ") (Map.lookup k $ headers a)
-
-
-------------------------------------------------------------------------------
--- | Enumerates the HTTP method values (see
--- <http://tools.ietf.org/html/rfc2068.html#section-5.1.1>).
-data Method  = GET | HEAD | POST | PUT | DELETE | TRACE | OPTIONS | CONNECT
-               deriving(Show,Read,Ord,Eq)
-
-
-------------------------------------------------------------------------------
-type HttpVersion = (Int,Int)
-
-
-------------------------------------------------------------------------------
--- | A datatype representing an HTTP cookie.
-data Cookie = Cookie {
-      -- | The name of the cookie.
-      cookieName    :: !ByteString
-
-      -- | The cookie's string value.
-    , cookieValue   :: !ByteString
-
-      -- | The cookie's expiration value, if it has one.
-    , cookieExpires :: !(Maybe UTCTime)
-
-      -- | The cookie's \"domain\" value, if it has one.
-    , cookieDomain  :: !(Maybe ByteString)
-
-      -- | The cookie path.
-    , cookiePath    :: !(Maybe ByteString)
-} deriving (Eq, Show)
-
-
-------------------------------------------------------------------------------
--- | A type alias for the HTTP parameters mapping. Each parameter
--- key maps to a list of ByteString values; if a parameter is specified
--- multiple times (e.g.: \"@GET /foo?param=bar1&param=bar2@\"), looking up
--- \"@param@\" in the mapping will give you @[\"bar1\", \"bar2\"]@.
-type Params = Map ByteString [ByteString]
-
-
-------------------------------------------------------------------------------
--- request type
-------------------------------------------------------------------------------
-
-data SomeEnumerator = SomeEnumerator (forall a . Enumerator a)
-
-
-------------------------------------------------------------------------------
--- | Contains all of the information about an incoming HTTP request.
-data Request = Request
-    { -- | The server name of the request, as it came in from the request's
-      -- @Host:@ header.
-      rqServerName     :: !ByteString
-
-      -- | Returns the port number the HTTP server is listening on.
-    , rqServerPort     :: !Int
-
-      -- | The remote IP address.
-    , rqRemoteAddr     :: !ByteString
-
-      -- | The remote TCP port number.
-    , rqRemotePort     :: !Int
-
-      -- | The local IP address for this request.
-    , rqLocalAddr      :: !ByteString
-
-      -- | Returns the port number the HTTP server is listening on.
-    , rqLocalPort      :: !Int
-
-      -- | Returns the HTTP server's idea of its local hostname.
-    , rqLocalHostname  :: !ByteString
-
-      -- | Returns @True@ if this is an @HTTPS@ session (currently always
-      -- @False@).
-    , rqIsSecure       :: !Bool
-    , rqHeaders        :: Headers
-    , rqBody           :: IORef SomeEnumerator
-
-      -- | Returns the @Content-Length@ of the HTTP request body.
-    , rqContentLength  :: !(Maybe Int)
-
-      -- | Returns the HTTP request method.
-    , rqMethod         :: !Method
-
-      -- | Returns the HTTP version used by the client.
-    , rqVersion        :: !HttpVersion
-
-      -- | Returns a list of the cookies that came in from the HTTP request
-      -- headers.
-    , rqCookies        :: [Cookie]
-
-
-      -- | We'll be doing web components (or \"snaplets\") for version 0.2. The
-      -- \"snaplet path\" refers to the place on the URL where your containing
-      -- snaplet is hung. The value of 'rqSnapletPath' is either @\"\"@ (at the
-      -- top-level context) or is a path beginning with a slash, but not ending
-      -- with one.
-      --
-      -- An identity is that:
-      --
-      -- > rqURI r == 'S.concat' [ rqSnapletPath r
-      -- >                       , rqContextPath r
-      -- >                       , rqPathInfo r ]
-      --
-      -- note that until we introduce snaplets in v0.2, 'rqSnapletPath' will be
-      -- \"\"
-    , rqSnapletPath    :: !ByteString
-
-      -- | Handlers can (/will be; --ed/) be hung on a @URI@ \"entry point\";
-      -- this is called the \"context path\". If a handler is hung on the
-      -- context path @\"\/foo\/\"@, and you request @\"\/foo\/bar\"@, the value
-      -- of 'rqPathInfo' will be @\"bar\"@.
-    , rqPathInfo       :: !ByteString
-
-      -- | The \"context path\" of the request; catenating 'rqContextPath', and
-      -- 'rqPathInfo' should get you back to the original 'rqURI'. The
-      -- 'rqContextPath' always begins and ends with a slash (@\"\/\"@)
-      -- character, and represents the path (relative to your
-      -- component\/snaplet) you took to get to your handler.
-    , rqContextPath    :: !ByteString
-
-      -- | Returns the @URI@ requested by the client.
-    , rqURI            :: !ByteString
-
-      -- | Returns the HTTP query string for this 'Request'.
-    , rqQueryString    :: !ByteString
-
-      -- | Returns the 'Params' mapping for this 'Request'. \"Parameters\" are
-      -- automatically decoded from the query string and @POST@ body and
-      -- entered into this mapping.
-    , rqParams         :: Params
-    }
-
-
-------------------------------------------------------------------------------
-instance Show Request where
-  show r = concat [ "Request <\n"
-                  , body
-                  , ">" ]
-    where
-      body = concat $ map (("    "++) . (++ "\n")) [
-                      sname
-                    , remote
-                    , local
-                    , beginheaders
-                    , hdrs
-                    , endheaders
-                    , contentlength
-                    , method
-                    , version
-                    , cookies
-                    , pathinfo
-                    , contextpath
-                    , snapletpath
-                    , uri
-                    , params
-                    ]
-
-      sname         = concat [ "server-name: ", toStr $ rqServerName r ]
-      remote        = concat [ "remote: "
-                             , toStr $ rqRemoteAddr r
-                             , ":"
-                             , show (rqRemotePort r)
-                             ]
-      local         = concat [ "local: "
-                             , toStr $ rqLocalAddr r
-                             , ":"
-                             , show $ rqServerPort r
-                             ]
-      beginheaders  = "Headers:\n      ========================================"
-      endheaders    = "  ========================================"
-      hdrs          = "      " ++ show (rqHeaders r)
-      contentlength = concat [ "content-length: "
-                             , show $ rqContentLength r
-                             ]
-      method        = concat [ "method: "
-                             , show $ rqMethod r
-                             ]
-      version       = concat [ "version: "
-                             , show $ rqVersion r
-                             ]
-      cookies       = concat [ "cookies:\n"
-                             , "      ========================================\n"
-                             , "      " ++ (show $ rqCookies r)
-                             , "\n      ========================================"
-                             ]
-      pathinfo      = concat [ "pathinfo: ", toStr $ rqPathInfo r ]
-      contextpath   = concat [ "contextpath: ", toStr $ rqContextPath r ]
-      snapletpath   = concat [ "snapletpath: ", toStr $ rqSnapletPath r ]
-      uri           = concat [ "URI: ", toStr $ rqURI r ]
-      params        = concat [ "params:\n"
-                             , "      ========================================\n"
-                             , "      " ++ (show $ rqParams r)
-                             , "\n      ========================================"
-                             ]
-
-
-------------------------------------------------------------------------------
-instance HasHeaders Request where
-    headers           = rqHeaders
-    updateHeaders f r = r { rqHeaders = f (rqHeaders r) }
-
-
-------------------------------------------------------------------------------
-instance HasHeaders Headers where
-    headers       = id
-    updateHeaders = id
-
-------------------------------------------------------------------------------
--- response type
-------------------------------------------------------------------------------
-
-data ResponseBody = Enum (forall a . Enumerator a) -- ^ output body is enumerator
-                  | SendFile FilePath              -- ^ output body is sendfile()
-
-
-------------------------------------------------------------------------------
-rspBodyMap :: (forall a . Enumerator a -> Enumerator a)
-           -> ResponseBody
-           -> ResponseBody
-rspBodyMap f b      = Enum $ f $ rspBodyToEnum b
-
-
-------------------------------------------------------------------------------
-rspBodyToEnum :: ResponseBody -> Enumerator a
-rspBodyToEnum (Enum e) = e
-rspBodyToEnum (SendFile fp) = I.enumFile fp
-
-
-------------------------------------------------------------------------------
--- | Represents an HTTP response.
-data Response = Response
-    { rspHeaders       :: Headers
-    , rspHttpVersion   :: !HttpVersion
-
-      -- | We will need to inspect the content length no matter what, and
-      --   looking up \"content-length\" in the headers and parsing the number
-      --   out of the text will be too expensive.
-    , rspContentLength :: !(Maybe Int)
-    , rspBody          :: ResponseBody
-
-      -- | Returns the HTTP status code.
-    , rspStatus        :: !Int
-
-      -- | Returns the HTTP status explanation string.
-    , rspStatusReason  :: !ByteString
-    }
-
-
-------------------------------------------------------------------------------
-instance Show Response where
-  show r = concat [ "Response <\n"
-                  , body
-                  , ">" ]
-    where
-      body = concat $ map (("    "++) . (++ "\n")) [
-                         hdrs
-                       , version
-                       , status
-                       , reason
-                       ]
-
-      hdrs    = concat [ "headers:\n"
-                       , "      ==============================\n      "
-                       , show $ rspHeaders r
-                       , "\n      ==============================" ]
-
-      version = concat [ "version: ", show $ rspHttpVersion r ]
-      status  = concat [ "status: ", show $ rspStatus r ]
-      reason  = concat [ "reason: ", toStr $ rspStatusReason r ]
-
-
-------------------------------------------------------------------------------
-instance HasHeaders Response where
-    headers = rspHeaders
-    updateHeaders f r = r { rspHeaders = f (rspHeaders r) }
-
-
-------------------------------------------------------------------------------
--- | Looks up the value(s) for the given named parameter. Parameters initially
--- come from the request's query string and any decoded POST body (if the
--- request's @Content-Type@ is @application\/x-www-form-urlencoded@). Parameter
--- values can be modified within handlers using "rqModifyParams".
-rqParam :: ByteString           -- ^ parameter name to look up
-        -> Request              -- ^ HTTP request
-        -> Maybe [ByteString]
-rqParam k rq = Map.lookup k $ rqParams rq
-{-# INLINE rqParam #-}
-
-
-------------------------------------------------------------------------------
--- | Modifies the parameters mapping (which is a @Map ByteString ByteString@) in
--- a 'Request' using the given function.
-rqModifyParams :: (Params -> Params) -> Request -> Request
-rqModifyParams f r = r { rqParams = p }
-  where
-    p = f $ rqParams r
-{-# INLINE rqModifyParams #-}
-
-
-------------------------------------------------------------------------------
--- | Writes a key-value pair to the parameters mapping within the given request.
-rqSetParam :: ByteString        -- ^ parameter name
-           -> [ByteString]      -- ^ parameter values
-           -> Request           -- ^ request
-           -> Request
-rqSetParam k v = rqModifyParams $ Map.insert k v
-{-# INLINE rqSetParam #-}
-
-------------------------------------------------------------------------------
--- responses
-------------------------------------------------------------------------------
-
--- | An empty 'Response'.
-emptyResponse       :: Response
-emptyResponse       = Response Map.empty (1,1) Nothing (Enum return) 200 "OK"
-
-
-------------------------------------------------------------------------------
--- | Sets an HTTP response body to the given 'Enumerator' value.
-setResponseBody     :: (forall a . Enumerator a)  -- ^ new response body
-                                                  -- enumerator
-                    -> Response                   -- ^ response to modify
-                    -> Response
-setResponseBody e r = r { rspBody = Enum e }
-{-# INLINE setResponseBody #-}
-
-
-------------------------------------------------------------------------------
--- | Sets the HTTP response status.
-setResponseStatus   :: Int        -- ^ HTTP response integer code
-                    -> ByteString -- ^ HTTP response explanation
-                    -> Response   -- ^ Response to be modified
-                    -> Response
-setResponseStatus s reason r = r { rspStatus=s, rspStatusReason=reason }
-{-# INLINE setResponseStatus #-}
-
-
-------------------------------------------------------------------------------
--- | Modifies a response body.
-modifyResponseBody  :: (forall a . Enumerator a -> Enumerator a)
-                    -> Response
-                    -> Response
-modifyResponseBody f r = r { rspBody = rspBodyMap f (rspBody r) }
-{-# INLINE modifyResponseBody #-}
-
-
-------------------------------------------------------------------------------
--- | Sets the @Content-Type@ in the 'Response' headers.
-setContentType      :: ByteString -> Response -> Response
-setContentType = setHeader "Content-Type"
-{-# INLINE setContentType #-}
-
-
-------------------------------------------------------------------------------
--- | Adds an HTTP 'Cookie' to the 'Response' headers.
-addCookie :: Cookie            -- ^ cookie value
-          -> Response          -- ^ response to modify
-          -> Response
-addCookie (Cookie k v mbExpTime mbDomain mbPath) = updateHeaders f
-  where
-    f       = Map.insertWith' (++) "Set-Cookie" [cookie]
-    cookie  = S.concat [k, "=", v, path, exptime, domain]
-    path    = maybe "" (S.append "; path=") mbPath
-    domain  = maybe "" (S.append "; domain=") mbDomain
-    exptime = maybe "" (S.append "; expires=" . fmt) mbExpTime
-    fmt     = fromStr . formatTime defaultTimeLocale "%a, %d-%b-%Y %H:%M:%S GMT"
-
-
-------------------------------------------------------------------------------
--- | A note here: if you want to set the @Content-Length@ for the response,
--- Snap forces you to do it with this function rather than by setting it in the
--- headers; the @Content-Length@ in the headers will be ignored.
---
--- The reason for this is that Snap needs to look up the value of
--- @Content-Length@ for each request, and looking the string value up in the
--- headers and parsing the number out of the text will be too expensive.
---
--- If you don't set a content length in your response, HTTP keep-alive will be
--- disabled for HTTP\/1.0 clients, forcing a @Connection: close@. For HTTP\/1.1
--- clients, Snap will switch to the chunked transfer encoding if
--- @Content-Length@ is not specified.
-setContentLength    :: Int -> Response -> Response
-setContentLength l r = r { rspContentLength = Just l }
-{-# INLINE setContentLength #-}
-
-
-------------------------------------------------------------------------------
--- | Removes any @Content-Length@ set in the 'Response'.
-clearContentLength :: Response -> Response
-clearContentLength r = r { rspContentLength = Nothing }
-{-# INLINE clearContentLength #-}
-
-
-------------------------------------------------------------------------------
--- HTTP dates
-
--- | Converts a 'CTime' into an HTTP timestamp.
-formatHttpTime :: CTime -> IO ByteString
-
--- | Converts a 'CTime' into common log entry format.
-formatLogTime :: CTime -> IO ByteString
-
--- | Converts an HTTP timestamp into a 'CTime'.
-parseHttpTime :: ByteString -> IO CTime
-
-#ifdef PORTABLE
-
-formatHttpTime = return . format . toUTCTime
-  where
-    format :: UTCTime -> ByteString
-    format = fromStr . formatTime defaultTimeLocale "%a, %d %b %Y %X GMT"
-
-    toUTCTime :: CTime -> UTCTime
-    toUTCTime = posixSecondsToUTCTime . realToFrac
-
-formatLogTime ctime = do
-  t <- utcToLocalZonedTime $ toUTCTime ctime
-  return $ format t
-
-  where
-    format :: ZonedTime -> ByteString
-    format = fromStr . formatTime defaultTimeLocale "%d/%b/%Y:%H:%M:%S %z"
-
-    toUTCTime :: CTime -> UTCTime
-    toUTCTime = posixSecondsToUTCTime . realToFrac
-
-
-parseHttpTime = return . toCTime . parse . toStr
-  where
-    parse :: String -> Maybe UTCTime
-    parse = parseTime defaultTimeLocale "%a, %d %b %Y %H:%M:%S GMT"
-
-    toCTime :: Maybe UTCTime -> CTime
-    toCTime (Just t) = fromInteger $ truncate $ utcTimeToPOSIXSeconds t
-    toCTime Nothing  = fromInteger 0
-
-#else
-
-formatLogTime t = do
-    ptr <- mallocBytes 40
-    c_format_log_time t ptr
-    S.unsafePackMallocCString ptr
-
-formatHttpTime t = do
-    ptr <- mallocBytes 40
-    c_format_http_time t ptr
-    S.unsafePackMallocCString ptr
-
-parseHttpTime s = S.unsafeUseAsCString s $ \ptr ->
-    c_parse_http_time ptr
-
-#endif
-
-
-------------------------------------------------------------------------------
--- URL ENCODING
-------------------------------------------------------------------------------
-
-parseToCompletion :: Parser a -> ByteString -> Maybe a
-parseToCompletion p s = toResult $ finish r
-  where
-    r = parse p s
-
-    toResult (Atto.Done _ c) = Just c
-    toResult _               = Nothing
-
-
-------------------------------------------------------------------------------
-pUrlEscaped :: Parser ByteString
-pUrlEscaped = do
-    sq <- nextChunk DL.empty
-    return $ S.concat $ DL.toList sq
-
-  where
-    nextChunk :: DList ByteString -> Parser (DList ByteString)
-    nextChunk s = (endOfInput *> pure s) <|> do
-        c <- anyWord8
-        case w2c c of
-          '+' -> plusSpace s
-          '%' -> percentEncoded s
-          _   -> unEncoded c s
-
-    percentEncoded :: DList ByteString -> Parser (DList ByteString)
-    percentEncoded l = do
-        hx <- take 2
-        when (S.length hx /= 2 ||
-               (not $ S.all (isHexDigit . w2c) hx)) $
-             fail "bad hex in url"
-          
-        let code = (Cvt.hex hx) :: Word8
-        nextChunk $ DL.snoc l (S.singleton code)
-
-    unEncoded :: Word8 -> DList ByteString -> Parser (DList ByteString)
-    unEncoded c l' = do
-        let l = DL.snoc l' (S.singleton c)
-        bs <- takeTill (flip elem (map c2w "%+"))
-        if S.null bs
-          then nextChunk l
-          else nextChunk $ DL.snoc l bs
-
-    plusSpace :: DList ByteString -> Parser (DList ByteString)
-    plusSpace l = nextChunk (DL.snoc l (S.singleton $ c2w ' '))
-
-
-------------------------------------------------------------------------------
--- | Decodes an URL-escaped string (see
--- <http://tools.ietf.org/html/rfc2396.html#section-2.4>)
-urlDecode :: ByteString -> Maybe ByteString
-urlDecode = parseToCompletion pUrlEscaped
-
-
-------------------------------------------------------------------------------
--- "...Only alphanumerics [0-9a-zA-Z], the special characters "$-_.+!*'(),"
--- [not including the quotes - ed], and reserved characters used for their
--- reserved purposes may be used unencoded within a URL."
-
--- | URL-escapes a string (see
--- <http://tools.ietf.org/html/rfc2396.html#section-2.4>)
-urlEncode :: ByteString -> ByteString
-urlEncode = toByteString . S.foldl' f empty
-  where
-    f b c =
-        if c == c2w ' '
-          then b `mappend` singleton (c2w '+')
-          else if isKosher c
-                 then b `mappend` singleton c
-                 else b `mappend` hexd c
-
-    isKosher w = any ($ c) [ isAlphaNum
-                           , flip elem ['$', '-', '.', '!', '*'
-                                       , '\'', '(', ')', ',' ]]
-      where
-        c = w2c w
-
-
-------------------------------------------------------------------------------
-hexd :: Word8 -> Builder
-hexd c = singleton (c2w '%') `mappend` singleton hi `mappend` singleton low
-  where
-    d   = c2w . intToDigit
-    low = d $ fromEnum $ c .&. 0xf
-    hi  = d $ fromEnum $ (c .&. 0xf0) `shift` (-4)
-
-
-------------------------------------------------------------------------------
-finish :: Atto.Result a -> Atto.Result a
-finish (Atto.Partial f) = flip feed "" $ f ""
-finish x                = x
-
-
-------------------------------------------------------------------------------
--- local definitions
-fromStr :: String -> ByteString
-fromStr = S.pack . map c2w
-{-# INLINE fromStr #-}
-
-------------------------------------------------------------------------------
--- private helper functions
-toStr :: ByteString -> String
-toStr = map w2c . S.unpack
-
-
- diff --git a/static/docs/0.2.4/snap-core/src/Snap-Internal-Iteratee-Debug.html b/static/docs/0.2.4/snap-core/src/Snap-Internal-Iteratee-Debug.html deleted file mode 100644 index 972fc9d..0000000 --- a/static/docs/0.2.4/snap-core/src/Snap-Internal-Iteratee-Debug.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - -src/Snap/Internal/Iteratee/Debug.hs - - - -
-- | An internal Snap module for debugging iteratees.
---
--- /N.B./ this is an internal interface, please don't write user code that
--- depends on it.
-
-{-# OPTIONS_GHC -fno-warn-orphans #-}
-{-# LANGUAGE FlexibleInstances #-}
-
-module Snap.Internal.Iteratee.Debug ( debugIteratee ) where
-
-------------------------------------------------------------------------------
-import           Data.Iteratee.WrappedByteString
-import           Data.Word (Word8)
-import           System.IO
-------------------------------------------------------------------------------
-import           Snap.Iteratee
-------------------------------------------------------------------------------
-
-
-------------------------------------------------------------------------------
-instance Show (WrappedByteString Word8) where
-    show (WrapBS s) = show s
-
-
-------------------------------------------------------------------------------
-debugIteratee :: Iteratee IO ()
-debugIteratee = IterateeG f
-  where
-    f c@(EOF _) = do
-        putStrLn $ "got chunk: " ++ show c
-        hFlush stdout
-        return (Done () c)
-
-    f c@(Chunk _) = do
-        putStrLn $ "got chunk: " ++ show c
-        hFlush stdout
-        return $ Cont debugIteratee Nothing
-
- diff --git a/static/docs/0.2.4/snap-core/src/Snap-Internal-Routing.html b/static/docs/0.2.4/snap-core/src/Snap-Internal-Routing.html deleted file mode 100644 index 63cffe2..0000000 --- a/static/docs/0.2.4/snap-core/src/Snap-Internal-Routing.html +++ /dev/null @@ -1,191 +0,0 @@ - - - - -src/Snap/Internal/Routing.hs - - - -
module Snap.Internal.Routing where
-
-
-------------------------------------------------------------------------------
-import           Control.Applicative ((<|>))
-import           Data.ByteString (ByteString)
-import           Data.ByteString.Internal (c2w)
-import qualified Data.ByteString as B
-import           Data.Monoid
-import qualified Data.Map as Map
-
-------------------------------------------------------------------------------
-import           Snap.Internal.Http.Types
-import           Snap.Internal.Types
-
-
-------------------------------------------------------------------------------
-{-|
-
-The internal data type you use to build a routing tree.  Matching is
-done unambiguously.
-
-'Capture' and 'Dir' routes can have a "fallback" route:
-
-  - For 'Capture', the fallback is routed when there is nothing to capture
-  - For 'Dir', the fallback is routed when we can't find a route in its map
-
-Fallback routes are stacked: i.e. for a route like:
-
-> Dir [("foo", Capture "bar" (Action bar) NoRoute)] baz
-
-visiting the URI foo/ will result in the "bar" capture being empty and
-triggering its fallback. It's NoRoute, so we go to the nearest parent
-fallback and try that, which is the baz action.
-
--}
-data Route a = Action (Snap a)                        -- wraps a 'Snap' action
-             | Capture ByteString (Route a) (Route a) -- captures the dir in a param
-             | Dir (Map.Map ByteString (Route a)) (Route a)  -- match on a dir
-             | NoRoute
-
-
-------------------------------------------------------------------------------
-instance Monoid (Route a) where
-    mempty = NoRoute
-
-    -- Unions two routes, favoring the right-hand side
-    mappend NoRoute r = r
-
-    mappend l@(Action _) r = case r of
-      (Action _)        -> r
-      (Capture p r' fb) -> Capture p r' (mappend fb l)
-      (Dir _ _)         -> mappend (Dir Map.empty l) r
-      NoRoute           -> l
-
-    mappend l@(Capture p r' fb) r = case r of
-      (Action _)           -> Capture p r' (mappend fb r)
-      (Capture p' r'' fb')
-               | p == p'   -> Capture p (mappend r' r'') (mappend fb fb')
-               | otherwise -> r
-      (Dir rm fb')         -> Dir rm (mappend fb' l)
-      NoRoute              -> l
-
-    mappend l@(Dir rm fb) r = case r of
-      (Action _)      -> Dir rm (mappend fb r)
-      (Capture _ _ _) -> Dir rm (mappend fb r)
-      (Dir rm' fb')   -> Dir (Map.unionWith mappend rm rm') (mappend fb fb')
-      NoRoute         -> l
-
-
-------------------------------------------------------------------------------
--- | A web handler which, given a mapping from URL entry points to web
--- handlers, efficiently routes requests to the correct handler.
---
--- The URL entry points are given as relative paths, for example:
---
--- > route [ ("foo/bar/quux", fooBarQuux) ]
---
--- If the URI of the incoming request is
---
--- > /foo/bar/quux
---
--- or
---
--- > /foo/bar/quux/...anything...
---
--- then the request will be routed to \"@fooBarQuux@\", with 'rqContextPath'
--- set to \"@\/foo\/bar\/quux\/@\" and 'rqPathInfo' set to
--- \"@...anything...@\".
---
--- A path component within an URL entry point beginning with a colon (\"@:@\")
--- is treated as a /variable capture/; the corresponding path component within
--- the request URI will be entered into the 'rqParams' parameters mapping with
--- the given name. For instance, if the routes were:
---
--- > route [ ("foo/:bar/baz", fooBazHandler) ]
---
--- Then a request for \"@\/foo\/saskatchewan\/baz@\" would be routed to
--- @fooBazHandler@ with a mapping for:
---
--- > "bar" => "saskatchewan"
---
--- in its parameters table.
---
--- Longer paths are matched first, and specific routes are matched before
--- captures. That is, if given routes:
---
--- > [ ("a", h1), ("a/b", h2), ("a/:x", h3) ]
---
--- a request for \"@\/a\/b@\" will go to @h2@, \"@\/a\/s@\" for any /s/ will go
--- to @h3@, and \"@\/a@\" will go to @h1@.
---
--- The following example matches \"@\/article@\" to an article index,
--- \"@\/login@\" to a login, and \"@\/article\/...@\" to an article renderer.
---
--- > route [ ("article",     renderIndex)
--- >       , ("article/:id", renderArticle)
--- >       , ("login",       method POST doLogin) ]
---
-route :: [(ByteString, Snap a)] -> Snap a
-route rts = route' (return ()) rts' []
-  where
-    rts' = mconcat (map pRoute rts)
-
-
-------------------------------------------------------------------------------
--- | The 'routeLocal' function is the same as 'route', except it doesn't change
--- the request's context path. This is useful if you want to route to a
--- particular handler but you want that handler to receive the 'rqPathInfo' as
--- it is.
-routeLocal :: [(ByteString, Snap a)] -> Snap a
-routeLocal rts' = do
-    req    <- getRequest
-    let ctx = rqContextPath req
-    let p   = rqPathInfo req
-    let md  = modifyRequest $ \r -> r {rqContextPath=ctx, rqPathInfo=p}
-
-    route' md rts []   <|>   (md >> pass)
-
-  where
-    rts = mconcat (map pRoute rts')
-
-          
-------------------------------------------------------------------------------
-pRoute :: (ByteString, Snap a) -> Route a
-pRoute (r, a) = foldr f (Action a) hier
-  where
-    hier   = filter (not . B.null) $ B.splitWith (== (c2w '/')) r
-    f s rt = if B.head s == c2w ':'
-        then Capture (B.tail s) rt NoRoute
-        else Dir (Map.fromList [(s, rt)]) NoRoute
-
-
-------------------------------------------------------------------------------
-route' :: Snap ()               -- ^ an action to be run before any user
-                                -- handler
-       -> Route a               -- ^ currently active routing table
-       -> [Route a]             -- ^ list of fallback routing tables in case
-                                -- the current table fails
-       -> Snap a
-route' pre (Action action) _ = pre >> action
-
-route' pre (Capture param rt fb) fbs = do
-    cwd <- getRequest >>= return . B.takeWhile (/= (c2w '/')) . rqPathInfo
-    if B.null cwd
-      then route' pre fb fbs
-      else do localRequest (updateContextPath (B.length cwd) . (f cwd)) $
-                           route' pre rt (fb:fbs)
-  where
-    f v req = req { rqParams = Map.insertWith (++) param [v] (rqParams req) }
-
-route' pre (Dir rtm fb) fbs = do
-    cwd <- getRequest >>= return . B.takeWhile (/= (c2w '/')) . rqPathInfo
-    case Map.lookup cwd rtm of
-      Just rt -> do
-          localRequest (updateContextPath (B.length cwd)) $
-                       route' pre rt (fb:fbs)
-      Nothing -> route' pre fb fbs
-
-route' _ NoRoute       []   = pass
-route' pre NoRoute (fb:fbs) = route' pre fb fbs
-
- diff --git a/static/docs/0.2.4/snap-core/src/Snap-Internal-Types.html b/static/docs/0.2.4/snap-core/src/Snap-Internal-Types.html deleted file mode 100644 index 1aa853c..0000000 --- a/static/docs/0.2.4/snap-core/src/Snap-Internal-Types.html +++ /dev/null @@ -1,544 +0,0 @@ - - - - -src/Snap/Internal/Types.hs - - - -
{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE EmptyDataDecls #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RankNTypes #-}
-
-module Snap.Internal.Types where
-
-------------------------------------------------------------------------------
-import           Control.Applicative
-import           Control.Exception (throwIO, ErrorCall(..))
-import           Control.Monad.CatchIO
-import           Control.Monad.State.Strict
-import           Data.ByteString.Char8 (ByteString)
-import qualified Data.ByteString.Char8 as S
-import qualified Data.ByteString.Lazy.Char8 as L
-import           Data.IORef
-import qualified Data.Iteratee as Iter
-import           Data.Maybe
-import qualified Data.Text as T
-import qualified Data.Text.Encoding as T
-import qualified Data.Text.Lazy as LT
-import qualified Data.Text.Lazy.Encoding as LT
-
-import           Data.Typeable
-
-------------------------------------------------------------------------------
-import           Snap.Iteratee hiding (Enumerator)
-import           Snap.Internal.Http.Types
-
-
-------------------------------------------------------------------------------
--- The Snap Monad
-------------------------------------------------------------------------------
-
-{-|
-
-'Snap' is the 'Monad' that user web handlers run in. 'Snap' gives you:
-
-1. stateful access to fetch or modify an HTTP 'Request'
-
-2. stateful access to fetch or modify an HTTP 'Response'
-
-3. failure \/ 'Alternative' \/ 'MonadPlus' semantics: a 'Snap' handler can
-   choose not to handle a given request, using 'empty' or its synonym 'pass',
-   and you can try alternative handlers with the '<|>' operator:
-
-   > a :: Snap String
-   > a = pass
-   >
-   > b :: Snap String
-   > b = return "foo"
-   >
-   > c :: Snap String
-   > c = a <|> b             -- try running a, if it fails then try b
-
-4. convenience functions ('writeBS', 'writeLBS', 'writeText', 'writeLazyText',
-   'addToOutput') for writing output to the 'Response':
-
-   > a :: (forall a . Enumerator a) -> Snap ()
-   > a someEnumerator = do
-   >     writeBS "I'm a strict bytestring"
-   >     writeLBS "I'm a lazy bytestring"
-   >     addToOutput someEnumerator
-
-5. early termination: if you call 'finishWith':
-
-   > a :: Snap ()
-   > a = do
-   >   modifyResponse $ setResponseStatus 500 "Internal Server Error"
-   >   writeBS "500 error"
-   >   r <- getResponse
-   >   finishWith r
-
-   then any subsequent processing will be skipped and supplied 'Response' value
-   will be returned from 'runSnap' as-is.
-
-6. access to the 'IO' monad through a 'MonadIO' instance:
-
-   > a :: Snap ()
-   > a = liftIO fireTheMissiles
--}
-
-
-------------------------------------------------------------------------------
-newtype Snap a = Snap {
-      unSnap :: StateT SnapState (Iteratee IO) (Maybe (Either Response a))
-} deriving Typeable
-
-
-------------------------------------------------------------------------------
-data SnapState = SnapState
-    { _snapRequest  :: Request
-    , _snapResponse :: Response
-    , _snapLogError :: ByteString -> IO () }
-
-
-------------------------------------------------------------------------------
-instance Monad Snap where
-    (Snap m) >>= f =
-        Snap $ do
-            eth <- m
-            maybe (return Nothing)
-                  (either (return . Just . Left)
-                          (unSnap . f))
-                  eth
-
-    return = Snap . return . Just . Right
-    fail   = const $ Snap $ return Nothing
-
-
-------------------------------------------------------------------------------
-instance MonadIO Snap where
-    liftIO m = Snap $ liftM (Just . Right) $ liftIO m
-
-
-------------------------------------------------------------------------------
-instance MonadCatchIO Snap where
-    catch (Snap m) handler = Snap $ do
-        x <- try m
-        case x of
-          (Left e)  -> let (Snap z) = handler e in z
-          (Right y) -> return y
-
-    block (Snap m) = Snap $ block m
-    unblock (Snap m) = Snap $ unblock m
-
-
-------------------------------------------------------------------------------
-instance MonadPlus Snap where
-    mzero = Snap $ return Nothing
-
-    a `mplus` b =
-        Snap $ do
-            mb <- unSnap a
-            if isJust mb then return mb else unSnap b
-
-
-------------------------------------------------------------------------------
-instance Functor Snap where
-    fmap = liftM
-
-
-------------------------------------------------------------------------------
-instance Applicative Snap where
-    pure  = return
-    (<*>) = ap
-
-
-------------------------------------------------------------------------------
-instance Alternative Snap where
-    empty = mzero
-    (<|>) = mplus
-
-
-------------------------------------------------------------------------------
-liftIter :: Iteratee IO a -> Snap a
-liftIter i = Snap (lift i >>= return . Just . Right)
-
-
-------------------------------------------------------------------------------
--- | Sends the request body through an iteratee (data consumer) and
--- returns the result.
-runRequestBody :: Iteratee IO a -> Snap a
-runRequestBody iter = do
-    req  <- getRequest
-    senum <- liftIO $ readIORef $ rqBody req
-    let (SomeEnumerator enum) = senum
-
-    -- make sure the iteratee consumes all of the output
-    let iter' = iter >>= (\a -> Iter.skipToEof >> return a)
-
-    -- run the iteratee
-    result <- liftIter $ Iter.joinIM $ enum iter'
-
-    -- stuff a new dummy enumerator into the request, so you can only try to
-    -- read the request body from the socket once
-    liftIO $ writeIORef (rqBody req)
-                        (SomeEnumerator $ return . Iter.joinI . Iter.take 0 )
-
-    return result
-
-
-------------------------------------------------------------------------------
--- | Returns the request body as a bytestring.
-getRequestBody :: Snap L.ByteString
-getRequestBody = liftM fromWrap $ runRequestBody stream2stream
-{-# INLINE getRequestBody #-}
-
-
-------------------------------------------------------------------------------
--- | Detaches the request body's 'Enumerator' from the 'Request' and
--- returns it. You would want to use this if you needed to send the
--- HTTP request body (transformed or otherwise) through to the output
--- in O(1) space. (Examples: transcoding, \"echo\", etc)
--- 
--- Normally Snap is careful to ensure that the request body is fully
--- consumed after your web handler runs; this function is marked
--- \"unsafe\" because it breaks this guarantee and leaves the
--- responsibility up to you. If you don't fully consume the
--- 'Enumerator' you get here, the next HTTP request in the pipeline
--- (if any) will misparse. Be careful with exception handlers.
-unsafeDetachRequestBody :: Snap (Enumerator a)
-unsafeDetachRequestBody = do
-    req <- getRequest
-    let ioref = rqBody req
-    senum <- liftIO $ readIORef ioref
-    let (SomeEnumerator enum) = senum
-    liftIO $ writeIORef ioref
-               (SomeEnumerator $ return . Iter.joinI . Iter.take 0)
-    return enum
-
-
-------------------------------------------------------------------------------
--- | Short-circuits a 'Snap' monad action early, storing the given
--- 'Response' value in its state.
-finishWith :: Response -> Snap ()
-finishWith = Snap . return . Just . Left
-{-# INLINE finishWith #-}
-
-
-------------------------------------------------------------------------------
--- | Fails out of a 'Snap' monad action.  This is used to indicate
--- that you choose not to handle the given request within the given
--- handler.
-pass :: Snap a
-pass = empty
-
-
-------------------------------------------------------------------------------
--- | Runs a 'Snap' monad action only if the request's HTTP method matches
--- the given method.
-method :: Method -> Snap a -> Snap a
-method m action = do
-    req <- getRequest
-    unless (rqMethod req == m) pass
-    action
-{-# INLINE method #-}
-
-
-------------------------------------------------------------------------------
--- Appends n bytes of the path info to the context path with a
--- trailing slash.
-updateContextPath :: Int -> Request -> Request
-updateContextPath n req | n > 0     = req { rqContextPath = ctx
-                                          , rqPathInfo    = pinfo }
-                        | otherwise = req
-  where
-    ctx'  = S.take n (rqPathInfo req)
-    ctx   = S.concat [rqContextPath req, ctx', "/"]
-    pinfo = S.drop (n+1) (rqPathInfo req)
-
-
-------------------------------------------------------------------------------
--- Runs a 'Snap' monad action only if the 'rqPathInfo' matches the given
--- predicate.
-pathWith :: (ByteString -> ByteString -> Bool)
-         -> ByteString
-         -> Snap a
-         -> Snap a
-pathWith c p action = do
-    req <- getRequest
-    unless (c p (rqPathInfo req)) pass
-    localRequest (updateContextPath $ S.length p) action
-
-
-------------------------------------------------------------------------------
--- | Runs a 'Snap' monad action only when the 'rqPathInfo' of the request
--- starts with the given path. For example,
---
--- > dir "foo" handler
---
--- Will fail if 'rqPathInfo' is not \"@\/foo@\" or \"@\/foo\/...@\", and will
--- add @\"foo\/\"@ to the handler's local 'rqContextPath'.
-dir :: ByteString  -- ^ path component to match
-    -> Snap a      -- ^ handler to run
-    -> Snap a
-dir = pathWith f
-  where
-    f dr pinfo = dr == x
-      where
-        (x,_) = S.break (=='/') pinfo
-{-# INLINE dir #-}
-
-
-------------------------------------------------------------------------------
--- | Runs a 'Snap' monad action only for requests where 'rqPathInfo' is exactly
--- equal to the given string. If the path matches, locally sets 'rqContextPath'
--- to the old value of 'rqPathInfo', sets 'rqPathInfo'=\"\", and runs the given
--- handler.
-path :: ByteString  -- ^ path to match against
-     -> Snap a      -- ^ handler to run
-     -> Snap a
-path = pathWith (==)
-{-# INLINE path #-}
-
-
-------------------------------------------------------------------------------
--- | Runs a 'Snap' monad action only when 'rqPathInfo' is empty.
-ifTop :: Snap a -> Snap a
-ifTop = path ""
-{-# INLINE ifTop #-}
-
-
-------------------------------------------------------------------------------
--- | Local Snap version of 'get'.
-sget :: Snap SnapState
-sget = Snap $ liftM (Just . Right) get
-{-# INLINE sget #-}
-
-
-------------------------------------------------------------------------------
--- | Local Snap monad version of 'modify'.
-smodify :: (SnapState -> SnapState) -> Snap ()
-smodify f = Snap $ modify f >> return (Just $ Right ())
-{-# INLINE smodify #-}
-
-
-------------------------------------------------------------------------------
--- | Grabs the 'Request' object out of the 'Snap' monad.
-getRequest :: Snap Request
-getRequest = liftM _snapRequest sget
-{-# INLINE getRequest #-}
-
-
-------------------------------------------------------------------------------
--- | Grabs the 'Response' object out of the 'Snap' monad.
-getResponse :: Snap Response
-getResponse = liftM _snapResponse sget
-{-# INLINE getResponse #-}
-
-
-------------------------------------------------------------------------------
--- | Puts a new 'Response' object into the 'Snap' monad.
-putResponse :: Response -> Snap ()
-putResponse r = smodify $ \ss -> ss { _snapResponse = r }
-{-# INLINE putResponse #-}
-
-
-------------------------------------------------------------------------------
--- | Puts a new 'Request' object into the 'Snap' monad.
-putRequest :: Request -> Snap ()
-putRequest r = smodify $ \ss -> ss { _snapRequest = r }
-{-# INLINE putRequest #-}
-
-
-------------------------------------------------------------------------------
--- | Modifies the 'Request' object stored in a 'Snap' monad.
-modifyRequest :: (Request -> Request) -> Snap ()
-modifyRequest f = smodify $ \ss -> ss { _snapRequest = f $ _snapRequest ss }
-{-# INLINE modifyRequest #-}
-
-
-------------------------------------------------------------------------------
--- | Modifes the 'Response' object stored in a 'Snap' monad.
-modifyResponse :: (Response -> Response) -> Snap () 
-modifyResponse f = smodify $ \ss -> ss { _snapResponse = f $ _snapResponse ss }
-{-# INLINE modifyResponse #-}
-
-
-------------------------------------------------------------------------------
--- | Log an error message in the 'Snap' monad
-logError :: ByteString -> Snap ()
-logError s = Snap $ gets _snapLogError >>= (\l -> liftIO $ l s)
-                                       >>  return (Just $ Right ())
-{-# INLINE logError #-}
-
-
-------------------------------------------------------------------------------
--- | Adds the output from the given enumerator to the 'Response'
--- stored in the 'Snap' monad state.
-addToOutput :: (forall a . Enumerator a)   -- ^ output to add
-            -> Snap ()
-addToOutput enum = modifyResponse $ modifyResponseBody (>. enum)
-
-
-------------------------------------------------------------------------------
--- | Adds the given strict 'ByteString' to the body of the 'Response' stored in
--- the 'Snap' monad state.
-writeBS :: ByteString -> Snap ()
-writeBS s = addToOutput $ enumBS s
-
-
-------------------------------------------------------------------------------
--- | Adds the given lazy 'L.ByteString' to the body of the 'Response' stored in
--- the 'Snap' monad state.
-writeLBS :: L.ByteString -> Snap ()
-writeLBS s = addToOutput $ enumLBS s
-
-
-------------------------------------------------------------------------------
--- | Adds the given strict 'T.Text' to the body of the 'Response' stored in the
--- 'Snap' monad state.
-writeText :: T.Text -> Snap ()
-writeText s = writeBS $ T.encodeUtf8 s
-
-
-------------------------------------------------------------------------------
--- | Adds the given lazy 'LT.Text' to the body of the 'Response' stored in the
--- 'Snap' monad state.
-writeLazyText :: LT.Text -> Snap ()
-writeLazyText s = writeLBS $ LT.encodeUtf8 s
-
-
-------------------------------------------------------------------------------
--- | Sets the output to be the contents of the specified file.
---
--- Calling 'sendFile' will overwrite any output queued to be sent in the
--- 'Response'. If the response body is not modified after the call to
--- 'sendFile', Snap will use the efficient @sendfile()@ system call on
--- platforms that support it.
---
--- If the response body is modified (using 'modifyResponseBody'), the file will
--- be read using @mmap()@.
-sendFile :: FilePath -> Snap ()
-sendFile f = modifyResponse $ \r -> r { rspBody = SendFile f }
-
-
-------------------------------------------------------------------------------
--- | Runs a 'Snap' action with a locally-modified 'Request' state
--- object. The 'Request' object in the Snap monad state after the call
--- to localRequest will be unchanged.
-localRequest :: (Request -> Request) -> Snap a -> Snap a
-localRequest f m = do
-    req <- getRequest
-
-    runAct req <|> (putRequest req >> pass)
-
-  where
-    runAct req = do
-        modifyRequest f
-        result <- m
-        putRequest req
-        return result
-{-# INLINE localRequest #-}
-
-
-------------------------------------------------------------------------------
--- | Fetches the 'Request' from state and hands it to the given action.
-withRequest :: (Request -> Snap a) -> Snap a
-withRequest = (getRequest >>=)
-{-# INLINE withRequest #-}
-
-
-------------------------------------------------------------------------------
--- | Fetches the 'Response' from state and hands it to the given action.
-withResponse :: (Response -> Snap a) -> Snap a
-withResponse = (getResponse >>=)
-{-# INLINE withResponse #-}
-
-
-------------------------------------------------------------------------------
--- | This exception is thrown if the handler you supply to 'runSnap' fails.
-data NoHandlerException = NoHandlerException
-   deriving (Eq, Typeable)
-
-
-------------------------------------------------------------------------------
-instance Show NoHandlerException where
-    show NoHandlerException = "No handler for request"
-
-
-------------------------------------------------------------------------------
-instance Exception NoHandlerException
-
-
-------------------------------------------------------------------------------
--- | Runs a 'Snap' monad action in the 'Iteratee IO' monad.
-runSnap :: Snap a
-        -> (ByteString -> IO ())
-        -> Request
-        -> Iteratee IO (Request,Response)
-runSnap (Snap m) logerr req = do
-    (r, ss') <- runStateT m ss
-
-    e <- maybe (return $ Left fourohfour)
-               return
-               r
-
-    -- is this a case of early termination?
-    let resp = case e of 
-                 Left x  -> x
-                 Right _ -> _snapResponse ss'
-
-    return (_snapRequest ss', resp)
-
-  where
-    fourohfour = setContentLength 3 $
-                 setResponseStatus 404 "Not Found" $
-                 modifyResponseBody (>. enumBS "404") $
-                 emptyResponse
-
-    dresp = emptyResponse { rspHttpVersion = rqVersion req }
-
-    ss = SnapState req dresp logerr
-{-# INLINE runSnap #-}
-
-
-------------------------------------------------------------------------------
-evalSnap :: Snap a
-         -> (ByteString -> IO ())
-         -> Request
-         -> Iteratee IO a
-evalSnap (Snap m) logerr req = do
-    (r, _) <- runStateT m ss
-
-    e <- maybe (liftIO $ throwIO NoHandlerException)
-               return
-               r
-
-    -- is this a case of early termination?
-    case e of 
-      Left _  -> liftIO $ throwIO $ ErrorCall "no value"
-      Right x -> return x
-  where
-    dresp = emptyResponse { rspHttpVersion = rqVersion req }
-    ss = SnapState req dresp logerr
-{-# INLINE evalSnap #-}
-
-
-
-------------------------------------------------------------------------------
--- | See 'rqParam'. Looks up a value for the given named parameter in the
--- 'Request'. If more than one value was entered for the given parameter name,
--- 'getParam' gloms the values together with:
---
--- @    'S.intercalate' \" \"@
---
-getParam :: ByteString          -- ^ parameter name to look up
-         -> Snap (Maybe ByteString)
-getParam k = do
-    rq <- getRequest
-    return $ liftM (S.intercalate " ") $ rqParam k rq
-
-
-
- diff --git a/static/docs/0.2.4/snap-core/src/Snap-Iteratee.html b/static/docs/0.2.4/snap-core/src/Snap-Iteratee.html deleted file mode 100644 index 68a3128..0000000 --- a/static/docs/0.2.4/snap-core/src/Snap-Iteratee.html +++ /dev/null @@ -1,427 +0,0 @@ - - - - -src/Snap/Iteratee.hs - - - -
{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE CPP #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE TypeSynonymInstances #-}
-
--- | Snap Framework type aliases and utilities for iteratees. Note that as a
--- convenience, this module also exports everything from @Data.Iteratee@ in the
--- @iteratee@ library.
---
--- /WARNING/: Note that all of these types are scheduled to change in the
--- @darcs@ head version of the @iteratee@ library; John Lato et al. are working
--- on a much improved iteratee formulation.
-
-module Snap.Iteratee
-  ( -- * Convenience aliases around types from @Data.Iteratee@
-    Stream
-  , IterV
-  , Iteratee
-  , Enumerator
-
-    -- * Re-export types and functions from @Data.Iteratee@
-  , module Data.Iteratee
-
-    -- * Helper functions
-
-    -- ** Enumerators
-  , enumBS
-  , enumLBS
-  , enumFile
-
-    -- ** Conversion to/from 'WrappedByteString'
-  , fromWrap
-  , toWrap
-
-    -- ** Iteratee utilities
-  , takeExactly
-  , takeNoMoreThan
-  , countBytes
-  , bufferIteratee
-  , mkIterateeBuffer
-  , unsafeBufferIterateeWithBuffer
-  , unsafeBufferIteratee
-  ) where
-
-------------------------------------------------------------------------------
-import           Control.Monad
-import           Control.Monad.CatchIO
-import           Data.ByteString (ByteString)
-import qualified Data.ByteString as S
-import qualified Data.ByteString.Unsafe as S
-import qualified Data.ByteString.Lazy as L
-import           Data.IORef
-import           Data.Iteratee
-#ifdef PORTABLE
-import           Data.Iteratee.IO (enumHandle)
-#endif
-import qualified Data.Iteratee.Base.StreamChunk as SC
-import           Data.Iteratee.WrappedByteString
-import           Data.Monoid (mappend)
-import           Foreign
-import           Foreign.C.Types
-import           GHC.ForeignPtr
-import           Prelude hiding (catch,drop)
-import qualified Data.DList as D
-
-#ifdef PORTABLE
-import           Control.Monad.Trans (liftIO)
-import           System.IO
-#else
-import           Control.Exception (SomeException)
-import           System.IO.Posix.MMap
-#endif
-
-------------------------------------------------------------------------------
-
-type Stream         = StreamG WrappedByteString Word8
-type IterV      m   = IterGV WrappedByteString Word8 m
-type Iteratee   m   = IterateeG WrappedByteString Word8 m
-type Enumerator m a = Iteratee m a -> m (Iteratee m a)
-
-
-------------------------------------------------------------------------------
-instance (Functor m, MonadCatchIO m) =>
-         MonadCatchIO (IterateeG s el m) where
-    --catch  :: Exception  e => m a -> (e -> m a) -> m a
-    catch m handler = IterateeG $ \str -> do
-        ee <- try $ runIter m str
-        case ee of
-          (Left e)  -> runIter (handler e) str
-          (Right v) -> return v
-
-    --block :: m a -> m a
-    block m = IterateeG $ \str -> block $ runIter m str
-    unblock m = IterateeG $ \str -> unblock $ runIter m str
-
-
-------------------------------------------------------------------------------
--- | Wraps an 'Iteratee', counting the number of bytes consumed by it.
-countBytes :: (Monad m) => Iteratee m a -> Iteratee m (a, Int)
-countBytes = go 0
-  where
-    go !n iter = IterateeG $ f n iter
-
-    f !n !iter ch@(Chunk ws) = do
-        iterv <- runIter iter ch
-        case iterv of
-          Done x rest -> let !n' = n + m - len rest
-                         in return $! Done (x, n') rest
-          Cont i err  -> return $ Cont ((go $! n + m) i) err
-      where
-        m = S.length $ unWrap ws
-
-        len (EOF _) = 0
-        len (Chunk s) = S.length $ unWrap s
-
-    f !n !iter stream = do
-        iterv <- runIter iter stream
-        case iterv of
-          Done x rest -> return $ Done (x, n) rest
-          Cont i err  -> return $ Cont (go n i) err
-
-
-------------------------------------------------------------------------------
--- | Buffers an iteratee.
---
--- Our enumerators produce a lot of little strings; rather than spending all
--- our time doing kernel context switches for 4-byte write() calls, we buffer
--- the iteratee to send 8KB at a time.
-bufferIteratee :: (Monad m) => Enumerator m a
-bufferIteratee = return . go (D.empty,0)
-  where
-    blocksize = 8192
-
-    --go :: (DList ByteString, Int) -> Iteratee m a -> Iteratee m a
-    go (!dl,!n) iter = IterateeG $! f (dl,n) iter
-
-    --f :: (DList ByteString, Int) -> Iteratee m a -> Stream -> m (IterV m a)
-    f _      !iter ch@(EOF (Just _)) = runIter iter ch
-    f (!dl,_) !iter ch@(EOF Nothing) = do
-        iterv <- runIter iter $ Chunk big
-        case iterv of
-          Done x rest     -> return $ Done x rest
-          Cont i (Just e) -> return $ Cont i (Just e)
-          Cont i Nothing  -> runIter i ch
-      where
-        big = toWrap $ L.fromChunks [S.concat $ D.toList dl]
-
-    f (!dl,!n) iter (Chunk ws) =
-        if n' > blocksize
-           then do
-               iterv <- runIter iter (Chunk big)
-               case iterv of
-                  Done x rest     -> return $ Done x rest
-                  Cont i (Just e) -> return $ Cont i (Just e)
-                  Cont i Nothing  -> return $ Cont (go (D.empty,0) i) Nothing
-           else return $ Cont (go (dl',n') iter) Nothing
-      where
-        s   = S.concat $ L.toChunks $ fromWrap ws
-        m   = S.length s
-        n'  = n+m
-        dl' = D.snoc dl s
-        big = toWrap $ L.fromChunks [S.concat $ D.toList dl']
-
-
-bUFSIZ :: Int
-bUFSIZ = 8192
-
-
--- | Creates a buffer to be passed into 'unsafeBufferIterateeWithBuffer'.
-mkIterateeBuffer :: IO (ForeignPtr CChar)
-mkIterateeBuffer = mallocPlainForeignPtrBytes bUFSIZ
-
-------------------------------------------------------------------------------
--- | Buffers an iteratee, \"unsafely\". Here we use a fixed binary buffer which
--- we'll re-use, meaning that if you hold on to any of the bytestring data
--- passed into your iteratee (instead of, let's say, shoving it right out a
--- socket) it'll get changed out from underneath you, breaking referential
--- transparency. Use with caution!
---
--- The IORef returned can be set to True to "cancel" buffering. We added this
--- so that transfer-encoding: chunked (which needs its own buffer and therefore
--- doesn't need /its/ output buffered) can switch the outer buffer off.
---
-unsafeBufferIteratee :: Iteratee IO a -> IO (Iteratee IO a, IORef Bool)
-unsafeBufferIteratee iter = do
-    buf <- mkIterateeBuffer
-    unsafeBufferIterateeWithBuffer buf iter
-
-
-------------------------------------------------------------------------------
--- | Buffers an iteratee, \"unsafely\". Here we use a fixed binary buffer which
--- we'll re-use, meaning that if you hold on to any of the bytestring data
--- passed into your iteratee (instead of, let's say, shoving it right out a
--- socket) it'll get changed out from underneath you, breaking referential
--- transparency. Use with caution!
---
--- This version accepts a buffer created by 'mkIterateeBuffer'.
---
--- The IORef returned can be set to True to "cancel" buffering. We added this
--- so that transfer-encoding: chunked (which needs its own buffer and therefore
--- doesn't need /its/ output buffered) can switch the outer buffer off.
---
-unsafeBufferIterateeWithBuffer :: ForeignPtr CChar
-                               -> Iteratee IO a
-                               -> IO (Iteratee IO a, IORef Bool)
-unsafeBufferIterateeWithBuffer buf iteratee = do
-    esc <- newIORef False
-    return $! (start esc iteratee, esc)
-
-  where
-    start esc iter = IterateeG $! checkRef esc iter
-    go bytesSoFar iter =
-        {-# SCC "unsafeBufferIteratee/go" #-}
-        IterateeG $! f bytesSoFar iter
-
-    checkRef esc iter ch = do
-        quit <- readIORef esc
-        if quit
-          then runIter iter ch
-          else f 0 iter ch
-
-    sendBuf n iter =
-        {-# SCC "unsafeBufferIteratee/sendBuf" #-}
-        withForeignPtr buf $ \ptr -> do
-            s <- S.unsafePackCStringLen (ptr, n)
-            runIter iter $ Chunk $ WrapBS s
-
-    copy c@(EOF _) = c
-    copy (Chunk (WrapBS s)) = Chunk $ WrapBS $ S.copy s
-
-    f _ iter ch@(EOF (Just _)) = runIter iter ch
-
-    f !n iter ch@(EOF Nothing) =
-        if n == 0
-          then runIter iter ch
-          else do
-              iterv <- sendBuf n iter
-              case iterv of
-                Done x rest     -> return $ Done x $ copy rest
-                Cont i (Just e) -> return $ Cont i (Just e)
-                Cont i Nothing  -> runIter i ch
-
-    f !n iter (Chunk (WrapBS s)) = do
-        let m = S.length s
-        if m+n > bUFSIZ
-          then overflow n iter s m
-          else copyAndCont n iter s m
-
-    copyAndCont n iter s m =
-      {-# SCC "unsafeBufferIteratee/copyAndCont" #-} do
-        S.unsafeUseAsCStringLen s $ \(p,sz) ->
-            withForeignPtr buf $ \bufp -> do
-                let b' = plusPtr bufp n
-                copyBytes b' p sz
-
-        return $ Cont (go (n+m) iter) Nothing
-
-
-    overflow n iter s m =
-      {-# SCC "unsafeBufferIteratee/overflow" #-} do
-        let rest = bUFSIZ - n
-        let m2   = m - rest
-        let (s1,s2) = S.splitAt rest s
-
-        S.unsafeUseAsCStringLen s1 $ \(p,_) ->
-          withForeignPtr buf $ \bufp -> do
-            let b' = plusPtr bufp n
-            copyBytes b' p rest
-
-            iv <- sendBuf bUFSIZ iter
-            case iv of
-              Done x r        -> return $
-                                 Done x (copy r `mappend` (Chunk $ WrapBS s2))
-              Cont i (Just e) -> return $ Cont i (Just e)
-              Cont i Nothing  -> do
-                  -- check the size of the remainder; if it's bigger than the
-                  -- buffer size then just send it
-                  if m2 >= bUFSIZ
-                    then do
-                        iv' <- runIter i (Chunk $ WrapBS s2)
-                        case iv' of
-                          Done x r         -> return $ Done x (copy r)
-                          Cont i' (Just e) -> return $ Cont i' (Just e)
-                          Cont i' Nothing  -> return $ Cont (go 0 i') Nothing
-                    else copyAndCont 0 i s2 m2
-
-
-------------------------------------------------------------------------------
--- | Enumerates a strict bytestring.
-enumBS :: (Monad m) => ByteString -> Enumerator m a
-enumBS bs = enumPure1Chunk $ WrapBS bs
-{-# INLINE enumBS #-}
-
-
-------------------------------------------------------------------------------
--- | Enumerates a lazy bytestring.
-enumLBS :: (Monad m) => L.ByteString -> Enumerator m a
-enumLBS lbs = el chunks
-  where
-    el [] i     = liftM liftI $ runIter i (EOF Nothing)
-    el (x:xs) i = do
-        i' <- liftM liftI $ runIter i (Chunk $ WrapBS x)
-        el xs i'
-
-    chunks = L.toChunks lbs
-
-
-------------------------------------------------------------------------------
--- | Converts a lazy bytestring to a wrapped bytestring.
-toWrap :: L.ByteString -> WrappedByteString Word8
-toWrap = WrapBS . S.concat . L.toChunks
-{-# INLINE toWrap #-}
-
-
-------------------------------------------------------------------------------
--- | Converts a wrapped bytestring to a lazy bytestring.
-fromWrap :: WrappedByteString Word8 -> L.ByteString
-fromWrap = L.fromChunks . (:[]) . unWrap
-{-# INLINE fromWrap #-}
-
-
-------------------------------------------------------------------------------
--- | Reads n elements from a stream and applies the given iteratee to
--- the stream of the read elements. Reads exactly n elements, and if
--- the stream is short propagates an error.
-takeExactly :: (SC.StreamChunk s el, Monad m) =>
-               Int ->
-               EnumeratorN s el s el m a
-takeExactly 0 iter = return iter
-takeExactly n' iter =
-    if n' < 0
-      then takeExactly 0 iter
-      else IterateeG (step n')
-  where
-  step n chk@(Chunk str)
-    | SC.null str = return $ Cont (takeExactly n iter) Nothing
-    | SC.length str < n = liftM (flip Cont Nothing) inner
-      where inner = liftM (check (n - SC.length str)) (runIter iter chk)
-  step n (Chunk str) = done (Chunk s1) (Chunk s2)
-    where (s1, s2) = SC.splitAt n str
-  step _n (EOF (Just e))    = return $ Cont undefined (Just e)
-  step _n (EOF Nothing)     = return $ Cont undefined (Just (Err "short write"))
-  check n (Done x _)        = drop n >> return (return x)
-  check n (Cont x Nothing)  = takeExactly n x
-  check n (Cont _ (Just e)) = drop n >> throwErr e
-  done s1 s2 = liftM (flip Done s2) (runIter iter s1 >>= checkIfDone return)
-
-
-------------------------------------------------------------------------------
--- | Reads up to n elements from a stream and applies the given iteratee to the
--- stream of the read elements. If more than n elements are read, propagates an
--- error.
-takeNoMoreThan :: (SC.StreamChunk s el, Monad m) =>
-                  Int ->
-                  EnumeratorN s el s el m a
-takeNoMoreThan n' iter =
-    if n' < 0
-      then takeNoMoreThan 0 iter
-      else IterateeG (step n')
-  where
-    step n chk@(Chunk str)
-      | SC.null str = return $ Cont (takeNoMoreThan n iter) Nothing
-      | SC.length str < n = liftM (flip Cont Nothing) inner
-      | otherwise = done (Chunk s1) (Chunk s2)
-          where inner    = liftM (check (n - SC.length str)) (runIter iter chk)
-                (s1, s2) = SC.splitAt n str
-
-    step _n (EOF (Just e))    = return $ Cont undefined (Just e)
-    step _n chk@(EOF Nothing) = do
-        v  <- runIter iter chk
-
-        case v of
-          (Done x s)        -> return $ Done (return x) s
-          (Cont _ (Just e)) -> return $ Cont undefined (Just e)
-          (Cont _ Nothing)  -> return $ Cont (throwErr $ Err "premature EOF") Nothing
-
-    check _ v@(Done _ _)      = return $ liftI v
-    check n (Cont x Nothing)  = takeNoMoreThan n x
-    check _ (Cont _ (Just e)) = throwErr e
-
-    done _ (EOF _) = error "impossible"
-    done s1 s2@(Chunk s2') = do
-        v <- runIter iter s1
-        case v of
-          (Done x s')       -> return $ Done (return x) (s' `mappend` s2)
-          (Cont _ (Just e)) -> return $ Cont undefined (Just e)
-          (Cont i Nothing)  ->
-              if SC.null s2'
-                then return $ Cont (takeNoMoreThan 0 i) Nothing
-                else return $ Cont undefined (Just $ Err "too many bytes")
-
-
-------------------------------------------------------------------------------
-enumFile :: FilePath -> Iteratee IO a -> IO (Iteratee IO a)
-
-#ifdef PORTABLE
-
-enumFile fp iter = do
-    h  <- liftIO $ openBinaryFile fp ReadMode
-    i' <- enumHandle h iter
-    return $ do
-        x <- i'
-        liftIO (hClose h)
-        return x
-
-#else
-
-enumFile fp iter = do
-    es <- (try $
-           liftM WrapBS $
-           unsafeMMapFile fp) :: IO (Either SomeException (WrappedByteString Word8))
-
-    case es of
-      (Left e)  -> return $ throwErr $ Err $ "IO error" ++ show e
-      (Right s) -> liftM liftI $ runIter iter $ Chunk s
-
-#endif
-
- diff --git a/static/docs/0.2.4/snap-core/src/Snap-Types.html b/static/docs/0.2.4/snap-core/src/Snap-Types.html deleted file mode 100644 index ecbe5f0..0000000 --- a/static/docs/0.2.4/snap-core/src/Snap-Types.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - -src/Snap/Types.hs - - - -
{-|
-
-This module contains the core type definitions, class instances, and functions
-for HTTP as well as the 'Snap' monad, which is used for web handlers.
-
--}
-module Snap.Types
-  ( 
-    -- * The Snap Monad
-    Snap
-  , runSnap
-  , NoHandlerException(..)
-
-    -- ** Functions for control flow and early termination
-  , finishWith
-  , pass
-
-    -- ** Routing
-  , method
-  , path
-  , dir
-  , ifTop
-  , route
-  , routeLocal
-
-    -- ** Access to state
-  , getRequest
-  , getResponse
-  , putRequest
-  , putResponse
-  , modifyRequest
-  , modifyResponse
-  , localRequest
-  , withRequest
-  , withResponse
-
-    -- ** Logging
-  , logError
-
-    -- ** Grabbing request bodies
-  , runRequestBody
-  , getRequestBody
-  , unsafeDetachRequestBody
-    -- * HTTP Datatypes and Functions
-    -- $httpDoc
-    --
-  , Request
-  , Response
-  , Headers
-  , HasHeaders(..)
-  , Params
-  , Method(..)
-  , Cookie(..)
-  , HttpVersion
-
-    -- ** Headers
-  , addHeader
-  , setHeader
-  , getHeader
-
-    -- ** Requests
-  , rqServerName
-  , rqServerPort
-  , rqRemoteAddr
-  , rqRemotePort
-  , rqLocalAddr
-  , rqLocalHostname
-  , rqIsSecure
-  , rqContentLength
-  , rqMethod
-  , rqVersion
-  , rqCookies
-  , rqPathInfo
-  , rqContextPath
-  , rqURI
-  , rqQueryString
-  , rqParams
-  , rqParam
-  , getParam
-  , rqModifyParams
-  , rqSetParam
-
-    -- ** Responses
-  , emptyResponse
-  , setResponseStatus
-  , rspStatus
-  , rspStatusReason
-  , setContentType
-  , addCookie
-  , setContentLength
-  , clearContentLength
-
-    -- *** Response I/O
-  , setResponseBody
-  , modifyResponseBody
-  , addToOutput
-  , writeBS
-  , writeLazyText
-  , writeText
-  , writeLBS
-  , sendFile
-
-    -- * Iteratee
-  , Enumerator
-
-    -- * HTTP utilities
-  , formatHttpTime
-  , parseHttpTime 
-  , urlEncode
-  , urlDecode
-  ) where
-
-------------------------------------------------------------------------------
-import           Snap.Internal.Http.Types
-import           Snap.Internal.Routing
-import           Snap.Internal.Types
-------------------------------------------------------------------------------
-
--- $httpDoc
--- HTTP-related datatypes: 'Request', 'Response', 'Cookie', etc.
-
- diff --git a/static/docs/0.2.4/snap-core/src/Snap-Util-FileServe.html b/static/docs/0.2.4/snap-core/src/Snap-Util-FileServe.html deleted file mode 100644 index cd3b3bc..0000000 --- a/static/docs/0.2.4/snap-core/src/Snap-Util-FileServe.html +++ /dev/null @@ -1,274 +0,0 @@ - - - - -src/Snap/Util/FileServe.hs - - - -
{-# LANGUAGE CPP #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
--- | Contains web handlers to serve files from a directory.
-module Snap.Util.FileServe
-(
-  getSafePath
-, fileServe
-, fileServe'
-, fileServeSingle
-, fileServeSingle'
-, defaultMimeTypes
-, MimeMap
-) where
-
-------------------------------------------------------------------------------
-import           Control.Monad
-import           Control.Monad.Trans
-import qualified Data.ByteString.Char8 as S
-import           Data.ByteString.Char8 (ByteString)
-import           Data.Map (Map)
-import qualified Data.Map as Map
-import           Data.Maybe (fromMaybe)
-import           System.Directory
-import           System.FilePath
-import           System.PosixCompat.Files
-
-------------------------------------------------------------------------------
-import           Snap.Types
-
-
-------------------------------------------------------------------------------
--- | A type alias for MIME type 
-type MimeMap = Map FilePath ByteString
-
-
-------------------------------------------------------------------------------
--- | The default set of mime type mappings we use when serving files. Its
--- value:
---
--- > Map.fromList [
--- >   ( ".asc"     , "text/plain"                        ),
--- >   ( ".asf"     , "video/x-ms-asf"                    ),
--- >   ( ".asx"     , "video/x-ms-asf"                    ),
--- >   ( ".avi"     , "video/x-msvideo"                   ),
--- >   ( ".bz2"     , "application/x-bzip"                ),
--- >   ( ".c"       , "text/plain"                        ),
--- >   ( ".class"   , "application/octet-stream"          ),
--- >   ( ".conf"    , "text/plain"                        ),
--- >   ( ".cpp"     , "text/plain"                        ),
--- >   ( ".css"     , "text/css"                          ),
--- >   ( ".cxx"     , "text/plain"                        ),
--- >   ( ".dtd"     , "text/xml"                          ),
--- >   ( ".dvi"     , "application/x-dvi"                 ),
--- >   ( ".gif"     , "image/gif"                         ),
--- >   ( ".gz"      , "application/x-gzip"                ),
--- >   ( ".hs"      , "text/plain"                        ),
--- >   ( ".htm"     , "text/html"                         ),
--- >   ( ".html"    , "text/html"                         ),
--- >   ( ".jar"     , "application/x-java-archive"        ),
--- >   ( ".jpeg"    , "image/jpeg"                        ),
--- >   ( ".jpg"     , "image/jpeg"                        ),
--- >   ( ".js"      , "text/javascript"                   ),
--- >   ( ".log"     , "text/plain"                        ),
--- >   ( ".m3u"     , "audio/x-mpegurl"                   ),
--- >   ( ".mov"     , "video/quicktime"                   ),
--- >   ( ".mp3"     , "audio/mpeg"                        ),
--- >   ( ".mpeg"    , "video/mpeg"                        ),
--- >   ( ".mpg"     , "video/mpeg"                        ),
--- >   ( ".ogg"     , "application/ogg"                   ),
--- >   ( ".pac"     , "application/x-ns-proxy-autoconfig" ),
--- >   ( ".pdf"     , "application/pdf"                   ),
--- >   ( ".png"     , "image/png"                         ),
--- >   ( ".ps"      , "application/postscript"            ),
--- >   ( ".qt"      , "video/quicktime"                   ),
--- >   ( ".sig"     , "application/pgp-signature"         ),
--- >   ( ".spl"     , "application/futuresplash"          ),
--- >   ( ".swf"     , "application/x-shockwave-flash"     ),
--- >   ( ".tar"     , "application/x-tar"                 ),
--- >   ( ".tar.bz2" , "application/x-bzip-compressed-tar" ),
--- >   ( ".tar.gz"  , "application/x-tgz"                 ),
--- >   ( ".tbz"     , "application/x-bzip-compressed-tar" ),
--- >   ( ".text"    , "text/plain"                        ),
--- >   ( ".tgz"     , "application/x-tgz"                 ),
--- >   ( ".torrent" , "application/x-bittorrent"          ),
--- >   ( ".txt"     , "text/plain"                        ),
--- >   ( ".wav"     , "audio/x-wav"                       ),
--- >   ( ".wax"     , "audio/x-ms-wax"                    ),
--- >   ( ".wma"     , "audio/x-ms-wma"                    ),
--- >   ( ".wmv"     , "video/x-ms-wmv"                    ),
--- >   ( ".xbm"     , "image/x-xbitmap"                   ),
--- >   ( ".xml"     , "text/xml"                          ),
--- >   ( ".xpm"     , "image/x-xpixmap"                   ),
--- >   ( ".xwd"     , "image/x-xwindowdump"               ),
--- >   ( ".zip"     , "application/zip"                   ) ]
---
-defaultMimeTypes :: MimeMap
-defaultMimeTypes = Map.fromList [
-  ( ".asc"     , "text/plain"                        ),
-  ( ".asf"     , "video/x-ms-asf"                    ),
-  ( ".asx"     , "video/x-ms-asf"                    ),
-  ( ".avi"     , "video/x-msvideo"                   ),
-  ( ".bz2"     , "application/x-bzip"                ),
-  ( ".c"       , "text/plain"                        ),
-  ( ".class"   , "application/octet-stream"          ),
-  ( ".conf"    , "text/plain"                        ),
-  ( ".cpp"     , "text/plain"                        ),
-  ( ".css"     , "text/css"                          ),
-  ( ".cxx"     , "text/plain"                        ),
-  ( ".dtd"     , "text/xml"                          ),
-  ( ".dvi"     , "application/x-dvi"                 ),
-  ( ".gif"     , "image/gif"                         ),
-  ( ".gz"      , "application/x-gzip"                ),
-  ( ".hs"      , "text/plain"                        ),
-  ( ".htm"     , "text/html"                         ),
-  ( ".html"    , "text/html"                         ),
-  ( ".jar"     , "application/x-java-archive"        ),
-  ( ".jpeg"    , "image/jpeg"                        ),
-  ( ".jpg"     , "image/jpeg"                        ),
-  ( ".js"      , "text/javascript"                   ),
-  ( ".log"     , "text/plain"                        ),
-  ( ".m3u"     , "audio/x-mpegurl"                   ),
-  ( ".mov"     , "video/quicktime"                   ),
-  ( ".mp3"     , "audio/mpeg"                        ),
-  ( ".mpeg"    , "video/mpeg"                        ),
-  ( ".mpg"     , "video/mpeg"                        ),
-  ( ".ogg"     , "application/ogg"                   ),
-  ( ".pac"     , "application/x-ns-proxy-autoconfig" ),
-  ( ".pdf"     , "application/pdf"                   ),
-  ( ".png"     , "image/png"                         ),
-  ( ".ps"      , "application/postscript"            ),
-  ( ".qt"      , "video/quicktime"                   ),
-  ( ".sig"     , "application/pgp-signature"         ),
-  ( ".spl"     , "application/futuresplash"          ),
-  ( ".swf"     , "application/x-shockwave-flash"     ),
-  ( ".tar"     , "application/x-tar"                 ),
-  ( ".tar.bz2" , "application/x-bzip-compressed-tar" ),
-  ( ".tar.gz"  , "application/x-tgz"                 ),
-  ( ".tbz"     , "application/x-bzip-compressed-tar" ),
-  ( ".text"    , "text/plain"                        ),
-  ( ".tgz"     , "application/x-tgz"                 ),
-  ( ".torrent" , "application/x-bittorrent"          ),
-  ( ".ttf"     , "application/x-font-truetype"       ),
-  ( ".txt"     , "text/plain"                        ),
-  ( ".wav"     , "audio/x-wav"                       ),
-  ( ".wax"     , "audio/x-ms-wax"                    ),
-  ( ".wma"     , "audio/x-ms-wma"                    ),
-  ( ".wmv"     , "video/x-ms-wmv"                    ),
-  ( ".xbm"     , "image/x-xbitmap"                   ),
-  ( ".xml"     , "text/xml"                          ),
-  ( ".xpm"     , "image/x-xpixmap"                   ),
-  ( ".xwd"     , "image/x-xwindowdump"               ),
-  ( ".zip"     , "application/zip"                   ) ]
-
-------------------------------------------------------------------------------
--- | Gets a path from the 'Request' using 'rqPathInfo' and makes sure it is
--- safe to use for opening files.  A path is safe if it is a relative path
--- and has no ".." elements to escape the intended directory structure.
-getSafePath :: Snap FilePath
-getSafePath = do
-    req <- getRequest
-    let p = S.unpack $ rqPathInfo req
-
-    -- check that we don't have any sneaky .. paths
-    let dirs = splitDirectories p
-    when (elem ".." dirs) pass
-    return p
-
-
-------------------------------------------------------------------------------
--- | Serves files out of the given directory. The relative path given in
--- 'rqPathInfo' is searched for the given file, and the file is served with the
--- appropriate mime type if it is found. Absolute paths and \"@..@\" are prohibited
--- to prevent files from being served from outside the sandbox.
---
--- Uses 'defaultMimeTypes' to determine the @Content-Type@ based on the file's
--- extension.
-fileServe :: FilePath  -- ^ root directory
-          -> Snap ()
-fileServe = fileServe' defaultMimeTypes
-{-# INLINE fileServe #-}
-
-
-------------------------------------------------------------------------------
--- | Same as 'fileServe', with control over the MIME mapping used.
-fileServe' :: MimeMap           -- ^ MIME type mapping
-           -> FilePath          -- ^ root directory
-           -> Snap ()
-fileServe' mm root = do
-    sp <- getSafePath
-    let fp   = root </> sp
-
-    -- check that the file exists
-    liftIO (doesFileExist fp) >>= flip unless pass
-
-    let fn   = takeFileName fp
-    let mime = fileType mm fn
-    fileServeSingle' mime fp
-{-# INLINE fileServe' #-}
-
-
-------------------------------------------------------------------------------
--- | Serves a single file specified by a full or relative path.  The
--- path restrictions on fileServe don't apply to this function since
--- the path is not being supplied by the user.
-fileServeSingle :: FilePath          -- ^ path to file
-                -> Snap ()
-fileServeSingle fp =
-    fileServeSingle' (fileType defaultMimeTypes (takeFileName fp)) fp
-{-# INLINE fileServeSingle #-}
-
-
-------------------------------------------------------------------------------
--- | Same as 'fileServeSingle', with control over the MIME mapping used.
-fileServeSingle' :: ByteString        -- ^ MIME type mapping
-                 -> FilePath          -- ^ path to file
-                 -> Snap ()
-fileServeSingle' mime fp = do
-    req <- getRequest
-    
-    let mbH = getHeader "if-modified-since" req
-    mbIfModified <- liftIO $ case mbH of
-                               Nothing  -> return Nothing
-                               (Just s) -> liftM Just $ parseHttpTime s
-
-    -- check modification time and bug out early if the file is not modified.
-    filestat <- liftIO $ getFileStatus fp
-    let mt = modificationTime filestat
-    maybe (return ()) (chkModificationTime mt) mbIfModified
-
-    let sz = fromEnum $ fileSize filestat
-    lm <- liftIO $ formatHttpTime mt
-
-    modifyResponse $ setHeader "Last-Modified" lm
-                   . setContentType mime
-                   . setContentLength sz
-    sendFile fp
-
-  where
-    --------------------------------------------------------------------------
-    chkModificationTime mt lt = when (mt <= lt) notModified
-
-    --------------------------------------------------------------------------
-    notModified = finishWith $
-                  setResponseStatus 304 "Not Modified" emptyResponse
-
-
-------------------------------------------------------------------------------
-fileType :: MimeMap -> FilePath -> ByteString
-fileType mm f =
-    if null ext
-      then defaultMimeType
-      else fromMaybe (fileType mm (drop 1 ext))
-                     mbe
-
-  where
-    ext             = takeExtensions f
-    mbe             = Map.lookup ext mm
-
-
-------------------------------------------------------------------------------
-defaultMimeType :: ByteString
-defaultMimeType = "application/octet-stream"
-
- diff --git a/static/docs/0.2.4/snap-core/src/Snap-Util-GZip.html b/static/docs/0.2.4/snap-core/src/Snap-Util-GZip.html deleted file mode 100644 index 83ec5df..0000000 --- a/static/docs/0.2.4/snap-core/src/Snap-Util-GZip.html +++ /dev/null @@ -1,341 +0,0 @@ - - - - -src/Snap/Util/GZip.hs - - - -
{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE ExistentialQuantification #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module Snap.Util.GZip
-( withCompression
-, withCompression' ) where
-
-import qualified Codec.Compression.GZip as GZip
-import qualified Codec.Compression.Zlib as Zlib
-import           Control.Concurrent
-import           Control.Applicative hiding (many)
-import           Control.Exception
-import           Control.Monad
-import           Control.Monad.Trans
-import           Data.Attoparsec.Char8 hiding (Done)
-import qualified Data.Attoparsec.Char8 as Atto
-import qualified Data.ByteString.Lazy.Char8 as L
-import           Data.ByteString.Char8 (ByteString)
-import           Data.Iteratee.WrappedByteString
-import           Data.Maybe
-import qualified Data.Set as Set
-import           Data.Set (Set)
-import           Data.Typeable
-import           Prelude hiding (catch, takeWhile)
-
-------------------------------------------------------------------------------
-import           Snap.Internal.Debug
-import           Snap.Iteratee hiding (Enumerator)
-import           Snap.Types
-
-
-------------------------------------------------------------------------------
--- | Runs a 'Snap' web handler with compression if available.
---
--- If the client has indicated support for @gzip@ or @compress@ in its
--- @Accept-Encoding@ header, and the @Content-Type@ in the response is one of
--- the following types:
---
---   * @application/x-javascript@
---
---   * @text/css@
---
---   * @text/html@
---
---   * @text/javascript@
---
---   * @text/plain@
---
---   * @text/xml@
---
---   * @application/x-font-truetype@
---
--- Then the given handler's output stream will be compressed,
--- @Content-Encoding@ will be set in the output headers, and the
--- @Content-Length@ will be cleared if it was set. (We can't process the stream
--- in O(1) space if the length is known beforehand.)
---
--- The wrapped handler will be run to completion, and then the 'Response'
--- that's contained within the 'Snap' monad state will be passed to
--- 'finishWith' to prevent further processing.
---
-withCompression :: Snap a   -- ^ the web handler to run
-                -> Snap ()
-withCompression = withCompression' compressibleMimeTypes
-
-
-------------------------------------------------------------------------------
--- | The same as 'withCompression', with control over which MIME types to
--- compress.
-withCompression' :: Set ByteString
-                    -- ^ set of compressible MIME types
-                 -> Snap a
-                    -- ^ the web handler to run
-                 -> Snap ()
-withCompression' mimeTable action = do
-    _    <- action
-    resp <- getResponse
-
-    -- If a content-encoding is already set, do nothing. This prevents
-    -- "withCompression $ withCompression m" from ruining your day.
-    if isJust $ getHeader "Content-Encoding" resp
-       then return ()
-       else do
-           let mbCt = getHeader "Content-Type" resp
-
-           debug $ "withCompression', content-type is " ++ show mbCt
-
-           case mbCt of
-             (Just ct) -> if Set.member ct mimeTable
-                             then chkAcceptEncoding
-                             else return ()
-             _         -> return ()
-
-
-    getResponse >>= finishWith
-
-  where
-    chkAcceptEncoding :: Snap ()
-    chkAcceptEncoding = do
-        req <- getRequest
-        debug $ "checking accept-encoding"
-        let mbAcc = getHeader "Accept-Encoding" req
-        debug $ "accept-encoding is " ++ show mbAcc
-        let s = fromMaybe "" mbAcc
-
-        types <- liftIO $ parseAcceptEncoding s
-
-        chooseType types
-
-
-    chooseType []               = return ()
-    chooseType ("gzip":_)       = gzipCompression
-    chooseType ("compress":_)   = compressCompression
-    chooseType ("x-gzip":_)     = gzipCompression
-    chooseType ("x-compress":_) = compressCompression
-    chooseType (_:xs)           = chooseType xs
-
-
-------------------------------------------------------------------------------
--- private following
-------------------------------------------------------------------------------
-
-
-------------------------------------------------------------------------------
-compressibleMimeTypes :: Set ByteString
-compressibleMimeTypes = Set.fromList [ "application/x-font-truetype"
-                                     , "application/x-javascript"
-                                     , "text/css"
-                                     , "text/html"
-                                     , "text/javascript"
-                                     , "text/plain"
-                                     , "text/xml" ]
-
-
-
-
-------------------------------------------------------------------------------
-gzipCompression :: Snap ()
-gzipCompression = modifyResponse f
-  where
-    f = setHeader "Content-Encoding" "gzip" .
-        clearContentLength .
-        modifyResponseBody gcompress
-
-
-------------------------------------------------------------------------------
-compressCompression :: Snap ()
-compressCompression = modifyResponse f
-  where
-    f = setHeader "Content-Encoding" "compress" .
-        clearContentLength .
-        modifyResponseBody ccompress
-
-
-------------------------------------------------------------------------------
-gcompress :: forall a . Enumerator a -> Enumerator a
-gcompress = compressEnumerator GZip.compress
-
-
-------------------------------------------------------------------------------
-ccompress :: forall a . Enumerator a -> Enumerator a
-ccompress = compressEnumerator Zlib.compress
-
-
-------------------------------------------------------------------------------
-compressEnumerator :: forall a .
-                      (L.ByteString -> L.ByteString)
-                   -> Enumerator a
-                   -> Enumerator a
-compressEnumerator compFunc enum iteratee = do
-    writeEnd <- newChan
-    readEnd  <- newChan
-    tid      <- forkIO $ threadProc readEnd writeEnd
-
-    enum (IterateeG $ f readEnd writeEnd tid iteratee)
-
-  where
-    --------------------------------------------------------------------------
-    streamFinished :: Stream -> Bool
-    streamFinished (EOF _)   = True
-    streamFinished (Chunk _) = False
-
-
-    --------------------------------------------------------------------------
-    consumeSomeOutput :: Chan Stream
-                      -> Iteratee IO a
-                      -> IO (Iteratee IO a)
-    consumeSomeOutput writeEnd iter = do
-        e <- isEmptyChan writeEnd
-        if e
-          then return iter
-          else do
-            ch <- readChan writeEnd
-
-            iter' <- liftM liftI $ runIter iter ch
-            if (streamFinished ch)
-               then return iter'
-               else consumeSomeOutput writeEnd iter'
-
-
-    --------------------------------------------------------------------------
-    consumeRest :: Chan Stream
-                -> Iteratee IO a
-                -> IO (IterV IO a)
-    consumeRest writeEnd iter = do
-        ch <- readChan writeEnd
-
-        iv <- runIter iter ch
-        if (streamFinished ch)
-           then return iv
-           else consumeRest writeEnd $ liftI iv
-
-
-    --------------------------------------------------------------------------
-    f readEnd writeEnd tid i (EOF Nothing) = do
-        writeChan readEnd Nothing
-        x <- consumeRest writeEnd i
-        killThread tid
-        return x
-
-    f _ _ tid i ch@(EOF (Just _)) = do
-        x <- runIter i ch
-        killThread tid
-        return x
-
-    f readEnd writeEnd tid i (Chunk s') = do
-        let s = unWrap s'
-        writeChan readEnd $ Just s
-        i' <- consumeSomeOutput writeEnd i
-        return $ Cont (IterateeG $ f readEnd writeEnd tid i') Nothing
-
-
-    --------------------------------------------------------------------------
-    threadProc :: Chan (Maybe ByteString)
-               -> Chan Stream
-               -> IO ()
-    threadProc readEnd writeEnd = do
-        stream <- getChanContents readEnd
-        let bs = L.fromChunks $ streamToChunks stream
-
-        let output = L.toChunks $ compFunc bs
-        let runIt = do
-            mapM_ (writeChan writeEnd . toChunk) output
-            writeChan writeEnd $ EOF Nothing
-
-        runIt `catch` \(e::SomeException) ->
-            writeChan writeEnd $ EOF (Just $ Err $ show e)
-
-
-    --------------------------------------------------------------------------
-    streamToChunks []            = []
-    streamToChunks (Nothing:_)   = []
-    streamToChunks ((Just x):xs) = x:(streamToChunks xs)
-
-
-    --------------------------------------------------------------------------
-    toChunk = Chunk . WrapBS
-
-
-------------------------------------------------------------------------------
-fullyParse :: ByteString -> Parser a -> Either String a
-fullyParse s p =
-    case r' of
-      (Fail _ _ e)    -> Left e
-      (Partial _)     -> Left "parse failed"
-      (Atto.Done _ x) -> Right x
-  where
-    r  = parse p s
-    r' = feed r ""
-
-
-------------------------------------------------------------------------------
--- We're not gonna bother with quality values; we'll do gzip or compress in
--- that order.
-acceptParser :: Parser [ByteString]
-acceptParser = do
-    xs <- option [] $ (:[]) <$> encoding
-    ys <- many (char ',' *> encoding)
-    endOfInput
-    return $ xs ++ ys
-  where
-    encoding = skipSpace *> c <* skipSpace
-
-    c = do
-        x <- coding
-        option () qvalue
-        return x
-
-    qvalue = do
-        skipSpace
-        char ';'
-        skipSpace
-        char 'q'
-        skipSpace
-        char '='
-        float
-        return ()
-
-    coding = string "*" <|> takeWhile isCodingChar
-
-    isCodingChar ch = isDigit ch || isAlpha_ascii ch || ch == '-' || ch == '_'
-
-    float = takeWhile isDigit >>
-            option () (char '.' >> takeWhile isDigit >> pure ())
-
-
-------------------------------------------------------------------------------
-data BadAcceptEncodingException = BadAcceptEncodingException
-   deriving (Typeable)
-
-
-------------------------------------------------------------------------------
-instance Show BadAcceptEncodingException where
-    show BadAcceptEncodingException = "bad 'accept-encoding' header"
-
-
-------------------------------------------------------------------------------
-instance Exception BadAcceptEncodingException
-
-
-------------------------------------------------------------------------------
-parseAcceptEncoding :: ByteString -> IO [ByteString]
-parseAcceptEncoding s =
-    case r of
-      Left _ -> throwIO BadAcceptEncodingException
-      Right x -> return x
-  where
-    r = fullyParse s acceptParser
-
-
- diff --git a/static/docs/0.2.4/snap-core/src/hscolour.css b/static/docs/0.2.4/snap-core/src/hscolour.css deleted file mode 100644 index 150e4d0..0000000 --- a/static/docs/0.2.4/snap-core/src/hscolour.css +++ /dev/null @@ -1,15 +0,0 @@ -body { font-size: 90%; } - -pre, code, body { - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; -} - -.hs-keyglyph, .hs-layout {color: #5200A3;} -.hs-keyword {color: #3465a4; font-weight: bold;} -.hs-comment, .hs-comment a {color: #579; } -.hs-str, .hs-chr {color: #141B24;} -.hs-keyword, .hs-conid, .hs-varid, .hs-conop, .hs-varop, .hs-num, .hs-cpp, .hs-sel, .hs-definition {} diff --git a/static/docs/0.2.4/snap-server/Snap-Http-Server-Config.html b/static/docs/0.2.4/snap-server/Snap-Http-Server-Config.html deleted file mode 100644 index d60f3d6..0000000 --- a/static/docs/0.2.4/snap-server/Snap-Http-Server-Config.html +++ /dev/null @@ -1,287 +0,0 @@ - - -Snap.Http.Server.Config
 snap-server-0.2.4: A fast, iteratee-based, epoll-enabled web server for the Snap FrameworkSource codeContentsIndex
Snap.Http.Server.Config
Documentation
data Config Source
Constructors
Config
localHostname :: !ByteString
bindAddress :: !ByteString
listenPort :: !Int
accessLog :: !(Maybe FilePath)
errorLog :: !(Maybe FilePath)
show/hide Instances
readConfigFromCmdLineArgsSource
:: Stringapplication description, e.g. - "Foo applet v0.2" -
-> IO Config
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.4/snap-server/Snap-Http-Server.html b/static/docs/0.2.4/snap-server/Snap-Http-Server.html deleted file mode 100644 index e835350..0000000 --- a/static/docs/0.2.4/snap-server/Snap-Http-Server.html +++ /dev/null @@ -1,283 +0,0 @@ - - -Snap.Http.Server
 snap-server-0.2.4: A fast, iteratee-based, epoll-enabled web server for the Snap FrameworkSource codeContentsIndex
Snap.Http.Server
Description
The Snap HTTP server is a high performance, epoll-enabled, iteratee-based - web server library written in Haskell. Together with the snap-core library - upon which it depends, it provides a clean and efficient Haskell programming - interface to the HTTP protocol. -
Synopsis
httpServe :: ByteString -> Int -> ByteString -> Maybe FilePath -> Maybe FilePath -> Snap () -> IO ()
snapServerVersion :: ByteString
Documentation
httpServeSource
:: ByteStringbind address, or "*" for all -
-> Intport to bind to -
-> ByteStringlocal hostname (server name) -
-> Maybe FilePathpath to the (optional) access log -
-> Maybe FilePathpath to the (optional) error log -
-> Snap ()handler procedure -
-> IO ()
Starts serving HTTP requests on the given port using the given handler. - This function never returns; to shut down the HTTP server, kill the - controlling thread. -
snapServerVersion :: ByteStringSource
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.4/snap-server/System-FastLogger.html b/static/docs/0.2.4/snap-server/System-FastLogger.html deleted file mode 100644 index 7afec09..0000000 --- a/static/docs/0.2.4/snap-server/System-FastLogger.html +++ /dev/null @@ -1,510 +0,0 @@ - - -System.FastLogger
 snap-server-0.2.4: A fast, iteratee-based, epoll-enabled web server for the Snap FrameworkSource codeContentsIndex
System.FastLogger
Synopsis
data Logger
timestampedLogEntry :: ByteString -> IO ByteString
combinedLogEntry :: ByteString -> Maybe ByteString -> ByteString -> Int -> Maybe Int -> Maybe ByteString -> ByteString -> IO ByteString
newLogger :: FilePath -> IO Logger
logMsg :: Logger -> ByteString -> IO ()
stopLogger :: Logger -> IO ()
Documentation
data Logger Source
Holds the state for a logger. -
timestampedLogEntry :: ByteString -> IO ByteStringSource
Prepares a log message with the time prepended. -
combinedLogEntrySource
:: ByteStringremote host -
-> Maybe ByteStringremote user -
-> ByteStringrequest line (up to you to ensure - there are no quotes in here) -
-> Intstatus code -
-> Maybe Intnum bytes sent -
-> Maybe ByteStringreferer (up to you to ensure - there are no quotes in here) -
-> ByteStringuser agent (up to you to ensure - there are no quotes in here) -
-> IO ByteString
Prepares a log message in "combined" format. -
newLogger :: FilePath -> IO LoggerSource
Creates a new logger, logging to the given file. If the file argument is - "-", then log to stdout; if it's "stderr" then we log to stderr, - otherwise we log to a regular file in append mode. The file is closed and - re-opened every 15 minutes to facilitate external log rotation. -
logMsg :: Logger -> ByteString -> IO ()Source
Sends out a log message verbatim with a newline appended. Note: - if you want a fancy log message you'll have to format it yourself - (or use combinedLogEntry). -
stopLogger :: Logger -> IO ()Source
Kills a logger thread, causing any unwritten contents to be - flushed out to disk -
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.4/snap-server/doc-index.html b/static/docs/0.2.4/snap-server/doc-index.html deleted file mode 100644 index 5a84f66..0000000 --- a/static/docs/0.2.4/snap-server/doc-index.html +++ /dev/null @@ -1,176 +0,0 @@ - - -snap-server-0.2.4: A fast, iteratee-based, epoll-enabled web server for the Snap Framework (Index)
 snap-server-0.2.4: A fast, iteratee-based, epoll-enabled web server for the Snap FrameworkContentsIndex
accessLog
bindAddress
combinedLogEntry
Config
1 (Type/Class)
2 (Data Constructor)
errorLog
httpServe
listenPort
localHostname
Logger
logMsg
newLogger
readConfigFromCmdLineArgs
snapServerVersion
stopLogger
timestampedLogEntry
diff --git a/static/docs/0.2.4/snap-server/fonts/DroidSerif-Bold.eot b/static/docs/0.2.4/snap-server/fonts/DroidSerif-Bold.eot deleted file mode 100644 index 01b9e1f..0000000 Binary files a/static/docs/0.2.4/snap-server/fonts/DroidSerif-Bold.eot and /dev/null differ diff --git a/static/docs/0.2.4/snap-server/fonts/DroidSerif-Bold.svg b/static/docs/0.2.4/snap-server/fonts/DroidSerif-Bold.svg deleted file mode 100644 index 1f7f2d2..0000000 --- a/static/docs/0.2.4/snap-server/fonts/DroidSerif-Bold.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.2.4/snap-server/fonts/DroidSerif-Bold.ttf b/static/docs/0.2.4/snap-server/fonts/DroidSerif-Bold.ttf deleted file mode 100644 index da0ea11..0000000 Binary files a/static/docs/0.2.4/snap-server/fonts/DroidSerif-Bold.ttf and /dev/null differ diff --git a/static/docs/0.2.4/snap-server/fonts/DroidSerif-Bold.woff b/static/docs/0.2.4/snap-server/fonts/DroidSerif-Bold.woff deleted file mode 100644 index 91549cd..0000000 Binary files a/static/docs/0.2.4/snap-server/fonts/DroidSerif-Bold.woff and /dev/null differ diff --git a/static/docs/0.2.4/snap-server/fonts/DroidSerif-BoldItalic.eot b/static/docs/0.2.4/snap-server/fonts/DroidSerif-BoldItalic.eot deleted file mode 100644 index 47dd0a0..0000000 Binary files a/static/docs/0.2.4/snap-server/fonts/DroidSerif-BoldItalic.eot and /dev/null differ diff --git a/static/docs/0.2.4/snap-server/fonts/DroidSerif-BoldItalic.svg b/static/docs/0.2.4/snap-server/fonts/DroidSerif-BoldItalic.svg deleted file mode 100644 index 1a57dbb..0000000 --- a/static/docs/0.2.4/snap-server/fonts/DroidSerif-BoldItalic.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.2.4/snap-server/fonts/DroidSerif-BoldItalic.ttf b/static/docs/0.2.4/snap-server/fonts/DroidSerif-BoldItalic.ttf deleted file mode 100644 index 8be3fb4..0000000 Binary files a/static/docs/0.2.4/snap-server/fonts/DroidSerif-BoldItalic.ttf and /dev/null differ diff --git a/static/docs/0.2.4/snap-server/fonts/DroidSerif-BoldItalic.woff b/static/docs/0.2.4/snap-server/fonts/DroidSerif-BoldItalic.woff deleted file mode 100644 index 6d5fa3d..0000000 Binary files a/static/docs/0.2.4/snap-server/fonts/DroidSerif-BoldItalic.woff and /dev/null differ diff --git a/static/docs/0.2.4/snap-server/fonts/DroidSerif-Italic.eot b/static/docs/0.2.4/snap-server/fonts/DroidSerif-Italic.eot deleted file mode 100644 index 2d4850c..0000000 Binary files a/static/docs/0.2.4/snap-server/fonts/DroidSerif-Italic.eot and /dev/null differ diff --git a/static/docs/0.2.4/snap-server/fonts/DroidSerif-Italic.svg b/static/docs/0.2.4/snap-server/fonts/DroidSerif-Italic.svg deleted file mode 100644 index 356c374..0000000 --- a/static/docs/0.2.4/snap-server/fonts/DroidSerif-Italic.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.2.4/snap-server/fonts/DroidSerif-Italic.ttf b/static/docs/0.2.4/snap-server/fonts/DroidSerif-Italic.ttf deleted file mode 100644 index 3719dc2..0000000 Binary files a/static/docs/0.2.4/snap-server/fonts/DroidSerif-Italic.ttf and /dev/null differ diff --git a/static/docs/0.2.4/snap-server/fonts/DroidSerif-Italic.woff b/static/docs/0.2.4/snap-server/fonts/DroidSerif-Italic.woff deleted file mode 100644 index b64436f..0000000 Binary files a/static/docs/0.2.4/snap-server/fonts/DroidSerif-Italic.woff and /dev/null differ diff --git a/static/docs/0.2.4/snap-server/fonts/DroidSerif-Regular.eot b/static/docs/0.2.4/snap-server/fonts/DroidSerif-Regular.eot deleted file mode 100644 index 0d17523..0000000 Binary files a/static/docs/0.2.4/snap-server/fonts/DroidSerif-Regular.eot and /dev/null differ diff --git a/static/docs/0.2.4/snap-server/fonts/DroidSerif-Regular.svg b/static/docs/0.2.4/snap-server/fonts/DroidSerif-Regular.svg deleted file mode 100644 index b9b65fb..0000000 --- a/static/docs/0.2.4/snap-server/fonts/DroidSerif-Regular.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/docs/0.2.4/snap-server/fonts/DroidSerif-Regular.ttf b/static/docs/0.2.4/snap-server/fonts/DroidSerif-Regular.ttf deleted file mode 100644 index 066dcaa..0000000 Binary files a/static/docs/0.2.4/snap-server/fonts/DroidSerif-Regular.ttf and /dev/null differ diff --git a/static/docs/0.2.4/snap-server/fonts/DroidSerif-Regular.woff b/static/docs/0.2.4/snap-server/fonts/DroidSerif-Regular.woff deleted file mode 100644 index cfd3d67..0000000 Binary files a/static/docs/0.2.4/snap-server/fonts/DroidSerif-Regular.woff and /dev/null differ diff --git a/static/docs/0.2.4/snap-server/frames.html b/static/docs/0.2.4/snap-server/frames.html deleted file mode 100644 index 9e904fc..0000000 --- a/static/docs/0.2.4/snap-server/frames.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/static/docs/0.2.4/snap-server/haddock-util.js b/static/docs/0.2.4/snap-server/haddock-util.js deleted file mode 100644 index 364081f..0000000 --- a/static/docs/0.2.4/snap-server/haddock-util.js +++ /dev/null @@ -1,139 +0,0 @@ -// Haddock JavaScript utilities -function toggle(button,id) -{ - var n = document.getElementById(id).style; - if (n.display == "none") - { - button.src = "minus.gif"; - n.display = "block"; - } - else - { - button.src = "plus.gif"; - n.display = "none"; - } -} - - -var max_results = 75; // 50 is not enough to search for map in the base libraries -var shown_range = null; -var last_search = null; - -function quick_search() -{ - perform_search(false); -} - -function full_search() -{ - perform_search(true); -} - - -function perform_search(full) -{ - var text = document.getElementById("searchbox").value.toLowerCase(); - if (text == last_search && !full) return; - last_search = text; - - var table = document.getElementById("indexlist"); - var status = document.getElementById("searchmsg"); - var children = table.firstChild.childNodes; - - // first figure out the first node with the prefix - var first = bisect(-1); - var last = (first == -1 ? -1 : bisect(1)); - - if (first == -1) - { - table.className = ""; - status.innerHTML = "No results found, displaying all"; - } - else if (first == 0 && last == children.length - 1) - { - table.className = ""; - status.innerHTML = ""; - } - else if (last - first >= max_results && !full) - { - table.className = ""; - status.innerHTML = "More than " + max_results + ", press Search to display"; - } - else - { - // decide what you need to clear/show - if (shown_range) - setclass(shown_range[0], shown_range[1], "indexrow"); - setclass(first, last, "indexshow"); - shown_range = [first, last]; - table.className = "indexsearch"; - status.innerHTML = ""; - } - - - function setclass(first, last, status) - { - for (var i = first; i <= last; i++) - { - children[i].className = status; - } - } - - - // do a binary search, treating 0 as ... - // return either -1 (no 0's found) or location of most far match - function bisect(dir) - { - var first = 0, finish = children.length - 1; - var mid, success = false; - - while (finish - first > 3) - { - mid = Math.floor((finish + first) / 2); - - var i = checkitem(mid); - if (i == 0) i = dir; - if (i == -1) - finish = mid; - else - first = mid; - } - var a = (dir == 1 ? first : finish); - var b = (dir == 1 ? finish : first); - for (var i = b; i != a - dir; i -= dir) - { - if (checkitem(i) == 0) return i; - } - return -1; - } - - - // from an index, decide what the result is - // 0 = match, -1 is lower, 1 is higher - function checkitem(i) - { - var s = getitem(i).toLowerCase().substr(0, text.length); - if (s == text) return 0; - else return (s > text ? -1 : 1); - } - - - // from an index, get its string - // this abstracts over alternates - function getitem(i) - { - for ( ; i >= 0; i--) - { - var s = children[i].firstChild.firstChild.data; - if (s.indexOf(' ') == -1) - return s; - } - return ""; // should never be reached - } -} - -function setSynopsis(filename) { - if (parent.window.synopsis) { - parent.window.synopsis.location = filename; - } -} diff --git a/static/docs/0.2.4/snap-server/haddock.css b/static/docs/0.2.4/snap-server/haddock.css deleted file mode 100644 index fe050fe..0000000 --- a/static/docs/0.2.4/snap-server/haddock.css +++ /dev/null @@ -1,478 +0,0 @@ -/* -------- Global things --------- */ - -@font-face { - font-family: 'DroidSerif'; - src: url('fonts/DroidSerif-Regular.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Regular.woff') format('woff'), - url('fonts/DroidSerif-Regular.ttf') format('truetype'), - url('fonts/DroidSerif-Regular.svg#DroidSerif') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - font-style: italic; - src: url('fonts/DroidSerif-Italic.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Italic.woff') format('woff'), - url('fonts/DroidSerif-Italic.ttf') format('truetype'), - url('fonts/DroidSerif-Italic.svg#DroidSerif-Italic') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - font-weight: bold; - src: url('fonts/DroidSerif-Bold.eot'); - src: local('Droid Serif'), - url('fonts/DroidSerif-Bold.woff') format('woff'), - url('fonts/DroidSerif-Bold.ttf') format('truetype'), - url('fonts/DroidSerif-Bold.svg#DroidSerif-Bold') format('svg'); -} - -@font-face { - font-family: 'DroidSerif'; - src: url('fonts/DroidSerif-BoldItalic.eot'); - font-weight: bold; - font-style: italic; - src: local('Droid Serif'), - url('fonts/DroidSerif-BoldItalic.woff') format('woff'), - url('fonts/DroidSerif-BoldItalic.ttf') format('truetype'), - url('fonts/DroidSerif-BoldItalic.svg#DroidSerif-BoldItalic') format('svg'); -} - - - -HTML { - background-color: #f0f3ff; - width: 100%; -} - -BODY { - -moz-border-radius:5px; - -webkit-border-radius:5px; - width: 50em; - margin: 2em auto; - padding: 0; - background-color: #ffffff; - color: #000000; - font-size: 110%; - font-family: DroidSerif, Georgia, serif; - } - -A:link { color: #5200A3; text-decoration: none } -A:visited { color: #5200A3; text-decoration: none } -A:hover { color: #5200A3; text-decoration: none; border-bottom:#5200A3 dashed 1px; } - -TABLE.vanilla { - width: 100%; - border-width: 0px; - /* I can't seem to specify cellspacing or cellpadding properly using CSS... */ -} - -DL { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - letter-spacing: -0.01em; - margin: 0; -} - -.vanilla .vanilla dl { font-size: 80%; } -.vanilla .vanilla dl dl { padding-left: 0; font-size: 95%; } - -TD.section1, TD.section2, TD.section3, TD.section4, TD.doc, DL { - padding: 0 30px 0 34px; -} - -TABLE.vanilla2 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - border-width: 0px; -} - -/* font is a little too small in MSIE */ -TT, PRE, CODE { - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - font-size: 90%; -} - -LI P { margin: 0pt } - -P { margin-top: 0; margin-bottom: 0.75em; } - -TD { - border-width: 0px; -} - -TABLE.narrow { - border-width: 0px; -} - -TD.s8 { height: 0; margin:0; padding: 0 } -TD.s15 { height: 20px; } - -SPAN.keyword { text-decoration: underline; } - -/* Resize the buttom image to match the text size */ -IMG.coll { width : 0.75em; height: 0.75em; margin-bottom: 0; margin-right: 0.5em } - -/* --------- Contents page ---------- */ - -DIV.node { - padding-left: 3em; -} - -DIV.cnode { - padding-left: 1.75em; -} - -SPAN.pkg { - position: absolute; - left: 50em; -} - -/* --------- Documentation elements ---------- */ - -TD FONT { font-weight: bold; letter-spacing: -0.02em; } - -TD.children { - padding-left: 25px; - } - -TD.synopsis { - padding: 2px; - background-color: #f0f0f0; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - } - -TD.decl { - padding: 4px 8px; - background-color: #FAFAFA; - border-bottom: #F2F2F2 solid 1px; - border-top: #FCFCFC solid 1px; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - vertical-align: top; - } - -TD.decl TD.decl { - font-size: 100%; - padding: 4px 0; - border: 0; -} - -TD.topdecl { - padding: 20px 30px 0.5ex 30px; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; -; - vertical-align: top; -} - -.vanilla .vanilla .vanilla .topdecl { - padding-left: 0; - padding-right: 0; -} - -.vanilla .vanilla .vanilla { - padding-left: 30px; -} - -.decl .vanilla { - padding-left: 0px !important; -} - -.body .vanilla .body { - padding-left: 0; - padding-right: 0; -} - -.body .vanilla .body .decl { - padding-left: 12px; -} - -.body .vanilla .body div .vanilla .decl { - padding-left: 12px; -} - -TABLE.declbar { - background-color: #f0f0f0; - border-spacing: 0px; - border-bottom:1px solid #d7d7df; - border-right:1px solid #d7d7df; - border-top:1px solid #f4f4f9; - border-left:1px solid #f4f4f9; - padding: 4px; - } - -TD.declname { - width: 100%; - padding-right: 4px; - } - -TD.declbut { - padding-left: 8px; - padding-right: 5px; - border-left-width: 1px; - border-left-color: #000099; - border-left-style: solid; - white-space: nowrap; - font-size: x-small; - } - -/* - arg is just like decl, except that wrapping is not allowed. It is - used for function and constructor arguments which have a text box - to the right, where if wrapping is allowed the text box squashes up - the declaration by wrapping it. -*/ -TD.arg { - padding: 2px 12px; - background-color: #f0f0f0; - font-size: 80%; - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; - - vertical-align: top; - white-space: nowrap; - } - -TD.recfield { padding-left: 20px } - -TD.doc { - padding-left: 38px; - font-size: 95%; - line-height: 1.66; - } - -TD.ndoc { - font-size: 95%; - line-height: 1.66; - padding: 2px 4px 2px 8px; - } - -TD.rdoc { - padding: 2px; - padding-left: 30px; - width: 100%; - font-size: 80%; - font-style: italic; - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - } - -TD.body { - padding: 0 30px; - } - -TD.pkg { - width: 100%; - padding-left: 30px -} - -TABLE.indexsearch TR.indexrow { - display: none; -} -TABLE.indexsearch TR.indexshow { - display: table-row; -} - -TD.indexentry { - vertical-align: top; - padding: 0 30px - } - -TD.indexannot { - vertical-align: top; - padding-left: 20px; - white-space: nowrap - } - -TD.indexlinks { - width: 100% - } - -/* ------- Section Headings ------- */ - -TD.section1, TD.section2, TD.section3, TD.section4, TD.section5 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; -} - -TD.section1 { - padding-top: 14px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 140% - } - -TD.section2 { - padding-top: 4px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 120% - } - -TD.section3 { - padding-top: 5px; - font-weight: bold; - letter-spacing: -0.02em; - font-size: 105% - } - -TD.section4 { - font-weight: bold; - padding-top: 12px; - padding-bottom: 4px; - letter-spacing: -0.02em; - font-size: 90% - } - -/* -------------- The title bar at the top of the page */ - -TD.infohead { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - font-weight: bold; - padding: 0 30px; - text-align: left; -} - -TD.infoval { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - padding: 0 30px; - text-align: left; -} - -TD.topbar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - background-color: #3465a4; - padding: 5px; - -moz-border-radius-topleft:5px; - -moz-border-radius-topright:5px; - -webkit-border-radius-topleft:5px; - -webkit-border-radius-topright:5px; -} - -TD.title { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #ffffff; - padding-left: 30px; - letter-spacing: -0.02em; - font-weight: bold; - width: 100% - } - -TD.topbut { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - padding-left: 5px; - padding-right: 5px; - border-left-width: 1px; - border-left-color: #ffffff; - border-left-style: solid; - letter-spacing: -0.02em; - font-weight: bold; - white-space: nowrap; - } - -TD.topbut A:link { - color: #ffffff - } - -TD.topbut A:visited { - color: #ffff00 - } - -TD.topbut A:hover { - background-color: #C9D3DE; - } - -TD.topbut:hover { - background-color: #C9D3DE; - } - -TD.modulebar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - color: #141B24; - background-color: #C9D3DE; - padding: 5px; - border-top-width: 1px; - border-top-color: #ffffff; - border-top-style: solid; - -moz-border-radius-bottomleft:5px; - -moz-border-radius-bottomright:5px; - -webkit-border-radius-bottomleft:5px; - -webkit-border-radius-bottomright:5px; - - } - -/* --------- The page footer --------- */ - -TD.botbar { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - -moz-border-radius:5px; - -webkit-border-radius:5px; - background-color: #3465a4; - color: #ffffff; - padding: 5px - } -TD.botbar A:link { - color: #ffffff; - text-decoration: underline - } -TD.botbar A:visited { - color: #ffff00 - } -TD.botbar A:hover { - background-color: #6060ff - } - -/* --------- Mini Synopsis for Frame View --------- */ - -.outer { - margin: 0 0; - padding: 0 0; -} - -.mini-synopsis { - padding: 0.25em 0.25em; -} - -.mini-synopsis H1 { font-size: 120%; } -.mini-synopsis H2 { font-size: 107%; } -.mini-synopsis H3 { font-size: 100%; } -.mini-synopsis H1, .mini-synopsis H2, .mini-synopsis H3 { - font-family: "Gill Sans", "Helvetica Neue","Arial",sans-serif; - margin-top: 0.5em; - margin-bottom: 0.25em; - padding: 0 0; - font-weight: bold; letter-spacing: -0.02em; -} - -.mini-synopsis H1 { border-bottom: 1px solid #ccc; } - -.mini-topbar { - font-size: 120%; - background: #0077dd; - padding: 0.25em; -} - - diff --git a/static/docs/0.2.4/snap-server/haskell_icon.gif b/static/docs/0.2.4/snap-server/haskell_icon.gif deleted file mode 100644 index cb2a815..0000000 Binary files a/static/docs/0.2.4/snap-server/haskell_icon.gif and /dev/null differ diff --git a/static/docs/0.2.4/snap-server/index-frames.html b/static/docs/0.2.4/snap-server/index-frames.html deleted file mode 100644 index d4d0bd6..0000000 --- a/static/docs/0.2.4/snap-server/index-frames.html +++ /dev/null @@ -1,28 +0,0 @@ - - -snap-server-0.2.4: A fast, iteratee-based, epoll-enabled web server for the Snap Framework

Snap.Http.Server
Snap.Http.Server.Config
System.FastLogger

diff --git a/static/docs/0.2.4/snap-server/index.html b/static/docs/0.2.4/snap-server/index.html deleted file mode 100644 index 2ce9c4d..0000000 --- a/static/docs/0.2.4/snap-server/index.html +++ /dev/null @@ -1,178 +0,0 @@ - - -snap-server-0.2.4: A fast, iteratee-based, epoll-enabled web server for the Snap Framework
 snap-server-0.2.4: A fast, iteratee-based, epoll-enabled web server for the Snap FrameworkContentsIndex
snap-server-0.2.4: A fast, iteratee-based, epoll-enabled web server for the Snap Framework

This is the first developer prerelease of the Snap framework. Snap is a -simple and fast web development framework and server written in Haskell. For -more information or to download the latest version, you can visit the Snap -project website at http://snapframework.com/. -

The Snap HTTP server is a high performance, epoll-enabled, iteratee-based web -server library written in Haskell. Together with the snap-core library upon -which it depends, it provides a clean and efficient Haskell programming -interface to the HTTP protocol. -

Higher-level facilities for building web applications (like user/session -management, component interfaces, data modeling, etc.) are planned but not -yet implemented, so this release will mostly be of interest for those who: -

  • need a fast and minimal HTTP API at roughly the same level of abstraction -as Java servlets, or -
  • are interested in contributing to the Snap Framework project. -
Modules
show/hideSnap
show/hideHttp
show/hideSnap.Http.Server
Snap.Http.Server.Config
show/hideSystem
System.FastLogger
Produced by Haddock version 2.6.1
diff --git a/static/docs/0.2.4/snap-server/mini_Snap-Http-Server-Config.html b/static/docs/0.2.4/snap-server/mini_Snap-Http-Server-Config.html deleted file mode 100644 index c4ec20a..0000000 --- a/static/docs/0.2.4/snap-server/mini_Snap-Http-Server-Config.html +++ /dev/null @@ -1,31 +0,0 @@ - - -Snap.Http.Server.Config
Snap.Http.Server.Config
diff --git a/static/docs/0.2.4/snap-server/mini_Snap-Http-Server.html b/static/docs/0.2.4/snap-server/mini_Snap-Http-Server.html deleted file mode 100644 index 22d38da..0000000 --- a/static/docs/0.2.4/snap-server/mini_Snap-Http-Server.html +++ /dev/null @@ -1,29 +0,0 @@ - - -Snap.Http.Server diff --git a/static/docs/0.2.4/snap-server/mini_System-FastLogger.html b/static/docs/0.2.4/snap-server/mini_System-FastLogger.html deleted file mode 100644 index 891c97c..0000000 --- a/static/docs/0.2.4/snap-server/mini_System-FastLogger.html +++ /dev/null @@ -1,47 +0,0 @@ - - -System.FastLogger diff --git a/static/docs/0.2.4/snap-server/minus.gif b/static/docs/0.2.4/snap-server/minus.gif deleted file mode 100644 index 1deac2f..0000000 Binary files a/static/docs/0.2.4/snap-server/minus.gif and /dev/null differ diff --git a/static/docs/0.2.4/snap-server/plus.gif b/static/docs/0.2.4/snap-server/plus.gif deleted file mode 100644 index 2d15c14..0000000 Binary files a/static/docs/0.2.4/snap-server/plus.gif and /dev/null differ diff --git a/static/docs/0.2.4/snap-server/snap-server.haddock b/static/docs/0.2.4/snap-server/snap-server.haddock deleted file mode 100644 index 73eb88c..0000000 Binary files a/static/docs/0.2.4/snap-server/snap-server.haddock and /dev/null differ diff --git a/static/docs/0.2.4/snap-server/src/Paths_snap_server.html b/static/docs/0.2.4/snap-server/src/Paths_snap_server.html deleted file mode 100644 index b87f1a2..0000000 --- a/static/docs/0.2.4/snap-server/src/Paths_snap_server.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - -dist/build/autogen/Paths_snap_server.hs - - - -
module Paths_snap_server (
-    version,
-    getBinDir, getLibDir, getDataDir, getLibexecDir,
-    getDataFileName
-  ) where
-
-import Data.Version (Version(..))
-import System.Environment (getEnv)
-
-version :: Version
-version = Version {versionBranch = [0,2,4], versionTags = []}
-
-bindir, libdir, datadir, libexecdir :: FilePath
-
-bindir     = "/Users/greg/.cabal/bin"
-libdir     = "/Users/greg/.cabal/lib/snap-server-0.2.4/ghc-6.12.2"
-datadir    = "/Users/greg/.cabal/share/snap-server-0.2.4"
-libexecdir = "/Users/greg/.cabal/libexec"
-
-getBinDir, getLibDir, getDataDir, getLibexecDir :: IO FilePath
-getBinDir = catch (getEnv "snap_server_bindir") (\_ -> return bindir)
-getLibDir = catch (getEnv "snap_server_libdir") (\_ -> return libdir)
-getDataDir = catch (getEnv "snap_server_datadir") (\_ -> return datadir)
-getLibexecDir = catch (getEnv "snap_server_libexecdir") (\_ -> return libexecdir)
-
-getDataFileName :: FilePath -> IO FilePath
-getDataFileName name = do
-  dir <- getDataDir
-  return (dir ++ "/" ++ name)
-
- diff --git a/static/docs/0.2.4/snap-server/src/Snap-Http-Server-Config.html b/static/docs/0.2.4/snap-server/src/Snap-Http-Server-Config.html deleted file mode 100644 index 5c11ecf..0000000 --- a/static/docs/0.2.4/snap-server/src/Snap-Http-Server-Config.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - -src/Snap/Http/Server/Config.hs - - - -
{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# OPTIONS_GHC -fno-warn-orphans #-}
-
-module Snap.Http.Server.Config
-  ( Config(..)
-  , readConfigFromCmdLineArgs
-  ) where
-
-import           Data.ByteString (ByteString)
-import qualified Data.ByteString as B
-import           Data.ByteString.Internal (c2w)
-import           Data.ByteString.Char8 ()
-import           Data.Maybe
-import           Data.Monoid
-import           System.Console.GetOpt
-import           System.Environment
-import           System.Exit
-import           System.IO
-
-data Config = Config
-    { localHostname :: !ByteString
-    , bindAddress   :: !ByteString
-    , listenPort    :: !Int
-    , accessLog     :: !(Maybe FilePath)
-    , errorLog      :: !(Maybe FilePath)
-    } deriving (Show)
-
-
-data Flag = Flag
-    { flagLocalHost   :: Maybe String
-    , flagBindAddress :: Maybe String
-    , flagPort        :: Maybe Int
-    , flagAccessLog   :: Maybe String
-    , flagErrorLog    :: Maybe String
-    , flagUsage       :: Bool
-    }
-
-instance Monoid Flag where
-    mempty = Flag Nothing Nothing Nothing Nothing Nothing False
-
-    (Flag a1 b1 c1 d1 e1 f1) `mappend` (Flag a2 b2 c2 d2 e2 f2) =
-        Flag (getLast $ Last a1 `mappend` Last a2)
-             (getLast $ Last b1 `mappend` Last b2)
-             (getLast $ Last c1 `mappend` Last c2)
-             (getLast $ Last d1 `mappend` Last d2)
-             (getLast $ Last e1 `mappend` Last e2)
-             (f1 || f2)
-
-flagLH :: String -> Flag
-flagLH s = mempty { flagLocalHost = Just s }
-
-flagBA :: String -> Flag
-flagBA s = mempty { flagBindAddress = Just s }
-
-flagPt :: String -> Flag
-flagPt p = mempty { flagPort = Just (read p) }
-
-flagAL :: String -> Flag
-flagAL s = mempty { flagAccessLog = Just s }
-
-flagEL :: String -> Flag
-flagEL s = mempty { flagErrorLog = Just s }
-
-flagHelp :: Flag
-flagHelp = mempty { flagUsage = True }
-
-fromStr :: String -> ByteString
-fromStr = B.pack . map c2w
-
-flags2config :: Flag -> Config
-flags2config (Flag a b c d e _) =
-    Config (maybe "localhost" fromStr a)
-           (maybe "*" fromStr b)
-           (fromMaybe 8888 c)
-           d
-           e
-
-
-options :: [OptDescr Flag]
-options =
-    [ Option "l" ["localHostname"]
-                 (ReqArg flagLH "STR")
-                 "local hostname, default 'localhost'"
-    , Option "p" ["listenPort"]
-                 (ReqArg flagPt "NUM")
-                 "port to listen on, default 8888"
-    , Option "b" ["bindAddress"]
-                 (ReqArg flagBA "STR")
-                 "address to bind to, default '*'"
-    , Option "a" ["accessLog"]
-                 (ReqArg flagAL "STR")
-                 "access log in the 'combined' format, optional"
-    , Option "e" ["errorLog"]
-                 (ReqArg flagEL "STR")
-                 "error log, optional"
-    , Option "h" ["help"]
-                 (NoArg flagHelp)
-                 "display this usage statement" ]
-
-
-readConfigFromCmdLineArgs :: String     -- ^ application description, e.g.
-                                        --   \"Foo applet v0.2\"
-                          -> IO Config
-readConfigFromCmdLineArgs appName = do
-    argv     <- getArgs
-    progName <- getProgName
-
-    case getOpt Permute options argv of
-      (f,_,[]  ) -> withFlags progName f
-      (_,_,errs) -> bombout progName errs
-  where
-    bombout progName errs = do
-        let hdr = appName ++ "\n\nUsage: " ++ progName ++ " [OPTIONS]"
-        let msg = concat errs ++ usageInfo hdr options
-        hPutStrLn stderr msg
-        exitFailure
-
-    withFlags progName fs = do
-        let f = mconcat fs
-        if flagUsage f
-           then bombout progName []
-           else return $ flags2config f
-
- diff --git a/static/docs/0.2.4/snap-server/src/Snap-Http-Server.html b/static/docs/0.2.4/snap-server/src/Snap-Http-Server.html deleted file mode 100644 index 3c0f8bd..0000000 --- a/static/docs/0.2.4/snap-server/src/Snap-Http-Server.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - -src/Snap/Http/Server.hs - - - -
-- | The Snap HTTP server is a high performance, epoll-enabled, iteratee-based
--- web server library written in Haskell. Together with the @snap-core@ library
--- upon which it depends, it provides a clean and efficient Haskell programming
--- interface to the HTTP protocol.
-module Snap.Http.Server
-(
-  httpServe
-, snapServerVersion
-) where
-
-import           Data.ByteString (ByteString)
-import           Snap.Types
-import qualified Snap.Internal.Http.Server as Int
-
-
-------------------------------------------------------------------------------
-snapServerVersion :: ByteString
-snapServerVersion = Int.snapServerVersion
-
-
-------------------------------------------------------------------------------
--- | Starts serving HTTP requests on the given port using the given handler.
--- This function never returns; to shut down the HTTP server, kill the
--- controlling thread.
-httpServe :: ByteString      -- ^ bind address, or \"*\" for all
-          -> Int             -- ^ port to bind to
-          -> ByteString      -- ^ local hostname (server name)
-          -> Maybe FilePath  -- ^ path to the (optional) access log
-          -> Maybe FilePath  -- ^ path to the (optional) error log
-          -> Snap ()         -- ^ handler procedure
-          -> IO ()
-httpServe bindAddress bindPort localHostname alog elog handler =
-    Int.httpServe bindAddress bindPort localHostname alog elog handler'
-  where
-    handler' = runSnap handler
-
- diff --git a/static/docs/0.2.4/snap-server/src/Snap-Internal-Http-Parser.html b/static/docs/0.2.4/snap-server/src/Snap-Internal-Http-Parser.html deleted file mode 100644 index 70e287f..0000000 --- a/static/docs/0.2.4/snap-server/src/Snap-Internal-Http-Parser.html +++ /dev/null @@ -1,438 +0,0 @@ - - - - -src/Snap/Internal/Http/Parser.hs - - - -
{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RankNTypes #-}
-
-module Snap.Internal.Http.Parser
-  ( IRequest(..)
-  , parseRequest
-  , readChunkedTransferEncoding
-  , parserToIteratee
-  , parseCookie
-  , parseUrlEncoded
-  , writeChunkedTransferEncoding
-  , strictize
-  ) where
-
-
-------------------------------------------------------------------------------
-import           Control.Applicative
-import           Control.Arrow (second)
-import           Control.Monad (liftM)
-import           Control.Monad.Trans
-import           Data.Attoparsec hiding (many, Result(..))
-import           Data.Attoparsec.Iteratee
-import           Data.Bits
-import           Data.ByteString (ByteString)
-import qualified Data.ByteString as S
-import           Data.ByteString.Internal (c2w, w2c)
-import qualified Data.ByteString.Lazy as L
-import qualified Data.ByteString.Nums.Careless.Hex as Cvt
-import           Data.Char
-import           Data.List (foldl')
-import           Data.Int
-import           Data.Iteratee.WrappedByteString
-import           Data.Map (Map)
-import qualified Data.Map as Map
-import           Data.Maybe (catMaybes)
-import qualified Data.Vector.Unboxed as Vec
-import           Data.Vector.Unboxed (Vector)
-import           Data.Word (Word8, Word64)
-import           Foreign.C.Types
-import           Foreign.ForeignPtr
-import           Prelude hiding (take, takeWhile)
-------------------------------------------------------------------------------
-import           Snap.Internal.Http.Types hiding (Enumerator)
-import           Snap.Iteratee hiding (take, foldl', filter)
-
-
-
-------------------------------------------------------------------------------
--- | an internal version of the headers part of an HTTP request
-data IRequest = IRequest
-    { iMethod :: Method
-    , iRequestUri :: ByteString
-    , iHttpVersion :: (Int,Int)
-    , iRequestHeaders :: [(ByteString, ByteString)]
-    }
-
-instance Show IRequest where
-    show (IRequest m u v r) =
-        concat [ show m
-               , " "
-               , show u
-               , " "
-               , show v
-               , " "
-               , show r ]
-
-------------------------------------------------------------------------------
-parseRequest :: (Monad m) => Iteratee m (Maybe IRequest)
-parseRequest = parserToIteratee pRequest
-
-
-readChunkedTransferEncoding :: (Monad m) => Enumerator m a
-readChunkedTransferEncoding iter = do
-      i <- chunkParserToEnumerator (parserToIteratee pGetTransferChunk)
-                                   iter
-
-      return i 
-
-
-toHex :: Int64 -> ByteString
-toHex !i' = S.reverse s
-  where
-    !i     = abs i'
-    (!s,_) = S.unfoldrN 16 f (fromIntegral i)
-
-    f :: Word64 -> Maybe (Word8, Word64)
-    f d = if d == 0
-            then Nothing
-            else Just (ch, theRest)
-
-      where
-        low4    = fromIntegral $ d .&. 0xf
-        ch      = if low4 >= 10
-                    then c2w 'a' + low4 - 10
-                    else c2w '0' + low4
-        theRest = (d .&. (complement 0xf)) `shiftR` 4
-
-
--- | Given an iteratee, produces a new one that wraps chunks sent to it with a
--- chunked transfer-encoding. Example usage:
---
--- FIXME: sample output no longer looks like this, we buffer now
---
--- > > (writeChunkedTransferEncoding
--- >     (enumLBS (L.fromChunks ["foo","bar","quux"]))
--- >     stream2stream) >>=
--- >     run >>=
--- >     return . fromWrap
--- >
--- > Chunk "3\r\nfoo\r\n3\r\nbar\r\n4\r\nquux\r\n0\r\n\r\n" Empty
---
-writeChunkedTransferEncoding :: ForeignPtr CChar
-                             -> Enumerator IO a
-                             -> Enumerator IO a
-writeChunkedTransferEncoding buf enum it = do
-    i'    <- wrap it
-    (i,_) <- unsafeBufferIterateeWithBuffer buf i'
-    enum i
-
-  where
-    wrap iter = return $ IterateeG $ \s ->
-        case s of
-          (EOF Nothing) -> do
-              v <- runIter iter (Chunk $ toWrap "0\r\n\r\n")
-              i <- checkIfDone return v
-              runIter i (EOF Nothing)
-          (EOF e) -> return $ Cont undefined e
-          (Chunk (WrapBS x)) -> do
-              let n = S.length x
-              if n == 0
-                then do
-                    i' <- wrap iter
-                    return $ Cont i' Nothing
-                else do
-                  let o = S.concat [ toHex (toEnum n)
-                                   , "\r\n"
-                                   , x
-                                   , "\r\n" ]
-                  v <- runIter iter (Chunk $ WrapBS o)
-                  i <- checkIfDone wrap v
-                  return $ Cont i Nothing
-
-
-chunkParserToEnumerator :: (Monad m) =>
-                           Iteratee m (Maybe ByteString)
-                        -> Iteratee m a
-                        -> m (Iteratee m a)
-chunkParserToEnumerator getChunk client = return $ do
-    mbB <- getChunk
-    maybe (finishIt client) (sendBS client) mbB
-
-  where
-    sendBS iter s = do
-        v <- lift $ runIter iter (Chunk $ toWrap $ L.fromChunks [s])
-
-        case v of
-          (Done _ (EOF (Just e))) -> throwErr e
-
-          (Done x _) -> return x
-
-          (Cont _ (Just e)) -> throwErr e
-
-          (Cont k Nothing) -> joinIM $
-                              chunkParserToEnumerator getChunk k
-
-    finishIt iter = do
-        e <- lift $ sendEof iter
-
-        case e of
-          Left x  -> throwErr x
-          Right x -> return x
-
-    sendEof iter = do
-        v <- runIter iter (EOF Nothing)
-
-        return $ case v of
-          (Done _ (EOF (Just e))) -> Left e
-          (Done x _)              -> Right x
-          (Cont _ (Just e))       -> Left e
-          (Cont _ _)              -> Left $ Err $ "divergent iteratee"
-
-
-------------------------------------------------------------------------------
--- parse functions
-------------------------------------------------------------------------------
-
--- theft alert: many of these routines adapted from Johan Tibell's hyena
--- package
-
--- | Parsers for different tokens in an HTTP request.
-sp, digit, letter :: Parser Word8
-sp       = word8 $ c2w ' '
-digit    = satisfy (isDigit . w2c)
-letter   = satisfy (isAlpha . w2c)
-
-untilEOL :: Parser ByteString
-untilEOL = takeWhile notend
-  where
-    notend d = let c = w2c d in not $ c == '\r' || c == '\n'
-
-crlf :: Parser ByteString
-crlf = string "\r\n"
-
--- | Parser for zero or more spaces.
-spaces :: Parser [Word8]
-spaces = many sp
-
-pSpaces :: Parser ByteString
-pSpaces = takeWhile (isSpace . w2c)
-
--- | Parser for the internal request data type.
-pRequest :: Parser (Maybe IRequest)
-pRequest = (Just <$> pRequest') <|> (endOfInput *> pure Nothing)
-
-pRequest' :: Parser IRequest
-pRequest' = IRequest
-               <$> (option "" crlf *> pMethod)  <* sp
-               <*> pUri                         <* sp
-               <*> pVersion                     <* crlf
-               <*> pHeaders                     <* crlf
-
-  -- note: the optional crlf is at the beginning because some older browsers
-  -- send an extra crlf after a POST body
-
-
--- | Parser for the request method.
-pMethod :: Parser Method
-pMethod =     (OPTIONS <$ string "OPTIONS")
-          <|> (GET     <$ string "GET")
-          <|> (HEAD    <$ string "HEAD")
-          <|> word8 (c2w 'P') *> ((POST <$ string "OST") <|>
-                                  (PUT  <$ string "UT"))
-          <|> (DELETE  <$ string "DELETE")
-          <|> (TRACE   <$ string "TRACE")
-          <|> (CONNECT <$ string "CONNECT")
-
--- | Parser for the request URI.
-pUri :: Parser ByteString
-pUri = takeWhile (not . isSpace . w2c)
-
--- | Parser for the request's HTTP protocol version.
-pVersion :: Parser (Int, Int)
-pVersion = string "HTTP/" *>
-           liftA2 (,) (digit' <* word8 (c2w '.')) digit'
-    where
-      digit' = fmap (digitToInt . w2c) digit
-
-fieldChars :: Parser ByteString
-fieldChars = takeWhile isFieldChar
-  where
-    isFieldChar c = (Vec.!) fieldCharTable (fromEnum c)
-
-fieldCharTable :: Vector Bool
-fieldCharTable = Vec.generate 256 f
-  where
-    f d = let c=toEnum d in (isDigit c) || (isAlpha c) || c == '-' || c == '_'
-
-
--- | Parser for request headers.
-pHeaders :: Parser [(ByteString, ByteString)]
-pHeaders = many header
-  where
-    header = {-# SCC "pHeaders/header" #-}
-             liftA2 (,)
-                 fieldName
-                 (word8 (c2w ':') *> spaces *> contents)
-
-    fieldName = {-# SCC "pHeaders/fieldName" #-}
-                liftA2 S.cons letter fieldChars
-
-    contents = {-# SCC "pHeaders/contents" #-}
-               liftA2 S.append
-                   (untilEOL <* crlf)
-                   (continuation <|> pure S.empty)
-
-    isLeadingWS w = {-# SCC "pHeaders/isLeadingWS" #-}
-                    elem w wstab
-
-    wstab = map c2w " \t"
-
-    leadingWhiteSpace = {-# SCC "pHeaders/leadingWhiteSpace" #-}
-                        takeWhile1 isLeadingWS
-
-    continuation = {-# SCC "pHeaders/continuation" #-}
-                   liftA2 S.cons
-                          (leadingWhiteSpace *> pure (c2w ' '))
-                          contents
-
-
-pGetTransferChunk :: Parser (Maybe ByteString)
-pGetTransferChunk = do
-    !hex <- liftM fromHex $ (takeWhile (isHexDigit . w2c))
-    takeTill ((== '\r') . w2c)
-    crlf
-    if hex <= 0
-      then return Nothing
-      else do
-          x <- take hex
-          crlf
-          return $ Just x
-  where
-    fromHex :: ByteString -> Int
-    fromHex s = Cvt.hex (L.fromChunks [s])
-
-
-------------------------------------------------------------------------------
--- COOKIE PARSING
-------------------------------------------------------------------------------
-
--- these definitions try to mirror RFC-2068 (the HTTP/1.1 spec) and RFC-2109
--- (cookie spec): please point out any errors!
-
-{-# INLINE matchAll #-}
-matchAll :: [ Char -> Bool ] -> Char -> Bool
-matchAll x c = and $ map ($ c) x
-
-{-# INLINE isToken #-}
-isToken :: Char -> Bool
-isToken c = (Vec.!) tokenTable (fromEnum c)
-  where
-    tokenTable :: Vector Bool
-    tokenTable = Vec.generate 256 (f . toEnum)
-
-    f = matchAll [ isAscii
-                 , not . isControl
-                 , not . isSpace 
-                 , not . flip elem [ '(', ')', '<', '>', '@', ',', ';'
-                                   , ':', '\\', '\"', '/', '[', ']'
-                                   , '?', '=', '{', '}' ]
-                 ]
-
-{-# INLINE isRFCText #-}
-isRFCText :: Char -> Bool
-isRFCText = not . isControl
-
-pToken :: Parser ByteString
-pToken = takeWhile (isToken . w2c)
-
-
-pQuotedString :: Parser ByteString
-pQuotedString = q *> quotedText <* q
-  where
-    quotedText = (S.concat . reverse) <$> f []
-
-    f soFar = do
-        t <- takeWhile qdtext
-
-        let soFar' = t:soFar
-
-        -- RFC says that backslash only escapes for <">
-        choice [ string "\\\"" *> f ("\"" : soFar')
-               , pure soFar' ]
-
-
-    q = word8 $ c2w '\"'
-
-    qdtext = matchAll [ isRFCText, (/= '\"'), (/= '\\') ] . w2c
-    
-
-pCookies :: Parser [Cookie]
-pCookies = do
-    -- grab kvps and turn to strict bytestrings
-    kvps <- pAvPairs
-
-    return $ map toCookie $ filter (not . S.isPrefixOf "$" . fst) kvps
-
-  where
-    toCookie (nm,val) = Cookie nm val Nothing Nothing Nothing
-
-
--- unhelpfully, the spec mentions "old-style" cookies that don't have quotes
--- around the value. wonderful.
-pWord :: Parser ByteString
-pWord = pQuotedString <|> (takeWhile ((/= ';') . w2c))
-
-pAvPairs :: Parser [(ByteString, ByteString)]
-pAvPairs = do
-    a <- pAvPair
-    b <- many (pSpaces *> char ';' *> pSpaces *> pAvPair)
-
-    return $ a:b
-
-pAvPair :: Parser (ByteString, ByteString)
-pAvPair = do
-    key <- pToken <* pSpaces
-    val <- option "" $ char '=' *> pSpaces *> pWord
-
-    return (key,val)
-
-parseCookie :: ByteString -> Maybe [Cookie]
-parseCookie = parseToCompletion pCookies
-
-------------------------------------------------------------------------------
--- MULTIPART/FORMDATA
-------------------------------------------------------------------------------
-
-parseUrlEncoded :: ByteString -> Map ByteString [ByteString]
-parseUrlEncoded s = foldl' (\m (k,v) -> Map.insertWith' (++) k [v] m)
-                           Map.empty
-                           decoded
-  where
-    breakApart = (second (S.drop 1)) . S.break (== (c2w '=')) 
-
-    parts :: [(ByteString,ByteString)]
-    parts = map breakApart $ S.split (c2w '&') s
-
-    urldecode = parseToCompletion pUrlEscaped
-
-    decodeOne (a,b) = do
-        a' <- urldecode a
-        b' <- urldecode b
-        return (a',b')
-
-    decoded = catMaybes $ map decodeOne parts
-
-
-------------------------------------------------------------------------------
--- utility functions
-------------------------------------------------------------------------------
-
-strictize :: L.ByteString -> ByteString
-strictize         = S.concat . L.toChunks
-
-------------------------------------------------------------------------------
-char :: Char -> Parser Word8
-char = word8 . c2w
-
-
- diff --git a/static/docs/0.2.4/snap-server/src/Snap-Internal-Http-Server-Date.html b/static/docs/0.2.4/snap-server/src/Snap-Internal-Http-Server-Date.html deleted file mode 100644 index 07f8c6f..0000000 --- a/static/docs/0.2.4/snap-server/src/Snap-Internal-Http-Server-Date.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - -src/Snap/Internal/Http/Server/Date.hs - - - -
{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE CPP #-}
-
-module Snap.Internal.Http.Server.Date
-( getDateString
-, getLogDateString
-, getCurrentDateTime) where
-
-import           Control.Concurrent
-import           Control.Exception
-import           Control.Monad
-import           Data.ByteString (ByteString)
-import           Data.IORef
-import           Foreign.C.Types
-import           System.IO.Unsafe
-
-#ifndef PORTABLE
-import           System.Posix.Time
-#else
-import           Data.Time.Clock.POSIX
-#endif
-
-import           Snap.Internal.Http.Types (formatHttpTime, formatLogTime)
-
--- Here comes a dirty hack. We don't want to be wasting context switches
--- building date strings, so we're only going to compute one every two
--- seconds. (Approximate timestamps to within a couple of seconds are OK here,
--- and we'll reduce overhead.)
---
--- Note that we also don't want to wake up a potentially sleeping CPU by just
--- running the computation on a timer. We'll allow client traffic to trigger
--- the process.
-
-data DateState = DateState {
-      _cachedDateString :: !(IORef ByteString)
-    , _cachedLogString  :: !(IORef ByteString)
-    , _cachedDate       :: !(IORef CTime)
-    , _valueIsOld       :: !(IORef Bool)
-    , _morePlease       :: !(MVar ())
-    , _dataAvailable    :: !(MVar ())
-    , _dateThread       :: !(MVar ThreadId)
-    }
-
-dateState :: DateState
-dateState = unsafePerformIO $ do
-    (s1,s2,date) <- fetchTime
-    bs1 <- newIORef s1
-    bs2 <- newIORef s2
-    dt  <- newIORef date
-    ov  <- newIORef False
-    th  <- newEmptyMVar
-    mp  <- newMVar ()
-    da  <- newMVar ()
-
-    let d = DateState bs1 bs2 dt ov mp da th
-
-    t  <- forkIO $ dateThread d
-    putMVar th t
-
-    return d
-
-
-#ifdef PORTABLE
-epochTime :: IO CTime
-epochTime = do
-    t <- getPOSIXTime
-    return $ fromInteger $ truncate t
-#endif
-
-
-fetchTime :: IO (ByteString,ByteString,CTime)
-fetchTime = do
-    now <- epochTime
-    t1  <- formatHttpTime now
-    t2  <- formatLogTime now
-    return (t1, t2, now)
-
-
-dateThread :: DateState -> IO ()
-dateThread ds@(DateState dateString logString time valueIsOld morePlease
-                         dataAvailable _) = do
-    -- a lot of effort to make sure we don't deadlock
-    takeMVar morePlease
-
-    (s1,s2,now) <- fetchTime
-    atomicModifyIORef dateString $ const (s1,())
-    atomicModifyIORef logString $ const (s2,())
-    atomicModifyIORef time $ const (now,())
-
-    writeIORef valueIsOld False
-    tryPutMVar dataAvailable ()
-
-    threadDelay 2000000
-
-    takeMVar dataAvailable
-    writeIORef valueIsOld True
-
-    dateThread ds
-
-ensureFreshDate :: IO ()
-ensureFreshDate = block $ do
-    old <- readIORef $ _valueIsOld dateState
-    when old $ do
-        tryPutMVar (_morePlease dateState) ()
-        readMVar $ _dataAvailable dateState
-
-getDateString :: IO ByteString
-getDateString = block $ do
-    ensureFreshDate
-    readIORef $ _cachedDateString dateState
-
-
-getLogDateString :: IO ByteString
-getLogDateString = block $ do
-    ensureFreshDate
-    readIORef $ _cachedLogString dateState
-
-
-getCurrentDateTime :: IO CTime
-getCurrentDateTime = block $ do
-    ensureFreshDate
-    readIORef $ _cachedDate dateState
-
-
- diff --git a/static/docs/0.2.4/snap-server/src/Snap-Internal-Http-Server-LibevBackend.html b/static/docs/0.2.4/snap-server/src/Snap-Internal-Http-Server-LibevBackend.html deleted file mode 100644 index 94aeee4..0000000 --- a/static/docs/0.2.4/snap-server/src/Snap-Internal-Http-Server-LibevBackend.html +++ /dev/null @@ -1,745 +0,0 @@ - - - - -src/Snap/Internal/Http/Server/LibevBackend.hs - - - -
{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE ForeignFunctionInterface #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RankNTypes #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module Snap.Internal.Http.Server.LibevBackend
-  ( Backend
-  , BackendTerminatedException
-  , Connection
-  , TimeoutException
-  , name
-  , debug
-  , bindIt
-  , new
-  , stop
-  , withConnection
-  , sendFile
-  , tickleTimeout
-  , getReadEnd
-  , getWriteEnd
-  , getRemoteAddr
-  , getRemotePort
-  , getLocalAddr
-  , getLocalPort
-  ) where
-
----------------------------
--- TODO: document module --
----------------------------
-
-------------------------------------------------------------------------------
-import           Control.Concurrent
-import           Control.Exception
-import           Control.Monad
-import           Control.Monad.Trans
-import           Data.ByteString (ByteString)
-import           Data.ByteString.Internal (c2w, w2c)
-import qualified Data.ByteString.Unsafe as B
-import qualified Data.ByteString as B
-import           Data.IORef
-import           Data.Iteratee.WrappedByteString
-import           Data.Set (Set)
-import qualified Data.Set as Set
-import           Data.Typeable
-import           Foreign hiding (new)
-import           Foreign.C.Error
-import           Foreign.C.Types
-import           GHC.Conc (forkOnIO)
-import           Network.Libev
-import           Network.Socket
-import qualified Network.Socket.SendFile as SF
-import           Prelude hiding (catch)
-import           System.Timeout
-------------------------------------------------------------------------------
-import           Snap.Iteratee
-import           Snap.Internal.Debug
-
-
-data Backend = Backend
-    { _acceptSocket      :: Socket
-    , _acceptFd          :: CInt
-    , _connectionQueue   :: Chan CInt
-    , _evLoop            :: EvLoopPtr
-    , _acceptIOCallback  :: FunPtr IoCallback
-    , _acceptIOObj       :: EvIoPtr
-
-      -- FIXME: we don't need _loopThread
-    , _loopThread        :: MVar ThreadId
-    , _mutexCallbacks    :: (FunPtr MutexCallback, FunPtr MutexCallback)
-    , _loopLock          :: MVar ()
-    , _asyncCb           :: FunPtr AsyncCallback
-    , _asyncObj          :: EvAsyncPtr
-    , _killCb            :: FunPtr AsyncCallback
-    , _killObj           :: EvAsyncPtr
-    , _connectionThreads :: MVar (Set ThreadId)
-    , _backendCPU        :: Int
-    }
-
-
-data Connection = Connection
-    { _backend             :: !Backend
-    , _socket              :: !Socket
-    , _socketFd            :: !CInt
-    , _remoteAddr          :: !ByteString
-    , _remotePort          :: !Int
-    , _localAddr           :: !ByteString
-    , _localPort           :: !Int
-    , _readAvailable       :: !(MVar ())
-    , _writeAvailable      :: !(MVar ())
-    , _timerObj            :: !EvTimerPtr
-    , _timerCallback       :: !(FunPtr TimerCallback)
-    , _readActive          :: !(IORef Bool)
-    , _writeActive         :: !(IORef Bool)
-    , _connReadIOObj       :: !EvIoPtr
-    , _connReadIOCallback  :: !(FunPtr IoCallback)
-    , _connWriteIOObj      :: !EvIoPtr
-    , _connWriteIOCallback :: !(FunPtr IoCallback)
-    , _connThread          :: !(MVar ThreadId)
-    }
-
-{-# INLINE name #-}
-name :: ByteString
-name = "libev"
-
-
-sendFile :: Connection -> FilePath -> IO ()
-sendFile c fp = do
-    withMVar lock $ \_ -> do
-      act <- readIORef $ _writeActive c
-      when act $ evIoStop loop io
-
-    SF.sendFile s fp
-
-    withMVar lock $ \_ -> do
-      tryPutMVar (_readAvailable c) ()
-      tryPutMVar (_writeAvailable c) ()
-      evIoStart loop io
-      writeIORef (_writeActive c) True
-      evAsyncSend loop asy
-
-  where
-    s    = _socket c
-    io   = _connWriteIOObj c
-    b    = _backend c
-    loop = _evLoop b
-    lock = _loopLock b
-    asy  = _asyncObj b
-
-
-bindIt :: ByteString         -- ^ bind address, or \"*\" for all
-       -> Int                -- ^ port to bind to
-       -> IO (Socket,CInt)
-bindIt bindAddress bindPort = do
-    sock <- socket AF_INET Stream 0
-    addr <- getHostAddr bindPort bindAddress
-    setSocketOption sock ReuseAddr 1
-    bindSocket sock addr
-    listen sock 150
-    let sockFd = fdSocket sock
-    c_setnonblocking sockFd
-    return (sock, sockFd)
-
-
-new :: (Socket,CInt)   -- ^ value you got from bindIt
-    -> Int             -- ^ cpu
-    -> IO Backend
-new (sock,sockFd) cpu = do
-    connq <- newChan
-
-    -- We'll try kqueue on OSX even though the libev docs complain that it's
-    -- "broken", in the hope that it works as expected for sockets
-    f  <- evRecommendedBackends
-    lp <- evLoopNew $ toEnum . fromEnum $ f .|. evbackend_kqueue
-
-
-    -- we'll be working multithreaded so we need to set up locking for the C
-    -- event loop struct
-    (mc1,mc2,looplock) <- setupLockingForLoop lp
-
-    -- setup async callbacks -- these allow us to wake up the main loop
-    -- (normally blocked in c-land) from other threads
-    asyncObj <- mkEvAsync
-    asyncCB  <- mkAsyncCallback $ \_ _ _ -> do
-                            debug "async wakeup"
-                            return ()
-
-    killObj <- mkEvAsync
-    killCB  <- mkAsyncCallback $ \_ _ _ -> do
-                            debug "async kill wakeup"
-                            evUnloop lp 2
-                            return ()
-
-    evAsyncInit asyncObj asyncCB
-    evAsyncStart lp asyncObj
-    evAsyncInit killObj killCB
-    evAsyncStart lp killObj
-
-    -- setup the accept callback; this watches for read readiness on the listen
-    -- port
-    accCB <- mkIoCallback $ acceptCallback sockFd connq
-    accIO <- mkEvIo
-    evIoInit accIO accCB sockFd ev_read
-    evIoStart lp accIO
-
-    -- an MVar for the loop thread, and one to keep track of the set of active
-    -- threads
-    threadMVar <- newEmptyMVar
-    threadSetMVar <- newMVar Set.empty
-
-    let b = Backend sock
-                    sockFd
-                    connq
-                    lp
-                    accCB
-                    accIO
-                    threadMVar
-                    (mc1,mc2)
-                    looplock
-                    asyncCB
-                    asyncObj
-                    killCB
-                    killObj
-                    threadSetMVar
-                    cpu
-
-    tid <- forkOnIO cpu $ loopThread b
-    putMVar threadMVar tid
-
-    debug $ "Backend.new: loop spawned"
-    return b
-
-
--- | Run evLoop in a thread
-loopThread :: Backend -> IO ()
-loopThread backend = do
-    debug $ "starting loop"
-    (ignoreException go) `finally` cleanup
-    debug $ "loop finished"
-  where
-    cleanup = do
-        debug $ "loopThread: cleaning up"
-        ignoreException $ freeBackend backend
-    lock    = _loopLock backend
-    loop    = _evLoop backend
-    go      = takeMVar lock >> block (evLoop loop 0)
-
-
-acceptCallback :: CInt -> Chan CInt -> IoCallback
-acceptCallback accFd chan _loopPtr _ioPtr _ = do
-    debug "inside acceptCallback"  
-    r <- c_accept accFd
-
-    case r of
-      -- this (EWOULDBLOCK) shouldn't happen (we just got told it was ready!),
-      -- if it does (maybe the request got picked up by another thread) we'll
-      -- just bail out
-      -2 -> return ()
-      -1 -> debugErrno "Backend.acceptCallback:c_accept()"
-      fd -> do
-          debug $ "acceptCallback: accept()ed fd, writing to chan " ++ show fd
-          writeChan chan fd
-
-
-ioReadCallback :: CInt -> IORef Bool -> MVar () -> IoCallback
-ioReadCallback fd active ra _loopPtr _ioPtr _ = do
-    -- send notifications to the worker thread
-    debug $ "ioReadCallback: notification (" ++ show fd ++ ")"
-    tryPutMVar ra ()
-    debug $ "stopping ioReadCallback (" ++ show fd ++ ")"
-    evIoStop _loopPtr _ioPtr
-    writeIORef active False
-
-
-ioWriteCallback :: CInt -> IORef Bool -> MVar () -> IoCallback
-ioWriteCallback fd active wa _loopPtr _ioPtr _ = do
-    -- send notifications to the worker thread
-    debug $ "ioWriteCallback: notification (" ++ show fd ++ ")"
-    tryPutMVar wa ()
-    debug $ "stopping ioWriteCallback (" ++ show fd ++ ")"
-    evIoStop _loopPtr _ioPtr
-    writeIORef active False
-
-
-seconds :: Int -> Int
-seconds n = n * ((10::Int)^(6::Int))
-
-
-stop :: Backend -> IO ()
-stop b = ignoreException $ do
-    debug $ "Backend.stop"
-
-    -- FIXME: what are we gonna do here?
-    --
-    -- 1. take the loop lock
-    -- 2. shut down the accept() callback
-    -- 3. stuff a poison pill (a bunch of -1 values should do) down the
-    --    connection queue so that withConnection knows to throw an exception
-    --    back up to its caller
-    -- 4. release the loop lock
-    -- 5. wait until all of the threads have finished, or until 10 seconds have
-    --    elapsed, whichever comes first
-    -- 6. take the loop lock
-    -- 7. call evUnloop and wake up the loop using evAsyncSend
-    -- 8. release the loop lock, the main loop thread should then free/clean
-    --    everything up (threads, connections, io objects, callbacks, etc)
-
-    withMVar lock $ \_ -> do
-        evIoStop loop acceptObj
-        replicateM_ 10 $ writeChan connQ (-1)
-
-    debug $ "Backend.stop: waiting at most 10 seconds for connection threads to die"
-    waitForThreads b $ seconds 10
-    debug $ "Backend.stop: all threads dead, unlooping"
-
-    withMVar lock $ \_ -> do
-        -- FIXME: hlibev should export EVUNLOOP_ALL
-        evUnloop loop 2
-        evAsyncSend loop killObj
-
-    debug $ "unloop sent"
-
-
-  where
-    loop           = _evLoop b
-    acceptObj      = _acceptIOObj b
-    killObj        = _killObj b
-    lock           = _loopLock b
-    connQ          = _connectionQueue b
-
-
-
-waitForThreads :: Backend -> Int -> IO ()
-waitForThreads backend t = timeout t wait >> return ()
-  where
-    threadSet = _connectionThreads backend
-    wait = do
-        threads <- readMVar threadSet
-        if (Set.null threads)
-          then return ()
-          else threadDelay (seconds 1) >> wait
-
-
-
-getAddr :: SockAddr -> IO (ByteString, Int)
-getAddr addr =
-    case addr of
-      SockAddrInet p ha -> do
-          s <- liftM (B.pack . map c2w) (inet_ntoa ha)
-          return (s, fromIntegral p)
-
-      a -> throwIO $ AddressNotSupportedException (show a)
-
-
--- | throw a timeout exception to the handling thread -- it'll clean up
--- everything
-timerCallback :: MVar ThreadId -> TimerCallback
-timerCallback tmv _ _ _ = do
-    debug "timer callback"
-    tid <- readMVar tmv
-    throwTo tid TimeoutException
-
-
-freeConnection :: Connection -> IO ()
-freeConnection conn = ignoreException $ do
-    withMVar loopLock $ \_ -> block $ do
-        debug $ "freeConnection (" ++ show fd ++ ")"
-        c_close fd
-
-        -- stop and free timer object
-        evTimerStop loop timerObj
-        freeEvTimer timerObj
-        freeTimerCallback timerCb
-
-        -- stop and free i/o objects
-        evIoStop loop ioWrObj
-        freeEvIo ioWrObj
-        freeIoCallback ioWrCb
-
-        evIoStop loop ioRdObj
-        freeEvIo ioRdObj
-        freeIoCallback ioRdCb
-
-        -- remove the thread id from the backend set
-        tid <- readMVar threadMVar
-        modifyMVar_ tsetMVar $ \s -> do
-            let !s' = Set.delete tid s
-            return $! s'
-
-        -- wake up the event loop so it can be apprised of the changes
-        evAsyncSend loop asyncObj
-
-  where
-    backend    = _backend conn
-    tsetMVar   = _connectionThreads backend
-    loop       = _evLoop backend
-    loopLock   = _loopLock backend
-    asyncObj   = _asyncObj backend
-
-    fd         = _socketFd conn
-    threadMVar = _connThread conn
-    ioWrObj    = _connWriteIOObj conn
-    ioWrCb     = _connWriteIOCallback conn
-    ioRdObj    = _connReadIOObj conn
-    ioRdCb     = _connReadIOCallback conn
-    timerObj   = _timerObj conn
-    timerCb    = _timerCallback conn
-
-
-ignoreException :: IO () -> IO ()
-ignoreException = handle (\(_::SomeException) -> return ())
-
-
-freeBackend :: Backend -> IO ()
-freeBackend backend = ignoreException $ block $ do
-    -- note: we only get here after an unloop
-
-    withMVar tsetMVar $ \set -> do
-        mapM_ killThread $ Set.toList set
-
-    debug $ "Backend.freeBackend: wait at most 2 seconds for threads to die"
-    waitForThreads backend $ seconds 2
-
-    debug $ "Backend.freeBackend: all threads dead"
-
-    debug $ "Backend.freeBackend: destroying resources"
-    freeEvIo acceptObj
-    freeIoCallback acceptCb
-    c_close fd
-
-    evAsyncStop loop asyncObj
-    freeEvAsync asyncObj
-    freeAsyncCallback asyncCb
-
-    evAsyncStop loop killObj
-    freeEvAsync killObj
-    freeAsyncCallback killCb
-
-    freeMutexCallback mcb1
-    freeMutexCallback mcb2
-
-    evLoopDestroy loop
-    debug $ "Backend.freeBackend: resources destroyed"
-
-  where
-    fd          = _acceptFd backend
-    acceptObj   = _acceptIOObj backend
-    acceptCb    = _acceptIOCallback backend
-    tsetMVar    = _connectionThreads backend
-    asyncObj    = _asyncObj backend
-    asyncCb     = _asyncCb backend
-    killObj     = _killObj backend
-    killCb      = _killCb backend
-    (mcb1,mcb2) = _mutexCallbacks backend
-    loop        = _evLoop backend
-
-
--- | Note: proc gets run in the background
-withConnection :: Backend -> Int -> (Connection -> IO ()) -> IO ()
-withConnection backend cpu proc = go
-  where
-    threadProc conn = ignoreException (proc conn) `finally` freeConnection conn
-
-    go = do
-        debug $ "withConnection: reading from chan"
-        fd   <- readChan $ _connectionQueue backend
-        debug $ "withConnection: got fd " ++ show fd
-
-        -- if fd < 0 throw an exception here (because this only happens if stop
-        -- is called)
-        when (fd < 0) $ throwIO BackendTerminatedException
-
-        sock <- mkSocket fd AF_INET Stream 0 Connected
-        peerName <- getPeerName sock
-        sockName <- getSocketName sock
-
-        -- set_linger fd
-        c_setnonblocking fd
-
-        (remoteAddr, remotePort) <- getAddr peerName
-        (localAddr, localPort) <- getAddr sockName
-
-        let lp = _evLoop backend
-
-        -- makes sense to assume the socket is read/write available when
-        -- opened; worst-case is we get EWOULDBLOCK
-        ra    <- newMVar ()
-        wa    <- newMVar ()
-
-        tmr   <- mkEvTimer
-        thrmv <- newEmptyMVar
-        tcb   <- mkTimerCallback $ timerCallback thrmv
-        evTimerInit tmr tcb 0 20.0
-
-        readActive  <- newIORef True
-        writeActive <- newIORef True
-
-        evioRead <- mkEvIo
-        ioReadCb <- mkIoCallback $ ioReadCallback fd readActive ra
-
-        evioWrite <- mkEvIo
-        ioWriteCb <- mkIoCallback $ ioWriteCallback fd writeActive wa
-
-        evIoInit evioRead ioReadCb fd ev_read
-        evIoInit evioWrite ioWriteCb fd ev_write
-
-        -- take ev_loop lock, start timer and io watchers
-        withMVar (_loopLock backend) $ \_ -> do
-             evTimerAgain lp tmr
-             evIoStart lp evioRead
-             evIoStart lp evioWrite
-
-             -- wakeup the loop thread so that these new watchers get
-             -- registered next time through the loop
-             evAsyncSend lp $ _asyncObj backend
-
-        let conn = Connection backend
-                              sock
-                              fd
-                              remoteAddr
-                              remotePort
-                              localAddr
-                              localPort
-                              ra
-                              wa
-                              tmr
-                              tcb
-                              readActive
-                              writeActive
-                              evioRead
-                              ioReadCb
-                              evioWrite
-                              ioWriteCb
-                              thrmv
-
-
-        tid <- forkOnIO cpu $ threadProc conn
-
-        modifyMVar_ (_connectionThreads backend) $ ins tid
-        putMVar thrmv tid
-
-      where
-        ins !thr !s = let !r = Set.insert thr s in return (r `seq` r)
-
-
-data BackendTerminatedException = BackendTerminatedException
-   deriving (Typeable)
-
-instance Show BackendTerminatedException where
-    show BackendTerminatedException = "Backend terminated"
-
-instance Exception BackendTerminatedException
-
-
-
-data AddressNotSupportedException = AddressNotSupportedException String
-   deriving (Typeable)
-
-instance Show AddressNotSupportedException where
-    show (AddressNotSupportedException x) = "Address not supported: " ++ x
-
-instance Exception AddressNotSupportedException
-
-
-getRemoteAddr :: Connection -> ByteString
-getRemoteAddr = _remoteAddr
-
-getRemotePort :: Connection -> Int
-getRemotePort = _remotePort
-
-getLocalAddr :: Connection -> ByteString
-getLocalAddr = _localAddr
-
-getLocalPort :: Connection -> Int
-getLocalPort = _localPort
-
-------------------------------------------------------------------------------
-
--- fixme: new function name
-getHostAddr :: Int
-            -> ByteString
-            -> IO SockAddr
-getHostAddr p s = do
-    h <- if s == "*"
-          then return iNADDR_ANY
-          else inet_addr (map w2c . B.unpack $ s)
-
-    return $ SockAddrInet (fromIntegral p) h
-
-
-
-bLOCKSIZE :: Int
-bLOCKSIZE = 8192
-
---
--- About timeouts
---
--- It's not good enough to restart the timer from io(Read|Write)Callback,
--- because those seem to be edge-triggered. I've definitely had where after
--- 20 seconds they still weren't being re-awakened.
---
-
-data TimeoutException = TimeoutException
-   deriving (Typeable)
-
-instance Show TimeoutException where
-    show _ = "timeout"
-
-instance Exception TimeoutException
-
-tickleTimeout :: Connection -> IO ()
-tickleTimeout conn = debug "Backend.tickleTimeout" >> evTimerAgain lp tmr
-  where
-    bk  = _backend conn
-    lp  = _evLoop bk
-    tmr = _timerObj conn
-
-recvData :: Connection -> Int -> IO ByteString
-recvData conn n = do
-    dbg "entered"
-    allocaBytes n $ \cstr -> do
-    sz <- throwErrnoIfMinus1RetryMayBlock
-              "recvData"
-              (c_read fd cstr (toEnum n))
-              waitForLock
-
-    -- we got activity, but don't do restart timer due to the
-    -- slowloris attack
-
-    dbg $ "sz returned " ++ show sz
-
-    if sz == 0
-      then return ""
-      else B.packCStringLen ((castPtr cstr),(fromEnum sz))
-
-  where
-    io       = _connReadIOObj conn
-    bk       = _backend conn
-    active   = _readActive conn
-    lp       = _evLoop bk
-    looplock = _loopLock bk
-    async    = _asyncObj bk
-
-    dbg s = debug $ "Backend.recvData(" ++ show (_socketFd conn) ++ "): " ++ s
-
-    fd          = _socketFd conn
-    lock        = _readAvailable conn
-    waitForLock = do
-        dbg "start waitForLock"
-
-        withMVar looplock $ \_ -> do
-            act <- readIORef active
-            if act
-              then dbg "read watcher already active, skipping"
-              else do
-                dbg "starting watcher, sending async"
-                evIoStart lp io
-                writeIORef active True
-                evAsyncSend lp async
-
-        dbg "waitForLock: waiting for mvar"
-        takeMVar lock
-        dbg "waitForLock: took mvar"
-
-
-sendData :: Connection -> ByteString -> IO ()
-sendData conn bs = do
-    let len = B.length bs
-    dbg $ "entered w/ " ++ show len ++ " bytes"
-    written <- B.unsafeUseAsCString bs $ \cstr ->
-        throwErrnoIfMinus1RetryMayBlock
-                   "sendData"
-                   (c_write fd cstr (toEnum len))
-                   waitForLock
-
-    -- we got activity, so restart timer
-    tickleTimeout conn
-
-    let n = fromEnum written
-    let last10 = B.drop (n-10) $ B.take n bs
-
-    dbg $ "wrote " ++ show written ++ " bytes, last 10='" ++ show last10 ++ "'"
-
-    if n < len
-       then do
-         dbg $ "short write, need to write " ++ show (len-n) ++ " more bytes"
-         sendData conn $ B.drop n bs
-       else return ()
-
-  where
-    io       = _connWriteIOObj conn
-    bk       = _backend conn
-    active   = _writeActive conn
-    lp       = _evLoop bk
-    looplock = _loopLock bk
-    async    = _asyncObj bk
-
-    dbg s = debug $ "Backend.sendData(" ++ show (_socketFd conn) ++ "): " ++ s
-    fd          = _socketFd conn
-    lock        = _writeAvailable conn
-    waitForLock = do
-        dbg "waitForLock: starting"
-        withMVar looplock $ \_ -> do
-            act <- readIORef active
-            if act
-              then dbg "write watcher already running, skipping"
-              else do
-                dbg "starting watcher, sending async event"
-                evIoStart lp io
-                writeIORef active True
-                evAsyncSend lp async
-
-        dbg "waitForLock: taking mvar"
-        takeMVar lock
-        dbg "waitForLock: took mvar"
-
-
-getReadEnd :: Connection -> Enumerator IO a
-getReadEnd = enumerate
-
-
-getWriteEnd :: Connection -> Iteratee IO ()
-getWriteEnd = writeOut
-
-
-enumerate :: (MonadIO m) => Connection -> Enumerator m a
-enumerate = loop
-  where
-    loop conn f = do
-        s <- liftIO $ recvData conn bLOCKSIZE
-        sendOne conn f s
-
-    sendOne conn f s = do
-        v <- runIter f (if B.null s
-                         then EOF Nothing
-                         else Chunk $ WrapBS s)
-        case v of
-          r@(Done _ _)      -> return $ liftI r
-          (Cont k Nothing)  -> loop conn k
-          (Cont _ (Just e)) -> return $ throwErr e
-
-
-writeOut :: (MonadIO m) => Connection -> Iteratee m ()
-writeOut conn = IterateeG out
-  where
-    out c@(EOF _)   = return $ Done () c
-
-    out (Chunk s) = do
-        let x = unWrap s
-
-        liftIO $ sendData conn x
-
-        return $ Cont (writeOut conn) Nothing
-
-
- diff --git a/static/docs/0.2.4/snap-server/src/Snap-Internal-Http-Server.html b/static/docs/0.2.4/snap-server/src/Snap-Internal-Http-Server.html deleted file mode 100644 index 075db14..0000000 --- a/static/docs/0.2.4/snap-server/src/Snap-Internal-Http-Server.html +++ /dev/null @@ -1,676 +0,0 @@ - - - - -src/Snap/Internal/Http/Server.hs - - - -
{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE CPP #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module Snap.Internal.Http.Server where
-
-------------------------------------------------------------------------------
-import           Control.Arrow (first, second)
-import           Control.Monad.State.Strict
-import           Control.Concurrent.MVar
-import           Control.Exception
-import           Data.Char
-import           Data.CIByteString
-import           Data.ByteString (ByteString)
-import qualified Data.ByteString as S
-import qualified Data.ByteString.Char8 as SC
-import qualified Data.ByteString.Lazy as L
-import           Data.ByteString.Internal (c2w, w2c)
-import qualified Data.ByteString.Nums.Careless.Int as Cvt
-import           Data.IORef
-import           Data.List (foldl')
-import qualified Data.Map as Map
-import           Data.Maybe (fromJust, catMaybes, fromMaybe)
-import           Data.Monoid
-import           Data.Version
-import           Foreign.C.Types
-import           Foreign.ForeignPtr
-import           GHC.Conc
-import           Prelude hiding (catch, show, Show)
-import qualified Prelude
-import           System.PosixCompat.Files hiding (setFileSize)
-import           System.Posix.Types (FileOffset)
-import           Text.Show.ByteString hiding (runPut)
-------------------------------------------------------------------------------
-import           System.FastLogger
-import           Snap.Internal.Http.Types hiding (Enumerator)
-import           Snap.Internal.Http.Parser
-import           Snap.Iteratee hiding (foldl', head, take, FileOffset)
-import qualified Snap.Iteratee as I
-
-#ifdef LIBEV
-import qualified Snap.Internal.Http.Server.LibevBackend as Backend
-import           Snap.Internal.Http.Server.LibevBackend (debug)
-#else
-import qualified Snap.Internal.Http.Server.SimpleBackend as Backend
-import           Snap.Internal.Http.Server.SimpleBackend (debug)
-#endif
-
-import           Snap.Internal.Http.Server.Date
-
-import qualified Paths_snap_server as V
-
-------------------------------------------------------------------------------
--- | The handler has to return the request object because we have to clear the
--- HTTP request body before we send the response. If the handler consumes the
--- request body, it is responsible for setting @rqBody=return@ in the returned
--- request (otherwise we will mess up reading the input stream).
---
--- Note that we won't be bothering end users with this -- the details will be
--- hidden inside the Snap monad
-type ServerHandler = (ByteString -> IO ())
-                   -> Request
-                   -> Iteratee IO (Request,Response)
-
-type ServerMonad = StateT ServerState (Iteratee IO)
-
-data ServerState = ServerState
-    { _forceConnectionClose  :: Bool
-    , _localHostname         :: ByteString
-    , _localAddress          :: ByteString
-    , _localPort             :: Int
-    , _remoteAddr            :: ByteString
-    , _remotePort            :: Int
-    , _logAccess             :: Request -> Response -> IO ()
-    , _logError              :: ByteString -> IO ()
-    }
-
-
-------------------------------------------------------------------------------
-runServerMonad :: ByteString                     -- ^ local host name
-               -> ByteString                     -- ^ local ip address
-               -> Int                            -- ^ local port
-               -> ByteString                     -- ^ remote ip address
-               -> Int                            -- ^ remote port
-               -> (Request -> Response -> IO ()) -- ^ access log function
-               -> (ByteString -> IO ())          -- ^ error log function
-               -> ServerMonad a                  -- ^ monadic action to run
-               -> Iteratee IO a
-runServerMonad lh lip lp rip rp la le m = evalStateT m st
-  where
-    st = ServerState False lh lip lp rip rp la le
-
-
-
-------------------------------------------------------------------------------
--- input/output
-
-
-------------------------------------------------------------------------------
-httpServe :: ByteString         -- ^ bind address, or \"*\" for all
-          -> Int                -- ^ port to bind to
-          -> ByteString         -- ^ local hostname (server name)
-          -> Maybe FilePath     -- ^ path to the access log
-          -> Maybe FilePath     -- ^ path to the error log
-          -> ServerHandler      -- ^ handler procedure
-          -> IO ()
-httpServe bindAddress bindPort localHostname alogPath elogPath handler =
-    withLoggers alogPath elogPath
-                (\(alog, elog) -> spawnAll alog elog)
-
-  where
-    spawnAll alog elog = {-# SCC "httpServe/spawnAll" #-} do
-        logE elog $ S.concat [ "Server.httpServe: START ("
-                             , Backend.name, ")"]
-        let n = numCapabilities
-        bracket (spawn n)
-                (\xs -> do
-                     logE elog "Server.httpServe: SHUTDOWN"
-                     mapM_ (Backend.stop . fst) xs
-                     logE elog "Server.httpServe: BACKEND STOPPED")
-                (runAll alog elog)
-
-
-    runAll alog elog xs = {-# SCC "httpServe/runAll" #-} do
-        mapM_ f $ xs `zip` [0..]
-        mapM_ (takeMVar . snd) xs
-      where
-        f ((backend,mvar),cpu) =
-            forkOnIO cpu $ do
-                labelMe $ map w2c $ S.unpack $
-                          S.concat ["accThread ", l2s $ show cpu]
-                (try $ (goooo alog elog backend cpu)) :: IO (Either SomeException ())
-                putMVar mvar ()
-
-    goooo alog elog backend cpu =
-        {-# SCC "httpServe/goooo" #-}
-        let loop = go alog elog backend cpu >> loop
-        in loop
-
-    maybeSpawnLogger = maybe (return Nothing) $ (liftM Just) . newLogger
-
-    withLoggers afp efp =
-        bracket (do alog <- maybeSpawnLogger afp
-                    elog <- maybeSpawnLogger efp
-                    return (alog, elog))
-                (\(alog, elog) -> do
-                    threadDelay 1000000
-                    maybe (return ()) stopLogger alog
-                    maybe (return ()) stopLogger elog)
-
-    labelMe :: String -> IO ()
-    labelMe s = do
-        tid <- myThreadId
-        labelThread tid s
-
-    spawn n = do
-        sock <- Backend.bindIt bindAddress bindPort
-        backends <- mapM (Backend.new sock) $ [0..(n-1)]
-        mvars <- replicateM n newEmptyMVar
-
-        return (backends `zip` mvars)
-
-
-    runOne alog elog backend cpu =
-        Backend.withConnection backend cpu $ \conn ->
-          {-# SCC "httpServe/runOne" #-} do
-            debug "Server.httpServe.runOne: entered"
-            let readEnd = Backend.getReadEnd conn
-            let writeEnd = Backend.getWriteEnd conn
-
-            let raddr = Backend.getRemoteAddr conn
-            let rport = Backend.getRemotePort conn
-            let laddr = Backend.getLocalAddr conn
-            let lport = Backend.getLocalPort conn
-
-            runHTTP localHostname laddr lport raddr rport
-                    alog elog readEnd writeEnd
-                    (Backend.sendFile conn)
-                    (Backend.tickleTimeout conn) handler
-
-            debug "Server.httpServe.runHTTP: finished"
-
-
-    go alog elog backend cpu = runOne alog elog backend cpu
-        `catches`
-        [ Handler $ \(_ :: Backend.TimeoutException) -> return ()
-
-        , Handler $ \(e :: AsyncException) -> do
-              logE elog $
-                   S.concat [ "Server.httpServe.go: got async exception, "
-                            , "terminating:\n", bshow e ]
-              throwIO e
-
-        , Handler $ \(e :: Backend.BackendTerminatedException) -> do
-              logE elog $ "Server.httpServe.go: got backend terminated, waiting for cleanup"
-              throwIO e
-
-        , Handler $ \(e :: IOException) -> do
-              logE elog $ S.concat [ "Server.httpServe.go: got io exception: "
-                                   , bshow e ]
-
-        , Handler $ \(e :: SomeException) -> do
-              logE elog $ S.concat [ "Server.httpServe.go: got someexception: "
-                                   , bshow e ] ]
-
-------------------------------------------------------------------------------
-debugE :: (MonadIO m) => ByteString -> m ()
-debugE s = debug $ "Server: " ++ (map w2c $ S.unpack s)
-
-
-------------------------------------------------------------------------------
-logE :: Maybe Logger -> ByteString -> IO ()
-logE elog = maybe debugE (\l s -> debugE s >> logE' l s) elog
-
-logE' :: Logger -> ByteString -> IO ()
-logE' logger s = (timestampedLogEntry s) >>= logMsg logger
-
-
-bshow :: (Prelude.Show a) => a -> ByteString
-bshow = toBS . Prelude.show
-
-------------------------------------------------------------------------------
-logA ::Maybe Logger -> Request -> Response -> IO ()
-logA alog = maybe (\_ _ -> return ()) logA' alog
-
-logA' :: Logger -> Request -> Response -> IO ()
-logA' logger req rsp = do
-    let hdrs      = rqHeaders req
-    let host      = rqRemoteAddr req
-    let user      = Nothing -- TODO we don't do authentication yet
-    let (v, v')   = rqVersion req
-    let ver       = S.concat [ "HTTP/", bshow v, ".", bshow v' ]
-    let method    = toBS $ Prelude.show (rqMethod req)
-    let reql      = S.intercalate " " [ method, rqURI req, ver ]
-    let status    = rspStatus rsp
-    let cl        = rspContentLength rsp
-    let referer   = maybe Nothing (Just . head) $ Map.lookup "referer" hdrs
-    let userAgent = maybe "-" head $ Map.lookup "user-agent" hdrs
-
-    msg <- combinedLogEntry host user reql status cl referer userAgent
-    logMsg logger msg
-
-
-------------------------------------------------------------------------------
-runHTTP :: ByteString           -- ^ local host name
-        -> ByteString           -- ^ local ip address
-        -> Int                  -- ^ local port
-        -> ByteString           -- ^ remote ip address
-        -> Int                  -- ^ remote port
-        -> Maybe Logger         -- ^ access logger
-        -> Maybe Logger         -- ^ error logger
-        -> Enumerator IO ()     -- ^ read end of socket
-        -> Iteratee IO ()       -- ^ write end of socket
-        -> (FilePath -> IO ())  -- ^ sendfile end
-        -> IO ()                -- ^ timeout tickler
-        -> ServerHandler        -- ^ handler procedure
-        -> IO ()
-runHTTP lh lip lp rip rp alog elog
-        readEnd writeEnd onSendFile tickle handler =
-    go `catches` [ Handler $ \(e :: AsyncException) -> do
-                       throwIO e
-
-                 , Handler $ \(_ :: Backend.TimeoutException) -> return ()
-
-                 , Handler $ \(e :: SomeException) ->
-                       logE elog $ S.concat [ logPrefix , bshow e ] ]
-
-  where
-    logPrefix = S.concat [ "[", rip, "]: error: " ]
-
-    go = do
-        buf <- mkIterateeBuffer
-        let iter = runServerMonad lh lip lp rip rp (logA alog) (logE elog) $
-                                  httpSession writeEnd buf onSendFile tickle
-                                  handler
-        readEnd iter >>= run
-
-
-------------------------------------------------------------------------------
-sERVER_HEADER :: [ByteString]
-sERVER_HEADER = [S.concat ["Snap/", snapServerVersion]]
-
-snapServerVersion :: ByteString
-snapServerVersion = SC.pack $ showVersion $ V.version
-
-------------------------------------------------------------------------------
-logAccess :: Request -> Response -> ServerMonad ()
-logAccess req rsp = gets _logAccess >>= (\l -> liftIO $ l req rsp)
-
-------------------------------------------------------------------------------
-logError :: ByteString -> ServerMonad ()
-logError s = gets _logError >>= (\l -> liftIO $ l s)
-
-------------------------------------------------------------------------------
--- | Runs an HTTP session.
-httpSession :: Iteratee IO ()       -- ^ write end of socket
-            -> ForeignPtr CChar     -- ^ iteratee buffer
-            -> (FilePath -> IO ())  -- ^ sendfile continuation
-            -> IO ()                -- ^ timeout tickler
-            -> ServerHandler        -- ^ handler procedure
-            -> ServerMonad ()
-httpSession writeEnd' ibuf onSendFile tickle handler = do
-
-    (writeEnd, cancelBuffering) <-
-        liftIO $ I.unsafeBufferIterateeWithBuffer ibuf writeEnd'
-
-    let killBuffer = writeIORef cancelBuffering True
-
-    liftIO $ debug "Server.httpSession: entered"
-    mreq  <- receiveRequest
-    -- successfully got a request, so restart timer
-    liftIO tickle
-
-    case mreq of
-      (Just req) -> do
-          logerr <- gets _logError
-          (req',rspOrig) <- lift $ handler logerr req
-          let rspTmp = rspOrig { rspHttpVersion = rqVersion req }
-          checkConnectionClose (rspHttpVersion rspTmp) (rspHeaders rspTmp)
-
-          cc <- gets _forceConnectionClose
-          let rsp = if cc
-                      then (setHeader "Connection" "close" rspTmp)
-                      else rspTmp
-
-
-          liftIO $ debug "Server.httpSession: handled, skipping request body"
-          srqEnum <- liftIO $ readIORef $ rqBody req'
-          let (SomeEnumerator rqEnum) = srqEnum
-          lift $ joinIM $ rqEnum skipToEof
-          liftIO $ debug "Server.httpSession: request body skipped, sending response"
-
-          date <- liftIO getDateString
-          let ins = (Map.insert "Date" [date] . Map.insert "Server" sERVER_HEADER)
-          let rsp' = updateHeaders ins rsp
-          (bytesSent,_) <- sendResponse rsp' writeEnd ibuf killBuffer onSendFile
-
-          liftIO . debug $ "Server.httpSession: sent " ++
-                           (Prelude.show bytesSent) ++ " bytes"
-
-          maybe (logAccess req rsp')
-                (\_ -> logAccess req $ setContentLength bytesSent rsp')
-                (rspContentLength rsp')
-
-          if cc
-             then return ()
-             else httpSession writeEnd ibuf onSendFile tickle handler
-
-      Nothing -> return ()
-
-------------------------------------------------------------------------------
-receiveRequest :: ServerMonad (Maybe Request)
-receiveRequest = do
-    mreq <- {-# SCC "receiveRequest/parseRequest" #-} lift parseRequest
-
-    case mreq of
-      (Just ireq) -> do
-          req' <- toRequest ireq
-          setEnumerator req'
-          req  <- parseForm req'
-          checkConnectionClose (rqVersion req) (rqHeaders req)
-          return $ Just req
-
-      Nothing     -> return Nothing
-
-
-  where
-    -- check: did the client specify "transfer-encoding: chunked"? then we have
-    -- to honor that.
-    --
-    -- otherwise: check content-length header. if set: only take N bytes from
-    -- the read end of the socket
-    --
-    -- if no content-length and no chunked encoding, enumerate the entire
-    -- socket and close afterwards
-    setEnumerator :: Request -> ServerMonad ()
-    setEnumerator req =
-        {-# SCC "receiveRequest/setEnumerator" #-}
-        if isChunked
-          then liftIO $ writeIORef (rqBody req)
-                                   (SomeEnumerator readChunkedTransferEncoding)
-          else maybe noContentLength hasContentLength mbCL
-
-      where
-        isChunked = maybe False
-                          ((== ["chunked"]) . map toCI)
-                          (Map.lookup "transfer-encoding" hdrs)
-
-        hasContentLength :: Int -> ServerMonad ()
-        hasContentLength l = do
-            liftIO $ writeIORef (rqBody req)
-                         (SomeEnumerator e)
-          where
-            e :: Enumerator IO a
-            e = return . joinI . I.take l
-
-        noContentLength :: ServerMonad ()
-        noContentLength =
-            liftIO $ writeIORef (rqBody req)
-                (SomeEnumerator $ return . joinI . I.take 0 )
-
-
-        hdrs = rqHeaders req
-        mbCL = Map.lookup "content-length" hdrs >>= return . Cvt.int . head
-
-
-    parseForm :: Request -> ServerMonad Request
-    parseForm req =
-        {-# SCC "receiveRequest/parseForm" #-} if doIt then getIt else return req
-      where
-        doIt = mbCT == Just "application/x-www-form-urlencoded"
-        mbCT = liftM head $ Map.lookup "content-type" (rqHeaders req)
-
-        maximumPOSTBodySize :: Int
-        maximumPOSTBodySize = 10*1024*1024
-
-        getIt :: ServerMonad Request
-        getIt = {-# SCC "receiveRequest/parseForm/getIt" #-} do
-            senum <- liftIO $ readIORef $ rqBody req
-            let (SomeEnumerator enum) = senum
-            let i = joinI $ takeNoMoreThan maximumPOSTBodySize stream2stream
-            iter <- liftIO $ enum i
-            body <- lift iter
-            let newParams = parseUrlEncoded $ strictize $ fromWrap body
-            liftIO $ writeIORef (rqBody req)
-                         (SomeEnumerator $ return . I.joinI . I.take 0)
-            return $ req { rqParams = rqParams req `mappend` newParams }
-
-
-    toRequest (IRequest method uri version kvps) =
-        {-# SCC "receiveRequest/toRequest" #-} do
-            localAddr     <- gets _localAddress
-            localPort     <- gets _localPort
-            remoteAddr    <- gets _remoteAddr
-            remotePort    <- gets _remotePort
-            localHostname <- gets _localHostname
-
-            let (serverName, serverPort) = fromMaybe
-                                             (localHostname, localPort)
-                                             (liftM (parseHost . head)
-                                                    (Map.lookup "host" hdrs))
-
-            -- will override in "setEnumerator"
-            enum <- liftIO $ newIORef $ SomeEnumerator return
-
-
-            return $ Request serverName
-                             serverPort
-                             remoteAddr
-                             remotePort
-                             localAddr
-                             localPort
-                             localHostname
-                             isSecure
-                             hdrs
-                             enum
-                             mbContentLength
-                             method
-                             version
-                             cookies
-                             snapletPath
-                             pathInfo
-                             contextPath
-                             uri
-                             queryString
-                             params
-
-      where
-        snapletPath = ""        -- TODO: snaplets in v0.2
-
-        dropLeadingSlash s = maybe s f mbS
-          where
-            f (a,s') = if a == c2w '/' then s' else s
-            mbS = S.uncons s
-
-        isSecure        = False
-
-        hdrs            = toHeaders kvps
-
-        mbContentLength = liftM (Cvt.int . head) $
-                          Map.lookup "content-length" hdrs
-
-        cookies         = concat $
-                          maybe []
-                                (catMaybes . map parseCookie)
-                                (Map.lookup "cookie" hdrs)
-
-        contextPath     = "/"
-
-        parseHost h = (a, Cvt.int (S.drop 1 b))
-          where
-            (a,b) = S.break (== (c2w ':')) h
-
-        params          = parseUrlEncoded queryString
-
-        (pathInfo, queryString) = first dropLeadingSlash . second (S.drop 1) $
-                                  S.break (== (c2w '?')) uri
-
-
-------------------------------------------------------------------------------
--- Response must be well-formed here
-sendResponse :: Response
-             -> Iteratee IO a
-             -> ForeignPtr CChar
-             -> IO ()
-             -> (FilePath -> IO a)
-             -> ServerMonad (Int,a)
-sendResponse rsp' writeEnd ibuf killBuffering onSendFile = do
-    rsp <- fixupResponse rsp'
-    let !headerString = mkHeaderString rsp
-
-    (!x,!bs) <- case (rspBody rsp) of
-                  (Enum e)     -> liftIO $ whenEnum headerString e
-                  (SendFile f) -> liftIO $ whenSendFile headerString rsp f
-
-    return $! (bs,x)
-
-  where
-    whenEnum hs e = do
-        let enum = enumBS hs >. e
-        let hl = S.length hs
-        (x,bs) <- liftIO $ enum (countBytes writeEnd) >>= run
-
-        return (x, bs-hl)
-
-    whenSendFile hs r f = do
-        -- guaranteed to have a content length here.
-        enumBS hs writeEnd >>= run
-
-        let !cl = fromJust $ rspContentLength r
-        x <- onSendFile f
-        return (x, cl)
-
-    (major,minor) = rspHttpVersion rsp'
-
-
-    fmtHdrs hdrs =
-        {-# SCC "fmtHdrs" #-}
-        concat xs
-      where
-        xs = map f $ Map.toList hdrs
-
-        f (k, ys) = map (g k) ys
-
-        g k y = S.concat [ unCI k, ": ", y, "\r\n" ]
-
-
-    noCL :: Response -> ServerMonad Response
-    noCL r =
-        {-# SCC "noCL" #-}
-        do
-            -- are we in HTTP/1.1?
-            let sendChunked = (rspHttpVersion r) == (1,1)
-            if sendChunked
-              then do
-                  liftIO $ killBuffering
-                  let r' = setHeader "Transfer-Encoding" "chunked" r
-                  let e  = writeChunkedTransferEncoding ibuf $
-                           rspBodyToEnum $ rspBody r
-                  return $ r' { rspBody = Enum e }
-
-              else do
-                  -- HTTP/1.0 and no content-length? We'll have to close the
-                  -- socket.
-                  modify $! \s -> s { _forceConnectionClose = True }
-                  return $ setHeader "Connection" "close" r
-
-
-    hasCL :: Int -> Response -> ServerMonad Response
-    hasCL cl r =
-        {-# SCC "hasCL" #-}
-        do
-            -- set the content-length header
-            let r' = setHeader "Content-Length" (l2s $ show cl) r
-            let b = case (rspBody r') of
-                      (Enum e)     -> Enum (i e)
-                      (SendFile f) -> SendFile f
-
-            return $ r' { rspBody = b }
-
-      where
-        i :: Enumerator IO a -> Enumerator IO a
-        i enum iter = enum (joinI $ takeExactly cl iter)
-
-
-    setFileSize :: FilePath -> Response -> ServerMonad Response
-    setFileSize fp r =
-        {-# SCC "setFileSize" #-}
-        do
-            fs <- liftM fromEnum $ liftIO $ getFileSize fp
-            return $ r { rspContentLength = Just fs }
-
-
-    fixupResponse :: Response -> ServerMonad Response
-    fixupResponse r =
-        {-# SCC "fixupResponse" #-}
-        do
-            let r' = updateHeaders (Map.delete "Content-Length") r
-            r'' <- case (rspBody r') of
-                     (Enum _)     -> return r'
-                     (SendFile f) -> setFileSize f r'
-            case (rspContentLength r'') of
-              Nothing   -> noCL r''
-              (Just sz) -> hasCL sz r''
-
-
-    bsshow = l2s . show
-
-
-    mkHeaderString :: Response -> ByteString
-    mkHeaderString r =
-        {-# SCC "mkHeaderString" #-}
-        S.concat $ concat [hl, hdr, eol]
-      where
-        hl = [ "HTTP/"
-             , bsshow major
-             , "."
-             , bsshow minor
-             , " "
-             , bsshow $ rspStatus r
-             , " "
-             , rspStatusReason r
-             , "\r\n" ]
-
-        hdr = fmtHdrs $ headers r
-
-        eol = ["\r\n"]
-
-
-------------------------------------------------------------------------------
-checkConnectionClose :: (Int, Int) -> Headers -> ServerMonad ()
-checkConnectionClose ver hdrs =
-    -- For HTTP/1.1:
-    --   if there is an explicit Connection: close, close the socket.
-    -- For HTTP/1.0:
-    --   if there is no explicit Connection: Keep-Alive, close the socket.
-    if (ver == (1,1) && l == Just ["close"]) ||
-       (ver == (1,0) && l /= Just ["Keep-Alive"])
-       then modify $ \s -> s { _forceConnectionClose = True }
-       else return ()
-  where
-    l  = liftM (map tl) $ Map.lookup "Connection" hdrs
-    tl = S.map (c2w . toLower . w2c)
-
-
-------------------------------------------------------------------------------
--- FIXME: whitespace-trim the values here.
-toHeaders :: [(ByteString,ByteString)] -> Headers
-toHeaders kvps = foldl' f Map.empty kvps'
-  where
-    kvps'     = map (first toCI . second (:[])) kvps
-    f m (k,v) = Map.insertWith' (flip (++)) k v m
-
-
-------------------------------------------------------------------------------
-getFileSize :: FilePath -> IO FileOffset
-getFileSize fp = liftM fileSize $ getFileStatus fp
-
-
-l2s :: L.ByteString -> S.ByteString
-l2s = S.concat . L.toChunks
-
-
-toBS :: String -> ByteString
-toBS = S.pack . map c2w
-
- diff --git a/static/docs/0.2.4/snap-server/src/System-FastLogger.html b/static/docs/0.2.4/snap-server/src/System-FastLogger.html deleted file mode 100644 index d2f4dce..0000000 --- a/static/docs/0.2.4/snap-server/src/System-FastLogger.html +++ /dev/null @@ -1,211 +0,0 @@ - - - - -src/System/FastLogger.hs - - - -
{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module System.FastLogger 
-( Logger
-, timestampedLogEntry
-, combinedLogEntry
-, newLogger
-, logMsg
-, stopLogger
-) where
-
-import           Control.Concurrent
-import           Control.Exception
-import           Control.Monad
-import           Data.ByteString.Char8 (ByteString)
-import qualified Data.ByteString.Char8 as S
-import qualified Data.ByteString.Lazy.Char8 as L
-import           Data.ByteString.Internal (c2w)
-import           Data.DList (DList)
-import qualified Data.DList as D
-import           Data.IORef
-import           Data.Maybe
-import           Data.Serialize.Put
-import           Prelude hiding (catch, show)
-import qualified Prelude
-import           System.IO
-import           Text.Show.ByteString hiding (runPut)
-
-import           Snap.Internal.Http.Server.Date
-
-
--- | Holds the state for a logger.
-data Logger = Logger
-    { _queuedMessages :: !(IORef (DList ByteString))
-    , _dataWaiting    :: !(MVar ())
-    , _loggerPath     :: !(FilePath)
-    , _loggingThread  :: !(MVar ThreadId) }
-
-
--- | Creates a new logger, logging to the given file. If the file argument is
--- \"-\", then log to stdout; if it's \"stderr\" then we log to stderr,
--- otherwise we log to a regular file in append mode. The file is closed and
--- re-opened every 15 minutes to facilitate external log rotation.
-newLogger :: FilePath -> IO Logger
-newLogger fp = do
-    q  <- newIORef D.empty
-    dw <- newEmptyMVar
-    th <- newEmptyMVar
-
-    let lg = Logger q dw fp th
-
-    tid <- forkIO $ loggingThread lg
-    putMVar th tid
-
-    return lg
-
--- | Prepares a log message with the time prepended.
-timestampedLogEntry :: ByteString -> IO ByteString
-timestampedLogEntry msg = do
-    timeStr <- getLogDateString
-
-    return $! runPut $! do
-        putWord8 $ c2w '['
-        putByteString timeStr
-        putByteString "] "
-        putByteString msg
-
-
--- | Prepares a log message in \"combined\" format.
-combinedLogEntry :: ByteString        -- ^ remote host
-                 -> Maybe ByteString  -- ^ remote user
-                 -> ByteString        -- ^ request line (up to you to ensure
-                                      --   there are no quotes in here)
-                 -> Int               -- ^ status code
-                 -> Maybe Int         -- ^ num bytes sent
-                 -> Maybe ByteString  -- ^ referer (up to you to ensure
-                                      --   there are no quotes in here)
-                 -> ByteString        -- ^ user agent (up to you to ensure
-                                      --   there are no quotes in here)
-                 -> IO ByteString
-combinedLogEntry !host !mbUser !req !status !mbNumBytes !mbReferer !userAgent = do
-    let user = fromMaybe "-" mbUser
-    let numBytes = maybe "-" (\s -> strict $ show s) mbNumBytes
-    let referer = maybe "-" (\s -> S.concat ["\"", s, "\""]) mbReferer
-
-    timeStr <- getLogDateString
-
-    let !p = [ host
-            , " - "
-            , user
-            , " ["
-            , timeStr
-            , "] \""
-            , req
-            , "\" "
-            , strict $ show status
-            , " "
-            , numBytes
-            , " "
-            , referer
-            , " \""
-            , userAgent
-            , "\"" ]
-
-    let !output = S.concat p
-
-    return $! output
-
-
-  where
-    strict = S.concat . L.toChunks
-
-
--- | Sends out a log message verbatim with a newline appended. Note:
--- if you want a fancy log message you'll have to format it yourself
--- (or use 'combinedLogEntry').
-logMsg :: Logger -> ByteString -> IO ()
-logMsg !lg !s = do
-    let !s' = S.snoc s '\n'
-    atomicModifyIORef (_queuedMessages lg) $ \d -> (D.snoc d s',())
-    tryPutMVar (_dataWaiting lg) () >> return ()
-
-
-loggingThread :: Logger -> IO ()
-loggingThread (Logger queue notifier filePath _) = do
-    initialize >>= go
-
-  where
-    openIt = if filePath == "-"
-               then return stdout
-               else if filePath == "stderr"
-                      then return stderr
-                      else openFile filePath AppendMode
-
-    closeIt h = if filePath == "-" || filePath == "stderr"
-                  then return ()
-                  else hClose h
-
-    go (href, lastOpened) =
-        (loop (href, lastOpened))
-          `catches`
-          [ Handler $ \(_::AsyncException) -> killit (href, lastOpened)
-          , Handler $ \(e::SomeException)  -> do
-                hPutStrLn stderr $ "logger got exception: " ++ Prelude.show e
-                threadDelay 20000000
-                go (href, lastOpened) ]
-
-
-    initialize = do
-        lh   <- openIt
-        href <- newIORef lh
-        t    <- getCurrentDateTime
-        tref <- newIORef t
-        return (href, tref)
-
-
-    killit (href, lastOpened) = do
-        flushIt (href, lastOpened)
-        h <- readIORef href
-        closeIt h
-
-
-    flushIt (!href, !lastOpened) = do
-        dl <- atomicModifyIORef queue $ \x -> (D.empty,x)
-
-        let !msgs = D.toList dl
-        let !s = L.fromChunks msgs
-        h <- readIORef href
-        L.hPut h s
-        hFlush h
-
-        -- close the file every 15 minutes (for log rotation)
-        t <- getCurrentDateTime
-        old <- readIORef lastOpened
-
-        if t-old > 900
-          then do
-              closeIt h
-              openIt >>= writeIORef href
-              writeIORef lastOpened t
-          else return ()
-
-
-    loop !d = do
-        -- wait on the notification mvar
-        _ <- takeMVar notifier
-
-        -- grab the queued messages and write them out
-        flushIt d
-
-        -- at least five seconds between log dumps
-        threadDelay 5000000
-        loop d
-
-
--- | Kills a logger thread, causing any unwritten contents to be
--- flushed out to disk
-stopLogger :: Logger -> IO ()
-stopLogger lg = withMVar (_loggingThread lg) killThread
-
- diff --git a/static/docs/0.2.4/snap-server/src/hscolour.css b/static/docs/0.2.4/snap-server/src/hscolour.css deleted file mode 100644 index 150e4d0..0000000 --- a/static/docs/0.2.4/snap-server/src/hscolour.css +++ /dev/null @@ -1,15 +0,0 @@ -body { font-size: 90%; } - -pre, code, body { - font-family: Monaco, - "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", - "Lucida Console", - monospace; -} - -.hs-keyglyph, .hs-layout {color: #5200A3;} -.hs-keyword {color: #3465a4; font-weight: bold;} -.hs-comment, .hs-comment a {color: #579; } -.hs-str, .hs-chr {color: #141B24;} -.hs-keyword, .hs-conid, .hs-varid, .hs-conop, .hs-varop, .hs-num, .hs-cpp, .hs-sel, .hs-definition {} diff --git a/static/docs/heist-hpc/Text.Templating.Heist.Constants.hs.html b/static/docs/heist-hpc/Text.Templating.Heist.Constants.hs.html index 1a6757e..7bf17d9 100644 --- a/static/docs/heist-hpc/Text.Templating.Heist.Constants.hs.html +++ b/static/docs/heist-hpc/Text.Templating.Heist.Constants.hs.html @@ -15,255 +15,268 @@ 4 import Data.ByteString.Char8 (ByteString) 5 import qualified Data.Map as Map 6 import Data.Map (Map) - 7 - 8 htmlEntityLookupTable :: Map ByteString ByteString - 9 htmlEntityLookupTable = Map.fromList [ - 10 ("acute" , "\xc2\xb4") - 11 , ("cedil" , "\xc2\xb8") - 12 , ("circ" , "\xcb\x86") - 13 , ("macr" , "\xc2\xaf") - 14 , ("middot" , "\xc2\xb7") - 15 , ("tilde" , "\xcb\x9c") - 16 , ("uml" , "\xc2\xa8") - 17 , ("Aacute" , "\xc3\x81") - 18 , ("aacute" , "\xc3\xa1") - 19 , ("Acirc" , "\xc3\x82") - 20 , ("acirc" , "\xc3\xa2") - 21 , ("AElig" , "\xc3\x86") - 22 , ("aelig" , "\xc3\xa6") - 23 , ("Agrave" , "\xc3\x80") - 24 , ("agrave" , "\xc3\xa0") - 25 , ("Aring" , "\xc3\x85") - 26 , ("aring" , "\xc3\xa5") - 27 , ("Atilde" , "\xc3\x83") - 28 , ("atilde" , "\xc3\xa3") - 29 , ("Auml" , "\xc3\x84") - 30 , ("auml" , "\xc3\xa4") - 31 , ("Ccedil" , "\xc3\x87") - 32 , ("ccedil" , "\xc3\xa7") - 33 , ("Eacute" , "\xc3\x89") - 34 , ("eacute" , "\xc3\xa9") - 35 , ("Ecirc" , "\xc3\x8a") - 36 , ("ecirc" , "\xc3\xaa") - 37 , ("Egrave" , "\xc3\x88") - 38 , ("egrave" , "\xc3\xa8") - 39 , ("ETH" , "\xc3\x90") - 40 , ("eth" , "\xc3\xb0") - 41 , ("Euml" , "\xc3\x8b") - 42 , ("euml" , "\xc3\xab") - 43 , ("Iacute" , "\xc3\x8d") - 44 , ("iacute" , "\xc3\xad") - 45 , ("Icirc" , "\xc3\x8e") - 46 , ("icirc" , "\xc3\xae") - 47 , ("Igrave" , "\xc3\x8c") - 48 , ("igrave" , "\xc3\xac") - 49 , ("Iuml" , "\xc3\x8f") - 50 , ("iuml" , "\xc3\xaf") - 51 , ("Ntilde" , "\xc3\x91") - 52 , ("ntilde" , "\xc3\xb1") - 53 , ("Oacute" , "\xc3\x93") - 54 , ("oacute" , "\xc3\xb3") - 55 , ("Ocirc" , "\xc3\x94") - 56 , ("ocirc" , "\xc3\xb4") - 57 , ("OElig" , "\xc5\x92") - 58 , ("oelig" , "\xc5\x93") - 59 , ("Ograve" , "\xc3\x92") - 60 , ("ograve" , "\xc3\xb2") - 61 , ("Oslash" , "\xc3\x98") - 62 , ("oslash" , "\xc3\xb8") - 63 , ("Otilde" , "\xc3\x95") - 64 , ("otilde" , "\xc3\xb5") - 65 , ("Ouml" , "\xc3\x96") - 66 , ("ouml" , "\xc3\xb6") - 67 , ("Scaron" , "\xc5\xa0") - 68 , ("scaron" , "\xc5\xa1") - 69 , ("szlig" , "\xc3\x9f") - 70 , ("THORN" , "\xc3\x9e") - 71 , ("thorn" , "\xc3\xbe") - 72 , ("Uacute" , "\xc3\x9a") - 73 , ("uacute" , "\xc3\xba") - 74 , ("Ucirc" , "\xc3\x9b") - 75 , ("ucirc" , "\xc3\xbb") - 76 , ("Ugrave" , "\xc3\x99") - 77 , ("ugrave" , "\xc3\xb9") - 78 , ("Uuml" , "\xc3\x9c") - 79 , ("uuml" , "\xc3\xbc") - 80 , ("Yacute" , "\xc3\x9d") - 81 , ("yacute" , "\xc3\xbd") - 82 , ("yuml" , "\xc3\xbf") - 83 , ("Yuml" , "\xc5\xb8") - 84 , ("cent" , "\xc2\xa2") - 85 , ("curren" , "\xc2\xa4") - 86 , ("euro" , "\xe2\x82\xac") - 87 , ("pound" , "\xc2\xa3") - 88 , ("yen" , "\xc2\xa5") - 89 , ("brvbar" , "\xc2\xa6") - 90 , ("bull" , "\xe2\x80\xa2") - 91 , ("copy" , "\xc2\xa9") - 92 , ("dagger" , "\xe2\x80\xa0") - 93 , ("Dagger" , "\xe2\x80\xa1") - 94 , ("frasl" , "\xe2\x81\x84") - 95 , ("hellip" , "\xe2\x80\xa6") - 96 , ("iexcl" , "\xc2\xa1") - 97 , ("image" , "\xe2\x84\x91") - 98 , ("iquest" , "\xc2\xbf") - 99 , ("mdash" , "\xe2\x80\x94") - 100 , ("ndash" , "\xe2\x80\x93") - 101 , ("not" , "\xc2\xac") - 102 , ("oline" , "\xe2\x80\xbe") - 103 , ("ordf" , "\xc2\xaa") - 104 , ("ordm" , "\xc2\xba") - 105 , ("para" , "\xc2\xb6") - 106 , ("permil" , "\xe2\x80\xb0") - 107 , ("prime" , "\xe2\x80\xb2") - 108 , ("Prime" , "\xe2\x80\xb3") - 109 , ("real" , "\xe2\x84\x9c") - 110 , ("reg" , "\xc2\xae") - 111 , ("sect" , "\xc2\xa7") - 112 , ("shy" , "\173") - 113 , ("sup1" , "\xc2\xb9") - 114 , ("trade" , "\xe2\x84\xa2") - 115 , ("weierp" , "\xe2\x84\x98") - 116 , ("bdquo" , "\xe2\x80\x9e") - 117 , ("laquo" , "\xc2\xab") - 118 , ("ldquo" , "\xe2\x80\x9c") - 119 , ("lsaquo" , "\xe2\x80\xb9") - 120 , ("lsquo" , "\xe2\x80\x98") - 121 , ("raquo" , "\xc2\xbb") - 122 , ("rdquo" , "\xe2\x80\x9d") - 123 , ("rsaquo" , "\xe2\x80\xba") - 124 , ("rsquo" , "\xe2\x80\x99") - 125 , ("sbquo" , "\xe2\x80\x9a") - 126 , ("emsp" , "\xe2\x80\x83") - 127 , ("ensp" , "\xe2\x80\x82") - 128 , ("nbsp" , "\x20") - 129 , ("thinsp" , "\xe2\x80\x89") - 130 , ("zwj" , "\xe2\x80\x8d") - 131 , ("zwnj" , "\xe2\x80\x8c") - 132 , ("deg" , "\xc2\xb0") - 133 , ("divide" , "\xc3\xb7") - 134 , ("frac12" , "\xc2\xbd") - 135 , ("frac14" , "\xc2\xbc") - 136 , ("frac34" , "\xc2\xbe") - 137 , ("ge" , "\xe2\x89\xa5") - 138 , ("le" , "\xe2\x89\xa4") - 139 , ("minus" , "\xe2\x88\x92") - 140 , ("sup2" , "\xc2\xb2") - 141 , ("sup3" , "\xc2\xb3") - 142 , ("times" , "\xc3\x97") - 143 , ("alefsym" , "\xe2\x84\xb5") - 144 , ("and" , "\xe2\x88\xa7") - 145 , ("ang" , "\xe2\x88\xa0") - 146 , ("asymp" , "\xe2\x89\x88") - 147 , ("cap" , "\xe2\x88\xa9") - 148 , ("cong" , "\xe2\x89\x85") - 149 , ("cup" , "\xe2\x88\xaa") - 150 , ("empty" , "\xe2\x88\x85") - 151 , ("equiv" , "\xe2\x89\xa1") - 152 , ("exist" , "\xe2\x88\x83") - 153 , ("fnof" , "\xc6\x92") - 154 , ("forall" , "\xe2\x88\x80") - 155 , ("infin" , "\xe2\x88\x9e") - 156 , ("int" , "\xe2\x88\xab") - 157 , ("isin" , "\xe2\x88\x88") - 158 , ("lang" , "\xe3\x80\x88") - 159 , ("lceil" , "\xe2\x8c\x88") - 160 , ("lfloor" , "\xe2\x8c\x8a") - 161 , ("lowast" , "\xe2\x88\x97") - 162 , ("micro" , "\xc2\xb5") - 163 , ("nabla" , "\xe2\x88\x87") - 164 , ("ne" , "\xe2\x89\xa0") - 165 , ("ni" , "\xe2\x88\x8b") - 166 , ("notin" , "\xe2\x88\x89") - 167 , ("nsub" , "\xe2\x8a\x84") - 168 , ("oplus" , "\xe2\x8a\x95") - 169 , ("or" , "\xe2\x88\xa8") - 170 , ("otimes" , "\xe2\x8a\x97") - 171 , ("part" , "\xe2\x88\x82") - 172 , ("perp" , "\xe2\x8a\xa5") - 173 , ("plusmn" , "\xc2\xb1") - 174 , ("prod" , "\xe2\x88\x8f") - 175 , ("prop" , "\xe2\x88\x9d") - 176 , ("radic" , "\xe2\x88\x9a") - 177 , ("rang" , "\xe3\x80\x89") - 178 , ("rceil" , "\xe2\x8c\x89") - 179 , ("rfloor" , "\xe2\x8c\x8b") - 180 , ("sdot" , "\xe2\x8b\x85") - 181 , ("sim" , "\xe2\x88\xbc") - 182 , ("sub" , "\xe2\x8a\x82") - 183 , ("sube" , "\xe2\x8a\x86") - 184 , ("sum" , "\xe2\x88\x91") - 185 , ("sup" , "\xe2\x8a\x83") - 186 , ("supe" , "\xe2\x8a\x87") - 187 , ("there4" , "\xe2\x88\xb4") - 188 , ("Alpha" , "\xce\x91") - 189 , ("alpha" , "\xce\xb1") - 190 , ("Beta" , "\xce\x92") - 191 , ("beta" , "\xce\xb2") - 192 , ("Chi" , "\xce\xa7") - 193 , ("chi" , "\xcf\x87") - 194 , ("Delta" , "\xce\x94") - 195 , ("delta" , "\xce\xb4") - 196 , ("Epsilon" , "\xce\x95") - 197 , ("epsilon" , "\xce\xb5") - 198 , ("Eta" , "\xce\x97") - 199 , ("eta" , "\xce\xb7") - 200 , ("Gamma" , "\xce\x93") - 201 , ("gamma" , "\xce\xb3") - 202 , ("Iota" , "\xce\x99") - 203 , ("iota" , "\xce\xb9") - 204 , ("Kappa" , "\xce\x9a") - 205 , ("kappa" , "\xce\xba") - 206 , ("Lambda" , "\xce\x9b") - 207 , ("lambda" , "\xce\xbb") - 208 , ("Mu" , "\xce\x9c") - 209 , ("mu" , "\xce\xbc") - 210 , ("Nu" , "\xce\x9d") - 211 , ("nu" , "\xce\xbd") - 212 , ("Omega" , "\xce\xa9") - 213 , ("omega" , "\xcf\x89") - 214 , ("Omicron" , "\xce\x9f") - 215 , ("omicron" , "\xce\xbf") - 216 , ("Phi" , "\xce\xa6") - 217 , ("phi" , "\xcf\x86") - 218 , ("Pi" , "\xce\xa0") - 219 , ("pi" , "\xcf\x80") - 220 , ("piv" , "\xcf\x96") - 221 , ("Psi" , "\xce\xa8") - 222 , ("psi" , "\xcf\x88") - 223 , ("Rho" , "\xce\xa1") - 224 , ("rho" , "\xcf\x81") - 225 , ("Sigma" , "\xce\xa3") - 226 , ("sigma" , "\xcf\x83") - 227 , ("sigmaf" , "\xcf\x82") - 228 , ("Tau" , "\xce\xa4") - 229 , ("tau" , "\xcf\x84") - 230 , ("Theta" , "\xce\x98") - 231 , ("theta" , "\xce\xb8") - 232 , ("thetasym" , "\xcf\x91") - 233 , ("upsih" , "\xcf\x92") - 234 , ("Upsilon" , "\xce\xa5") - 235 , ("upsilon" , "\xcf\x85") - 236 , ("Xi" , "\xce\x9e") - 237 , ("xi" , "\xce\xbe") - 238 , ("Zeta" , "\xce\x96") - 239 , ("zeta" , "\xce\xb6") - 240 , ("crarr" , "\xe2\x86\xb5") - 241 , ("darr" , "\xe2\x86\x93") - 242 , ("dArr" , "\xe2\x87\x93") - 243 , ("harr" , "\xe2\x86\x94") - 244 , ("hArr" , "\xe2\x87\x94") - 245 , ("larr" , "\xe2\x86\x90") - 246 , ("lArr" , "\xe2\x87\x90") - 247 , ("rarr" , "\xe2\x86\x92") - 248 , ("rArr" , "\xe2\x87\x92") - 249 , ("uarr" , "\xe2\x86\x91") - 250 , ("uArr" , "\xe2\x87\x91") - 251 , ("clubs" , "\xe2\x99\xa3") - 252 , ("diams" , "\xe2\x99\xa6") - 253 , ("hearts" , "\xe2\x99\xa5") - 254 , ("spades" , "\xe2\x99\xa0") - 255 , ("loz" , "\xe2\x97\x8a") ] + 7 import Text.XML.Expat.Tree + 8 + 9 + 10 ------------------------------------------------------------------------------ + 11 -- | Options passed to hexpat for XML parsing. + 12 heistExpatOptions :: ParserOptions ByteString ByteString + 13 heistExpatOptions = + 14 defaultParserOptions { + 15 parserEncoding = Just UTF8 + 16 , entityDecoder = Just (\k -> Map.lookup k htmlEntityLookupTable) + 17 } + 18 + 19 ------------------------------------------------------------------------------ + 20 -- | Character entity references for HTML. + 21 htmlEntityLookupTable :: Map ByteString ByteString + 22 htmlEntityLookupTable = Map.fromList [ + 23 ("acute" , "\xc2\xb4") + 24 , ("cedil" , "\xc2\xb8") + 25 , ("circ" , "\xcb\x86") + 26 , ("macr" , "\xc2\xaf") + 27 , ("middot" , "\xc2\xb7") + 28 , ("tilde" , "\xcb\x9c") + 29 , ("uml" , "\xc2\xa8") + 30 , ("Aacute" , "\xc3\x81") + 31 , ("aacute" , "\xc3\xa1") + 32 , ("Acirc" , "\xc3\x82") + 33 , ("acirc" , "\xc3\xa2") + 34 , ("AElig" , "\xc3\x86") + 35 , ("aelig" , "\xc3\xa6") + 36 , ("Agrave" , "\xc3\x80") + 37 , ("agrave" , "\xc3\xa0") + 38 , ("Aring" , "\xc3\x85") + 39 , ("aring" , "\xc3\xa5") + 40 , ("Atilde" , "\xc3\x83") + 41 , ("atilde" , "\xc3\xa3") + 42 , ("Auml" , "\xc3\x84") + 43 , ("auml" , "\xc3\xa4") + 44 , ("Ccedil" , "\xc3\x87") + 45 , ("ccedil" , "\xc3\xa7") + 46 , ("Eacute" , "\xc3\x89") + 47 , ("eacute" , "\xc3\xa9") + 48 , ("Ecirc" , "\xc3\x8a") + 49 , ("ecirc" , "\xc3\xaa") + 50 , ("Egrave" , "\xc3\x88") + 51 , ("egrave" , "\xc3\xa8") + 52 , ("ETH" , "\xc3\x90") + 53 , ("eth" , "\xc3\xb0") + 54 , ("Euml" , "\xc3\x8b") + 55 , ("euml" , "\xc3\xab") + 56 , ("Iacute" , "\xc3\x8d") + 57 , ("iacute" , "\xc3\xad") + 58 , ("Icirc" , "\xc3\x8e") + 59 , ("icirc" , "\xc3\xae") + 60 , ("Igrave" , "\xc3\x8c") + 61 , ("igrave" , "\xc3\xac") + 62 , ("Iuml" , "\xc3\x8f") + 63 , ("iuml" , "\xc3\xaf") + 64 , ("Ntilde" , "\xc3\x91") + 65 , ("ntilde" , "\xc3\xb1") + 66 , ("Oacute" , "\xc3\x93") + 67 , ("oacute" , "\xc3\xb3") + 68 , ("Ocirc" , "\xc3\x94") + 69 , ("ocirc" , "\xc3\xb4") + 70 , ("OElig" , "\xc5\x92") + 71 , ("oelig" , "\xc5\x93") + 72 , ("Ograve" , "\xc3\x92") + 73 , ("ograve" , "\xc3\xb2") + 74 , ("Oslash" , "\xc3\x98") + 75 , ("oslash" , "\xc3\xb8") + 76 , ("Otilde" , "\xc3\x95") + 77 , ("otilde" , "\xc3\xb5") + 78 , ("Ouml" , "\xc3\x96") + 79 , ("ouml" , "\xc3\xb6") + 80 , ("Scaron" , "\xc5\xa0") + 81 , ("scaron" , "\xc5\xa1") + 82 , ("szlig" , "\xc3\x9f") + 83 , ("THORN" , "\xc3\x9e") + 84 , ("thorn" , "\xc3\xbe") + 85 , ("Uacute" , "\xc3\x9a") + 86 , ("uacute" , "\xc3\xba") + 87 , ("Ucirc" , "\xc3\x9b") + 88 , ("ucirc" , "\xc3\xbb") + 89 , ("Ugrave" , "\xc3\x99") + 90 , ("ugrave" , "\xc3\xb9") + 91 , ("Uuml" , "\xc3\x9c") + 92 , ("uuml" , "\xc3\xbc") + 93 , ("Yacute" , "\xc3\x9d") + 94 , ("yacute" , "\xc3\xbd") + 95 , ("yuml" , "\xc3\xbf") + 96 , ("Yuml" , "\xc5\xb8") + 97 , ("cent" , "\xc2\xa2") + 98 , ("curren" , "\xc2\xa4") + 99 , ("euro" , "\xe2\x82\xac") + 100 , ("pound" , "\xc2\xa3") + 101 , ("yen" , "\xc2\xa5") + 102 , ("brvbar" , "\xc2\xa6") + 103 , ("bull" , "\xe2\x80\xa2") + 104 , ("copy" , "\xc2\xa9") + 105 , ("dagger" , "\xe2\x80\xa0") + 106 , ("Dagger" , "\xe2\x80\xa1") + 107 , ("frasl" , "\xe2\x81\x84") + 108 , ("hellip" , "\xe2\x80\xa6") + 109 , ("iexcl" , "\xc2\xa1") + 110 , ("image" , "\xe2\x84\x91") + 111 , ("iquest" , "\xc2\xbf") + 112 , ("mdash" , "\xe2\x80\x94") + 113 , ("ndash" , "\xe2\x80\x93") + 114 , ("not" , "\xc2\xac") + 115 , ("oline" , "\xe2\x80\xbe") + 116 , ("ordf" , "\xc2\xaa") + 117 , ("ordm" , "\xc2\xba") + 118 , ("para" , "\xc2\xb6") + 119 , ("permil" , "\xe2\x80\xb0") + 120 , ("prime" , "\xe2\x80\xb2") + 121 , ("Prime" , "\xe2\x80\xb3") + 122 , ("real" , "\xe2\x84\x9c") + 123 , ("reg" , "\xc2\xae") + 124 , ("sect" , "\xc2\xa7") + 125 , ("shy" , "\173") + 126 , ("sup1" , "\xc2\xb9") + 127 , ("trade" , "\xe2\x84\xa2") + 128 , ("weierp" , "\xe2\x84\x98") + 129 , ("bdquo" , "\xe2\x80\x9e") + 130 , ("laquo" , "\xc2\xab") + 131 , ("ldquo" , "\xe2\x80\x9c") + 132 , ("lsaquo" , "\xe2\x80\xb9") + 133 , ("lsquo" , "\xe2\x80\x98") + 134 , ("raquo" , "\xc2\xbb") + 135 , ("rdquo" , "\xe2\x80\x9d") + 136 , ("rsaquo" , "\xe2\x80\xba") + 137 , ("rsquo" , "\xe2\x80\x99") + 138 , ("sbquo" , "\xe2\x80\x9a") + 139 , ("emsp" , "\xe2\x80\x83") + 140 , ("ensp" , "\xe2\x80\x82") + 141 , ("nbsp" , "\x20") + 142 , ("thinsp" , "\xe2\x80\x89") + 143 , ("zwj" , "\xe2\x80\x8d") + 144 , ("zwnj" , "\xe2\x80\x8c") + 145 , ("deg" , "\xc2\xb0") + 146 , ("divide" , "\xc3\xb7") + 147 , ("frac12" , "\xc2\xbd") + 148 , ("frac14" , "\xc2\xbc") + 149 , ("frac34" , "\xc2\xbe") + 150 , ("ge" , "\xe2\x89\xa5") + 151 , ("le" , "\xe2\x89\xa4") + 152 , ("minus" , "\xe2\x88\x92") + 153 , ("sup2" , "\xc2\xb2") + 154 , ("sup3" , "\xc2\xb3") + 155 , ("times" , "\xc3\x97") + 156 , ("alefsym" , "\xe2\x84\xb5") + 157 , ("and" , "\xe2\x88\xa7") + 158 , ("ang" , "\xe2\x88\xa0") + 159 , ("asymp" , "\xe2\x89\x88") + 160 , ("cap" , "\xe2\x88\xa9") + 161 , ("cong" , "\xe2\x89\x85") + 162 , ("cup" , "\xe2\x88\xaa") + 163 , ("empty" , "\xe2\x88\x85") + 164 , ("equiv" , "\xe2\x89\xa1") + 165 , ("exist" , "\xe2\x88\x83") + 166 , ("fnof" , "\xc6\x92") + 167 , ("forall" , "\xe2\x88\x80") + 168 , ("infin" , "\xe2\x88\x9e") + 169 , ("int" , "\xe2\x88\xab") + 170 , ("isin" , "\xe2\x88\x88") + 171 , ("lang" , "\xe3\x80\x88") + 172 , ("lceil" , "\xe2\x8c\x88") + 173 , ("lfloor" , "\xe2\x8c\x8a") + 174 , ("lowast" , "\xe2\x88\x97") + 175 , ("micro" , "\xc2\xb5") + 176 , ("nabla" , "\xe2\x88\x87") + 177 , ("ne" , "\xe2\x89\xa0") + 178 , ("ni" , "\xe2\x88\x8b") + 179 , ("notin" , "\xe2\x88\x89") + 180 , ("nsub" , "\xe2\x8a\x84") + 181 , ("oplus" , "\xe2\x8a\x95") + 182 , ("or" , "\xe2\x88\xa8") + 183 , ("otimes" , "\xe2\x8a\x97") + 184 , ("part" , "\xe2\x88\x82") + 185 , ("perp" , "\xe2\x8a\xa5") + 186 , ("plusmn" , "\xc2\xb1") + 187 , ("prod" , "\xe2\x88\x8f") + 188 , ("prop" , "\xe2\x88\x9d") + 189 , ("radic" , "\xe2\x88\x9a") + 190 , ("rang" , "\xe3\x80\x89") + 191 , ("rceil" , "\xe2\x8c\x89") + 192 , ("rfloor" , "\xe2\x8c\x8b") + 193 , ("sdot" , "\xe2\x8b\x85") + 194 , ("sim" , "\xe2\x88\xbc") + 195 , ("sub" , "\xe2\x8a\x82") + 196 , ("sube" , "\xe2\x8a\x86") + 197 , ("sum" , "\xe2\x88\x91") + 198 , ("sup" , "\xe2\x8a\x83") + 199 , ("supe" , "\xe2\x8a\x87") + 200 , ("there4" , "\xe2\x88\xb4") + 201 , ("Alpha" , "\xce\x91") + 202 , ("alpha" , "\xce\xb1") + 203 , ("Beta" , "\xce\x92") + 204 , ("beta" , "\xce\xb2") + 205 , ("Chi" , "\xce\xa7") + 206 , ("chi" , "\xcf\x87") + 207 , ("Delta" , "\xce\x94") + 208 , ("delta" , "\xce\xb4") + 209 , ("Epsilon" , "\xce\x95") + 210 , ("epsilon" , "\xce\xb5") + 211 , ("Eta" , "\xce\x97") + 212 , ("eta" , "\xce\xb7") + 213 , ("Gamma" , "\xce\x93") + 214 , ("gamma" , "\xce\xb3") + 215 , ("Iota" , "\xce\x99") + 216 , ("iota" , "\xce\xb9") + 217 , ("Kappa" , "\xce\x9a") + 218 , ("kappa" , "\xce\xba") + 219 , ("Lambda" , "\xce\x9b") + 220 , ("lambda" , "\xce\xbb") + 221 , ("Mu" , "\xce\x9c") + 222 , ("mu" , "\xce\xbc") + 223 , ("Nu" , "\xce\x9d") + 224 , ("nu" , "\xce\xbd") + 225 , ("Omega" , "\xce\xa9") + 226 , ("omega" , "\xcf\x89") + 227 , ("Omicron" , "\xce\x9f") + 228 , ("omicron" , "\xce\xbf") + 229 , ("Phi" , "\xce\xa6") + 230 , ("phi" , "\xcf\x86") + 231 , ("Pi" , "\xce\xa0") + 232 , ("pi" , "\xcf\x80") + 233 , ("piv" , "\xcf\x96") + 234 , ("Psi" , "\xce\xa8") + 235 , ("psi" , "\xcf\x88") + 236 , ("Rho" , "\xce\xa1") + 237 , ("rho" , "\xcf\x81") + 238 , ("Sigma" , "\xce\xa3") + 239 , ("sigma" , "\xcf\x83") + 240 , ("sigmaf" , "\xcf\x82") + 241 , ("Tau" , "\xce\xa4") + 242 , ("tau" , "\xcf\x84") + 243 , ("Theta" , "\xce\x98") + 244 , ("theta" , "\xce\xb8") + 245 , ("thetasym" , "\xcf\x91") + 246 , ("upsih" , "\xcf\x92") + 247 , ("Upsilon" , "\xce\xa5") + 248 , ("upsilon" , "\xcf\x85") + 249 , ("Xi" , "\xce\x9e") + 250 , ("xi" , "\xce\xbe") + 251 , ("Zeta" , "\xce\x96") + 252 , ("zeta" , "\xce\xb6") + 253 , ("crarr" , "\xe2\x86\xb5") + 254 , ("darr" , "\xe2\x86\x93") + 255 , ("dArr" , "\xe2\x87\x93") + 256 , ("harr" , "\xe2\x86\x94") + 257 , ("hArr" , "\xe2\x87\x94") + 258 , ("larr" , "\xe2\x86\x90") + 259 , ("lArr" , "\xe2\x87\x90") + 260 , ("rarr" , "\xe2\x86\x92") + 261 , ("rArr" , "\xe2\x87\x92") + 262 , ("uarr" , "\xe2\x86\x91") + 263 , ("uArr" , "\xe2\x87\x91") + 264 , ("clubs" , "\xe2\x99\xa3") + 265 , ("diams" , "\xe2\x99\xa6") + 266 , ("hearts" , "\xe2\x99\xa5") + 267 , ("spades" , "\xe2\x99\xa0") + 268 , ("loz" , "\xe2\x97\x8a") ] diff --git a/static/docs/heist-hpc/Text.Templating.Heist.Internal.hs.html b/static/docs/heist-hpc/Text.Templating.Heist.Internal.hs.html index 2fbd5c4..a242c9d 100644 --- a/static/docs/heist-hpc/Text.Templating.Heist.Internal.hs.html +++ b/static/docs/heist-hpc/Text.Templating.Heist.Internal.hs.html @@ -16,513 +16,544 @@ 5 module Text.Templating.Heist.Internal where 6 7 ------------------------------------------------------------------------------ - 8 import Control.Exception (SomeException) - 9 import Control.Monad.CatchIO - 10 import Control.Monad.RWS.Strict - 11 import Data.ByteString.Char8 (ByteString) - 12 import qualified Data.ByteString.Char8 as B - 13 import qualified Data.ByteString.Lazy as L - 14 import Data.Either - 15 import qualified Data.Foldable as F - 16 import Data.List - 17 import qualified Data.Map as Map - 18 import Data.Map (Map) - 19 import Data.Typeable - 20 import Prelude hiding (catch) - 21 import System.Directory.Tree hiding (name) - 22 import Text.XML.Expat.Format - 23 import qualified Text.XML.Expat.Tree as X - 24 - 25 ------------------------------------------------------------------------------ - 26 import Text.Templating.Heist.Constants - 27 - 28 ------------------------------------------------------------------------------ - 29 -- Types - 30 ------------------------------------------------------------------------------ + 8 import Control.Applicative + 9 import Control.Exception (SomeException) + 10 import Control.Monad.CatchIO + 11 import Control.Monad.RWS.Strict + 12 import qualified Data.Attoparsec.Char8 as AP + 13 import Data.ByteString.Char8 (ByteString) + 14 import qualified Data.ByteString.Char8 as B + 15 import qualified Data.ByteString.Lazy as L + 16 import Data.Either + 17 import qualified Data.Foldable as F + 18 import Data.List + 19 import qualified Data.Map as Map + 20 import Data.Maybe + 21 import Prelude hiding (catch) + 22 import System.Directory.Tree hiding (name) + 23 import System.FilePath + 24 import Text.XML.Expat.Format + 25 import qualified Text.XML.Expat.Tree as X + 26 + 27 ------------------------------------------------------------------------------ + 28 import Text.Templating.Heist.Constants + 29 import Text.Templating.Heist.Types + 30 31 - 32 -- | Heist templates are XML documents. The hexpat library is polymorphic over - 33 -- the type of strings, so here we define a 'Node' alias to fix the string - 34 -- types of the tag names and tag bodies to 'ByteString'. - 35 type Node = X.Node ByteString ByteString - 36 - 37 - 38 ------------------------------------------------------------------------------ - 39 -- | A 'Template' is a forest of XML nodes. - 40 type Template = [Node] - 41 - 42 - 43 ------------------------------------------------------------------------------ - 44 -- | Reversed list of directories - 45 type TPath = [ByteString] + 32 ------------------------------------------------------------------------------ + 33 -- | Restores the components of TemplateState that can get modified in + 34 -- template calls. You should use this function instead of @putTS@ to restore + 35 -- an old state. Thas was needed because doctypes needs to be in a "global + 36 -- scope" as opposed to the template call "local scope" of state items such + 37 -- as recursionDepth, curContext, and spliceMap. + 38 restoreState :: Monad m => TemplateState m -> TemplateMonad m () + 39 restoreState ts1 = + 40 modifyTS (\ts2 -> ts2 + 41 { _recursionDepth = _recursionDepth ts1 + 42 , _curContext = _curContext ts1 + 43 , _spliceMap = _spliceMap ts1 + 44 }) + 45 46 - 47 - 48 ------------------------------------------------------------------------------ - 49 type TemplateMap = Map TPath Template - 50 - 51 - 52 ------------------------------------------------------------------------------ - 53 -- | Holds all the state information needed for template processing: - 54 -- - 55 -- * a collection of named templates. If you use the @\<apply - 56 -- template=\"foo\"\>@ tag to include another template by name, @\"foo\"@ - 57 -- is looked up in here. - 58 -- - 59 -- * the mapping from tag names to 'Splice's. - 60 -- - 61 -- * a flag to control whether we will recurse during splice processing. - 62 -- - 63 -- We'll illustrate the recursion flag with a small example template: - 64 -- - 65 -- > <foo> - 66 -- > <bar> - 67 -- > ... - 68 -- > </bar> - 69 -- > </foo> - 70 -- - 71 -- Assume that @\"foo\"@ is bound to a splice procedure. Running the @foo@ - 72 -- splice will result in a list of nodes @L@; if the recursion flag is on we - 73 -- will recursively scan @L@ for splices, otherwise @L@ will be included in the - 74 -- output verbatim. - 75 data TemplateState m = TemplateState { - 76 -- | A mapping of splice names to splice actions - 77 _spliceMap :: SpliceMap m - 78 -- | A mapping of template names to templates - 79 , _templateMap :: TemplateMap - 80 -- | A flag to control splice recursion - 81 , _recurse :: Bool - 82 , _curContext :: TPath - 83 , _recursionDepth :: Int - 84 , _onLoadHook :: Template -> IO Template - 85 , _preRunHook :: Template -> m Template - 86 , _postRunHook :: Template -> m Template - 87 } - 88 - 89 - 90 ------------------------------------------------------------------------------ - 91 instance Eq (TemplateState m) where - 92 a == b = (_recurse a == _recurse b) && - 93 (_templateMap a == _templateMap b) && - 94 (_curContext a == _curContext b) + 47 ------------------------------------------------------------------------------ + 48 -- | Mappends a doctype to the state. + 49 addDoctype :: Monad m => [ByteString] -> TemplateMonad m () + 50 addDoctype dt = do + 51 modifyTS (\s -> s { _doctypes = _doctypes s `mappend` dt }) + 52 + 53 + 54 ------------------------------------------------------------------------------ + 55 -- TemplateState functions + 56 ------------------------------------------------------------------------------ + 57 + 58 + 59 ------------------------------------------------------------------------------ + 60 -- | Adds an on-load hook to a `TemplateState`. + 61 addOnLoadHook :: (Monad m) => + 62 (Template -> IO Template) + 63 -> TemplateState m + 64 -> TemplateState m + 65 addOnLoadHook hook ts = ts { _onLoadHook = _onLoadHook ts >=> hook } + 66 + 67 + 68 ------------------------------------------------------------------------------ + 69 -- | Adds a pre-run hook to a `TemplateState`. + 70 addPreRunHook :: (Monad m) => + 71 (Template -> m Template) + 72 -> TemplateState m + 73 -> TemplateState m + 74 addPreRunHook hook ts = ts { _preRunHook = _preRunHook ts >=> hook } + 75 + 76 + 77 ------------------------------------------------------------------------------ + 78 -- | Adds a post-run hook to a `TemplateState`. + 79 addPostRunHook :: (Monad m) => + 80 (Template -> m Template) + 81 -> TemplateState m + 82 -> TemplateState m + 83 addPostRunHook hook ts = ts { _postRunHook = _postRunHook ts >=> hook } + 84 + 85 + 86 ------------------------------------------------------------------------------ + 87 -- | Bind a new splice declaration to a tag name within a 'TemplateState'. + 88 bindSplice :: Monad m => + 89 ByteString -- ^ tag name + 90 -> Splice m -- ^ splice action + 91 -> TemplateState m -- ^ source state + 92 -> TemplateState m + 93 bindSplice n v ts = ts {_spliceMap = Map.insert n v (_spliceMap ts)} + 94 95 - 96 - 97 ------------------------------------------------------------------------------ - 98 -- | 'TemplateMonad' is a monad transformer that gives you access to the 'Node' - 99 -- being processed (using the 'MonadReader' instance) as well as holding the - 100 -- 'TemplateState' that contains splice and template mappings (accessible - 101 -- using the 'MonadState' instance. - 102 newtype TemplateMonad m a = TemplateMonad (RWST Node () (TemplateState m) m a) - 103 deriving ( Monad - 104 , MonadIO - 105 , MonadCatchIO - 106 , MonadReader Node - 107 , MonadState (TemplateState m) ) - 108 - 109 - 110 ------------------------------------------------------------------------------ - 111 instance (Monad m) => Monoid (TemplateState m) where - 112 mempty = TemplateState Map.empty Map.empty True [] 0 - 113 return return return - 114 - 115 (TemplateState s1 t1 r1 _ d1 o1 b1 a1) `mappend` - 116 (TemplateState s2 t2 r2 c2 d2 o2 b2 a2) = - 117 TemplateState s t r c2 d (o1 >=> o2) (b1 >=> b2) (a1 >=> a2) - 118 where - 119 s = s1 `mappend` s2 - 120 t = t1 `mappend` t2 - 121 r = r1 && r2 - 122 d = max d1 d2 - 123 - 124 - 125 ------------------------------------------------------------------------------ - 126 instance MonadTrans TemplateMonad where - 127 lift = TemplateMonad . lift + 96 ------------------------------------------------------------------------------ + 97 -- | Convenience function for looking up a splice. + 98 lookupSplice :: Monad m => + 99 ByteString + 100 -> TemplateState m + 101 -> Maybe (Splice m) + 102 lookupSplice nm ts = Map.lookup nm $ _spliceMap ts + 103 + 104 + 105 ------------------------------------------------------------------------------ + 106 -- | Converts a path into an array of the elements in reverse order. If the + 107 -- path is absolute, we need to remove the leading slash so the split doesn't + 108 -- leave @\"\"@ as the last element of the TPath. + 109 -- + 110 -- FIXME @\"..\"@ currently doesn't work in paths, the solution is non-trivial + 111 splitPathWith :: Char -> ByteString -> TPath + 112 splitPathWith s p = if B.null p then [] else (reverse $ B.split s path) + 113 where + 114 path = if B.head p == s then B.tail p else p + 115 + 116 -- | Converts a path into an array of the elements in reverse order using the + 117 -- path separator of the local operating system. See 'splitPathWith' for more + 118 -- details. + 119 splitLocalPath :: ByteString -> TPath + 120 splitLocalPath = splitPathWith pathSeparator + 121 + 122 -- | Converts a path into an array of the elements in reverse order using a + 123 -- forward slash (/) as the path separator. See 'splitPathWith' for more + 124 -- details. + 125 splitTemplatePath :: ByteString -> TPath + 126 splitTemplatePath = splitPathWith '/' + 127 128 129 ------------------------------------------------------------------------------ - 130 instance (Typeable1 m, Typeable a) => Typeable (TemplateMonad m a) where - 131 typeOf _ = mkTyConApp tCon [mRep, aRep] - 132 where - 133 tCon = mkTyCon "TemplateMonad" - 134 maRep = typeOf (undefined :: m a) - 135 (mCon, [aRep]) = splitTyConApp maRep - 136 mRep = mkTyConApp mCon [] + 130 -- | Does a single template lookup without cascading up. + 131 singleLookup :: TemplateMap + 132 -> TPath + 133 -> ByteString + 134 -> Maybe (InternalTemplate, TPath) + 135 singleLookup tm path name = fmap (\a -> (a,path)) $ Map.lookup (name:path) tm + 136 137 - 138 - 139 ------------------------------------------------------------------------------ - 140 -- | A Splice is a TemplateMonad computation that returns [Node]. - 141 type Splice m = TemplateMonad m Template - 142 - 143 - 144 ------------------------------------------------------------------------------ - 145 -- | SpliceMap associates a name and a Splice. - 146 type SpliceMap m = Map ByteString (Splice m) - 147 - 148 - 149 ------------------------------------------------------------------------------ - 150 -- TemplateState functions + 138 ------------------------------------------------------------------------------ + 139 -- | Searches for a template by looking in the full path then backing up into each + 140 -- of the parent directories until the template is found. + 141 traversePath :: TemplateMap + 142 -> TPath + 143 -> ByteString + 144 -> Maybe (InternalTemplate, TPath) + 145 traversePath tm [] name = fmap (\a -> (a,[])) (Map.lookup [name] tm) + 146 traversePath tm path name = + 147 singleLookup tm path name `mplus` + 148 traversePath tm (tail path) name + 149 + 150 151 ------------------------------------------------------------------------------ - 152 - 153 - 154 ------------------------------------------------------------------------------ - 155 -- | Adds an on-load hook to a `TemplateState`. - 156 addOnLoadHook :: (Monad m) => - 157 (Template -> IO Template) - 158 -> TemplateState m - 159 -> TemplateState m - 160 addOnLoadHook hook ts = ts { _onLoadHook = _onLoadHook ts >=> hook } - 161 - 162 - 163 ------------------------------------------------------------------------------ - 164 -- | Adds a pre-run hook to a `TemplateState`. - 165 addPreRunHook :: (Monad m) => - 166 (Template -> m Template) - 167 -> TemplateState m - 168 -> TemplateState m - 169 addPreRunHook hook ts = ts { _preRunHook = _preRunHook ts >=> hook } - 170 - 171 - 172 ------------------------------------------------------------------------------ - 173 -- | Adds a post-run hook to a `TemplateState`. - 174 addPostRunHook :: (Monad m) => - 175 (Template -> m Template) - 176 -> TemplateState m - 177 -> TemplateState m - 178 addPostRunHook hook ts = ts { _postRunHook = _postRunHook ts >=> hook } - 179 - 180 - 181 ------------------------------------------------------------------------------ - 182 -- | Bind a new splice declaration to a tag name within a 'TemplateState'. - 183 bindSplice :: Monad m => - 184 ByteString -- ^ tag name - 185 -> Splice m -- ^ splice action - 186 -> TemplateState m -- ^ source state - 187 -> TemplateState m - 188 bindSplice n v ts = ts {_spliceMap = Map.insert n v (_spliceMap ts)} - 189 - 190 - 191 ------------------------------------------------------------------------------ - 192 -- | Convenience function for looking up a splice. - 193 lookupSplice :: Monad m => - 194 ByteString - 195 -> TemplateState m - 196 -> Maybe (Splice m) - 197 lookupSplice nm ts = Map.lookup nm $ _spliceMap ts - 198 - 199 - 200 ------------------------------------------------------------------------------ - 201 -- | Converts a path into an array of the elements in reverse order. If the - 202 -- path is absolute, we need to remove the leading slash so the split doesn't - 203 -- leave @\"\"@ as the last element of the TPath. + 152 -- | Convenience function for looking up a template. + 153 lookupTemplate :: Monad m => + 154 ByteString + 155 -> TemplateState m + 156 -> Maybe (InternalTemplate, TPath) + 157 lookupTemplate nameStr ts = + 158 f (_templateMap ts) path name + 159 where (name:p) = case splitTemplatePath nameStr of + 160 [] -> [""] + 161 ps -> ps + 162 path = p ++ (_curContext ts) + 163 f = if '/' `B.elem` nameStr + 164 then singleLookup + 165 else traversePath + 166 + 167 + 168 ------------------------------------------------------------------------------ + 169 -- | Sets the templateMap in a TemplateState. + 170 setTemplates :: Monad m => TemplateMap -> TemplateState m -> TemplateState m + 171 setTemplates m ts = ts { _templateMap = m } + 172 + 173 + 174 ------------------------------------------------------------------------------ + 175 -- | Adds a template to the template state. + 176 insertTemplate :: Monad m => + 177 TPath + 178 -> InternalTemplate + 179 -> TemplateState m + 180 -> TemplateState m + 181 insertTemplate p t st = + 182 setTemplates (Map.insert p t (_templateMap st)) st + 183 + 184 + 185 ------------------------------------------------------------------------------ + 186 -- | Adds a template to the template state. + 187 addTemplate :: Monad m => + 188 ByteString + 189 -> InternalTemplate + 190 -> TemplateState m + 191 -> TemplateState m + 192 addTemplate n t st = insertTemplate (splitTemplatePath n) t st + 193 + 194 + 195 ------------------------------------------------------------------------------ + 196 -- | Stops the recursive processing of splices. Consider the following + 197 -- example: + 198 -- + 199 -- > <foo> + 200 -- > <bar> + 201 -- > ... + 202 -- > </bar> + 203 -- > </foo> 204 -- - 205 -- FIXME @\"..\"@ currently doesn't work in paths, the solution is non-trivial - 206 splitPaths :: ByteString -> TPath - 207 splitPaths p = if B.null p then [] else (reverse $ B.split '/' path) - 208 where - 209 path = if B.head p == '/' then B.tail p else p - 210 + 205 -- Assume that @\"foo\"@ is bound to a splice procedure. Running the @foo@ + 206 -- splice will result in a list of nodes @L@. Normally @foo@ will recursively + 207 -- scan @L@ for splices and run them. If @foo@ calls @stopRecursion@, @L@ + 208 -- will be included in the output verbatim without running any splices. + 209 stopRecursion :: Monad m => TemplateMonad m () + 210 stopRecursion = modifyTS (\st -> st { _recurse = False }) 211 - 212 ------------------------------------------------------------------------------ - 213 -- | Does a single template lookup without cascading up. - 214 singleLookup :: TemplateMap - 215 -> TPath - 216 -> ByteString - 217 -> Maybe (Template, TPath) - 218 singleLookup tm path name = fmap (\a -> (a,path)) $ Map.lookup (name:path) tm - 219 - 220 - 221 ------------------------------------------------------------------------------ - 222 -- | Searches for a template by looking in the full path then backing up into each - 223 -- of the parent directories until the template is found. - 224 traversePath :: TemplateMap - 225 -> TPath - 226 -> ByteString - 227 -> Maybe (Template, TPath) - 228 traversePath tm [] name = fmap (\a -> (a,[])) (Map.lookup [name] tm) - 229 traversePath tm path name = - 230 singleLookup tm path name `mplus` - 231 traversePath tm (tail path) name - 232 - 233 - 234 ------------------------------------------------------------------------------ - 235 -- | Convenience function for looking up a template. - 236 lookupTemplate :: Monad m => - 237 ByteString - 238 -> TemplateState m - 239 -> Maybe (Template, TPath) - 240 lookupTemplate nameStr ts = - 241 f (_templateMap ts) path name - 242 where (name:p) = case splitPaths nameStr of - 243 [] -> [""] - 244 ps -> ps - 245 path = p ++ (_curContext ts) - 246 f = if '/' `B.elem` nameStr - 247 then singleLookup - 248 else traversePath - 249 - 250 - 251 ------------------------------------------------------------------------------ - 252 -- | Sets the templateMap in a TemplateState. - 253 setTemplates :: Monad m => TemplateMap -> TemplateState m -> TemplateState m - 254 setTemplates m ts = ts { _templateMap = m } - 255 - 256 - 257 ------------------------------------------------------------------------------ - 258 -- | Adds a template to the template state. - 259 insertTemplate :: Monad m => - 260 TPath - 261 -> Template - 262 -> TemplateState m - 263 -> TemplateState m - 264 insertTemplate p t st = - 265 setTemplates (Map.insert p t (_templateMap st)) st - 266 - 267 - 268 ------------------------------------------------------------------------------ - 269 -- | Adds a template to the template state. - 270 addTemplate :: Monad m => - 271 ByteString - 272 -> Template - 273 -> TemplateState m - 274 -> TemplateState m - 275 addTemplate n t st = insertTemplate (splitPaths n) t st - 276 - 277 - 278 ------------------------------------------------------------------------------ - 279 -- | Gets the node currently being processed. - 280 getParamNode :: Monad m => TemplateMonad m Node - 281 getParamNode = ask - 282 + 212 + 213 ------------------------------------------------------------------------------ + 214 -- | Sets the current context + 215 setContext :: Monad m => TPath -> TemplateMonad m () + 216 setContext c = modifyTS (\st -> st { _curContext = c }) + 217 + 218 + 219 ------------------------------------------------------------------------------ + 220 -- | Gets the current context + 221 getContext :: Monad m => TemplateMonad m TPath + 222 getContext = getsTS _curContext + 223 + 224 + 225 ------------------------------------------------------------------------------ + 226 -- | Performs splice processing on a single node. + 227 runNode :: Monad m => Node -> Splice m + 228 runNode n@(X.Text _) = return [n] + 229 runNode n@(X.Element nm at ch) = do + 230 s <- liftM (lookupSplice nm) getTS + 231 maybe runChildren (recurseSplice n) s + 232 + 233 where + 234 runChildren = do + 235 newKids <- runNodeList ch + 236 newAtts <- mapM attSubst at + 237 return [X.Element nm newAtts newKids] + 238 + 239 + 240 ------------------------------------------------------------------------------ + 241 -- | Helper function for substituting a parsed attribute into an attribute + 242 -- tuple. + 243 attSubst :: (Monad m) => (t, ByteString) -> TemplateMonad m (t, ByteString) + 244 attSubst (n,v) = do + 245 v' <- parseAtt v + 246 return (n,v') + 247 + 248 + 249 ------------------------------------------------------------------------------ + 250 -- | Parses an attribute for any identifier expressions and performs + 251 -- appropriate substitution. + 252 parseAtt :: (Monad m) => ByteString -> TemplateMonad m ByteString + 253 parseAtt bs = do + 254 let ast = case AP.feed (AP.parse attParser bs) "" of + 255 (AP.Fail _ _ _) -> [] + 256 (AP.Done _ res) -> res + 257 (AP.Partial _) -> [] + 258 chunks <- mapM cvt ast + 259 return $ B.concat chunks + 260 where + 261 cvt (Literal x) = return x + 262 cvt (Ident x) = getAttributeSplice x + 263 + 264 + 265 ------------------------------------------------------------------------------ + 266 -- | AST to hold attribute parsing structure. This is necessary because + 267 -- attoparsec doesn't support parsers running in another monad. + 268 data AttAST = Literal ByteString | + 269 Ident ByteString + 270 deriving (Show) + 271 + 272 + 273 ------------------------------------------------------------------------------ + 274 -- | Parser for attribute variable substitution. + 275 attParser :: AP.Parser [AttAST] + 276 attParser = AP.many1 (identParser <|> litParser) + 277 where + 278 escChar = (AP.char '\\' *> AP.anyChar) <|> + 279 AP.satisfy (AP.notInClass "\\$") + 280 litParser = Literal <$> (B.pack <$> AP.many1 escChar) + 281 identParser = AP.string "$(" *> + 282 (Ident <$> AP.takeWhile (/=')')) <* AP.string ")" 283 - 284 ------------------------------------------------------------------------------ - 285 -- | Stops the recursive processing of splices. - 286 stopRecursion :: Monad m => TemplateMonad m () - 287 stopRecursion = modify (\st -> st { _recurse = False }) - 288 - 289 - 290 ------------------------------------------------------------------------------ - 291 -- | Sets the current context - 292 setContext :: Monad m => TPath -> TemplateMonad m () - 293 setContext c = modify (\st -> st { _curContext = c }) - 294 - 295 - 296 ------------------------------------------------------------------------------ - 297 -- | Gets the current context - 298 getContext :: Monad m => TemplateMonad m TPath - 299 getContext = gets _curContext - 300 - 301 - 302 ------------------------------------------------------------------------------ - 303 -- | Performs splice processing on a list of nodes. - 304 runNodeList :: Monad m => [Node] -> Splice m - 305 runNodeList nodes = liftM concat $ sequence (map runNode nodes) - 306 - 307 - 308 ------------------------------------------------------------------------------ - 309 -- | Performs splice processing on a single node. - 310 runNode :: Monad m => Node -> Splice m - 311 runNode n@(X.Text _) = return [n] - 312 runNode n@(X.Element nm _ ch) = do - 313 s <- liftM (lookupSplice nm) get - 314 maybe runChildren (recurseSplice n) s - 315 - 316 where - 317 runChildren = do - 318 newKids <- runNodeList ch - 319 return [X.modifyChildren (const newKids) n] - 320 - 321 - 322 ------------------------------------------------------------------------------ - 323 -- | The maximum recursion depth. (Used to prevent infinite loops.) - 324 mAX_RECURSION_DEPTH :: Int - 325 mAX_RECURSION_DEPTH = 20 - 326 + 284 + 285 ------------------------------------------------------------------------------ + 286 -- | Get's the attribute value. This is just a normal splice lookup with the + 287 -- added restriction that the splice's result list has to contain a single + 288 -- text element. Otherwise the attribute evaluates to the empty string. + 289 getAttributeSplice :: Monad m => ByteString -> TemplateMonad m ByteString + 290 getAttributeSplice name = do + 291 s <- liftM (lookupSplice name) getTS + 292 nodes <- maybe (return []) id s + 293 return $ check nodes + 294 where + 295 check ((X.Text t):_) = t + 296 check _ = "" + 297 + 298 ------------------------------------------------------------------------------ + 299 -- | Performs splice processing on a list of nodes. + 300 runNodeList :: Monad m => [Node] -> Splice m + 301 runNodeList nodes = liftM concat $ sequence (map runNode nodes) + 302 + 303 + 304 ------------------------------------------------------------------------------ + 305 -- | The maximum recursion depth. (Used to prevent infinite loops.) + 306 mAX_RECURSION_DEPTH :: Int + 307 mAX_RECURSION_DEPTH = 50 + 308 + 309 + 310 ------------------------------------------------------------------------------ + 311 -- | Checks the recursion flag and recurses accordingly. Does not recurse + 312 -- deeper than mAX_RECURSION_DEPTH to avoid infinite loops. + 313 recurseSplice :: Monad m => Node -> Splice m -> Splice m + 314 recurseSplice node splice = do + 315 result <- localParamNode (const node) splice + 316 ts' <- getTS + 317 if _recurse ts' && _recursionDepth ts' < mAX_RECURSION_DEPTH + 318 then do modRecursionDepth (+1) + 319 res <- runNodeList result + 320 restoreState ts' + 321 return res + 322 else return result + 323 where + 324 modRecursionDepth :: Monad m => (Int -> Int) -> TemplateMonad m () + 325 modRecursionDepth f = + 326 modifyTS (\st -> st { _recursionDepth = f (_recursionDepth st) }) 327 - 328 ------------------------------------------------------------------------------ - 329 -- | Checks the recursion flag and recurses accordingly. Does not recurse - 330 -- deeper than mAX_RECURSION_DEPTH to avoid infinite loops. - 331 recurseSplice :: Monad m => Node -> Splice m -> Splice m - 332 recurseSplice node splice = do - 333 result <- local (const node) splice - 334 ts' <- get - 335 if _recurse ts' && _recursionDepth ts' < mAX_RECURSION_DEPTH - 336 then do modify (\st -> st { _recursionDepth = _recursionDepth st + 1 }) - 337 res <- runNodeList result - 338 put ts' - 339 return res - 340 else return result - 341 - 342 - 343 ------------------------------------------------------------------------------ - 344 -- | Runs a splice in the underlying monad. Splices require two - 345 -- parameters, the template state, and an input node. - 346 runSplice :: Monad m => - 347 TemplateState m -- ^ The initial template state - 348 -> Node -- ^ The splice's input node - 349 -> Splice m -- ^ The splice - 350 -> m [Node] - 351 runSplice ts node (TemplateMonad splice) = do - 352 (result,_,_) <- runRWST splice node ts - 353 return result + 328 + 329 ------------------------------------------------------------------------------ + 330 -- | Looks up a template name runs a TemplateMonad computation on it. + 331 lookupAndRun :: Monad m + 332 => ByteString + 333 -> ((InternalTemplate, TPath) -> TemplateMonad m (Maybe a)) + 334 -> TemplateMonad m (Maybe a) + 335 lookupAndRun name k = do + 336 ts <- getTS + 337 maybe (return Nothing) k + 338 (lookupTemplate name ts) + 339 + 340 + 341 ------------------------------------------------------------------------------ + 342 -- | Looks up a template name evaluates it by calling runNodeList. + 343 evalTemplate :: Monad m + 344 => ByteString + 345 -> TemplateMonad m (Maybe Template) + 346 evalTemplate name = lookupAndRun name + 347 (\(t,ctx) -> do + 348 ts <- getTS + 349 putTS (ts {_curContext = ctx}) + 350 res <- runNodeList $ _itNodes t + 351 restoreState ts + 352 return $ Just res) + 353 354 - 355 - 356 ------------------------------------------------------------------------------ - 357 -- | Runs a template in the underlying monad. Similar to runSplice - 358 -- except that templates don't require a Node as a parameter. - 359 runRawTemplate :: Monad m => TemplateState m -> Template -> m [Node] - 360 runRawTemplate ts template = - 361 _preRunHook ts template >>= - 362 runSplice ts (X.Text "") . runNodeList >>= - 363 _postRunHook ts - 364 - 365 - 366 ------------------------------------------------------------------------------ - 367 -- | Looks up a template name in the supplied 'TemplateState' and runs - 368 -- it in the underlying monad. - 369 runTemplate :: Monad m - 370 => TemplateState m - 371 -> ByteString - 372 -> m (Maybe [Node]) - 373 runTemplate ts name = - 374 maybe (return Nothing) - 375 (\(t,ctx) -> - 376 return . Just =<< - 377 runRawTemplate (ts {_curContext = ctx}) t) - 378 (lookupTemplate name ts) - 379 - 380 - 381 ------------------------------------------------------------------------------ - 382 -- | Looks up a template name evaluates it. Same as runTemplate except it - 383 -- runs in TemplateMonad instead of m. - 384 evalTemplate :: Monad m - 385 => ByteString - 386 -> TemplateMonad m (Maybe [Node]) - 387 evalTemplate name = do - 388 ts <- get - 389 lift $ runTemplate ts name - 390 - 391 - 392 ------------------------------------------------------------------------------ - 393 -- | Binds a list of constant string splices - 394 bindStrings :: Monad m - 395 => [(ByteString, ByteString)] - 396 -> TemplateState m - 397 -> TemplateState m - 398 bindStrings pairs ts = foldr add ts pairs - 399 where - 400 add (n,v) = bindSplice n (return [X.Text v]) - 401 - 402 - 403 ------------------------------------------------------------------------------ - 404 -- | Renders a template with the specified parameters. This is the function - 405 -- to use when you want to "call" a template and pass in parameters from code. - 406 callTemplate :: Monad m - 407 => ByteString -- ^ The name of the template - 408 -> [(ByteString, ByteString)] -- ^ Association list of - 409 -- (name,value) parameter pairs - 410 -> TemplateMonad m (Maybe Template) - 411 callTemplate name params = do - 412 modify $ bindStrings params - 413 evalTemplate name - 414 + 355 ------------------------------------------------------------------------------ + 356 -- | Looks up a template name evaluates it by calling runNodeList. This also + 357 -- executes pre- and post-run hooks and adds the doctype. + 358 evalWithHooks :: Monad m + 359 => ByteString + 360 -> TemplateMonad m (Maybe Template) + 361 evalWithHooks name = lookupAndRun name + 362 (\(t,ctx) -> do + 363 addDoctype $ maybeToList $ _itDoctype t + 364 ts <- getTS + 365 nodes <- lift $ _preRunHook ts $ _itNodes t + 366 putTS (ts {_curContext = ctx}) + 367 res <- runNodeList nodes + 368 restoreState ts + 369 return . Just =<< lift (_postRunHook ts res)) + 370 + 371 + 372 ------------------------------------------------------------------------------ + 373 -- | Binds a list of constant string splices + 374 bindStrings :: Monad m + 375 => [(ByteString, ByteString)] + 376 -> TemplateState m + 377 -> TemplateState m + 378 bindStrings pairs ts = foldr add ts pairs + 379 where + 380 add (n,v) = bindSplice n (return [X.Text v]) + 381 + 382 + 383 ------------------------------------------------------------------------------ + 384 -- | Renders a template with the specified parameters. This is the function + 385 -- to use when you want to "call" a template and pass in parameters from code. + 386 callTemplate :: Monad m + 387 => ByteString -- ^ The name of the template + 388 -> [(ByteString, ByteString)] -- ^ Association list of + 389 -- (name,value) parameter pairs + 390 -> TemplateMonad m (Maybe Template) + 391 callTemplate name params = do + 392 modifyTS $ bindStrings params + 393 evalTemplate name + 394 + 395 + 396 ------------------------------------------------------------------------------ + 397 -- | Converts a Template to an InternalTemplate. This can only be done inside + 398 -- TemplateMonad where the doctype is available. + 399 toInternalTemplate :: Monad m => Template -> TemplateMonad m InternalTemplate + 400 toInternalTemplate t = do + 401 dts <- getsTS _doctypes + 402 return $ InternalTemplate { + 403 _itDoctype = listToMaybe dts, + 404 _itNodes = t + 405 } + 406 + 407 + 408 ------------------------------------------------------------------------------ + 409 -- | Renders an internal template by prepending the appropriate doctype. + 410 renderInternal :: Monad m => InternalTemplate -> TemplateMonad m ByteString + 411 renderInternal (InternalTemplate dt nodes) = + 412 return $ maybe bs (flip B.append bs) dt + 413 where + 414 bs = formatList' nodes 415 - 416 ------------------------------------------------------------------------------ - 417 -- | Renders a template from the specified TemplateState. - 418 renderTemplate :: Monad m - 419 => TemplateState m - 420 -> ByteString - 421 -> m (Maybe ByteString) - 422 renderTemplate ts name = do - 423 ns <- runTemplate ts name - 424 return $ (Just . formatList') =<< ns - 425 - 426 - 427 ------------------------------------------------------------------------------ - 428 heistExpatOptions :: X.ParserOptions ByteString ByteString - 429 heistExpatOptions = - 430 X.defaultParserOptions { - 431 X.parserEncoding = Just X.UTF8 - 432 , X.entityDecoder = Just (\k -> Map.lookup k htmlEntityLookupTable) - 433 } + 416 + 417 ------------------------------------------------------------------------------ + 418 -- | Renders a template from the specified TemplateState. + 419 renderTemplate :: Monad m + 420 => TemplateState m + 421 -> ByteString + 422 -> m (Maybe ByteString) + 423 renderTemplate ts name = do + 424 evalTemplateMonad + 425 (do mt <- evalWithHooks name + 426 maybe (return Nothing) + 427 (\t -> liftM Just $ renderInternal =<< toInternalTemplate t) + 428 mt + 429 ) (X.Text "") ts + 430 + 431 ------------------------------------------------------------------------------ + 432 -- Template loading + 433 ------------------------------------------------------------------------------ 434 - 435 ------------------------------------------------------------------------------ - 436 -- Template loading - 437 ------------------------------------------------------------------------------ - 438 - 439 -- | Reads an XML document from disk. - 440 getDoc :: String -> IO (Either String Template) - 441 getDoc f = do - 442 bs <- catch (liftM Right $ B.readFile f) - 443 (\(e::SomeException) -> return $ Left $ show e) - 444 let wrap b = "<snap:root>\n" `B.append` b `B.append` "\n</snap:root>" - 445 return $ (mapRight X.getChildren . - 446 mapLeft genErrorMsg . - 447 X.parse' heistExpatOptions . wrap) =<< bs - 448 where - 449 genErrorMsg (X.XMLParseError str loc) = f ++ " " ++ locMsg loc ++ ": " ++ translate str - 450 locMsg (X.XMLParseLocation line col _ _) = - 451 "(line " ++ show (line-1) ++ ", col " ++ show col ++ ")" - 452 translate "junk after document element" = "document must have a single root element" - 453 translate s = s - 454 - 455 ------------------------------------------------------------------------------ - 456 mapLeft :: (a -> b) -> Either a c -> Either b c - 457 mapLeft g = either (Left . g) Right - 458 mapRight :: (b -> c) -> Either a b -> Either a c - 459 mapRight g = either Left (Right . g) - 460 - 461 - 462 ------------------------------------------------------------------------------ - 463 -- | Loads a template with the specified path and filename. The - 464 -- template is only loaded if it has a ".tpl" extension. - 465 loadTemplate :: String -- ^ path of the template root - 466 -> String -- ^ full file path (includes the template root) - 467 -> IO [Either String (TPath, Template)] --TemplateMap - 468 loadTemplate templateRoot fname - 469 | ".tpl" `isSuffixOf` fname = do - 470 c <- getDoc fname - 471 return [fmap (\t -> (splitPaths $ B.pack tName, t)) c] - 472 | otherwise = return [] - 473 where -- tName is path relative to the template root directory - 474 tName = drop ((length templateRoot)+1) $ - 475 -- We're only dropping the template root, not the whole path - 476 take ((length fname) - 4) fname - 477 - 478 - 479 ------------------------------------------------------------------------------ - 480 -- | Traverses the specified directory structure and builds a - 481 -- TemplateState by loading all the files with a ".tpl" extension. - 482 loadTemplates :: Monad m => FilePath -> TemplateState m -> IO (Either String (TemplateState m)) - 483 loadTemplates dir ts = do - 484 d <- readDirectoryWith (loadTemplate dir) dir - 485 let tlist = F.fold (free d) - 486 errs = lefts tlist - 487 case errs of - 488 [] -> liftM Right $ foldM loadHook ts $ rights tlist - 489 _ -> return $ Left $ unlines errs - 490 - 491 - 492 ------------------------------------------------------------------------------ - 493 -- | Runs the onLoad hook on the template and returns the `TemplateState` - 494 -- with the result inserted. - 495 loadHook :: Monad m => TemplateState m -> (TPath, Template) -> IO (TemplateState m) - 496 loadHook ts (tp, t) = do - 497 t' <- _onLoadHook ts t - 498 return $ insertTemplate tp t' ts + 435 -- | Reads an XML document from disk. + 436 getDoc :: String -> IO (Either String InternalTemplate) + 437 getDoc f = do + 438 bs <- catch (liftM Right $ B.readFile f) + 439 (\(e::SomeException) -> return $ Left $ show e) + 440 return $ do + 441 (doctype, rest) <- liftM extractDoctype bs + 442 let wrap b = "<snap:root>\n" `B.append` b `B.append` "\n</snap:root>" + 443 toTemplate t = InternalTemplate { + 444 _itDoctype = doctype, + 445 _itNodes = t + 446 } + 447 mapRight (toTemplate . X.getChildren) . + 448 mapLeft genErrorMsg . + 449 X.parse' heistExpatOptions . wrap $ rest + 450 where + 451 genErrorMsg (X.XMLParseError str loc) = f ++ " " ++ locMsg loc ++ ": " ++ translate str + 452 locMsg (X.XMLParseLocation line col _ _) = + 453 "(line " ++ show (line-1) ++ ", col " ++ show col ++ ")" + 454 translate "junk after document element" = "document must have a single root element" + 455 translate s = s + 456 + 457 + 458 ------------------------------------------------------------------------------ + 459 -- | Checks whether the bytestring has a doctype. + 460 hasDoctype :: ByteString -> Bool + 461 hasDoctype bs = "<!DOCTYPE" `B.isPrefixOf` bs + 462 + 463 + 464 ------------------------------------------------------------------------------ + 465 -- | Converts a ByteString into a tuple containing a possible doctype + 466 -- ByteString and the rest of the document. + 467 extractDoctype :: ByteString -> (Maybe ByteString, ByteString) + 468 extractDoctype bs = + 469 if hasDoctype bs + 470 then (Just $ B.snoc (B.takeWhile p bs) '>', B.tail $ B.dropWhile p bs) + 471 else (Nothing, bs) + 472 where + 473 p = (/='>') + 474 + 475 ------------------------------------------------------------------------------ + 476 mapLeft :: (a -> b) -> Either a c -> Either b c + 477 mapLeft g = either (Left . g) Right + 478 mapRight :: (b -> c) -> Either a b -> Either a c + 479 mapRight g = either Left (Right . g) + 480 + 481 + 482 ------------------------------------------------------------------------------ + 483 -- | Loads a template with the specified path and filename. The + 484 -- template is only loaded if it has a ".tpl" extension. + 485 loadTemplate :: String -- ^ path of the template root + 486 -> String -- ^ full file path (includes the template root) + 487 -> IO [Either String (TPath, InternalTemplate)] --TemplateMap + 488 loadTemplate templateRoot fname + 489 | ".tpl" `isSuffixOf` fname = do + 490 c <- getDoc fname + 491 return [fmap (\t -> (splitLocalPath $ B.pack tName, t)) c] + 492 | otherwise = return [] + 493 where -- tName is path relative to the template root directory + 494 correction = if last templateRoot == '/' then 0 else 1 + 495 tName = drop ((length templateRoot)+correction) $ + 496 -- We're only dropping the template root, not the whole path + 497 take ((length fname) - 4) fname + 498 499 - 500 - 501 ------------------------------------------------------------------------------ - 502 -- These are here until we can get them into hexpat. - 503 ------------------------------------------------------------------------------ - 504 - 505 formatList :: (X.GenericXMLString tag, X.GenericXMLString text) => - 506 [X.Node tag text] - 507 -> L.ByteString - 508 formatList nodes = foldl L.append L.empty $ map formatNode nodes - 509 - 510 formatList' :: (X.GenericXMLString tag, X.GenericXMLString text) => - 511 [X.Node tag text] - 512 -> B.ByteString - 513 formatList' = B.concat . L.toChunks . formatList - 514 + 500 ------------------------------------------------------------------------------ + 501 -- | Traverses the specified directory structure and builds a + 502 -- TemplateState by loading all the files with a ".tpl" extension. + 503 loadTemplates :: Monad m => FilePath -> TemplateState m -> IO (Either String (TemplateState m)) + 504 loadTemplates dir ts = do + 505 d <- readDirectoryWith (loadTemplate dir) dir + 506 let tlist = F.fold (free d) + 507 errs = lefts tlist + 508 case errs of + 509 [] -> liftM Right $ foldM loadHook ts $ rights tlist + 510 _ -> return $ Left $ unlines errs + 511 + 512 + 513 ------------------------------------------------------------------------------ + 514 -- | Reversed list of directories. This holds the path to the template + 515 runHookInternal :: Monad m => (Template -> m Template) + 516 -> InternalTemplate + 517 -> m InternalTemplate + 518 runHookInternal f t = do + 519 n <- f $ _itNodes t + 520 return $ t { _itNodes = n } + 521 + 522 + 523 ------------------------------------------------------------------------------ + 524 -- | Runs the onLoad hook on the template and returns the `TemplateState` + 525 -- with the result inserted. + 526 loadHook :: Monad m => TemplateState m -> (TPath, InternalTemplate) -> IO (TemplateState m) + 527 loadHook ts (tp, t) = do + 528 t' <- runHookInternal (_onLoadHook ts) t + 529 return $ insertTemplate tp t' ts + 530 + 531 + 532 ------------------------------------------------------------------------------ + 533 -- These are here until we can get them into hexpat. + 534 ------------------------------------------------------------------------------ + 535 + 536 formatList :: (X.GenericXMLString tag, X.GenericXMLString text) => + 537 [X.Node tag text] + 538 -> L.ByteString + 539 formatList nodes = foldl L.append L.empty $ map formatNode nodes + 540 + 541 formatList' :: (X.GenericXMLString tag, X.GenericXMLString text) => + 542 [X.Node tag text] + 543 -> B.ByteString + 544 formatList' = B.concat . L.toChunks . formatList + 545 diff --git a/static/docs/heist-hpc/Text.Templating.Heist.Splices.Apply.hs.html b/static/docs/heist-hpc/Text.Templating.Heist.Splices.Apply.hs.html index bfe3909..6336bab 100644 --- a/static/docs/heist-hpc/Text.Templating.Heist.Splices.Apply.hs.html +++ b/static/docs/heist-hpc/Text.Templating.Heist.Splices.Apply.hs.html @@ -17,45 +17,49 @@ 6 import Control.Monad.RWS.Strict 7 import Data.ByteString.Char8 (ByteString) 8 import qualified Data.ByteString.Char8 as B - 9 import qualified Text.XML.Expat.Tree as X - 10 - 11 ------------------------------------------------------------------------------ - 12 import Text.Templating.Heist.Internal - 13 - 14 ------------------------------------------------------------------------------ - 15 -- | Default name for the apply splice. - 16 applyTag :: ByteString - 17 applyTag = "apply" - 18 - 19 - 20 ------------------------------------------------------------------------------ - 21 -- | Default attribute name for the apply tag. - 22 applyAttr :: ByteString - 23 applyAttr = "template" - 24 - 25 - 26 ------------------------------------------------------------------------------ - 27 -- | Implementation of the apply splice. - 28 applyImpl :: Monad m => Splice m - 29 applyImpl = do - 30 node <- getParamNode - 31 case X.getAttribute node applyAttr of - 32 Nothing -> return [] -- TODO: error handling - 33 Just attr -> do - 34 st <- get - 35 processedChildren <- runNodeList $ X.getChildren node - 36 modify (bindSplice "content" $ return processedChildren) - 37 maybe (return []) -- TODO: error handling - 38 (\(t,ctx) -> do setContext ctx - 39 result <- runNodeList t - 40 put st - 41 return result) - 42 (lookupTemplate attr (st {_curContext = nextCtx attr st})) - 43 where nextCtx name st - 44 | B.isPrefixOf "/" name = [] - 45 | otherwise = _curContext st - 46 - 47 + 9 import Data.Maybe + 10 import qualified Text.XML.Expat.Tree as X + 11 + 12 ------------------------------------------------------------------------------ + 13 import Text.Templating.Heist.Internal + 14 import Text.Templating.Heist.Types + 15 + 16 ------------------------------------------------------------------------------ + 17 -- | Default name for the apply splice. + 18 applyTag :: ByteString + 19 applyTag = "apply" + 20 + 21 + 22 ------------------------------------------------------------------------------ + 23 -- | Default attribute name for the apply tag. + 24 applyAttr :: ByteString + 25 applyAttr = "template" + 26 + 27 + 28 ------------------------------------------------------------------------------ + 29 -- | Implementation of the apply splice. + 30 applyImpl :: Monad m => Splice m + 31 applyImpl = do + 32 node <- getParamNode + 33 case X.getAttribute node applyAttr of + 34 Nothing -> return [] -- TODO: error handling + 35 Just attr -> do + 36 st <- getTS + 37 maybe (return []) -- TODO: error handling + 38 (\(t,ctx) -> do + 39 addDoctype $ maybeToList $ _itDoctype t + 40 processedChildren <- runNodeList $ X.getChildren node + 41 modifyTS (bindSplice "content" $ return processedChildren) + 42 setContext ctx + 43 result <- runNodeList $ _itNodes t + 44 restoreState st + 45 return result) + 46 (lookupTemplate attr (st {_curContext = nextCtx attr st})) + 47 where nextCtx name st + 48 | B.isPrefixOf "/" name = [] + 49 | otherwise = _curContext st + 50 + 51 diff --git a/static/docs/heist-hpc/Text.Templating.Heist.Splices.Bind.hs.html b/static/docs/heist-hpc/Text.Templating.Heist.Splices.Bind.hs.html index 43c6bf5..131d3b7 100644 --- a/static/docs/heist-hpc/Text.Templating.Heist.Splices.Bind.hs.html +++ b/static/docs/heist-hpc/Text.Templating.Heist.Splices.Bind.hs.html @@ -20,32 +20,33 @@ 9 10 ------------------------------------------------------------------------------ 11 import Text.Templating.Heist.Internal - 12 - 13 -- | Default name for the bind splice. - 14 bindTag :: ByteString - 15 bindTag = "bind" - 16 + 12 import Text.Templating.Heist.Types + 13 + 14 -- | Default name for the bind splice. + 15 bindTag :: ByteString + 16 bindTag = "bind" 17 - 18 ------------------------------------------------------------------------------ - 19 -- | Default attribute name for the bind tag. - 20 bindAttr :: ByteString - 21 bindAttr = "tag" - 22 + 18 + 19 ------------------------------------------------------------------------------ + 20 -- | Default attribute name for the bind tag. + 21 bindAttr :: ByteString + 22 bindAttr = "tag" 23 - 24 ------------------------------------------------------------------------------ - 25 -- | Implementation of the bind splice. - 26 bindImpl :: Monad m => Splice m - 27 bindImpl = do - 28 node <- getParamNode - 29 maybe (return ()) - 30 (add node) - 31 (X.getAttribute node bindAttr) - 32 return [] - 33 - 34 where - 35 add node nm = modify $ bindSplice nm (return $ X.getChildren node) - 36 + 24 + 25 ------------------------------------------------------------------------------ + 26 -- | Implementation of the bind splice. + 27 bindImpl :: Monad m => Splice m + 28 bindImpl = do + 29 node <- getParamNode + 30 maybe (return ()) + 31 (add node) + 32 (X.getAttribute node bindAttr) + 33 return [] + 34 + 35 where + 36 add node nm = modifyTS $ bindSplice nm (return $ X.getChildren node) 37 + 38 diff --git a/static/docs/heist-hpc/Text.Templating.Heist.Splices.Ignore.hs.html b/static/docs/heist-hpc/Text.Templating.Heist.Splices.Ignore.hs.html index 87582cf..86fc17d 100644 --- a/static/docs/heist-hpc/Text.Templating.Heist.Splices.Ignore.hs.html +++ b/static/docs/heist-hpc/Text.Templating.Heist.Splices.Ignore.hs.html @@ -17,7 +17,7 @@ 6 import Data.ByteString.Char8 (ByteString) 7 8 ------------------------------------------------------------------------------ - 9 import Text.Templating.Heist.Internal + 9 import Text.Templating.Heist.Types 10 11 12 ------------------------------------------------------------------------------ diff --git a/static/docs/heist-hpc/Text.Templating.Heist.Splices.Markdown.hs.html b/static/docs/heist-hpc/Text.Templating.Heist.Splices.Markdown.hs.html index ffc1d04..6090300 100644 --- a/static/docs/heist-hpc/Text.Templating.Heist.Splices.Markdown.hs.html +++ b/static/docs/heist-hpc/Text.Templating.Heist.Splices.Markdown.hs.html @@ -13,152 +13,155 @@ 2 3 module Text.Templating.Heist.Splices.Markdown where 4 - 5 import Data.ByteString (ByteString) - 6 import qualified Data.ByteString as B - 7 import qualified Data.ByteString.Char8 as BC - 8 import Data.Maybe - 9 import Control.Concurrent - 10 import Control.Exception (throwIO) - 11 import Control.Monad - 12 import Control.Monad.CatchIO - 13 import Control.Monad.Trans - 14 import Data.Typeable - 15 import Prelude hiding (catch) - 16 import System.Directory - 17 import System.Exit - 18 import System.IO - 19 import System.Process - 20 import Text.Templating.Heist.Internal + 5 ------------------------------------------------------------------------------ + 6 import Data.ByteString (ByteString) + 7 import qualified Data.ByteString as B + 8 import qualified Data.ByteString.Char8 as BC + 9 import Data.Maybe + 10 import Control.Concurrent + 11 import Control.Exception (throwIO) + 12 import Control.Monad + 13 import Control.Monad.CatchIO + 14 import Control.Monad.Trans + 15 import Data.Typeable + 16 import Prelude hiding (catch) + 17 import System.Directory + 18 import System.Exit + 19 import System.IO + 20 import System.Process 21 import Text.XML.Expat.Tree hiding (Node) 22 - 23 - 24 data PandocMissingException = PandocMissingException - 25 deriving (Typeable) + 23 ------------------------------------------------------------------------------ + 24 import Text.Templating.Heist.Constants + 25 import Text.Templating.Heist.Types 26 - 27 instance Show PandocMissingException where - 28 show PandocMissingException = - 29 "Cannot find the \"pandoc\" executable; is it on your $PATH?" - 30 - 31 instance Exception PandocMissingException - 32 + 27 data PandocMissingException = PandocMissingException + 28 deriving (Typeable) + 29 + 30 instance Show PandocMissingException where + 31 show PandocMissingException = + 32 "Cannot find the \"pandoc\" executable; is it on your $PATH?" 33 - 34 data MarkdownException = MarkdownException ByteString - 35 deriving (Typeable) + 34 instance Exception PandocMissingException + 35 36 - 37 instance Show MarkdownException where - 38 show (MarkdownException e) = - 39 "Markdown error: pandoc replied:\n\n" ++ BC.unpack e - 40 - 41 instance Exception MarkdownException - 42 + 37 data MarkdownException = MarkdownException ByteString + 38 deriving (Typeable) + 39 + 40 instance Show MarkdownException where + 41 show (MarkdownException e) = + 42 "Markdown error: pandoc replied:\n\n" ++ BC.unpack e 43 - 44 ------------------------------------------------------------------------------ - 45 -- | Default name for the markdown splice. - 46 markdownTag :: ByteString - 47 markdownTag = "markdown" - 48 - 49 ------------------------------------------------------------------------------ - 50 -- | Implementation of the markdown splice. - 51 markdownSplice :: MonadIO m => Splice m - 52 markdownSplice = do - 53 pdMD <- liftIO $ findExecutable "pandoc" - 54 - 55 when (isNothing pdMD) $ liftIO $ throwIO PandocMissingException - 56 - 57 tree <- getParamNode - 58 markup <- liftIO $ - 59 case getAttribute tree "file" of - 60 Just f -> pandoc (fromJust pdMD) $ BC.unpack f - 61 Nothing -> pandocBS (fromJust pdMD) $ textContent tree - 62 - 63 let ee = parse' heistExpatOptions markup - 64 case ee of - 65 (Left e) -> throw $ MarkdownException - 66 $ BC.pack ("Error parsing markdown output: " ++ show e) - 67 (Right n) -> return [n] - 68 - 69 - 70 pandoc :: FilePath -> FilePath -> IO ByteString - 71 pandoc pandocPath inputFile = do - 72 (ex, sout, serr) <- readProcessWithExitCode' pandocPath args "" - 73 - 74 when (isFail ex) $ throw $ MarkdownException serr - 75 return $ BC.concat [ "<div class=\"markdown\">\n" - 76 , sout - 77 , "\n</div>" ] - 78 - 79 where - 80 isFail ExitSuccess = False - 81 isFail _ = True - 82 - 83 -- FIXME: hardcoded path - 84 args = [ "-S", "--no-wrap", "templates/"++inputFile ] - 85 - 86 - 87 pandocBS :: FilePath -> ByteString -> IO ByteString - 88 pandocBS pandocPath s = do - 89 -- using the crummy string functions for convenience here - 90 (ex, sout, serr) <- readProcessWithExitCode' pandocPath args s - 91 - 92 when (isFail ex) $ throw $ MarkdownException serr - 93 return $ BC.concat [ "<div class=\"markdown\">\n" - 94 , sout - 95 , "\n</div>" ] - 96 - 97 where - 98 isFail ExitSuccess = False - 99 isFail _ = True - 100 args = [ "-S", "--no-wrap" ] - 101 - 102 - 103 -- a version of readProcessWithExitCode that does I/O properly - 104 readProcessWithExitCode' - 105 :: FilePath -- ^ command to run - 106 -> [String] -- ^ any arguments - 107 -> ByteString -- ^ standard input - 108 -> IO (ExitCode,ByteString,ByteString) -- ^ exitcode, stdout, stderr - 109 readProcessWithExitCode' cmd args input = do - 110 (Just inh, Just outh, Just errh, pid) <- - 111 createProcess (proc cmd args){ std_in = CreatePipe, - 112 std_out = CreatePipe, - 113 std_err = CreatePipe } - 114 outMVar <- newEmptyMVar - 115 - 116 outM <- newEmptyMVar - 117 errM <- newEmptyMVar + 44 instance Exception MarkdownException + 45 + 46 + 47 ------------------------------------------------------------------------------ + 48 -- | Default name for the markdown splice. + 49 markdownTag :: ByteString + 50 markdownTag = "markdown" + 51 + 52 ------------------------------------------------------------------------------ + 53 -- | Implementation of the markdown splice. + 54 markdownSplice :: MonadIO m => Splice m + 55 markdownSplice = do + 56 pdMD <- liftIO $ findExecutable "pandoc" + 57 + 58 when (isNothing pdMD) $ liftIO $ throwIO PandocMissingException + 59 + 60 tree <- getParamNode + 61 markup <- liftIO $ + 62 case getAttribute tree "file" of + 63 Just f -> pandoc (fromJust pdMD) $ BC.unpack f + 64 Nothing -> pandocBS (fromJust pdMD) $ textContent tree + 65 + 66 let ee = parse' heistExpatOptions markup + 67 case ee of + 68 (Left e) -> throw $ MarkdownException + 69 $ BC.pack ("Error parsing markdown output: " ++ show e) + 70 (Right n) -> return [n] + 71 + 72 + 73 pandoc :: FilePath -> FilePath -> IO ByteString + 74 pandoc pandocPath inputFile = do + 75 (ex, sout, serr) <- readProcessWithExitCode' pandocPath args "" + 76 + 77 when (isFail ex) $ throw $ MarkdownException serr + 78 return $ BC.concat [ "<div class=\"markdown\">\n" + 79 , sout + 80 , "\n</div>" ] + 81 + 82 where + 83 isFail ExitSuccess = False + 84 isFail _ = True + 85 + 86 -- FIXME: hardcoded path + 87 args = [ "-S", "--no-wrap", "templates/"++inputFile ] + 88 + 89 + 90 pandocBS :: FilePath -> ByteString -> IO ByteString + 91 pandocBS pandocPath s = do + 92 -- using the crummy string functions for convenience here + 93 (ex, sout, serr) <- readProcessWithExitCode' pandocPath args s + 94 + 95 when (isFail ex) $ throw $ MarkdownException serr + 96 return $ BC.concat [ "<div class=\"markdown\">\n" + 97 , sout + 98 , "\n</div>" ] + 99 + 100 where + 101 isFail ExitSuccess = False + 102 isFail _ = True + 103 args = [ "-S", "--no-wrap" ] + 104 + 105 + 106 -- a version of readProcessWithExitCode that does I/O properly + 107 readProcessWithExitCode' + 108 :: FilePath -- ^ command to run + 109 -> [String] -- ^ any arguments + 110 -> ByteString -- ^ standard input + 111 -> IO (ExitCode,ByteString,ByteString) -- ^ exitcode, stdout, stderr + 112 readProcessWithExitCode' cmd args input = do + 113 (Just inh, Just outh, Just errh, pid) <- + 114 createProcess (proc cmd args){ std_in = CreatePipe, + 115 std_out = CreatePipe, + 116 std_err = CreatePipe } + 117 outMVar <- newEmptyMVar 118 - 119 -- fork off a thread to start consuming stdout - 120 forkIO $ do - 121 out <- B.hGetContents outh - 122 putMVar outM out - 123 putMVar outMVar () - 124 - 125 -- fork off a thread to start consuming stderr - 126 forkIO $ do - 127 err <- B.hGetContents errh - 128 putMVar errM err - 129 putMVar outMVar () - 130 - 131 -- now write and flush any input - 132 when (not (B.null input)) $ do B.hPutStr inh input; hFlush inh - 133 hClose inh -- done with stdin - 134 - 135 -- wait on the output - 136 takeMVar outMVar - 137 takeMVar outMVar - 138 hClose outh - 139 - 140 -- wait on the process - 141 ex <- waitForProcess pid + 119 outM <- newEmptyMVar + 120 errM <- newEmptyMVar + 121 + 122 -- fork off a thread to start consuming stdout + 123 forkIO $ do + 124 out <- B.hGetContents outh + 125 putMVar outM out + 126 putMVar outMVar () + 127 + 128 -- fork off a thread to start consuming stderr + 129 forkIO $ do + 130 err <- B.hGetContents errh + 131 putMVar errM err + 132 putMVar outMVar () + 133 + 134 -- now write and flush any input + 135 when (not (B.null input)) $ do B.hPutStr inh input; hFlush inh + 136 hClose inh -- done with stdin + 137 + 138 -- wait on the output + 139 takeMVar outMVar + 140 takeMVar outMVar + 141 hClose outh 142 - 143 out <- readMVar outM - 144 err <- readMVar errM + 143 -- wait on the process + 144 ex <- waitForProcess pid 145 - 146 return (ex, out, err) - 147 - 148 - 149 + 146 out <- readMVar outM + 147 err <- readMVar errM + 148 + 149 return (ex, out, err) 150 + 151 + 152 + 153 diff --git a/static/docs/heist-hpc/Text.Templating.Heist.Splices.Static.hs.html b/static/docs/heist-hpc/Text.Templating.Heist.Splices.Static.hs.html index fab1cd4..8b0d1ae 100644 --- a/static/docs/heist-hpc/Text.Templating.Heist.Splices.Static.hs.html +++ b/static/docs/heist-hpc/Text.Templating.Heist.Splices.Static.hs.html @@ -35,91 +35,92 @@ 24 25 ------------------------------------------------------------------------------ 26 import Text.Templating.Heist.Internal - 27 + 27 import Text.Templating.Heist.Types 28 - 29 ------------------------------------------------------------------------------ - 30 -- | State for storing static tag information - 31 newtype StaticTagState = STS (MVar (Map ByteString Template)) - 32 + 29 + 30 ------------------------------------------------------------------------------ + 31 -- | State for storing static tag information + 32 newtype StaticTagState = STS (MVar (Map ByteString Template)) 33 - 34 ------------------------------------------------------------------------------ - 35 -- | Clears the static tag state. - 36 clearStaticTagCache :: StaticTagState -> IO () - 37 clearStaticTagCache (STS staticMVar) = - 38 modifyMVar_ staticMVar (const $ return Map.empty) - 39 + 34 + 35 ------------------------------------------------------------------------------ + 36 -- | Clears the static tag state. + 37 clearStaticTagCache :: StaticTagState -> IO () + 38 clearStaticTagCache (STS staticMVar) = + 39 modifyMVar_ staticMVar (const $ return Map.empty) 40 - 41 ------------------------------------------------------------------------------ - 42 -- | The "static" splice ensures that its contents are evaluated once and then - 43 -- cached. The cached contents are returned every time the splice is - 44 -- referenced. - 45 staticImpl :: (MonadIO m) - 46 => StaticTagState - 47 -> TemplateMonad m Template - 48 staticImpl (STS mv) = do - 49 tree <- getParamNode - 50 let i = fromJust $ getAttribute tree "id" - 51 - 52 mp <- liftIO $ readMVar mv - 53 - 54 (mp',ns) <- do - 55 let mbn = Map.lookup i mp - 56 case mbn of - 57 Nothing -> do - 58 nodes' <- runNodeList $ getChildren tree - 59 return $! (Map.insert i nodes' mp, nodes') - 60 (Just n) -> do - 61 stopRecursion - 62 return $! (mp,n) - 63 - 64 liftIO $ modifyMVar_ mv (const $ return mp') - 65 - 66 return ns - 67 + 41 + 42 ------------------------------------------------------------------------------ + 43 -- | The "static" splice ensures that its contents are evaluated once and then + 44 -- cached. The cached contents are returned every time the splice is + 45 -- referenced. + 46 staticImpl :: (MonadIO m) + 47 => StaticTagState + 48 -> TemplateMonad m Template + 49 staticImpl (STS mv) = do + 50 tree <- getParamNode + 51 let i = fromJust $ getAttribute tree "id" + 52 + 53 mp <- liftIO $ readMVar mv + 54 + 55 (mp',ns) <- do + 56 let mbn = Map.lookup i mp + 57 case mbn of + 58 Nothing -> do + 59 nodes' <- runNodeList $ getChildren tree + 60 return $! (Map.insert i nodes' mp, nodes') + 61 (Just n) -> do + 62 stopRecursion + 63 return $! (mp,n) + 64 + 65 liftIO $ modifyMVar_ mv (const $ return mp') + 66 + 67 return ns 68 - 69 ------------------------------------------------------------------------------ - 70 -- | Modifies a TemplateState to include a "static" tag. - 71 bindStaticTag :: MonadIO m - 72 => TemplateState m - 73 -> IO (TemplateState m, StaticTagState) - 74 bindStaticTag ts = do - 75 sr <- newIORef $ Set.empty - 76 mv <- liftM STS $ newMVar Map.empty - 77 - 78 return $ (addOnLoadHook (assignIds sr) $ - 79 bindSplice "static" (staticImpl mv) ts, - 80 mv) - 81 - 82 where - 83 generateId :: IO Int - 84 generateId = getStdRandom random - 85 - 86 assignIds setref = mapM f - 87 where - 88 f node = g $ fromTree node - 89 - 90 getId = do - 91 i <- liftM (B.pack . show) generateId - 92 st <- readIORef setref - 93 if Set.member i st - 94 then getId - 95 else do - 96 writeIORef setref $ Set.insert i st - 97 return i - 98 - 99 g curs = do - 100 let node = current curs - 101 curs' <- if getName node == "static" - 102 then do - 103 i <- getId - 104 return $ modifyContent (setAttribute "id" i) curs - 105 else return curs - 106 let mbc = nextDF curs' - 107 maybe (return $ toTree curs') g mbc - 108 + 69 + 70 ------------------------------------------------------------------------------ + 71 -- | Modifies a TemplateState to include a "static" tag. + 72 bindStaticTag :: MonadIO m + 73 => TemplateState m + 74 -> IO (TemplateState m, StaticTagState) + 75 bindStaticTag ts = do + 76 sr <- newIORef $ Set.empty + 77 mv <- liftM STS $ newMVar Map.empty + 78 + 79 return $ (addOnLoadHook (assignIds sr) $ + 80 bindSplice "static" (staticImpl mv) ts, + 81 mv) + 82 + 83 where + 84 generateId :: IO Int + 85 generateId = getStdRandom random + 86 + 87 assignIds setref = mapM f + 88 where + 89 f node = g $ fromTree node + 90 + 91 getId = do + 92 i <- liftM (B.pack . show) generateId + 93 st <- readIORef setref + 94 if Set.member i st + 95 then getId + 96 else do + 97 writeIORef setref $ Set.insert i st + 98 return i + 99 + 100 g curs = do + 101 let node = current curs + 102 curs' <- if getName node == "static" + 103 then do + 104 i <- getId + 105 return $ modifyContent (setAttribute "id" i) curs + 106 else return curs + 107 let mbc = nextDF curs' + 108 maybe (return $ toTree curs') g mbc 109 110 111 + 112 diff --git a/static/docs/heist-hpc/Text.Templating.Heist.Tests.hs.html b/static/docs/heist-hpc/Text.Templating.Heist.Tests.hs.html index 74e193f..f323c8d 100644 --- a/static/docs/heist-hpc/Text.Templating.Heist.Tests.hs.html +++ b/static/docs/heist-hpc/Text.Templating.Heist.Tests.hs.html @@ -15,367 +15,414 @@ 4 , quickRender 5 ) where 6 - 7 import Test.Framework (Test) - 8 import Test.Framework.Providers.HUnit - 9 import Test.Framework.Providers.QuickCheck2 - 10 import qualified Test.HUnit as H - 11 import Test.QuickCheck - 12 import Test.QuickCheck.Monadic - 13 - 14 import Control.Monad.State - 15 - 16 import Data.ByteString.Char8 (ByteString) - 17 import qualified Data.ByteString.Char8 as B - 18 import qualified Data.ByteString.Lazy.Char8 as L - 19 import qualified Data.Map as Map - 20 import Data.Maybe - 21 import Data.Monoid + 7 ------------------------------------------------------------------------------ + 8 import Control.Monad.State + 9 import Data.ByteString.Char8 (ByteString) + 10 import qualified Data.ByteString.Char8 as B + 11 import qualified Data.ByteString.Lazy.Char8 as L + 12 import qualified Data.Map as Map + 13 import Data.Maybe + 14 import Data.Monoid + 15 import System.IO.Unsafe + 16 import Test.Framework (Test) + 17 import Test.Framework.Providers.HUnit + 18 import Test.Framework.Providers.QuickCheck2 + 19 import qualified Test.HUnit as H + 20 import Test.QuickCheck + 21 import Test.QuickCheck.Monadic 22 - 23 import System.IO.Unsafe - 24 + 23 + 24 ------------------------------------------------------------------------------ 25 import Text.Templating.Heist 26 import Text.Templating.Heist.Internal - 27 import Text.XML.Expat.Cursor - 28 import Text.XML.Expat.Format - 29 import qualified Text.XML.Expat.Tree as X - 30 - 31 tests :: [Test] - 32 tests = [ testProperty "simpleBindTest" $ monadicIO $ forAllM arbitrary prop_simpleBindTest - 33 , testProperty "simpleApplyTest" $ monadicIO $ forAllM arbitrary prop_simpleApplyTest - 34 , testCase "stateMonoidTest" monoidTest - 35 , testCase "templateAddTest" addTest - 36 , testCase "getDocTest" getDocTest - 37 , testCase "loadTest" loadTest - 38 , testCase "fsLoadTest" fsLoadTest - 39 , testCase "renderNoNameTest" renderNoNameTest - 40 ] - 41 - 42 monoidTest :: IO () - 43 monoidTest = do - 44 H.assertBool "left monoid identity" $ mempty `mappend` es == es - 45 H.assertBool "right monoid identity" $ es `mappend` mempty == es - 46 where es = emptyTemplateState :: TemplateState IO - 47 - 48 addTest :: IO () - 49 addTest = do - 50 H.assertBool "lookup test" $ Just [] == (fmap fst $ lookupTemplate "aoeu" ts) - 51 H.assertBool "splice touched" $ Map.size (_spliceMap ts) == 0 - 52 where ts = addTemplate "aoeu" [] (mempty::TemplateState IO) - 53 - 54 isLeft :: Either a b -> Bool - 55 isLeft (Left _) = True - 56 isLeft (Right _) = False - 57 - 58 - 59 loadT :: String -> IO (Either String (TemplateState IO)) - 60 loadT s = loadTemplates s emptyTemplateState - 61 - 62 loadTest :: H.Assertion - 63 loadTest = do - 64 ets <- loadT "templates" - 65 either (error "Error loading templates") - 66 (\ts -> do let tm = _templateMap ts - 67 H.assertBool "loadTest size" $ Map.size tm == 12 - 68 ) ets + 27 import Text.Templating.Heist.Types + 28 import Text.Templating.Heist.Splices.Apply + 29 import Text.XML.Expat.Cursor + 30 import Text.XML.Expat.Format + 31 import qualified Text.XML.Expat.Tree as X + 32 + 33 tests :: [Test] + 34 tests = [ testProperty "simpleBindTest" $ monadicIO $ forAllM arbitrary prop_simpleBindTest + 35 , testProperty "simpleApplyTest" $ monadicIO $ forAllM arbitrary prop_simpleApplyTest + 36 , testCase "stateMonoidTest" monoidTest + 37 , testCase "templateAddTest" addTest + 38 , testCase "getDocTest" getDocTest + 39 , testCase "loadTest" loadTest + 40 , testCase "fsLoadTest" fsLoadTest + 41 , testCase "renderNoNameTest" renderNoNameTest + 42 , testCase "doctypeTest" doctypeTest + 43 , testCase "attributeSubstitution" attrSubst + 44 , testCase "applyTest" applyTest + 45 ] + 46 + 47 applyTest :: H.Assertion + 48 applyTest = do + 49 let es = emptyTemplateState :: TemplateState IO + 50 res <- evalTemplateMonad applyImpl + 51 (X.Element "apply" [("template", "nonexistant")] []) es + 52 H.assertEqual "apply nothing" res [] + 53 + 54 monoidTest :: IO () + 55 monoidTest = do + 56 H.assertBool "left monoid identity" $ mempty `mappend` es == es + 57 H.assertBool "right monoid identity" $ es `mappend` mempty == es + 58 where es = emptyTemplateState :: TemplateState IO + 59 + 60 addTest :: IO () + 61 addTest = do + 62 H.assertBool "lookup test" $ Just [] == (fmap (_itNodes . fst) $ lookupTemplate "aoeu" ts) + 63 H.assertBool "splice touched" $ Map.size (_spliceMap ts) == 0 + 64 where ts = addTemplate "aoeu" (InternalTemplate Nothing []) (mempty::TemplateState IO) + 65 + 66 isLeft :: Either a b -> Bool + 67 isLeft (Left _) = True + 68 isLeft (Right _) = False 69 - 70 renderNoNameTest :: H.Assertion - 71 renderNoNameTest = do - 72 ets <- loadT "templates" - 73 either (error "Error loading templates") - 74 (\ts -> do t <- renderTemplate ts "" - 75 H.assertBool "renderNoName" $ t == Nothing - 76 ) ets - 77 - 78 getDocTest :: H.Assertion - 79 getDocTest = do - 80 d <- getDoc "bkteoar" - 81 H.assertBool "non-existent doc" $ isLeft d - 82 f <- getDoc "templates/index.tpl" - 83 H.assertBool "index doc" $ not $ isLeft f - 84 - 85 fsLoadTest :: H.Assertion - 86 fsLoadTest = do - 87 ets <- loadT "templates" - 88 let tm = either (error "Error loading templates") _templateMap ets - 89 let ts = setTemplates tm emptyTemplateState :: TemplateState IO - 90 f p n = H.assertBool ("loading template "++n) $ p $ lookupTemplate (B.pack n) ts - 91 f isNothing "abc/def/xyz" - 92 f isJust "a" - 93 f isJust "bar/a" - 94 f isJust "/bar/a" - 95 - 96 -- dotdotTest :: H.Assertion - 97 -- dotdotTest = do - 98 -- ets <- loadT "templates" - 99 -- let tm = either (error "Error loading templates") _templateMap ets - 100 -- let ts = setTemplates tm emptyTemplateState :: TemplateState IO - 101 -- f p n = H.assertBool ("loading template "++n) $ p $ lookupTemplate (B.pack n) ts - 102 - 103 identStartChar :: [Char] - 104 identStartChar = ['a'..'z'] - 105 identChar :: [Char] - 106 identChar = '_' : identStartChar + 70 + 71 loadT :: String -> IO (Either String (TemplateState IO)) + 72 loadT s = loadTemplates s emptyTemplateState + 73 + 74 loadTest :: H.Assertion + 75 loadTest = do + 76 ets <- loadT "templates" + 77 either (error "Error loading templates") + 78 (\ts -> do let tm = _templateMap ts + 79 H.assertBool "loadTest size" $ Map.size tm == 15 + 80 ) ets + 81 + 82 renderNoNameTest :: H.Assertion + 83 renderNoNameTest = do + 84 ets <- loadT "templates" + 85 either (error "Error loading templates") + 86 (\ts -> do t <- renderTemplate ts "" + 87 H.assertBool "renderNoName" $ t == Nothing + 88 ) ets + 89 + 90 getDocTest :: H.Assertion + 91 getDocTest = do + 92 d <- getDoc "bkteoar" + 93 H.assertBool "non-existent doc" $ isLeft d + 94 f <- getDoc "templates/index.tpl" + 95 H.assertBool "index doc" $ not $ isLeft f + 96 + 97 fsLoadTest :: H.Assertion + 98 fsLoadTest = do + 99 ets <- loadT "templates" + 100 let tm = either (error "Error loading templates") _templateMap ets + 101 let ts = setTemplates tm emptyTemplateState :: TemplateState IO + 102 f p n = H.assertBool ("loading template "++n) $ p $ lookupTemplate (B.pack n) ts + 103 f isNothing "abc/def/xyz" + 104 f isJust "a" + 105 f isJust "bar/a" + 106 f isJust "/bar/a" 107 - 108 newtype Name = Name { unName :: B.ByteString } deriving (Show) - 109 - 110 instance Arbitrary Name where - 111 arbitrary = do - 112 first <- elements identStartChar - 113 n <- choose (4,10) - 114 rest <- vectorOf n $ elements identChar - 115 return $ Name $ B.pack $ first : rest + 108 doctypeTest :: H.Assertion + 109 doctypeTest = do + 110 ets <- loadT "templates" + 111 let ts = either (error "Error loading templates") id ets + 112 index <- renderTemplate ts "index" + 113 H.assertBool "doctype test index" $ hasDoctype $ fromJust index + 114 ioc <- renderTemplate ts "ioc" + 115 H.assertBool "doctype test ioc" $ hasDoctype $ fromJust ioc 116 - 117 instance Arbitrary Node where - 118 arbitrary = limitedDepth 3 - 119 shrink (X.Text _) = [] - 120 shrink (X.Element _ [] []) = [] - 121 shrink (X.Element n [] (_:cs)) = [X.Element n [] cs] - 122 shrink (X.Element n (_:as) []) = [X.Element n as []] - 123 shrink (X.Element n as cs) = [X.Element n as (tail cs), X.Element n (tail as) cs] - 124 - 125 textGen :: Gen [Char] - 126 textGen = listOf $ elements ((replicate 5 ' ') ++ identStartChar) - 127 - 128 limitedDepth :: Int -> Gen Node - 129 limitedDepth 0 = liftM (X.Text . B.pack) textGen - 130 limitedDepth n = oneof [ liftM (X.Text . B.pack) textGen - 131 , liftM3 X.Element arbitrary - 132 (liftM (take 2) arbitrary) - 133 (liftM (take 3) $ listOf $ limitedDepth (n-1)) - 134 ] - 135 - 136 instance Arbitrary B.ByteString where - 137 arbitrary = liftM unName arbitrary + 117 attrSubst :: H.Assertion + 118 attrSubst = do + 119 ets <- loadT "templates" + 120 let ts = either (error "Error loading templates") id ets + 121 check (setTs "meaning_of_everything" ts) "pre_meaning_of_everything_post" + 122 check ts "pre__post" + 123 where + 124 setTs val = bindSplice "foo" (return [X.Text val]) + 125 check ts str = do + 126 res <- renderTemplate ts "attrs" + 127 H.assertBool ("attr subst "++(show str)) $ + 128 not $ B.null $ snd $ B.breakSubstring str $ fromJust res + 129 H.assertBool ("attr subst foo") $ + 130 not $ B.null $ snd $ B.breakSubstring "$(foo)" $ fromJust res + 131 + 132 -- dotdotTest :: H.Assertion + 133 -- dotdotTest = do + 134 -- ets <- loadT "templates" + 135 -- let tm = either (error "Error loading templates") _templateMap ets + 136 -- let ts = setTemplates tm emptyTemplateState :: TemplateState IO + 137 -- f p n = H.assertBool ("loading template "++n) $ p $ lookupTemplate (B.pack n) ts 138 - 139 {- - 140 - Code for inserting nodes into any point of a tree - 141 -} - 142 - 143 type Loc = Cursor B.ByteString B.ByteString - 144 type Insert a = State Int a + 139 identStartChar :: [Char] + 140 identStartChar = ['a'..'z'] + 141 identChar :: [Char] + 142 identChar = '_' : identStartChar + 143 + 144 newtype Name = Name { unName :: B.ByteString } deriving (Show) 145 - 146 {- - 147 - Returns the number of unique insertion points in the tree. - 148 - If h = insertAt f n g", the following property holds: - 149 - insSize h == (insSize f) + (insSize g) - 1 - 150 -} - 151 insSize :: [X.Node tag text] -> Int - 152 insSize ns = 1 + (sum $ map nodeSize ns) - 153 where nodeSize (X.Text _) = 1 - 154 nodeSize (X.Element _ _ c) = 1 + (insSize c) - 155 - 156 insertAt :: [Node] -> Int -> [Node] -> [Node] - 157 insertAt elems 0 ns = elems ++ ns - 158 insertAt elems _ [] = elems - 159 insertAt elems n list = maybe [] (toForest . root) $ - 160 evalState (processNode elems $ fromJust $ fromForest list) n - 161 - 162 move :: Insert () - 163 move = modify (\x -> x-1) - 164 - 165 processNode :: [Node] -> Loc -> Insert (Maybe Loc) - 166 processNode elems loc = liftM2 mplus (move >> goDown loc) (move >> goRight loc) - 167 where goDown l = case current l of - 168 X.Text _ -> modify (+1) >> return Nothing - 169 X.Element _ _ _ -> doneCheck (insertManyFirstChild elems) firstChild l - 170 goRight = doneCheck (Just . insertManyRight elems) right - 171 doneCheck insertFunc next l = do - 172 s <- get - 173 if s == 0 - 174 then return $ insertFunc l - 175 else maybe (return Nothing) (processNode elems) $ next l - 176 - 177 {- - 178 - <bind> tests - 179 -} - 180 - 181 -- Data type encapsulating the parameters for a bind operation - 182 data Bind = Bind { - 183 _bindElemName :: Name, - 184 _bindChildren :: [Node], - 185 _bindDoc :: [Node], - 186 _bindPos :: Int, - 187 _bindRefPos :: Int - 188 } -- deriving (Show) - 189 - 190 instance Show Bind where - 191 show b@(Bind e c d p r) = unlines - 192 ["\n" - 193 ,"Bind element name: "++(show e) - 194 ,"Bind pos: "++(show p) - 195 ,"Bind ref pos: "++(show r) - 196 ,"Bind document:" - 197 ,L.unpack $ L.concat $ map formatNode d - 198 ,"Bind children:" - 199 ,L.unpack $ L.concat $ map formatNode c - 200 ,"Result:" - 201 ,L.unpack $ L.concat $ map formatNode $ buildResult b - 202 ,"Splice result:" - 203 ,L.unpack $ L.concat $ map formatNode $ unsafePerformIO $ - 204 runRawTemplate emptyTemplateState $ buildBindTemplate b - 205 ,"Template:" - 206 ,L.unpack $ L.concat $ map formatNode $ buildBindTemplate b - 207 ] - 208 - 209 buildNode :: B.ByteString -> B.ByteString -> Bind -> Node - 210 buildNode tag attr (Bind s c _ _ _) = X.Element tag [(attr, unName s)] c - 211 - 212 buildBind :: Bind -> Node - 213 buildBind = buildNode "bind" "tag" - 214 - 215 instance Arbitrary Bind where - 216 arbitrary = do - 217 name <- arbitrary - 218 kids <- liftM (take 3) arbitrary - 219 doc <- liftM (take 5) arbitrary - 220 let s = insSize doc - 221 loc <- choose (0, s-1) - 222 loc2 <- choose (0, s-loc-1) - 223 return $ Bind name kids doc loc loc2 - 224 shrink (Bind e [c] (_:ds) p r) = [Bind e [c] ds p r] - 225 shrink (Bind e (_:cs) d p r) = [Bind e cs d p r] - 226 shrink _ = [] - 227 - 228 empty :: tag -> X.Node tag text - 229 empty n = X.Element n [] [] - 230 - 231 buildBindTemplate :: Bind -> [Node] - 232 buildBindTemplate s@(Bind n _ d b r) = - 233 insertAt [empty $ unName $ n] pos $ withBind - 234 where bind = [buildBind s] - 235 bindSize = insSize bind - 236 withBind = insertAt bind b d - 237 pos = b + bindSize - 1 + r - 238 - 239 buildResult :: Bind -> [Node] - 240 buildResult (Bind _ c d b r) = insertAt c (b+r) d - 241 - 242 prop_simpleBindTest :: Bind -> PropertyM IO () - 243 prop_simpleBindTest bind = do - 244 let template = buildBindTemplate bind - 245 result = buildResult bind - 246 spliceResult <- run $ runRawTemplate emptyTemplateState template - 247 assert $ result == spliceResult + 146 instance Arbitrary Name where + 147 arbitrary = do + 148 first <- elements identStartChar + 149 n <- choose (4,10) + 150 rest <- vectorOf n $ elements identChar + 151 return $ Name $ B.pack $ first : rest + 152 + 153 instance Arbitrary Node where + 154 arbitrary = limitedDepth 3 + 155 shrink (X.Text _) = [] + 156 shrink (X.Element _ [] []) = [] + 157 shrink (X.Element n [] (_:cs)) = [X.Element n [] cs] + 158 shrink (X.Element n (_:as) []) = [X.Element n as []] + 159 shrink (X.Element n as cs) = [X.Element n as (tail cs), X.Element n (tail as) cs] + 160 + 161 textGen :: Gen [Char] + 162 textGen = listOf $ elements ((replicate 5 ' ') ++ identStartChar) + 163 + 164 limitedDepth :: Int -> Gen Node + 165 limitedDepth 0 = liftM (X.Text . B.pack) textGen + 166 limitedDepth n = oneof [ liftM (X.Text . B.pack) textGen + 167 , liftM3 X.Element arbitrary + 168 (liftM (take 2) arbitrary) + 169 (liftM (take 3) $ listOf $ limitedDepth (n-1)) + 170 ] + 171 + 172 instance Arbitrary B.ByteString where + 173 arbitrary = liftM unName arbitrary + 174 + 175 {- + 176 - Code for inserting nodes into any point of a tree + 177 -} + 178 + 179 type Loc = Cursor B.ByteString B.ByteString + 180 type Insert a = State Int a + 181 + 182 {- + 183 - Returns the number of unique insertion points in the tree. + 184 - If h = insertAt f n g", the following property holds: + 185 - insSize h == (insSize f) + (insSize g) - 1 + 186 -} + 187 insSize :: [X.Node tag text] -> Int + 188 insSize ns = 1 + (sum $ map nodeSize ns) + 189 where nodeSize (X.Text _) = 1 + 190 nodeSize (X.Element _ _ c) = 1 + (insSize c) + 191 + 192 insertAt :: [Node] -> Int -> [Node] -> [Node] + 193 insertAt elems 0 ns = elems ++ ns + 194 insertAt elems _ [] = elems + 195 insertAt elems n list = maybe [] (toForest . root) $ + 196 evalState (processNode elems $ fromJust $ fromForest list) n + 197 + 198 move :: Insert () + 199 move = modify (\x -> x-1) + 200 + 201 processNode :: [Node] -> Loc -> Insert (Maybe Loc) + 202 processNode elems loc = liftM2 mplus (move >> goDown loc) (move >> goRight loc) + 203 where goDown l = case current l of + 204 X.Text _ -> modify (+1) >> return Nothing + 205 X.Element _ _ _ -> doneCheck (insertManyFirstChild elems) firstChild l + 206 goRight = doneCheck (Just . insertManyRight elems) right + 207 doneCheck insertFunc next l = do + 208 s <- get + 209 if s == 0 + 210 then return $ insertFunc l + 211 else maybe (return Nothing) (processNode elems) $ next l + 212 + 213 {- + 214 - <bind> tests + 215 -} + 216 + 217 -- Data type encapsulating the parameters for a bind operation + 218 data Bind = Bind { + 219 _bindElemName :: Name, + 220 _bindChildren :: [Node], + 221 _bindDoc :: [Node], + 222 _bindPos :: Int, + 223 _bindRefPos :: Int + 224 } -- deriving (Show) + 225 + 226 instance Show Bind where + 227 show b@(Bind e c d p r) = unlines + 228 ["\n" + 229 ,"Bind element name: "++(show e) + 230 ,"Bind pos: "++(show p) + 231 ,"Bind ref pos: "++(show r) + 232 ,"Bind document:" + 233 ,L.unpack $ L.concat $ map formatNode d + 234 ,"Bind children:" + 235 ,L.unpack $ L.concat $ map formatNode c + 236 ,"Result:" + 237 ,L.unpack $ L.concat $ map formatNode $ buildResult b + 238 ,"Splice result:" + 239 ,L.unpack $ L.concat $ map formatNode $ unsafePerformIO $ + 240 evalTemplateMonad (runNodeList $ buildBindTemplate b) + 241 (X.Text "") emptyTemplateState + 242 ,"Template:" + 243 ,L.unpack $ L.concat $ map formatNode $ buildBindTemplate b + 244 ] + 245 + 246 buildNode :: B.ByteString -> B.ByteString -> Bind -> Node + 247 buildNode tag attr (Bind s c _ _ _) = X.Element tag [(attr, unName s)] c 248 - 249 {- - 250 - <apply> tests - 251 -} - 252 - 253 data Apply = Apply { - 254 _applyName :: Name, - 255 _applyCaller :: [Node], - 256 _applyCallee :: Template, - 257 _applyChildren :: [Node], - 258 _applyPos :: Int - 259 } deriving (Show) - 260 - 261 instance Arbitrary Apply where - 262 arbitrary = do - 263 name <- arbitrary - 264 kids <- liftM (take 3) $ listOf $ limitedDepth 2 - 265 caller <- liftM (take 5) arbitrary - 266 callee <- liftM (take 1) $ listOf $ limitedDepth 3 - 267 let s = insSize caller - 268 loc <- choose (0, s-1) - 269 return $ Apply name caller callee kids loc - 270 - 271 buildApplyCaller :: Apply -> [Node] - 272 buildApplyCaller (Apply name caller _ kids pos) = - 273 insertAt [X.Element "apply" [("template", unName name)] kids] pos caller - 274 - 275 calcCorrect :: Apply -> [Node] - 276 calcCorrect (Apply _ caller callee _ pos) = insertAt callee pos caller - 277 - 278 calcResult :: (MonadIO m) => Apply -> m [Node] - 279 calcResult apply@(Apply name _ callee _ _) = - 280 runRawTemplate ts $ buildApplyCaller apply - 281 where ts = setTemplates (Map.singleton [unName name] callee) emptyTemplateState - 282 - 283 prop_simpleApplyTest :: Apply -> PropertyM IO () - 284 prop_simpleApplyTest apply = do - 285 let correct = calcCorrect apply - 286 result <- run $ calcResult apply - 287 assert $ correct == result + 249 buildBind :: Bind -> Node + 250 buildBind = buildNode "bind" "tag" + 251 + 252 instance Arbitrary Bind where + 253 arbitrary = do + 254 name <- arbitrary + 255 kids <- liftM (take 3) arbitrary + 256 doc <- liftM (take 5) arbitrary + 257 let s = insSize doc + 258 loc <- choose (0, s-1) + 259 loc2 <- choose (0, s-loc-1) + 260 return $ Bind name kids doc loc loc2 + 261 shrink (Bind e [c] (_:ds) p r) = [Bind e [c] ds p r] + 262 shrink (Bind e (_:cs) d p r) = [Bind e cs d p r] + 263 shrink _ = [] + 264 + 265 empty :: tag -> X.Node tag text + 266 empty n = X.Element n [] [] + 267 + 268 buildBindTemplate :: Bind -> [Node] + 269 buildBindTemplate s@(Bind n _ d b r) = + 270 insertAt [empty $ unName $ n] pos $ withBind + 271 where bind = [buildBind s] + 272 bindSize = insSize bind + 273 withBind = insertAt bind b d + 274 pos = b + bindSize - 1 + r + 275 + 276 buildResult :: Bind -> [Node] + 277 buildResult (Bind _ c d b r) = insertAt c (b+r) d + 278 + 279 prop_simpleBindTest :: Bind -> PropertyM IO () + 280 prop_simpleBindTest bind = do + 281 let template = buildBindTemplate bind + 282 result = buildResult bind + 283 spliceResult <- run $ evalTemplateMonad (runNodeList template) + 284 (X.Text "") + 285 emptyTemplateState + 286 + 287 assert $ result == spliceResult 288 - 289 - 290 ------------------------------------------------------------------------------ - 291 -- | Reloads the templates from disk and renders the specified - 292 -- template. (Old convenience code.) - 293 quickRender :: FilePath -> ByteString -> IO (Maybe ByteString) - 294 quickRender baseDir name = do - 295 etm <- loadTemplates baseDir emptyTemplateState - 296 let ts = either (const emptyTemplateState) id etm - 297 ns <- runTemplate ts name - 298 return $ (Just . formatList') =<< ns - 299 + 289 {- + 290 - <apply> tests + 291 -} + 292 + 293 data Apply = Apply { + 294 _applyName :: Name, + 295 _applyCaller :: [Node], + 296 _applyCallee :: Template, + 297 _applyChildren :: [Node], + 298 _applyPos :: Int + 299 } deriving (Show) 300 - 301 {- - 302 -- The beginning of some future tests for hook functions. - 303 - 304 p :: ByteString -> Node - 305 p t = X.Element "p" [] [X.Text t] - 306 - 307 hookG :: Monad m => ByteString -> Template -> m Template - 308 hookG str t = return $ (p str) : t - 309 - 310 onLoad = hookG "Inserted on load" - 311 preRun = hookG "Inserted on preRun" - 312 postRun = hookG "Inserted on postRun" - 313 - 314 ts :: IO (Either String (TemplateState IO)) - 315 ts = loadTemplates "test/templates" $ - 316 foldr ($) emptyTemplateState - 317 [setOnLoadHook onLoad - 318 ,setPreRunHook preRun - 319 ,setPostRunHook postRun - 320 ] - 321 - 322 r name etm = do - 323 let ts = either (error "Danger Will Robinson!") id etm - 324 ns <- runTemplate ts name - 325 return $ (Just . formatList') =<< ns + 301 instance Arbitrary Apply where + 302 arbitrary = do + 303 name <- arbitrary + 304 kids <- liftM (take 3) $ listOf $ limitedDepth 2 + 305 caller <- liftM (take 5) arbitrary + 306 callee <- liftM (take 1) $ listOf $ limitedDepth 3 + 307 let s = insSize caller + 308 loc <- choose (0, s-1) + 309 return $ Apply name caller callee kids loc + 310 + 311 buildApplyCaller :: Apply -> [Node] + 312 buildApplyCaller (Apply name caller _ kids pos) = + 313 insertAt [X.Element "apply" [("template", unName name)] kids] pos caller + 314 + 315 calcCorrect :: Apply -> [Node] + 316 calcCorrect (Apply _ caller callee _ pos) = insertAt callee pos caller + 317 + 318 calcResult :: (MonadIO m) => Apply -> m [Node] + 319 calcResult apply@(Apply name _ callee _ _) = + 320 evalTemplateMonad (runNodeList $ buildApplyCaller apply) + 321 (X.Text "") ts + 322 + 323 where ts = setTemplates (Map.singleton [unName name] + 324 (InternalTemplate Nothing callee)) + 325 emptyTemplateState 326 - 327 - 328 -} - 329 - 330 - 331 {- - 332 - Convenience code for manual ghci experimentation - 333 -} - 334 - 335 --html :: [Node] -> Node - 336 --html c = X.Element "html" [] [hhead, body c] - 337 --hhead :: Node - 338 --hhead = X.Element "head" [] [title, X.Element "script" [] []] - 339 --title :: Node - 340 --title = X.Element "title" [] [X.Text "Test Page"] - 341 --body :: [Node] -> Node - 342 --body = X.Element "body" [] - 343 -- - 344 --para :: Int -> Node - 345 --para n = X.Element "p" [] [X.Text $ B.pack $ "This is paragraph " ++ show n] - 346 --para2 :: B.ByteString -> Node - 347 --para2 c = X.Element "p" [] [X.Text c] - 348 --para3 :: Node - 349 --para3 = X.Element "p" [] [X.Text "AHA!"] - 350 -- - 351 --foo :: Int -> [Node] - 352 --foo n = insertAt [X.Element "NEW" [] []] n [html [para 1, para 2]] - 353 -- - 354 --tdoc :: [Node] - 355 --tdoc = [para 1, para 2, para 3, para 4] - 356 -- - 357 --bindElem :: [Node] -> Int -> Int -> Bind - 358 --bindElem = Bind (Name "mytag") [para2 "bound paragraph"] - 359 -- - 360 --addBind :: Bind -> [Node] -> [Node] - 361 --addBind b = insertAt [buildBind b] 0 . insertAt [empty $ unName $ _bindElemName b] 2 - 362 -- - 363 --prn :: Node -> IO () - 364 --prn = L.putStrLn . formatNode - 365 --runTests :: IO () - 366 --runTests = defaultMain tests - 367 + 327 prop_simpleApplyTest :: Apply -> PropertyM IO () + 328 prop_simpleApplyTest apply = do + 329 let correct = calcCorrect apply + 330 result <- run $ calcResult apply + 331 assert $ correct == result + 332 + 333 + 334 loadTS :: FilePath -> IO (TemplateState IO) + 335 loadTS baseDir = do + 336 etm <- loadTemplates baseDir emptyTemplateState + 337 return $ either error id etm + 338 + 339 ------------------------------------------------------------------------------ + 340 -- | Reloads the templates from disk and renders the specified + 341 -- template. (Old convenience code.) + 342 quickRender :: FilePath -> ByteString -> IO (Maybe ByteString) + 343 quickRender baseDir name = do + 344 ts <- loadTS baseDir + 345 renderTemplate ts name + 346 + 347 + 348 {- + 349 -- The beginning of some future tests for hook functions. + 350 + 351 p :: ByteString -> Node + 352 p t = X.Element "p" [] [X.Text t] + 353 + 354 hookG :: Monad m => ByteString -> Template -> m Template + 355 hookG str t = return $ (p str) : t + 356 + 357 onLoad = hookG "Inserted on load" + 358 preRun = hookG "Inserted on preRun" + 359 postRun = hookG "Inserted on postRun" + 360 + 361 ts :: IO (Either String (TemplateState IO)) + 362 ts = loadTemplates "test/templates" $ + 363 foldr ($) emptyTemplateState + 364 [setOnLoadHook onLoad + 365 ,setPreRunHook preRun + 366 ,setPostRunHook postRun + 367 ] + 368 + 369 r name etm = do + 370 let ts = either (error "Danger Will Robinson!") id etm + 371 ns <- runNodeList ts name + 372 return $ (Just . formatList') =<< ns + 373 + 374 + 375 -} + 376 + 377 + 378 {- + 379 - Convenience code for manual ghci experimentation + 380 -} + 381 + 382 --html :: [Node] -> Node + 383 --html c = X.Element "html" [] [hhead, body c] + 384 --hhead :: Node + 385 --hhead = X.Element "head" [] [title, X.Element "script" [] []] + 386 --title :: Node + 387 --title = X.Element "title" [] [X.Text "Test Page"] + 388 --body :: [Node] -> Node + 389 --body = X.Element "body" [] + 390 -- + 391 --para :: Int -> Node + 392 --para n = X.Element "p" [] [X.Text $ B.pack $ "This is paragraph " ++ show n] + 393 --para2 :: B.ByteString -> Node + 394 --para2 c = X.Element "p" [] [X.Text c] + 395 --para3 :: Node + 396 --para3 = X.Element "p" [] [X.Text "AHA!"] + 397 -- + 398 --foo :: Int -> [Node] + 399 --foo n = insertAt [X.Element "NEW" [] []] n [html [para 1, para 2]] + 400 -- + 401 --tdoc :: [Node] + 402 --tdoc = [para 1, para 2, para 3, para 4] + 403 -- + 404 --bindElem :: [Node] -> Int -> Int -> Bind + 405 --bindElem = Bind (Name "mytag") [para2 "bound paragraph"] + 406 -- + 407 --addBind :: Bind -> [Node] -> [Node] + 408 --addBind b = insertAt [buildBind b] 0 . insertAt [empty $ unName $ _bindElemName b] 2 + 409 -- + 410 --prn :: Node -> IO () + 411 --prn = L.putStrLn . formatNode + 412 --runTests :: IO () + 413 --runTests = defaultMain tests + 414 diff --git a/static/docs/heist-hpc/Text.Templating.Heist.Types.hs.html b/static/docs/heist-hpc/Text.Templating.Heist.Types.hs.html new file mode 100644 index 0000000..eea2348 --- /dev/null +++ b/static/docs/heist-hpc/Text.Templating.Heist.Types.hs.html @@ -0,0 +1,360 @@ + +
+    1 {-# LANGUAGE OverloadedStrings #-}
+    2 {-# LANGUAGE ScopedTypeVariables #-}
+    3 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
+    4 {-# LANGUAGE FlexibleInstances #-}
+    5 {-# LANGUAGE UndecidableInstances #-}
+    6 {-# LANGUAGE MultiParamTypeClasses #-}
+    7 
+    8 {-|
+    9 
+   10 This module contains the core Heist data types.  TemplateMonad intentionally
+   11 does not expose any of it's functionality via MonadState or MonadReader
+   12 functions.  We define passthrough instances for the most common types of
+   13 monads.  These instances allow the user to use TemplateMonad in a monad stack
+   14 without needing calls to `lift`.
+   15 
+   16 Edward Kmett wrote most of the TemplateMonad code and associated instances,
+   17 liberating us from the unused writer portion of RWST.
+   18 
+   19 -}
+   20 
+   21 module Text.Templating.Heist.Types where
+   22 
+   23 ------------------------------------------------------------------------------
+   24 import           Control.Applicative
+   25 import           Control.Monad.Cont
+   26 import           Control.Monad.Error
+   27 import           Control.Monad.Reader
+   28 import           Control.Monad.State
+   29 import           Control.Monad.Trans
+   30 import           Data.ByteString.Char8 (ByteString)
+   31 import qualified Data.ByteString.Char8 as B
+   32 import qualified Data.Map as Map
+   33 import           Data.Map (Map)
+   34 import           Data.Monoid
+   35 import           Data.Typeable
+   36 import           Prelude hiding (catch)
+   37 import qualified Text.XML.Expat.Tree as X
+   38 
+   39 
+   40 ------------------------------------------------------------------------------
+   41 -- | Heist templates are XML documents. The hexpat library is polymorphic over
+   42 -- the type of strings, so here we define a 'Node' alias to fix the string
+   43 -- types of the tag names and tag bodies to 'ByteString'.
+   44 type Node = X.Node ByteString ByteString
+   45 
+   46 
+   47 ------------------------------------------------------------------------------
+   48 -- | A 'Template' is a forest of XML nodes.  Here we deviate from the "single
+   49 -- root node" constraint of well-formed XML because we want to allow templates
+   50 -- to contain fragments of a document that may not have a single root.
+   51 type Template = [Node]
+   52 
+   53 
+   54 ------------------------------------------------------------------------------
+   55 -- | An 'InternalTemplate' carries a doctype with it that we get from the
+   56 -- template at load time.  The tricks that we're playing so templates don't
+   57 -- have to have a single root node screw up doctypes, so we have to handle
+   58 -- them manually.
+   59 data InternalTemplate = InternalTemplate {
+   60     _itDoctype :: Maybe ByteString,
+   61     _itNodes   :: [Node]
+   62 } deriving (Eq, Show)
+   63 
+   64 
+   65 ------------------------------------------------------------------------------
+   66 -- | Reversed list of directories.  This holds the path to the template
+   67 -- currently being processed.
+   68 type TPath = [ByteString]
+   69 
+   70 
+   71 ------------------------------------------------------------------------------
+   72 -- | All templates are stored in a map.
+   73 type TemplateMap = Map TPath InternalTemplate
+   74 
+   75 
+   76 ------------------------------------------------------------------------------
+   77 -- | A Splice is a TemplateMonad computation that returns a 'Template'.
+   78 type Splice m = TemplateMonad m Template
+   79 
+   80 
+   81 ------------------------------------------------------------------------------
+   82 -- | SpliceMap associates a name and a Splice.
+   83 type SpliceMap m = Map ByteString (Splice m)
+   84 
+   85 
+   86 ------------------------------------------------------------------------------
+   87 -- | Holds all the state information needed for template processing.  You will
+   88 -- build a @TemplateState@ using any of Heist's @TemplateState m ->
+   89 -- TemplateState m@ \"filter\" functions.  Then you use the resulting
+   90 -- @TemplateState@ in calls to @renderTemplate@.
+   91 data TemplateState m = TemplateState {
+   92     -- | A mapping of splice names to splice actions
+   93       _spliceMap      :: SpliceMap m
+   94     -- | A mapping of template names to templates
+   95     , _templateMap    :: TemplateMap
+   96     -- | A flag to control splice recursion
+   97     , _recurse        :: Bool
+   98     -- | The path to the template currently being processed.
+   99     , _curContext     :: TPath
+  100     -- | A counter keeping track of the current recursion depth to prevent
+  101     -- infinite loops.
+  102     , _recursionDepth :: Int
+  103     -- | A hook run on all templates at load time.
+  104     , _onLoadHook     :: Template -> IO Template
+  105     -- | A hook run on all templates just before they are rendered.
+  106     , _preRunHook     :: Template -> m Template
+  107     -- | A hook run on all templates just after they are rendered.
+  108     , _postRunHook    :: Template -> m Template
+  109     -- | The doctypes encountered during template processing.
+  110     , _doctypes       :: [ByteString]
+  111 }
+  112 
+  113 
+  114 ------------------------------------------------------------------------------
+  115 instance (Monad m) => Monoid (TemplateState m) where
+  116     mempty = TemplateState Map.empty Map.empty True [] 0
+  117                            return return return []
+  118 
+  119     (TemplateState s1 t1 r1 _ d1 o1 b1 a1 dt1) `mappend`
+  120         (TemplateState s2 t2 r2 c2 d2 o2 b2 a2 dt2) =
+  121         TemplateState s t r c2 d (o1 >=> o2) (b1 >=> b2) (a1 >=> a2)
+  122             (dt1 `mappend` dt2)
+  123       where
+  124         s = s1 `mappend` s2
+  125         t = t1 `mappend` t2
+  126         r = r1 && r2
+  127         d = max d1 d2
+  128 
+  129 
+  130 ------------------------------------------------------------------------------
+  131 instance Eq (TemplateState m) where
+  132     a == b = (_recurse a == _recurse b) &&
+  133              (_templateMap a == _templateMap b) &&
+  134              (_curContext a == _curContext b)
+  135 
+  136 
+  137 ------------------------------------------------------------------------------
+  138 -- | TemplateMonad is the monad used for 'Splice' processing.  TemplateMonad
+  139 -- provides \"passthrough\" instances for many of the monads you might use in
+  140 -- the inner monad.  
+  141 newtype TemplateMonad m a = TemplateMonad {
+  142     runTemplateMonad :: Node
+  143                      -> TemplateState m
+  144                      -> m (a, TemplateState m)
+  145 }
+  146 
+  147 
+  148 ------------------------------------------------------------------------------
+  149 -- | Evaluates a template monad as a computation in the underlying monad.
+  150 evalTemplateMonad :: Monad m
+  151                   => TemplateMonad m a
+  152                   -> Node
+  153                   -> TemplateState m
+  154                   -> m a
+  155 evalTemplateMonad m r s = do
+  156     (a, _) <- runTemplateMonad m r s
+  157     return a
+  158   
+  159 ------------------------------------------------------------------------------
+  160 -- | Helper function for the functor instance
+  161 first :: (a -> b) -> (a, c) -> (b, c)
+  162 first f (a,b) = (f a, b)
+  163 
+  164 
+  165 ------------------------------------------------------------------------------
+  166 -- | Functor instance
+  167 instance Functor m => Functor (TemplateMonad m) where
+  168     fmap f (TemplateMonad m) = TemplateMonad $ \r s -> first f <$> m r s
+  169 
+  170 
+  171 ------------------------------------------------------------------------------
+  172 -- | Applicative instance
+  173 instance (Monad m, Functor m) => Applicative (TemplateMonad m) where
+  174     pure = return
+  175     (<*>) = ap
+  176 
+  177 
+  178 ------------------------------------------------------------------------------
+  179 -- | Monad instance
+  180 instance Monad m => Monad (TemplateMonad m) where
+  181     return a = TemplateMonad (\_ s -> return (a, s))
+  182     TemplateMonad m >>= k = TemplateMonad $ \r s -> do
+  183         (a, s') <- m r s
+  184         runTemplateMonad (k a) r s'
+  185 
+  186 
+  187 ------------------------------------------------------------------------------
+  188 -- | MonadIO instance
+  189 instance MonadIO m => MonadIO (TemplateMonad m) where
+  190     liftIO = lift . liftIO
+  191 
+  192 
+  193 ------------------------------------------------------------------------------
+  194 -- | MonadTrans instance
+  195 instance MonadTrans TemplateMonad where
+  196     lift m = TemplateMonad $ \_ s -> do
+  197         a <- m
+  198         return (a, s)
+  199 
+  200 
+  201 ------------------------------------------------------------------------------
+  202 -- | MonadFix passthrough instance
+  203 instance MonadFix m => MonadFix (TemplateMonad m) where
+  204     mfix f = TemplateMonad $ \r s ->
+  205         mfix $ \ (a, _) -> runTemplateMonad (f a) r s
+  206 
+  207 
+  208 ------------------------------------------------------------------------------
+  209 -- | Alternative passthrough instance
+  210 instance (Functor m, MonadPlus m) => Alternative (TemplateMonad m) where
+  211     empty = mzero
+  212     (<|>) = mplus
+  213 
+  214 
+  215 ------------------------------------------------------------------------------
+  216 -- | MonadPlus passthrough instance
+  217 instance MonadPlus m => MonadPlus (TemplateMonad m) where
+  218     mzero = lift mzero
+  219     m `mplus` n = TemplateMonad $ \r s ->
+  220         runTemplateMonad m r s `mplus` runTemplateMonad n r s
+  221 
+  222 
+  223 ------------------------------------------------------------------------------
+  224 -- | MonadState passthrough instance
+  225 instance MonadState s m => MonadState s (TemplateMonad m) where
+  226     get = lift get
+  227     put = lift . put
+  228 
+  229 
+  230 ------------------------------------------------------------------------------
+  231 -- | MonadReader passthrough instance
+  232 instance MonadReader r m => MonadReader r (TemplateMonad m) where
+  233     ask = TemplateMonad $ \_ s -> do
+  234             r <- ask
+  235             return (r,s)
+  236     local f (TemplateMonad m) =
+  237         TemplateMonad $ \r s -> local f (m r s)
+  238 
+  239 
+  240 ------------------------------------------------------------------------------
+  241 -- | Helper for MonadError instance.
+  242 liftCatch :: (m (a,TemplateState m)
+  243               -> (e -> m (a,TemplateState m))
+  244               -> m (a,TemplateState m))
+  245           -> TemplateMonad m a
+  246           -> (e -> TemplateMonad m a)
+  247           -> TemplateMonad m a
+  248 liftCatch ce m h =
+  249     TemplateMonad $ \r s ->
+  250         (runTemplateMonad m r s `ce`
+  251         (\e -> runTemplateMonad (h e) r s))
+  252 
+  253 
+  254 ------------------------------------------------------------------------------
+  255 -- | MonadError passthrough instance
+  256 instance (MonadError e m) => MonadError e (TemplateMonad m) where
+  257     throwError = lift . throwError
+  258     catchError = liftCatch catchError
+  259 
+  260 
+  261 ------------------------------------------------------------------------------
+  262 -- | Helper for MonadCont instance.
+  263 liftCallCC :: ((((a,TemplateState m) -> m (b, TemplateState m))
+  264                   -> m (a, TemplateState m))
+  265                 -> m (a, TemplateState m))
+  266            -> ((a -> TemplateMonad m b) -> TemplateMonad m a)
+  267            -> TemplateMonad m a
+  268 liftCallCC ccc f = TemplateMonad $ \r s ->
+  269     ccc $ \c ->
+  270     runTemplateMonad (f (\a -> TemplateMonad $ \_ _ -> c (a, s))) r s
+  271 
+  272 
+  273 ------------------------------------------------------------------------------
+  274 -- | MonadCont passthrough instance
+  275 instance (MonadCont m) => MonadCont (TemplateMonad m) where
+  276     callCC = liftCallCC callCC
+  277 
+  278 
+  279 ------------------------------------------------------------------------------
+  280 -- | The Typeable instance is here so Heist can be dynamically executed with
+  281 -- Hint.
+  282 instance (Typeable1 m, Typeable a) => Typeable (TemplateMonad m a) where
+  283     typeOf _ = mkTyConApp tCon [mRep, aRep]
+  284       where
+  285         tCon = mkTyCon "TemplateMonad"
+  286         maRep = typeOf (undefined :: m a)
+  287         (mCon, [aRep]) = splitTyConApp maRep
+  288         mRep = mkTyConApp mCon []
+  289 
+  290 
+  291 ------------------------------------------------------------------------------
+  292 -- Functions for our monad.
+  293 ------------------------------------------------------------------------------
+  294 
+  295 
+  296 ------------------------------------------------------------------------------
+  297 -- | Gets the node currently being processed.
+  298 --
+  299 --   > <speech author="Shakespeare">
+  300 --   >   To sleep, perchance to dream.
+  301 --   > </speech>
+  302 --
+  303 -- When you call @getParamNode@ inside the code for the @speech@ splice, it
+  304 -- returns the Node for the @speech@ tag and its children.  @getParamNode >>=
+  305 -- getChildren@ returns a list containing one 'Text' node containing part of
+  306 -- Hamlet's speech.  @getParamNode >>= getAttribute \"author\"@ would return
+  307 -- @Just "Shakespeare"@.
+  308 getParamNode :: Monad m => TemplateMonad m Node
+  309 getParamNode = TemplateMonad $ \r s -> return (r,s)
+  310 
+  311 
+  312 ------------------------------------------------------------------------------
+  313 -- | TemplateMonad's local
+  314 localParamNode :: Monad m
+  315                => (Node -> Node)
+  316                -> TemplateMonad m a
+  317                -> TemplateMonad m a
+  318 localParamNode f m = TemplateMonad $ \r s -> runTemplateMonad m (f r) s
+  319 
+  320 
+  321 ------------------------------------------------------------------------------
+  322 -- | TemplateMonad's gets
+  323 getsTS :: Monad m => (TemplateState m -> r) -> TemplateMonad m r
+  324 getsTS f = TemplateMonad $ \_ s -> return (f s, s)
+  325 
+  326 
+  327 ------------------------------------------------------------------------------
+  328 -- | TemplateMonad's get
+  329 getTS :: Monad m => TemplateMonad m (TemplateState m)
+  330 getTS = TemplateMonad $ \_ s -> return (s, s)
+  331 
+  332 
+  333 ------------------------------------------------------------------------------
+  334 -- | TemplateMonad's put
+  335 putTS :: Monad m => TemplateState m -> TemplateMonad m ()
+  336 putTS s = TemplateMonad $ \_ _ -> return ((), s)
+  337 
+  338 
+  339 ------------------------------------------------------------------------------
+  340 -- | TemplateMonad's modify
+  341 modifyTS :: Monad m
+  342                     => (TemplateState m -> TemplateState m)
+  343                     -> TemplateMonad m ()
+  344 modifyTS f = TemplateMonad $ \_ s -> return ((), f s)
+  345 
+  346 
+
+
+ diff --git a/static/docs/heist-hpc/Text.Templating.Heist.hs.html b/static/docs/heist-hpc/Text.Templating.Heist.hs.html index 6bb3209..83efca2 100644 --- a/static/docs/heist-hpc/Text.Templating.Heist.hs.html +++ b/static/docs/heist-hpc/Text.Templating.Heist.hs.html @@ -75,8 +75,8 @@ 64 ( 65 -- * Types 66 Node - 67 , Splice - 68 , Template + 67 , Template + 68 , Splice 69 , TemplateMonad 70 , TemplateState 71 @@ -101,59 +101,55 @@ 90 , getContext 91 92 -- * Functions for running splices and templates - 93 , runTemplate - 94 , evalTemplate - 95 , callTemplate - 96 , renderTemplate - 97 , bindStrings - 98 - 99 -- * Misc functions - 100 , runSplice - 101 , runRawTemplate - 102 , getDoc - 103 , bindStaticTag - 104 - 105 , heistExpatOptions - 106 , module Text.Templating.Heist.Constants - 107 ) where - 108 - 109 import Control.Monad.Trans - 110 import qualified Data.Map as Map - 111 import Text.Templating.Heist.Internal - 112 import Text.Templating.Heist.Constants - 113 import Text.Templating.Heist.Splices - 114 - 115 - 116 ------------------------------------------------------------------------------ - 117 -- | The default set of built-in splices. - 118 defaultSpliceMap :: MonadIO m => SpliceMap m - 119 defaultSpliceMap = Map.fromList - 120 [(applyTag, applyImpl) - 121 ,(bindTag, bindImpl) - 122 ,(ignoreTag, ignoreImpl) - 123 ,(markdownTag, markdownSplice) - 124 ] - 125 - 126 - 127 ------------------------------------------------------------------------------ - 128 -- | An empty template state, with Heist's default splices (@\<bind\>@ and - 129 -- @\<apply\>@) mapped. - 130 emptyTemplateState :: MonadIO m => TemplateState m - 131 emptyTemplateState = TemplateState defaultSpliceMap Map.empty True [] 0 - 132 return return return - 133 - 134 - 135 -- $hookDoc - 136 -- Heist hooks allow you to modify templates when they are loaded and before - 137 -- and after they are run. Every time you call one of the addAbcHook - 138 -- functions the hook is added to onto the processing pipeline. The hooks - 139 -- processes the template in the order that they were added to the - 140 -- TemplateState. - 141 -- - 142 -- The pre-run and post-run hooks are run before and after every template is - 143 -- run/rendered. You should be careful what code you put in these hooks - 144 -- because it can significantly affect the performance of your site. - 145 + 93 , evalTemplate + 94 , callTemplate + 95 , renderTemplate + 96 , bindStrings + 97 + 98 -- * Misc functions + 99 , getDoc + 100 , bindStaticTag + 101 + 102 ) where + 103 + 104 import Control.Monad.Trans + 105 import qualified Data.Map as Map + 106 import Text.Templating.Heist.Internal + 107 import Text.Templating.Heist.Splices + 108 import Text.Templating.Heist.Types + 109 + 110 + 111 ------------------------------------------------------------------------------ + 112 -- | The default set of built-in splices. + 113 defaultSpliceMap :: MonadIO m => SpliceMap m + 114 defaultSpliceMap = Map.fromList + 115 [(applyTag, applyImpl) + 116 ,(bindTag, bindImpl) + 117 ,(ignoreTag, ignoreImpl) + 118 ,(markdownTag, markdownSplice) + 119 ] + 120 + 121 + 122 ------------------------------------------------------------------------------ + 123 -- | An empty template state, with Heist's default splices (@\<apply\>@, + 124 -- @\<bind\>@, @\<ignore\>@, and @\<markdown\>@) mapped. The static tag is + 125 -- not mapped here because it must be mapped manually in your application. + 126 emptyTemplateState :: MonadIO m => TemplateState m + 127 emptyTemplateState = TemplateState defaultSpliceMap Map.empty True [] 0 + 128 return return return [] + 129 + 130 + 131 -- $hookDoc + 132 -- Heist hooks allow you to modify templates when they are loaded and before + 133 -- and after they are run. Every time you call one of the addAbcHook + 134 -- functions the hook is added to onto the processing pipeline. The hooks + 135 -- processes the template in the order that they were added to the + 136 -- TemplateState. + 137 -- + 138 -- The pre-run and post-run hooks are run before and after every template is + 139 -- run/rendered. You should be careful what code you put in these hooks + 140 -- because it can significantly affect the performance of your site. + 141 diff --git a/static/docs/heist-hpc/hpc_index.html b/static/docs/heist-hpc/hpc_index.html index b1e5f6d..56875d0 100644 --- a/static/docs/heist-hpc/hpc_index.html +++ b/static/docs/heist-hpc/hpc_index.html @@ -8,19 +8,19 @@ - + - + - + - + @@ -35,8 +35,11 @@ - + + + + - +
moduleTop Level DefinitionsAlternativesExpressions
%covered / total%covered / total%covered / total
  module Text.Templating.Heist100%2/2
0/0 91%21/23
100%2/2
0/0 91%22/24
  module Text.Templating.Heist.Constants0%0/1
0/0 0%0/740
50%1/2
0/0 0%5/749
  module Text.Templating.Heist.Internal70%29/41
75%15/20
62%314/501
79%38/48
77%24/31
78%480/609
  module Text.Templating.Heist.Splices 0/0 0/0 0/0 
  module Text.Templating.Heist.Splices.Apply100%3/3
50%2/4
84%42/50
100%3/3
100%4/4
98%57/58
  module Text.Templating.Heist.Splices.Bind 100%3/3
0/0 91%21/23
0%0/3
0%0/6
0%0/134
  module Text.Templating.Heist.Tests80%32/40
57%12/21
75%479/633
79%35/44
57%12/21
77%582/755
  module Text.Templating.Heist.Types35%13/37
0/0 44%120/270
  Program Coverage Total68%71/104
49%29/59
38%879/2280
63%97/153
57%40/70
46%1289/2798
diff --git a/static/docs/heist-hpc/hpc_index_alt.html b/static/docs/heist-hpc/hpc_index_alt.html index cb54c30..7bd96ce 100644 --- a/static/docs/heist-hpc/hpc_index_alt.html +++ b/static/docs/heist-hpc/hpc_index_alt.html @@ -7,14 +7,14 @@ + + + - + - - - - + @@ -22,11 +22,14 @@ + + + - + - + @@ -38,5 +41,5 @@ - +
moduleTop Level DefinitionsAlternativesExpressions
%covered / total%covered / total%covered / total
  module Text.Templating.Heist.Splices.Apply100%3/3
100%4/4
98%57/58
  module Text.Templating.Heist.Internal70%29/41
75%15/20
62%314/501
79%38/48
77%24/31
78%480/609
  module Text.Templating.Heist.Tests80%32/40
57%12/21
75%479/633
  module Text.Templating.Heist.Splices.Apply100%3/3
50%2/4
84%42/50
79%35/44
57%12/21
77%582/755
  module Text.Templating.Heist.Splices.Static 0%0/3
0%0/6
0%0/134
  module Text.Templating.Heist.Splices.Markdown 11%1/9
0%0/8
0%1/173
  module Text.Templating.Heist.Types35%13/37
0/0 44%120/270
  module Text.Templating.Heist.Constants0%0/1
0/0 0%0/740
50%1/2
0/0 0%5/749
  module Text.Templating.Heist100%2/2
0/0 91%21/23
100%2/2
0/0 91%22/24
  module Text.Templating.Heist.Splices 0/0 0/0 0/0 
100%3/3
0/0 91%21/23
  Program Coverage Total68%71/104
49%29/59
38%879/2280
63%97/153
57%40/70
46%1289/2798
diff --git a/static/docs/heist-hpc/hpc_index_exp.html b/static/docs/heist-hpc/hpc_index_exp.html index 426bb7b..d28235c 100644 --- a/static/docs/heist-hpc/hpc_index_exp.html +++ b/static/docs/heist-hpc/hpc_index_exp.html @@ -7,26 +7,29 @@ + + + - + - - + + - + - - + + - + @@ -38,5 +41,5 @@ - +
moduleTop Level DefinitionsAlternativesExpressions
%covered / total%covered / total%covered / total
  module Text.Templating.Heist.Splices.Apply100%3/3
100%4/4
98%57/58
  module Text.Templating.Heist100%2/2
0/0 91%21/23
100%2/2
0/0 91%22/24
  module Text.Templating.Heist.Splices.Bind 100%3/3
0/0 91%21/23
  module Text.Templating.Heist.Splices.Apply100%3/3
50%2/4
84%42/50
  module Text.Templating.Heist.Internal79%38/48
77%24/31
78%480/609
  module Text.Templating.Heist.Tests80%32/40
57%12/21
75%479/633
79%35/44
57%12/21
77%582/755
  module Text.Templating.Heist.Internal70%29/41
75%15/20
62%314/501
  module Text.Templating.Heist.Types35%13/37
0/0 44%120/270
  module Text.Templating.Heist.Splices.Ignore 50%1/2
0/0 33%1/3
  module Text.Templating.Heist.Constants0%0/1
0/0 0%0/740
50%1/2
0/0 0%5/749
  module Text.Templating.Heist.Splices.Static 0%0/3
0%0/6
0%0/134
0/0 0/0 0/0 
  Program Coverage Total68%71/104
49%29/59
38%879/2280
63%97/153
57%40/70
46%1289/2798
diff --git a/static/docs/heist-hpc/hpc_index_fun.html b/static/docs/heist-hpc/hpc_index_fun.html index 433e054..beccf00 100644 --- a/static/docs/heist-hpc/hpc_index_fun.html +++ b/static/docs/heist-hpc/hpc_index_fun.html @@ -7,30 +7,33 @@ + + + - + - - - - + - + + + + + + + - - - @@ -38,5 +41,5 @@ - +
moduleTop Level DefinitionsAlternativesExpressions
%covered / total%covered / total%covered / total
  module Text.Templating.Heist.Splices.Apply100%3/3
100%4/4
98%57/58
  module Text.Templating.Heist100%2/2
0/0 91%21/23
100%2/2
0/0 91%22/24
  module Text.Templating.Heist.Splices.Bind 100%3/3
0/0 91%21/23
  module Text.Templating.Heist.Splices.Apply100%3/3
50%2/4
84%42/50
  module Text.Templating.Heist.Tests80%32/40
57%12/21
75%479/633
79%35/44
57%12/21
77%582/755
  module Text.Templating.Heist.Internal70%29/41
75%15/20
62%314/501
79%38/48
77%24/31
78%480/609
  module Text.Templating.Heist.Constants50%1/2
0/0 0%5/749
  module Text.Templating.Heist.Splices.Ignore 50%1/2
0/0 33%1/3
  module Text.Templating.Heist.Types35%13/37
0/0 44%120/270
  module Text.Templating.Heist.Splices.Markdown 11%1/9
0%0/8
0%1/173
  module Text.Templating.Heist.Constants0%0/1
0/0 0%0/740
  module Text.Templating.Heist.Splices.Static 0%0/3
0%0/6
0%0/134
0/0 0/0 0/0 
  Program Coverage Total68%71/104
49%29/59
38%879/2280
63%97/153
57%40/70
46%1289/2798
diff --git a/static/docs/snap-core-hpc/Snap.Internal.Http.Types.hs.html b/static/docs/snap-core-hpc/Snap.Internal.Http.Types.hs.html index 09df623..f969458 100644 --- a/static/docs/snap-core-hpc/Snap.Internal.Http.Types.hs.html +++ b/static/docs/snap-core-hpc/Snap.Internal.Http.Types.hs.html @@ -40,658 +40,659 @@ 29 import Data.Char 30 import Data.DList (DList) 31 import qualified Data.DList as DL - 32 import Data.IORef - 33 import Data.Map (Map) - 34 import qualified Data.Map as Map - 35 import Data.Monoid - 36 import Data.Serialize.Builder - 37 import Data.Time.Clock - 38 import Data.Time.Format - 39 import Data.Word - 40 import Foreign hiding (new) - 41 import Foreign.C.Types - 42 import Prelude hiding (take) - 43 import System.Locale (defaultTimeLocale) - 44 + 32 import Data.Int + 33 import Data.IORef + 34 import Data.Map (Map) + 35 import qualified Data.Map as Map + 36 import Data.Monoid + 37 import Data.Serialize.Builder + 38 import Data.Time.Clock + 39 import Data.Time.Format + 40 import Data.Word + 41 import Foreign hiding (new) + 42 import Foreign.C.Types + 43 import Prelude hiding (take) + 44 import System.Locale (defaultTimeLocale) 45 - 46 #ifdef PORTABLE - 47 import Data.Time.LocalTime - 48 import Data.Time.Clock.POSIX - 49 #else - 50 import Foreign.C.String - 51 #endif - 52 - 53 ------------------------------------------------------------------------------ - 54 import Data.CIByteString - 55 import qualified Snap.Iteratee as I - 56 + 46 + 47 #ifdef PORTABLE + 48 import Data.Time.LocalTime + 49 import Data.Time.Clock.POSIX + 50 #else + 51 import Foreign.C.String + 52 #endif + 53 + 54 ------------------------------------------------------------------------------ + 55 import Data.CIByteString + 56 import qualified Snap.Iteratee as I 57 - 58 #ifndef PORTABLE - 59 - 60 ------------------------------------------------------------------------------ - 61 -- foreign imports from cbits - 62 - 63 foreign import ccall unsafe "set_c_locale" - 64 set_c_locale :: IO () - 65 - 66 foreign import ccall unsafe "c_parse_http_time" - 67 c_parse_http_time :: CString -> IO CTime - 68 - 69 foreign import ccall unsafe "c_format_http_time" - 70 c_format_http_time :: CTime -> CString -> IO () - 71 - 72 foreign import ccall unsafe "c_format_log_time" - 73 c_format_log_time :: CTime -> CString -> IO () - 74 - 75 #endif - 76 - 77 ------------------------------------------------------------------------------ - 78 type Enumerator a = I.Enumerator IO a - 79 - 80 ------------------------------------------------------------------------------ - 81 -- | A type alias for a case-insensitive key-value mapping. - 82 type Headers = Map CIByteString [ByteString] - 83 + 58 + 59 #ifndef PORTABLE + 60 + 61 ------------------------------------------------------------------------------ + 62 -- foreign imports from cbits + 63 + 64 foreign import ccall unsafe "set_c_locale" + 65 set_c_locale :: IO () + 66 + 67 foreign import ccall unsafe "c_parse_http_time" + 68 c_parse_http_time :: CString -> IO CTime + 69 + 70 foreign import ccall unsafe "c_format_http_time" + 71 c_format_http_time :: CTime -> CString -> IO () + 72 + 73 foreign import ccall unsafe "c_format_log_time" + 74 c_format_log_time :: CTime -> CString -> IO () + 75 + 76 #endif + 77 + 78 ------------------------------------------------------------------------------ + 79 type Enumerator a = I.Enumerator IO a + 80 + 81 ------------------------------------------------------------------------------ + 82 -- | A type alias for a case-insensitive key-value mapping. + 83 type Headers = Map CIByteString [ByteString] 84 - 85 ------------------------------------------------------------------------------ - 86 -- | A typeclass for datatypes which contain HTTP headers. - 87 class HasHeaders a where - 88 - 89 -- | Modify the datatype's headers. - 90 updateHeaders :: (Headers -> Headers) -> a -> a - 91 - 92 -- | Retrieve the headers from a datatype that has headers. - 93 headers :: a -> Headers - 94 + 85 + 86 ------------------------------------------------------------------------------ + 87 -- | A typeclass for datatypes which contain HTTP headers. + 88 class HasHeaders a where + 89 + 90 -- | Modify the datatype's headers. + 91 updateHeaders :: (Headers -> Headers) -> a -> a + 92 + 93 -- | Retrieve the headers from a datatype that has headers. + 94 headers :: a -> Headers 95 - 96 ------------------------------------------------------------------------------ - 97 -- | Adds a header key-value-pair to the 'HasHeaders' datatype. If a header with - 98 -- the same name already exists, the new value is appended to the headers list. - 99 addHeader :: (HasHeaders a) => CIByteString -> ByteString -> a -> a - 100 addHeader k v = updateHeaders $ Map.insertWith' (++) k [v] - 101 + 96 + 97 ------------------------------------------------------------------------------ + 98 -- | Adds a header key-value-pair to the 'HasHeaders' datatype. If a header with + 99 -- the same name already exists, the new value is appended to the headers list. + 100 addHeader :: (HasHeaders a) => CIByteString -> ByteString -> a -> a + 101 addHeader k v = updateHeaders $ Map.insertWith' (++) k [v] 102 - 103 ------------------------------------------------------------------------------ - 104 -- | Sets a header key-value-pair in a 'HasHeaders' datatype. If a header with - 105 -- the same name already exists, it is overwritten with the new value. - 106 setHeader :: (HasHeaders a) => CIByteString -> ByteString -> a -> a - 107 setHeader k v = updateHeaders $ Map.insert k [v] - 108 + 103 + 104 ------------------------------------------------------------------------------ + 105 -- | Sets a header key-value-pair in a 'HasHeaders' datatype. If a header with + 106 -- the same name already exists, it is overwritten with the new value. + 107 setHeader :: (HasHeaders a) => CIByteString -> ByteString -> a -> a + 108 setHeader k v = updateHeaders $ Map.insert k [v] 109 - 110 ------------------------------------------------------------------------------ - 111 -- | Gets all of the values for a given header. - 112 getHeaders :: (HasHeaders a) => CIByteString -> a -> Maybe [ByteString] - 113 getHeaders k a = Map.lookup k $ headers a - 114 + 110 + 111 ------------------------------------------------------------------------------ + 112 -- | Gets all of the values for a given header. + 113 getHeaders :: (HasHeaders a) => CIByteString -> a -> Maybe [ByteString] + 114 getHeaders k a = Map.lookup k $ headers a 115 - 116 ------------------------------------------------------------------------------ - 117 -- | Gets a header value out of a 'HasHeaders' datatype. If many headers came - 118 -- in with the same name, they will be catenated together. - 119 getHeader :: (HasHeaders a) => CIByteString -> a -> Maybe ByteString - 120 getHeader k a = liftM (S.intercalate " ") (Map.lookup k $ headers a) - 121 + 116 + 117 ------------------------------------------------------------------------------ + 118 -- | Gets a header value out of a 'HasHeaders' datatype. If many headers came + 119 -- in with the same name, they will be catenated together. + 120 getHeader :: (HasHeaders a) => CIByteString -> a -> Maybe ByteString + 121 getHeader k a = liftM (S.intercalate " ") (Map.lookup k $ headers a) 122 - 123 ------------------------------------------------------------------------------ - 124 -- | Enumerates the HTTP method values (see - 125 -- <http://tools.ietf.org/html/rfc2068.html#section-5.1.1>). - 126 data Method = GET | HEAD | POST | PUT | DELETE | TRACE | OPTIONS | CONNECT - 127 deriving(Show,Read,Ord,Eq) - 128 + 123 + 124 ------------------------------------------------------------------------------ + 125 -- | Enumerates the HTTP method values (see + 126 -- <http://tools.ietf.org/html/rfc2068.html#section-5.1.1>). + 127 data Method = GET | HEAD | POST | PUT | DELETE | TRACE | OPTIONS | CONNECT + 128 deriving(Show,Read,Ord,Eq) 129 - 130 ------------------------------------------------------------------------------ - 131 type HttpVersion = (Int,Int) - 132 + 130 + 131 ------------------------------------------------------------------------------ + 132 type HttpVersion = (Int,Int) 133 - 134 ------------------------------------------------------------------------------ - 135 -- | A datatype representing an HTTP cookie. - 136 data Cookie = Cookie { - 137 -- | The name of the cookie. - 138 cookieName :: !ByteString - 139 - 140 -- | The cookie's string value. - 141 , cookieValue :: !ByteString - 142 - 143 -- | The cookie's expiration value, if it has one. - 144 , cookieExpires :: !(Maybe UTCTime) - 145 - 146 -- | The cookie's \"domain\" value, if it has one. - 147 , cookieDomain :: !(Maybe ByteString) - 148 - 149 -- | The cookie path. - 150 , cookiePath :: !(Maybe ByteString) - 151 } deriving (Eq, Show) - 152 + 134 + 135 ------------------------------------------------------------------------------ + 136 -- | A datatype representing an HTTP cookie. + 137 data Cookie = Cookie { + 138 -- | The name of the cookie. + 139 cookieName :: !ByteString + 140 + 141 -- | The cookie's string value. + 142 , cookieValue :: !ByteString + 143 + 144 -- | The cookie's expiration value, if it has one. + 145 , cookieExpires :: !(Maybe UTCTime) + 146 + 147 -- | The cookie's \"domain\" value, if it has one. + 148 , cookieDomain :: !(Maybe ByteString) + 149 + 150 -- | The cookie path. + 151 , cookiePath :: !(Maybe ByteString) + 152 } deriving (Eq, Show) 153 - 154 ------------------------------------------------------------------------------ - 155 -- | A type alias for the HTTP parameters mapping. Each parameter - 156 -- key maps to a list of ByteString values; if a parameter is specified - 157 -- multiple times (e.g.: \"@GET /foo?param=bar1&param=bar2@\"), looking up - 158 -- \"@param@\" in the mapping will give you @[\"bar1\", \"bar2\"]@. - 159 type Params = Map ByteString [ByteString] - 160 + 154 + 155 ------------------------------------------------------------------------------ + 156 -- | A type alias for the HTTP parameters mapping. Each parameter + 157 -- key maps to a list of ByteString values; if a parameter is specified + 158 -- multiple times (e.g.: \"@GET /foo?param=bar1&param=bar2@\"), looking up + 159 -- \"@param@\" in the mapping will give you @[\"bar1\", \"bar2\"]@. + 160 type Params = Map ByteString [ByteString] 161 - 162 ------------------------------------------------------------------------------ - 163 -- request type - 164 ------------------------------------------------------------------------------ - 165 - 166 data SomeEnumerator = SomeEnumerator (forall a . Enumerator a) - 167 + 162 + 163 ------------------------------------------------------------------------------ + 164 -- request type + 165 ------------------------------------------------------------------------------ + 166 + 167 data SomeEnumerator = SomeEnumerator (forall a . Enumerator a) 168 - 169 ------------------------------------------------------------------------------ - 170 -- | Contains all of the information about an incoming HTTP request. - 171 data Request = Request - 172 { -- | The server name of the request, as it came in from the request's - 173 -- @Host:@ header. - 174 rqServerName :: !ByteString - 175 - 176 -- | Returns the port number the HTTP server is listening on. - 177 , rqServerPort :: !Int - 178 - 179 -- | The remote IP address. - 180 , rqRemoteAddr :: !ByteString - 181 - 182 -- | The remote TCP port number. - 183 , rqRemotePort :: !Int - 184 - 185 -- | The local IP address for this request. - 186 , rqLocalAddr :: !ByteString - 187 - 188 -- | Returns the port number the HTTP server is listening on. - 189 , rqLocalPort :: !Int - 190 - 191 -- | Returns the HTTP server's idea of its local hostname. - 192 , rqLocalHostname :: !ByteString - 193 - 194 -- | Returns @True@ if this is an @HTTPS@ session (currently always - 195 -- @False@). - 196 , rqIsSecure :: !Bool - 197 , rqHeaders :: Headers - 198 , rqBody :: IORef SomeEnumerator - 199 - 200 -- | Returns the @Content-Length@ of the HTTP request body. - 201 , rqContentLength :: !(Maybe Int) - 202 - 203 -- | Returns the HTTP request method. - 204 , rqMethod :: !Method - 205 - 206 -- | Returns the HTTP version used by the client. - 207 , rqVersion :: !HttpVersion - 208 - 209 -- | Returns a list of the cookies that came in from the HTTP request - 210 -- headers. - 211 , rqCookies :: [Cookie] - 212 + 169 + 170 ------------------------------------------------------------------------------ + 171 -- | Contains all of the information about an incoming HTTP request. + 172 data Request = Request + 173 { -- | The server name of the request, as it came in from the request's + 174 -- @Host:@ header. + 175 rqServerName :: !ByteString + 176 + 177 -- | Returns the port number the HTTP server is listening on. + 178 , rqServerPort :: !Int + 179 + 180 -- | The remote IP address. + 181 , rqRemoteAddr :: !ByteString + 182 + 183 -- | The remote TCP port number. + 184 , rqRemotePort :: !Int + 185 + 186 -- | The local IP address for this request. + 187 , rqLocalAddr :: !ByteString + 188 + 189 -- | Returns the port number the HTTP server is listening on. + 190 , rqLocalPort :: !Int + 191 + 192 -- | Returns the HTTP server's idea of its local hostname. + 193 , rqLocalHostname :: !ByteString + 194 + 195 -- | Returns @True@ if this is an @HTTPS@ session (currently always + 196 -- @False@). + 197 , rqIsSecure :: !Bool + 198 , rqHeaders :: Headers + 199 , rqBody :: IORef SomeEnumerator + 200 + 201 -- | Returns the @Content-Length@ of the HTTP request body. + 202 , rqContentLength :: !(Maybe Int) + 203 + 204 -- | Returns the HTTP request method. + 205 , rqMethod :: !Method + 206 + 207 -- | Returns the HTTP version used by the client. + 208 , rqVersion :: !HttpVersion + 209 + 210 -- | Returns a list of the cookies that came in from the HTTP request + 211 -- headers. + 212 , rqCookies :: [Cookie] 213 - 214 -- | We'll be doing web components (or \"snaplets\") for version 0.2. The - 215 -- \"snaplet path\" refers to the place on the URL where your containing - 216 -- snaplet is hung. The value of 'rqSnapletPath' is either @\"\"@ (at the - 217 -- top-level context) or is a path beginning with a slash, but not ending - 218 -- with one. - 219 -- - 220 -- An identity is that: - 221 -- - 222 -- > rqURI r == 'S.concat' [ rqSnapletPath r - 223 -- > , rqContextPath r - 224 -- > , rqPathInfo r ] - 225 -- - 226 -- note that until we introduce snaplets in v0.2, 'rqSnapletPath' will be - 227 -- \"\" - 228 , rqSnapletPath :: !ByteString - 229 - 230 -- | Handlers can (/will be; --ed/) be hung on a @URI@ \"entry point\"; - 231 -- this is called the \"context path\". If a handler is hung on the - 232 -- context path @\"\/foo\/\"@, and you request @\"\/foo\/bar\"@, the value - 233 -- of 'rqPathInfo' will be @\"bar\"@. - 234 , rqPathInfo :: !ByteString - 235 - 236 -- | The \"context path\" of the request; catenating 'rqContextPath', and - 237 -- 'rqPathInfo' should get you back to the original 'rqURI'. The - 238 -- 'rqContextPath' always begins and ends with a slash (@\"\/\"@) - 239 -- character, and represents the path (relative to your - 240 -- component\/snaplet) you took to get to your handler. - 241 , rqContextPath :: !ByteString - 242 - 243 -- | Returns the @URI@ requested by the client. - 244 , rqURI :: !ByteString - 245 - 246 -- | Returns the HTTP query string for this 'Request'. - 247 , rqQueryString :: !ByteString - 248 - 249 -- | Returns the 'Params' mapping for this 'Request'. \"Parameters\" are - 250 -- automatically decoded from the query string and @POST@ body and - 251 -- entered into this mapping. - 252 , rqParams :: Params - 253 } - 254 + 214 + 215 -- | We'll be doing web components (or \"snaplets\") for version 0.2. The + 216 -- \"snaplet path\" refers to the place on the URL where your containing + 217 -- snaplet is hung. The value of 'rqSnapletPath' is either @\"\"@ (at the + 218 -- top-level context) or is a path beginning with a slash, but not ending + 219 -- with one. + 220 -- + 221 -- An identity is that: + 222 -- + 223 -- > rqURI r == 'S.concat' [ rqSnapletPath r + 224 -- > , rqContextPath r + 225 -- > , rqPathInfo r ] + 226 -- + 227 -- note that until we introduce snaplets in v0.2, 'rqSnapletPath' will be + 228 -- \"\" + 229 , rqSnapletPath :: !ByteString + 230 + 231 -- | Handlers can (/will be; --ed/) be hung on a @URI@ \"entry point\"; + 232 -- this is called the \"context path\". If a handler is hung on the + 233 -- context path @\"\/foo\/\"@, and you request @\"\/foo\/bar\"@, the value + 234 -- of 'rqPathInfo' will be @\"bar\"@. + 235 , rqPathInfo :: !ByteString + 236 + 237 -- | The \"context path\" of the request; catenating 'rqContextPath', and + 238 -- 'rqPathInfo' should get you back to the original 'rqURI'. The + 239 -- 'rqContextPath' always begins and ends with a slash (@\"\/\"@) + 240 -- character, and represents the path (relative to your + 241 -- component\/snaplet) you took to get to your handler. + 242 , rqContextPath :: !ByteString + 243 + 244 -- | Returns the @URI@ requested by the client. + 245 , rqURI :: !ByteString + 246 + 247 -- | Returns the HTTP query string for this 'Request'. + 248 , rqQueryString :: !ByteString + 249 + 250 -- | Returns the 'Params' mapping for this 'Request'. \"Parameters\" are + 251 -- automatically decoded from the query string and @POST@ body and + 252 -- entered into this mapping. + 253 , rqParams :: Params + 254 } 255 - 256 ------------------------------------------------------------------------------ - 257 instance Show Request where - 258 show r = concat [ "Request <\n" - 259 , body - 260 , ">" ] - 261 where - 262 body = concat $ map ((" "++) . (++ "\n")) [ - 263 sname - 264 , remote - 265 , local - 266 , beginheaders - 267 , hdrs - 268 , endheaders - 269 , contentlength - 270 , method - 271 , version - 272 , cookies - 273 , pathinfo - 274 , contextpath - 275 , snapletpath - 276 , uri - 277 , params - 278 ] - 279 - 280 sname = concat [ "server-name: ", toStr $ rqServerName r ] - 281 remote = concat [ "remote: " - 282 , toStr $ rqRemoteAddr r - 283 , ":" - 284 , show (rqRemotePort r) - 285 ] - 286 local = concat [ "local: " - 287 , toStr $ rqLocalAddr r - 288 , ":" - 289 , show $ rqServerPort r - 290 ] - 291 beginheaders = "Headers:\n ========================================" - 292 endheaders = " ========================================" - 293 hdrs = " " ++ show (rqHeaders r) - 294 contentlength = concat [ "content-length: " - 295 , show $ rqContentLength r - 296 ] - 297 method = concat [ "method: " - 298 , show $ rqMethod r - 299 ] - 300 version = concat [ "version: " - 301 , show $ rqVersion r - 302 ] - 303 cookies = concat [ "cookies:\n" - 304 , " ========================================\n" - 305 , " " ++ (show $ rqCookies r) - 306 , "\n ========================================" - 307 ] - 308 pathinfo = concat [ "pathinfo: ", toStr $ rqPathInfo r ] - 309 contextpath = concat [ "contextpath: ", toStr $ rqContextPath r ] - 310 snapletpath = concat [ "snapletpath: ", toStr $ rqSnapletPath r ] - 311 uri = concat [ "URI: ", toStr $ rqURI r ] - 312 params = concat [ "params:\n" - 313 , " ========================================\n" - 314 , " " ++ (show $ rqParams r) - 315 , "\n ========================================" - 316 ] - 317 + 256 + 257 ------------------------------------------------------------------------------ + 258 instance Show Request where + 259 show r = concat [ "Request <\n" + 260 , body + 261 , ">" ] + 262 where + 263 body = concat $ map ((" "++) . (++ "\n")) [ + 264 sname + 265 , remote + 266 , local + 267 , beginheaders + 268 , hdrs + 269 , endheaders + 270 , contentlength + 271 , method + 272 , version + 273 , cookies + 274 , pathinfo + 275 , contextpath + 276 , snapletpath + 277 , uri + 278 , params + 279 ] + 280 + 281 sname = concat [ "server-name: ", toStr $ rqServerName r ] + 282 remote = concat [ "remote: " + 283 , toStr $ rqRemoteAddr r + 284 , ":" + 285 , show (rqRemotePort r) + 286 ] + 287 local = concat [ "local: " + 288 , toStr $ rqLocalAddr r + 289 , ":" + 290 , show $ rqServerPort r + 291 ] + 292 beginheaders = "Headers:\n ========================================" + 293 endheaders = " ========================================" + 294 hdrs = " " ++ show (rqHeaders r) + 295 contentlength = concat [ "content-length: " + 296 , show $ rqContentLength r + 297 ] + 298 method = concat [ "method: " + 299 , show $ rqMethod r + 300 ] + 301 version = concat [ "version: " + 302 , show $ rqVersion r + 303 ] + 304 cookies = concat [ "cookies:\n" + 305 , " ========================================\n" + 306 , " " ++ (show $ rqCookies r) + 307 , "\n ========================================" + 308 ] + 309 pathinfo = concat [ "pathinfo: ", toStr $ rqPathInfo r ] + 310 contextpath = concat [ "contextpath: ", toStr $ rqContextPath r ] + 311 snapletpath = concat [ "snapletpath: ", toStr $ rqSnapletPath r ] + 312 uri = concat [ "URI: ", toStr $ rqURI r ] + 313 params = concat [ "params:\n" + 314 , " ========================================\n" + 315 , " " ++ (show $ rqParams r) + 316 , "\n ========================================" + 317 ] 318 - 319 ------------------------------------------------------------------------------ - 320 instance HasHeaders Request where - 321 headers = rqHeaders - 322 updateHeaders f r = r { rqHeaders = f (rqHeaders r) } - 323 + 319 + 320 ------------------------------------------------------------------------------ + 321 instance HasHeaders Request where + 322 headers = rqHeaders + 323 updateHeaders f r = r { rqHeaders = f (rqHeaders r) } 324 - 325 ------------------------------------------------------------------------------ - 326 instance HasHeaders Headers where - 327 headers = id - 328 updateHeaders = id - 329 - 330 ------------------------------------------------------------------------------ - 331 -- response type - 332 ------------------------------------------------------------------------------ - 333 - 334 data ResponseBody = Enum (forall a . Enumerator a) -- ^ output body is enumerator - 335 | SendFile FilePath -- ^ output body is sendfile() - 336 + 325 + 326 ------------------------------------------------------------------------------ + 327 instance HasHeaders Headers where + 328 headers = id + 329 updateHeaders = id + 330 + 331 ------------------------------------------------------------------------------ + 332 -- response type + 333 ------------------------------------------------------------------------------ + 334 + 335 data ResponseBody = Enum (forall a . Enumerator a) -- ^ output body is enumerator + 336 | SendFile FilePath -- ^ output body is sendfile() 337 - 338 ------------------------------------------------------------------------------ - 339 rspBodyMap :: (forall a . Enumerator a -> Enumerator a) - 340 -> ResponseBody + 338 + 339 ------------------------------------------------------------------------------ + 340 rspBodyMap :: (forall a . Enumerator a -> Enumerator a) 341 -> ResponseBody - 342 rspBodyMap f b = Enum $ f $ rspBodyToEnum b - 343 + 342 -> ResponseBody + 343 rspBodyMap f b = Enum $ f $ rspBodyToEnum b 344 - 345 ------------------------------------------------------------------------------ - 346 rspBodyToEnum :: ResponseBody -> Enumerator a - 347 rspBodyToEnum (Enum e) = e - 348 rspBodyToEnum (SendFile fp) = I.enumFile fp - 349 + 345 + 346 ------------------------------------------------------------------------------ + 347 rspBodyToEnum :: ResponseBody -> Enumerator a + 348 rspBodyToEnum (Enum e) = e + 349 rspBodyToEnum (SendFile fp) = I.enumFile fp 350 - 351 ------------------------------------------------------------------------------ - 352 -- | Represents an HTTP response. - 353 data Response = Response - 354 { rspHeaders :: Headers - 355 , rspHttpVersion :: !HttpVersion - 356 - 357 -- | We will need to inspect the content length no matter what, and - 358 -- looking up \"content-length\" in the headers and parsing the number - 359 -- out of the text will be too expensive. - 360 , rspContentLength :: !(Maybe Int) - 361 , rspBody :: ResponseBody - 362 - 363 -- | Returns the HTTP status code. - 364 , rspStatus :: !Int - 365 - 366 -- | Returns the HTTP status explanation string. - 367 , rspStatusReason :: !ByteString - 368 } - 369 + 351 + 352 ------------------------------------------------------------------------------ + 353 -- | Represents an HTTP response. + 354 data Response = Response + 355 { rspHeaders :: Headers + 356 , rspHttpVersion :: !HttpVersion + 357 + 358 -- | We will need to inspect the content length no matter what, and + 359 -- looking up \"content-length\" in the headers and parsing the number + 360 -- out of the text will be too expensive. + 361 , rspContentLength :: !(Maybe Int64) + 362 , rspBody :: ResponseBody + 363 + 364 -- | Returns the HTTP status code. + 365 , rspStatus :: !Int + 366 + 367 -- | Returns the HTTP status explanation string. + 368 , rspStatusReason :: !ByteString + 369 } 370 - 371 ------------------------------------------------------------------------------ - 372 instance Show Response where - 373 show r = concat [ "Response <\n" - 374 , body - 375 , ">" ] - 376 where - 377 body = concat $ map ((" "++) . (++ "\n")) [ - 378 hdrs - 379 , version - 380 , status - 381 , reason - 382 ] - 383 - 384 hdrs = concat [ "headers:\n" - 385 , " ==============================\n " - 386 , show $ rspHeaders r - 387 , "\n ==============================" ] - 388 - 389 version = concat [ "version: ", show $ rspHttpVersion r ] - 390 status = concat [ "status: ", show $ rspStatus r ] - 391 reason = concat [ "reason: ", toStr $ rspStatusReason r ] - 392 + 371 + 372 ------------------------------------------------------------------------------ + 373 instance Show Response where + 374 show r = concat [ "Response <\n" + 375 , body + 376 , ">" ] + 377 where + 378 body = concat $ map ((" "++) . (++ "\n")) [ + 379 hdrs + 380 , version + 381 , status + 382 , reason + 383 ] + 384 + 385 hdrs = concat [ "headers:\n" + 386 , " ==============================\n " + 387 , show $ rspHeaders r + 388 , "\n ==============================" ] + 389 + 390 version = concat [ "version: ", show $ rspHttpVersion r ] + 391 status = concat [ "status: ", show $ rspStatus r ] + 392 reason = concat [ "reason: ", toStr $ rspStatusReason r ] 393 - 394 ------------------------------------------------------------------------------ - 395 instance HasHeaders Response where - 396 headers = rspHeaders - 397 updateHeaders f r = r { rspHeaders = f (rspHeaders r) } - 398 + 394 + 395 ------------------------------------------------------------------------------ + 396 instance HasHeaders Response where + 397 headers = rspHeaders + 398 updateHeaders f r = r { rspHeaders = f (rspHeaders r) } 399 - 400 ------------------------------------------------------------------------------ - 401 -- | Looks up the value(s) for the given named parameter. Parameters initially - 402 -- come from the request's query string and any decoded POST body (if the - 403 -- request's @Content-Type@ is @application\/x-www-form-urlencoded@). Parameter - 404 -- values can be modified within handlers using "rqModifyParams". - 405 rqParam :: ByteString -- ^ parameter name to look up - 406 -> Request -- ^ HTTP request - 407 -> Maybe [ByteString] - 408 rqParam k rq = Map.lookup k $ rqParams rq - 409 {-# INLINE rqParam #-} - 410 + 400 + 401 ------------------------------------------------------------------------------ + 402 -- | Looks up the value(s) for the given named parameter. Parameters initially + 403 -- come from the request's query string and any decoded POST body (if the + 404 -- request's @Content-Type@ is @application\/x-www-form-urlencoded@). Parameter + 405 -- values can be modified within handlers using "rqModifyParams". + 406 rqParam :: ByteString -- ^ parameter name to look up + 407 -> Request -- ^ HTTP request + 408 -> Maybe [ByteString] + 409 rqParam k rq = Map.lookup k $ rqParams rq + 410 {-# INLINE rqParam #-} 411 - 412 ------------------------------------------------------------------------------ - 413 -- | Modifies the parameters mapping (which is a @Map ByteString ByteString@) in - 414 -- a 'Request' using the given function. - 415 rqModifyParams :: (Params -> Params) -> Request -> Request - 416 rqModifyParams f r = r { rqParams = p } - 417 where - 418 p = f $ rqParams r - 419 {-# INLINE rqModifyParams #-} - 420 + 412 + 413 ------------------------------------------------------------------------------ + 414 -- | Modifies the parameters mapping (which is a @Map ByteString ByteString@) in + 415 -- a 'Request' using the given function. + 416 rqModifyParams :: (Params -> Params) -> Request -> Request + 417 rqModifyParams f r = r { rqParams = p } + 418 where + 419 p = f $ rqParams r + 420 {-# INLINE rqModifyParams #-} 421 - 422 ------------------------------------------------------------------------------ - 423 -- | Writes a key-value pair to the parameters mapping within the given request. - 424 rqSetParam :: ByteString -- ^ parameter name - 425 -> [ByteString] -- ^ parameter values - 426 -> Request -- ^ request - 427 -> Request - 428 rqSetParam k v = rqModifyParams $ Map.insert k v - 429 {-# INLINE rqSetParam #-} - 430 - 431 ------------------------------------------------------------------------------ - 432 -- responses - 433 ------------------------------------------------------------------------------ - 434 - 435 -- | An empty 'Response'. - 436 emptyResponse :: Response - 437 emptyResponse = Response Map.empty (1,1) Nothing (Enum return) 200 "OK" - 438 + 422 + 423 ------------------------------------------------------------------------------ + 424 -- | Writes a key-value pair to the parameters mapping within the given request. + 425 rqSetParam :: ByteString -- ^ parameter name + 426 -> [ByteString] -- ^ parameter values + 427 -> Request -- ^ request + 428 -> Request + 429 rqSetParam k v = rqModifyParams $ Map.insert k v + 430 {-# INLINE rqSetParam #-} + 431 + 432 ------------------------------------------------------------------------------ + 433 -- responses + 434 ------------------------------------------------------------------------------ + 435 + 436 -- | An empty 'Response'. + 437 emptyResponse :: Response + 438 emptyResponse = Response Map.empty (1,1) Nothing (Enum return) 200 "OK" 439 - 440 ------------------------------------------------------------------------------ - 441 -- | Sets an HTTP response body to the given 'Enumerator' value. - 442 setResponseBody :: (forall a . Enumerator a) -- ^ new response body - 443 -- enumerator - 444 -> Response -- ^ response to modify - 445 -> Response - 446 setResponseBody e r = r { rspBody = Enum e } - 447 {-# INLINE setResponseBody #-} - 448 + 440 + 441 ------------------------------------------------------------------------------ + 442 -- | Sets an HTTP response body to the given 'Enumerator' value. + 443 setResponseBody :: (forall a . Enumerator a) -- ^ new response body + 444 -- enumerator + 445 -> Response -- ^ response to modify + 446 -> Response + 447 setResponseBody e r = r { rspBody = Enum e } + 448 {-# INLINE setResponseBody #-} 449 - 450 ------------------------------------------------------------------------------ - 451 -- | Sets the HTTP response status. - 452 setResponseStatus :: Int -- ^ HTTP response integer code - 453 -> ByteString -- ^ HTTP response explanation - 454 -> Response -- ^ Response to be modified - 455 -> Response - 456 setResponseStatus s reason r = r { rspStatus=s, rspStatusReason=reason } - 457 {-# INLINE setResponseStatus #-} - 458 + 450 + 451 ------------------------------------------------------------------------------ + 452 -- | Sets the HTTP response status. + 453 setResponseStatus :: Int -- ^ HTTP response integer code + 454 -> ByteString -- ^ HTTP response explanation + 455 -> Response -- ^ Response to be modified + 456 -> Response + 457 setResponseStatus s reason r = r { rspStatus=s, rspStatusReason=reason } + 458 {-# INLINE setResponseStatus #-} 459 - 460 ------------------------------------------------------------------------------ - 461 -- | Modifies a response body. - 462 modifyResponseBody :: (forall a . Enumerator a -> Enumerator a) - 463 -> Response + 460 + 461 ------------------------------------------------------------------------------ + 462 -- | Modifies a response body. + 463 modifyResponseBody :: (forall a . Enumerator a -> Enumerator a) 464 -> Response - 465 modifyResponseBody f r = r { rspBody = rspBodyMap f (rspBody r) } - 466 {-# INLINE modifyResponseBody #-} - 467 + 465 -> Response + 466 modifyResponseBody f r = r { rspBody = rspBodyMap f (rspBody r) } + 467 {-# INLINE modifyResponseBody #-} 468 - 469 ------------------------------------------------------------------------------ - 470 -- | Sets the @Content-Type@ in the 'Response' headers. - 471 setContentType :: ByteString -> Response -> Response - 472 setContentType = setHeader "Content-Type" - 473 {-# INLINE setContentType #-} - 474 + 469 + 470 ------------------------------------------------------------------------------ + 471 -- | Sets the @Content-Type@ in the 'Response' headers. + 472 setContentType :: ByteString -> Response -> Response + 473 setContentType = setHeader "Content-Type" + 474 {-# INLINE setContentType #-} 475 - 476 ------------------------------------------------------------------------------ - 477 -- | Adds an HTTP 'Cookie' to the 'Response' headers. - 478 addCookie :: Cookie -- ^ cookie value - 479 -> Response -- ^ response to modify - 480 -> Response - 481 addCookie (Cookie k v mbExpTime mbDomain mbPath) = updateHeaders f - 482 where - 483 f = Map.insertWith' (++) "Set-Cookie" [cookie] - 484 cookie = S.concat [k, "=", v, path, exptime, domain] - 485 path = maybe "" (S.append "; path=") mbPath - 486 domain = maybe "" (S.append "; domain=") mbDomain - 487 exptime = maybe "" (S.append "; expires=" . fmt) mbExpTime - 488 fmt = fromStr . formatTime defaultTimeLocale "%a, %d-%b-%Y %H:%M:%S GMT" - 489 + 476 + 477 ------------------------------------------------------------------------------ + 478 -- | Adds an HTTP 'Cookie' to the 'Response' headers. + 479 addCookie :: Cookie -- ^ cookie value + 480 -> Response -- ^ response to modify + 481 -> Response + 482 addCookie (Cookie k v mbExpTime mbDomain mbPath) = updateHeaders f + 483 where + 484 f = Map.insertWith' (++) "Set-Cookie" [cookie] + 485 cookie = S.concat [k, "=", v, path, exptime, domain] + 486 path = maybe "" (S.append "; path=") mbPath + 487 domain = maybe "" (S.append "; domain=") mbDomain + 488 exptime = maybe "" (S.append "; expires=" . fmt) mbExpTime + 489 fmt = fromStr . formatTime defaultTimeLocale "%a, %d-%b-%Y %H:%M:%S GMT" 490 - 491 ------------------------------------------------------------------------------ - 492 -- | A note here: if you want to set the @Content-Length@ for the response, - 493 -- Snap forces you to do it with this function rather than by setting it in the - 494 -- headers; the @Content-Length@ in the headers will be ignored. - 495 -- - 496 -- The reason for this is that Snap needs to look up the value of - 497 -- @Content-Length@ for each request, and looking the string value up in the - 498 -- headers and parsing the number out of the text will be too expensive. - 499 -- - 500 -- If you don't set a content length in your response, HTTP keep-alive will be - 501 -- disabled for HTTP\/1.0 clients, forcing a @Connection: close@. For HTTP\/1.1 - 502 -- clients, Snap will switch to the chunked transfer encoding if - 503 -- @Content-Length@ is not specified. - 504 setContentLength :: Int -> Response -> Response - 505 setContentLength l r = r { rspContentLength = Just l } - 506 {-# INLINE setContentLength #-} - 507 + 491 + 492 ------------------------------------------------------------------------------ + 493 -- | A note here: if you want to set the @Content-Length@ for the response, + 494 -- Snap forces you to do it with this function rather than by setting it in the + 495 -- headers; the @Content-Length@ in the headers will be ignored. + 496 -- + 497 -- The reason for this is that Snap needs to look up the value of + 498 -- @Content-Length@ for each request, and looking the string value up in the + 499 -- headers and parsing the number out of the text will be too expensive. + 500 -- + 501 -- If you don't set a content length in your response, HTTP keep-alive will be + 502 -- disabled for HTTP\/1.0 clients, forcing a @Connection: close@. For HTTP\/1.1 + 503 -- clients, Snap will switch to the chunked transfer encoding if + 504 -- @Content-Length@ is not specified. + 505 setContentLength :: Int64 -> Response -> Response + 506 setContentLength l r = r { rspContentLength = Just l } + 507 {-# INLINE setContentLength #-} 508 - 509 ------------------------------------------------------------------------------ - 510 -- | Removes any @Content-Length@ set in the 'Response'. - 511 clearContentLength :: Response -> Response - 512 clearContentLength r = r { rspContentLength = Nothing } - 513 {-# INLINE clearContentLength #-} - 514 + 509 + 510 ------------------------------------------------------------------------------ + 511 -- | Removes any @Content-Length@ set in the 'Response'. + 512 clearContentLength :: Response -> Response + 513 clearContentLength r = r { rspContentLength = Nothing } + 514 {-# INLINE clearContentLength #-} 515 - 516 ------------------------------------------------------------------------------ - 517 -- HTTP dates - 518 - 519 -- | Converts a 'CTime' into an HTTP timestamp. - 520 formatHttpTime :: CTime -> IO ByteString - 521 - 522 -- | Converts a 'CTime' into common log entry format. - 523 formatLogTime :: CTime -> IO ByteString - 524 - 525 -- | Converts an HTTP timestamp into a 'CTime'. - 526 parseHttpTime :: ByteString -> IO CTime - 527 - 528 #ifdef PORTABLE - 529 - 530 formatHttpTime = return . format . toUTCTime - 531 where - 532 format :: UTCTime -> ByteString - 533 format = fromStr . formatTime defaultTimeLocale "%a, %d %b %Y %X GMT" - 534 - 535 toUTCTime :: CTime -> UTCTime - 536 toUTCTime = posixSecondsToUTCTime . realToFrac - 537 - 538 formatLogTime ctime = do - 539 t <- utcToLocalZonedTime $ toUTCTime ctime - 540 return $ format t - 541 - 542 where - 543 format :: ZonedTime -> ByteString - 544 format = fromStr . formatTime defaultTimeLocale "%d/%b/%Y:%H:%M:%S %z" - 545 - 546 toUTCTime :: CTime -> UTCTime - 547 toUTCTime = posixSecondsToUTCTime . realToFrac - 548 + 516 + 517 ------------------------------------------------------------------------------ + 518 -- HTTP dates + 519 + 520 -- | Converts a 'CTime' into an HTTP timestamp. + 521 formatHttpTime :: CTime -> IO ByteString + 522 + 523 -- | Converts a 'CTime' into common log entry format. + 524 formatLogTime :: CTime -> IO ByteString + 525 + 526 -- | Converts an HTTP timestamp into a 'CTime'. + 527 parseHttpTime :: ByteString -> IO CTime + 528 + 529 #ifdef PORTABLE + 530 + 531 formatHttpTime = return . format . toUTCTime + 532 where + 533 format :: UTCTime -> ByteString + 534 format = fromStr . formatTime defaultTimeLocale "%a, %d %b %Y %X GMT" + 535 + 536 toUTCTime :: CTime -> UTCTime + 537 toUTCTime = posixSecondsToUTCTime . realToFrac + 538 + 539 formatLogTime ctime = do + 540 t <- utcToLocalZonedTime $ toUTCTime ctime + 541 return $ format t + 542 + 543 where + 544 format :: ZonedTime -> ByteString + 545 format = fromStr . formatTime defaultTimeLocale "%d/%b/%Y:%H:%M:%S %z" + 546 + 547 toUTCTime :: CTime -> UTCTime + 548 toUTCTime = posixSecondsToUTCTime . realToFrac 549 - 550 parseHttpTime = return . toCTime . parse . toStr - 551 where - 552 parse :: String -> Maybe UTCTime - 553 parse = parseTime defaultTimeLocale "%a, %d %b %Y %H:%M:%S GMT" - 554 - 555 toCTime :: Maybe UTCTime -> CTime - 556 toCTime (Just t) = fromInteger $ truncate $ utcTimeToPOSIXSeconds t - 557 toCTime Nothing = fromInteger 0 - 558 - 559 #else - 560 - 561 formatLogTime t = do - 562 ptr <- mallocBytes 40 - 563 c_format_log_time t ptr - 564 S.unsafePackMallocCString ptr - 565 - 566 formatHttpTime t = do - 567 ptr <- mallocBytes 40 - 568 c_format_http_time t ptr - 569 S.unsafePackMallocCString ptr - 570 - 571 parseHttpTime s = S.unsafeUseAsCString s $ \ptr -> - 572 c_parse_http_time ptr - 573 - 574 #endif - 575 + 550 + 551 parseHttpTime = return . toCTime . parse . toStr + 552 where + 553 parse :: String -> Maybe UTCTime + 554 parse = parseTime defaultTimeLocale "%a, %d %b %Y %H:%M:%S GMT" + 555 + 556 toCTime :: Maybe UTCTime -> CTime + 557 toCTime (Just t) = fromInteger $ truncate $ utcTimeToPOSIXSeconds t + 558 toCTime Nothing = fromInteger 0 + 559 + 560 #else + 561 + 562 formatLogTime t = do + 563 ptr <- mallocBytes 40 + 564 c_format_log_time t ptr + 565 S.unsafePackMallocCString ptr + 566 + 567 formatHttpTime t = do + 568 ptr <- mallocBytes 40 + 569 c_format_http_time t ptr + 570 S.unsafePackMallocCString ptr + 571 + 572 parseHttpTime s = S.unsafeUseAsCString s $ \ptr -> + 573 c_parse_http_time ptr + 574 + 575 #endif 576 - 577 ------------------------------------------------------------------------------ - 578 -- URL ENCODING - 579 ------------------------------------------------------------------------------ - 580 - 581 parseToCompletion :: Parser a -> ByteString -> Maybe a - 582 parseToCompletion p s = toResult $ finish r - 583 where - 584 r = parse p s - 585 - 586 toResult (Atto.Done _ c) = Just c - 587 toResult _ = Nothing - 588 + 577 + 578 ------------------------------------------------------------------------------ + 579 -- URL ENCODING + 580 ------------------------------------------------------------------------------ + 581 + 582 parseToCompletion :: Parser a -> ByteString -> Maybe a + 583 parseToCompletion p s = toResult $ finish r + 584 where + 585 r = parse p s + 586 + 587 toResult (Atto.Done _ c) = Just c + 588 toResult _ = Nothing 589 - 590 ------------------------------------------------------------------------------ - 591 pUrlEscaped :: Parser ByteString - 592 pUrlEscaped = do - 593 sq <- nextChunk DL.empty - 594 return $ S.concat $ DL.toList sq - 595 - 596 where - 597 nextChunk :: DList ByteString -> Parser (DList ByteString) - 598 nextChunk s = (endOfInput *> pure s) <|> do - 599 c <- anyWord8 - 600 case w2c c of - 601 '+' -> plusSpace s - 602 '%' -> percentEncoded s - 603 _ -> unEncoded c s - 604 - 605 percentEncoded :: DList ByteString -> Parser (DList ByteString) - 606 percentEncoded l = do - 607 hx <- take 2 - 608 when (S.length hx /= 2 || - 609 (not $ S.all (isHexDigit . w2c) hx)) $ - 610 fail "bad hex in url" - 611 - 612 let code = (Cvt.hex hx) :: Word8 - 613 nextChunk $ DL.snoc l (S.singleton code) - 614 - 615 unEncoded :: Word8 -> DList ByteString -> Parser (DList ByteString) - 616 unEncoded c l' = do - 617 let l = DL.snoc l' (S.singleton c) - 618 bs <- takeTill (flip elem (map c2w "%+")) - 619 if S.null bs - 620 then nextChunk l - 621 else nextChunk $ DL.snoc l bs - 622 - 623 plusSpace :: DList ByteString -> Parser (DList ByteString) - 624 plusSpace l = nextChunk (DL.snoc l (S.singleton $ c2w ' ')) - 625 + 590 + 591 ------------------------------------------------------------------------------ + 592 pUrlEscaped :: Parser ByteString + 593 pUrlEscaped = do + 594 sq <- nextChunk DL.empty + 595 return $ S.concat $ DL.toList sq + 596 + 597 where + 598 nextChunk :: DList ByteString -> Parser (DList ByteString) + 599 nextChunk s = (endOfInput *> pure s) <|> do + 600 c <- anyWord8 + 601 case w2c c of + 602 '+' -> plusSpace s + 603 '%' -> percentEncoded s + 604 _ -> unEncoded c s + 605 + 606 percentEncoded :: DList ByteString -> Parser (DList ByteString) + 607 percentEncoded l = do + 608 hx <- take 2 + 609 when (S.length hx /= 2 || + 610 (not $ S.all (isHexDigit . w2c) hx)) $ + 611 fail "bad hex in url" + 612 + 613 let code = (Cvt.hex hx) :: Word8 + 614 nextChunk $ DL.snoc l (S.singleton code) + 615 + 616 unEncoded :: Word8 -> DList ByteString -> Parser (DList ByteString) + 617 unEncoded c l' = do + 618 let l = DL.snoc l' (S.singleton c) + 619 bs <- takeTill (flip elem (map c2w "%+")) + 620 if S.null bs + 621 then nextChunk l + 622 else nextChunk $ DL.snoc l bs + 623 + 624 plusSpace :: DList ByteString -> Parser (DList ByteString) + 625 plusSpace l = nextChunk (DL.snoc l (S.singleton $ c2w ' ')) 626 - 627 ------------------------------------------------------------------------------ - 628 -- | Decodes an URL-escaped string (see - 629 -- <http://tools.ietf.org/html/rfc2396.html#section-2.4>) - 630 urlDecode :: ByteString -> Maybe ByteString - 631 urlDecode = parseToCompletion pUrlEscaped - 632 + 627 + 628 ------------------------------------------------------------------------------ + 629 -- | Decodes an URL-escaped string (see + 630 -- <http://tools.ietf.org/html/rfc2396.html#section-2.4>) + 631 urlDecode :: ByteString -> Maybe ByteString + 632 urlDecode = parseToCompletion pUrlEscaped 633 - 634 ------------------------------------------------------------------------------ - 635 -- "...Only alphanumerics [0-9a-zA-Z], the special characters "$-_.+!*'()," - 636 -- [not including the quotes - ed], and reserved characters used for their - 637 -- reserved purposes may be used unencoded within a URL." - 638 - 639 -- | URL-escapes a string (see - 640 -- <http://tools.ietf.org/html/rfc2396.html#section-2.4>) - 641 urlEncode :: ByteString -> ByteString - 642 urlEncode = toByteString . S.foldl' f empty - 643 where - 644 f b c = - 645 if c == c2w ' ' - 646 then b `mappend` singleton (c2w '+') - 647 else if isKosher c - 648 then b `mappend` singleton c - 649 else b `mappend` hexd c - 650 - 651 isKosher w = any ($ c) [ isAlphaNum - 652 , flip elem ['$', '-', '.', '!', '*' - 653 , '\'', '(', ')', ',' ]] - 654 where - 655 c = w2c w - 656 + 634 + 635 ------------------------------------------------------------------------------ + 636 -- "...Only alphanumerics [0-9a-zA-Z], the special characters "$-_.+!*'()," + 637 -- [not including the quotes - ed], and reserved characters used for their + 638 -- reserved purposes may be used unencoded within a URL." + 639 + 640 -- | URL-escapes a string (see + 641 -- <http://tools.ietf.org/html/rfc2396.html#section-2.4>) + 642 urlEncode :: ByteString -> ByteString + 643 urlEncode = toByteString . S.foldl' f empty + 644 where + 645 f b c = + 646 if c == c2w ' ' + 647 then b `mappend` singleton (c2w '+') + 648 else if isKosher c + 649 then b `mappend` singleton c + 650 else b `mappend` hexd c + 651 + 652 isKosher w = any ($ c) [ isAlphaNum + 653 , flip elem ['$', '-', '.', '!', '*' + 654 , '\'', '(', ')', ',' ]] + 655 where + 656 c = w2c w 657 - 658 ------------------------------------------------------------------------------ - 659 hexd :: Word8 -> Builder - 660 hexd c = singleton (c2w '%') `mappend` singleton hi `mappend` singleton low - 661 where - 662 d = c2w . intToDigit - 663 low = d $ fromEnum $ c .&. 0xf - 664 hi = d $ fromEnum $ (c .&. 0xf0) `shift` (-4) - 665 + 658 + 659 ------------------------------------------------------------------------------ + 660 hexd :: Word8 -> Builder + 661 hexd c = singleton (c2w '%') `mappend` singleton hi `mappend` singleton low + 662 where + 663 d = c2w . intToDigit + 664 low = d $ fromEnum $ c .&. 0xf + 665 hi = d $ fromEnum $ (c .&. 0xf0) `shift` (-4) 666 - 667 ------------------------------------------------------------------------------ - 668 finish :: Atto.Result a -> Atto.Result a - 669 finish (Atto.Partial f) = flip feed "" $ f "" - 670 finish x = x - 671 + 667 + 668 ------------------------------------------------------------------------------ + 669 finish :: Atto.Result a -> Atto.Result a + 670 finish (Atto.Partial f) = flip feed "" $ f "" + 671 finish x = x 672 - 673 ------------------------------------------------------------------------------ - 674 -- local definitions - 675 fromStr :: String -> ByteString - 676 fromStr = S.pack . map c2w - 677 {-# INLINE fromStr #-} - 678 - 679 ------------------------------------------------------------------------------ - 680 -- private helper functions - 681 toStr :: ByteString -> String - 682 toStr = map w2c . S.unpack - 683 + 673 + 674 ------------------------------------------------------------------------------ + 675 -- local definitions + 676 fromStr :: String -> ByteString + 677 fromStr = S.pack . map c2w + 678 {-# INLINE fromStr #-} + 679 + 680 ------------------------------------------------------------------------------ + 681 -- private helper functions + 682 toStr :: ByteString -> String + 683 toStr = map w2c . S.unpack + 684 diff --git a/static/docs/snap-core-hpc/Snap.Internal.Routing.hs.html b/static/docs/snap-core-hpc/Snap.Internal.Routing.hs.html index b66cceb..9aa3bb5 100644 --- a/static/docs/snap-core-hpc/Snap.Internal.Routing.hs.html +++ b/static/docs/snap-core-hpc/Snap.Internal.Routing.hs.html @@ -55,141 +55,178 @@ 44 instance Monoid (Route a) where 45 mempty = NoRoute 46 - 47 -- Unions two routes, favoring the right-hand side - 48 mappend NoRoute r = r - 49 - 50 mappend l@(Action _) r = case r of - 51 (Action _) -> r - 52 (Capture p r' fb) -> Capture p r' (mappend fb l) - 53 (Dir _ _) -> mappend (Dir Map.empty l) r - 54 NoRoute -> l - 55 - 56 mappend l@(Capture p r' fb) r = case r of - 57 (Action _) -> Capture p r' (mappend fb r) - 58 (Capture p' r'' fb') - 59 | p == p' -> Capture p (mappend r' r'') (mappend fb fb') - 60 | otherwise -> r - 61 (Dir rm fb') -> Dir rm (mappend fb' l) - 62 NoRoute -> l - 63 - 64 mappend l@(Dir rm fb) r = case r of - 65 (Action _) -> Dir rm (mappend fb r) - 66 (Capture _ _ _) -> Dir rm (mappend fb r) - 67 (Dir rm' fb') -> Dir (Map.unionWith mappend rm rm') (mappend fb fb') - 68 NoRoute -> l - 69 - 70 - 71 ------------------------------------------------------------------------------ - 72 -- | A web handler which, given a mapping from URL entry points to web - 73 -- handlers, efficiently routes requests to the correct handler. - 74 -- - 75 -- The URL entry points are given as relative paths, for example: - 76 -- - 77 -- > route [ ("foo/bar/quux", fooBarQuux) ] - 78 -- - 79 -- If the URI of the incoming request is - 80 -- - 81 -- > /foo/bar/quux - 82 -- - 83 -- or - 84 -- - 85 -- > /foo/bar/quux/...anything... - 86 -- - 87 -- then the request will be routed to \"@fooBarQuux@\", with 'rqContextPath' - 88 -- set to \"@\/foo\/bar\/quux\/@\" and 'rqPathInfo' set to - 89 -- \"@...anything...@\". - 90 -- - 91 -- A path component within an URL entry point beginning with a colon (\"@:@\") - 92 -- is treated as a /variable capture/; the corresponding path component within - 93 -- the request URI will be entered into the 'rqParams' parameters mapping with - 94 -- the given name. For instance, if the routes were: - 95 -- - 96 -- > route [ ("foo/:bar/baz", fooBazHandler) ] - 97 -- - 98 -- Then a request for \"@\/foo\/saskatchewan\/baz@\" would be routed to - 99 -- @fooBazHandler@ with a mapping for: - 100 -- - 101 -- > "bar" => "saskatchewan" + 47 mappend NoRoute r = r + 48 + 49 mappend l@(Action a) r = case r of + 50 (Action a') -> Action (a <|> a') + 51 (Capture p r' fb) -> Capture p r' (mappend fb l) + 52 (Dir _ _) -> mappend (Dir Map.empty l) r + 53 NoRoute -> l + 54 + 55 -- Whenever we're unioning two Captures and their capture variables + 56 -- differ, we have an ambiguity. We resolve this in the following order: + 57 -- 1. Prefer whichever route is longer + 58 -- 2. Else, prefer whichever has the earliest non-capture + 59 -- 3. Else, prefer the right-hand side + 60 mappend l@(Capture p r' fb) r = case r of + 61 (Action _) -> Capture p r' (mappend fb r) + 62 (Capture p' r'' fb') + 63 | p == p' -> Capture p (mappend r' r'') (mappend fb fb') + 64 | rh' > rh'' -> Capture p r' (mappend fb r) + 65 | rh' < rh'' -> Capture p' r'' (mappend fb' l) + 66 | en' < en'' -> Capture p r' (mappend fb r) + 67 | otherwise -> Capture p' r'' (mappend fb' l) + 68 where + 69 rh' = routeHeight r' + 70 rh'' = routeHeight r'' + 71 en' = routeEarliestNC r' 1 + 72 en'' = routeEarliestNC r'' 1 + 73 (Dir rm fb') -> Dir rm (mappend fb' l) + 74 NoRoute -> l + 75 + 76 mappend l@(Dir rm fb) r = case r of + 77 (Action _) -> Dir rm (mappend fb r) + 78 (Capture _ _ _) -> Dir rm (mappend fb r) + 79 (Dir rm' fb') -> Dir (Map.unionWith mappend rm rm') (mappend fb fb') + 80 NoRoute -> l + 81 + 82 + 83 ------------------------------------------------------------------------------ + 84 routeHeight :: Route a -> Int + 85 routeHeight r = case r of + 86 NoRoute -> 1 + 87 (Action _) -> 1 + 88 (Capture _ r' _) -> 1+routeHeight r' + 89 (Dir rm _) -> 1+foldl max 1 (map routeHeight $ Map.elems rm) + 90 + 91 routeEarliestNC :: Route a -> Int -> Int + 92 routeEarliestNC r n = case r of + 93 NoRoute -> n + 94 (Action _) -> n + 95 (Capture _ r' _) -> routeEarliestNC r' n+1 + 96 (Dir _ _) -> n + 97 + 98 + 99 ------------------------------------------------------------------------------ + 100 -- | A web handler which, given a mapping from URL entry points to web + 101 -- handlers, efficiently routes requests to the correct handler. 102 -- - 103 -- in its parameters table. + 103 -- The URL entry points are given as relative paths, for example: 104 -- - 105 -- Longer paths are matched first, and specific routes are matched before - 106 -- captures. That is, if given routes: - 107 -- - 108 -- > [ ("a", h1), ("a/b", h2), ("a/:x", h3) ] - 109 -- - 110 -- a request for \"@\/a\/b@\" will go to @h2@, \"@\/a\/s@\" for any /s/ will go - 111 -- to @h3@, and \"@\/a@\" will go to @h1@. + 105 -- > route [ ("foo/bar/quux", fooBarQuux) ] + 106 -- + 107 -- If the URI of the incoming request is + 108 -- + 109 -- > /foo/bar/quux + 110 -- + 111 -- or 112 -- - 113 -- The following example matches \"@\/article@\" to an article index, - 114 -- \"@\/login@\" to a login, and \"@\/article\/...@\" to an article renderer. - 115 -- - 116 -- > route [ ("article", renderIndex) - 117 -- > , ("article/:id", renderArticle) - 118 -- > , ("login", method POST doLogin) ] - 119 -- - 120 route :: [(ByteString, Snap a)] -> Snap a - 121 route rts = route' (return ()) rts' [] - 122 where - 123 rts' = mconcat (map pRoute rts) - 124 - 125 - 126 ------------------------------------------------------------------------------ - 127 -- | The 'routeLocal' function is the same as 'route', except it doesn't change - 128 -- the request's context path. This is useful if you want to route to a - 129 -- particular handler but you want that handler to receive the 'rqPathInfo' as - 130 -- it is. - 131 routeLocal :: [(ByteString, Snap a)] -> Snap a - 132 routeLocal rts' = do - 133 req <- getRequest - 134 let ctx = rqContextPath req - 135 let p = rqPathInfo req - 136 let md = modifyRequest $ \r -> r {rqContextPath=ctx, rqPathInfo=p} - 137 - 138 route' md rts [] <|> (md >> pass) - 139 - 140 where - 141 rts = mconcat (map pRoute rts') - 142 - 143 - 144 ------------------------------------------------------------------------------ - 145 pRoute :: (ByteString, Snap a) -> Route a - 146 pRoute (r, a) = foldr f (Action a) hier - 147 where - 148 hier = filter (not . B.null) $ B.splitWith (== (c2w '/')) r - 149 f s rt = if B.head s == c2w ':' - 150 then Capture (B.tail s) rt NoRoute - 151 else Dir (Map.fromList [(s, rt)]) NoRoute - 152 - 153 - 154 ------------------------------------------------------------------------------ - 155 route' :: Snap () -- ^ an action to be run before any user - 156 -- handler - 157 -> Route a -- ^ currently active routing table - 158 -> [Route a] -- ^ list of fallback routing tables in case - 159 -- the current table fails - 160 -> Snap a - 161 route' pre (Action action) _ = pre >> action - 162 - 163 route' pre (Capture param rt fb) fbs = do - 164 cwd <- getRequest >>= return . B.takeWhile (/= (c2w '/')) . rqPathInfo - 165 if B.null cwd - 166 then route' pre fb fbs - 167 else do localRequest (updateContextPath (B.length cwd) . (f cwd)) $ - 168 route' pre rt (fb:fbs) - 169 where - 170 f v req = req { rqParams = Map.insertWith (++) param [v] (rqParams req) } - 171 - 172 route' pre (Dir rtm fb) fbs = do - 173 cwd <- getRequest >>= return . B.takeWhile (/= (c2w '/')) . rqPathInfo - 174 case Map.lookup cwd rtm of - 175 Just rt -> do - 176 localRequest (updateContextPath (B.length cwd)) $ - 177 route' pre rt (fb:fbs) - 178 Nothing -> route' pre fb fbs - 179 - 180 route' _ NoRoute [] = pass - 181 route' pre NoRoute (fb:fbs) = route' pre fb fbs + 113 -- > /foo/bar/quux/...anything... + 114 -- + 115 -- then the request will be routed to \"@fooBarQuux@\", with 'rqContextPath' + 116 -- set to \"@\/foo\/bar\/quux\/@\" and 'rqPathInfo' set to + 117 -- \"@...anything...@\". + 118 -- + 119 -- A path component within an URL entry point beginning with a colon (\"@:@\") + 120 -- is treated as a /variable capture/; the corresponding path component within + 121 -- the request URI will be entered into the 'rqParams' parameters mapping with + 122 -- the given name. For instance, if the routes were: + 123 -- + 124 -- > route [ ("foo/:bar/baz", fooBazHandler) ] + 125 -- + 126 -- Then a request for \"@\/foo\/saskatchewan\/baz@\" would be routed to + 127 -- @fooBazHandler@ with a mapping for: + 128 -- + 129 -- > "bar" => "saskatchewan" + 130 -- + 131 -- in its parameters table. + 132 -- + 133 -- Longer paths are matched first, and specific routes are matched before + 134 -- captures. That is, if given routes: + 135 -- + 136 -- > [ ("a", h1), ("a/b", h2), ("a/:x", h3) ] + 137 -- + 138 -- a request for \"@\/a\/b@\" will go to @h2@, \"@\/a\/s@\" for any /s/ will go + 139 -- to @h3@, and \"@\/a@\" will go to @h1@. + 140 -- + 141 -- The following example matches \"@\/article@\" to an article index, + 142 -- \"@\/login@\" to a login, and \"@\/article\/...@\" to an article renderer. + 143 -- + 144 -- > route [ ("article", renderIndex) + 145 -- > , ("article/:id", renderArticle) + 146 -- > , ("login", method POST doLogin) ] + 147 -- + 148 route :: [(ByteString, Snap a)] -> Snap a + 149 route rts = do + 150 p <- getRequest >>= return . rqPathInfo + 151 route' (return ()) ([], splitPath p) Map.empty rts' + 152 where + 153 rts' = mconcat (map pRoute rts) + 154 + 155 + 156 ------------------------------------------------------------------------------ + 157 -- | The 'routeLocal' function is the same as 'route'', except it doesn't change + 158 -- the request's context path. This is useful if you want to route to a + 159 -- particular handler but you want that handler to receive the 'rqPathInfo' as + 160 -- it is. + 161 routeLocal :: [(ByteString, Snap a)] -> Snap a + 162 routeLocal rts = do + 163 req <- getRequest + 164 let ctx = rqContextPath req + 165 let p = rqPathInfo req + 166 let md = modifyRequest $ \r -> r {rqContextPath=ctx, rqPathInfo=p} + 167 + 168 (route' md ([], splitPath p) Map.empty rts') <|> (md >> pass) + 169 + 170 where + 171 rts' = mconcat (map pRoute rts) + 172 + 173 ------------------------------------------------------------------------------ + 174 splitPath :: ByteString -> [ByteString] + 175 splitPath = B.splitWith (== (c2w '/')) + 176 + 177 + 178 ------------------------------------------------------------------------------ + 179 pRoute :: (ByteString, Snap a) -> Route a + 180 pRoute (r, a) = foldr f (Action a) hier + 181 where + 182 hier = filter (not . B.null) $ B.splitWith (== (c2w '/')) r + 183 f s rt = if B.head s == c2w ':' + 184 then Capture (B.tail s) rt NoRoute + 185 else Dir (Map.fromList [(s, rt)]) NoRoute + 186 + 187 + 188 ------------------------------------------------------------------------------ + 189 route' :: Snap () + 190 -> ([ByteString], [ByteString]) + 191 -> Params + 192 -> Route a + 193 -> Snap a + 194 route' pre (ctx, _) params (Action action) = + 195 localRequest (updateContextPath (B.length ctx') . updateParams) + 196 (pre >> action) + 197 where + 198 ctx' = B.intercalate (B.pack [c2w '/']) (reverse ctx) + 199 updateParams req = req + 200 { rqParams = Map.unionWith (++) params (rqParams req) } + 201 + 202 route' pre (ctx, []) params (Capture _ _ fb) = + 203 route' pre (ctx, []) params fb + 204 route' pre (ctx, cwd:rest) params (Capture p rt fb) = + 205 (route' pre (cwd:ctx, rest) params' rt) <|> + 206 (route' pre (ctx, cwd:rest) params fb) + 207 where + 208 params' = Map.insertWith (++) p [cwd] params + 209 + 210 route' pre (ctx, []) params (Dir _ fb) = + 211 route' pre (ctx, []) params fb + 212 route' pre (ctx, cwd:rest) params (Dir rtm fb) = + 213 case Map.lookup cwd rtm of + 214 Just rt -> (route' pre (cwd:ctx, rest) params rt) <|> + 215 (route' pre (ctx, cwd:rest) params fb) + 216 Nothing -> route' pre (ctx, cwd:rest) params fb + 217 + 218 route' _ _ _ NoRoute = pass diff --git a/static/docs/snap-core-hpc/Snap.Iteratee.hs.html b/static/docs/snap-core-hpc/Snap.Iteratee.hs.html index 2ddf0ad..06dd364 100644 --- a/static/docs/snap-core-hpc/Snap.Iteratee.hs.html +++ b/static/docs/snap-core-hpc/Snap.Iteratee.hs.html @@ -44,388 +44,424 @@ 33 , toWrap 34 35 -- ** Iteratee utilities - 36 , takeExactly - 37 , takeNoMoreThan - 38 , countBytes - 39 , bufferIteratee - 40 , mkIterateeBuffer - 41 , unsafeBufferIterateeWithBuffer - 42 , unsafeBufferIteratee - 43 ) where - 44 - 45 ------------------------------------------------------------------------------ - 46 import Control.Monad - 47 import Control.Monad.CatchIO - 48 import Data.ByteString (ByteString) - 49 import qualified Data.ByteString as S - 50 import qualified Data.ByteString.Unsafe as S - 51 import qualified Data.ByteString.Lazy as L - 52 import Data.IORef - 53 import Data.Iteratee - 54 #ifdef PORTABLE - 55 import Data.Iteratee.IO (enumHandle) - 56 #endif - 57 import qualified Data.Iteratee.Base.StreamChunk as SC - 58 import Data.Iteratee.WrappedByteString - 59 import Data.Monoid (mappend) - 60 import Foreign - 61 import Foreign.C.Types - 62 import GHC.ForeignPtr - 63 import Prelude hiding (catch,drop) - 64 import qualified Data.DList as D - 65 - 66 #ifdef PORTABLE - 67 import Control.Monad.Trans (liftIO) - 68 import System.IO - 69 #else - 70 import Control.Exception (SomeException) - 71 import System.IO.Posix.MMap - 72 #endif - 73 - 74 ------------------------------------------------------------------------------ - 75 - 76 type Stream = StreamG WrappedByteString Word8 - 77 type IterV m = IterGV WrappedByteString Word8 m - 78 type Iteratee m = IterateeG WrappedByteString Word8 m - 79 type Enumerator m a = Iteratee m a -> m (Iteratee m a) - 80 - 81 - 82 ------------------------------------------------------------------------------ - 83 instance (Functor m, MonadCatchIO m) => - 84 MonadCatchIO (IterateeG s el m) where - 85 --catch :: Exception e => m a -> (e -> m a) -> m a - 86 catch m handler = IterateeG $ \str -> do - 87 ee <- try $ runIter m str - 88 case ee of - 89 (Left e) -> runIter (handler e) str - 90 (Right v) -> return v - 91 - 92 --block :: m a -> m a - 93 block m = IterateeG $ \str -> block $ runIter m str - 94 unblock m = IterateeG $ \str -> unblock $ runIter m str - 95 - 96 - 97 ------------------------------------------------------------------------------ - 98 -- | Wraps an 'Iteratee', counting the number of bytes consumed by it. - 99 countBytes :: (Monad m) => Iteratee m a -> Iteratee m (a, Int) - 100 countBytes = go 0 - 101 where - 102 go !n iter = IterateeG $ f n iter - 103 - 104 f !n !iter ch@(Chunk ws) = do - 105 iterv <- runIter iter ch - 106 case iterv of - 107 Done x rest -> let !n' = n + m - len rest - 108 in return $! Done (x, n') rest - 109 Cont i err -> return $ Cont ((go $! n + m) i) err - 110 where - 111 m = S.length $ unWrap ws - 112 - 113 len (EOF _) = 0 - 114 len (Chunk s) = S.length $ unWrap s + 36 , drop' + 37 , takeExactly + 38 , takeNoMoreThan + 39 , countBytes + 40 , bufferIteratee + 41 , mkIterateeBuffer + 42 , unsafeBufferIterateeWithBuffer + 43 , unsafeBufferIteratee + 44 ) where + 45 + 46 ------------------------------------------------------------------------------ + 47 import Control.Monad + 48 import Control.Monad.CatchIO + 49 import Data.ByteString (ByteString) + 50 import qualified Data.ByteString as S + 51 import qualified Data.ByteString.Unsafe as S + 52 import qualified Data.ByteString.Lazy as L + 53 import Data.Int + 54 import Data.IORef + 55 import Data.Iteratee + 56 #ifdef PORTABLE + 57 import Data.Iteratee.IO (enumHandle) + 58 #endif + 59 import qualified Data.Iteratee.Base.StreamChunk as SC + 60 import Data.Iteratee.WrappedByteString + 61 import qualified Data.ListLike as LL + 62 import Data.Monoid (mappend) + 63 import Foreign + 64 import Foreign.C.Types + 65 import GHC.ForeignPtr + 66 import Prelude hiding (catch,drop) + 67 import qualified Data.DList as D + 68 + 69 #ifdef PORTABLE + 70 import Control.Monad.Trans (liftIO) + 71 import System.IO + 72 #else + 73 import Control.Exception (SomeException) + 74 import System.IO.Posix.MMap + 75 #endif + 76 + 77 ------------------------------------------------------------------------------ + 78 + 79 type Stream = StreamG WrappedByteString Word8 + 80 type IterV m = IterGV WrappedByteString Word8 m + 81 type Iteratee m = IterateeG WrappedByteString Word8 m + 82 type Enumerator m a = Iteratee m a -> m (Iteratee m a) + 83 + 84 + 85 ------------------------------------------------------------------------------ + 86 instance (Functor m, MonadCatchIO m) => + 87 MonadCatchIO (IterateeG s el m) where + 88 --catch :: Exception e => m a -> (e -> m a) -> m a + 89 catch m handler = IterateeG $ \str -> do + 90 ee <- try $ runIter m str + 91 case ee of + 92 (Left e) -> runIter (handler e) str + 93 (Right v) -> return v + 94 + 95 --block :: m a -> m a + 96 block m = IterateeG $ \str -> block $ runIter m str + 97 unblock m = IterateeG $ \str -> unblock $ runIter m str + 98 + 99 + 100 ------------------------------------------------------------------------------ + 101 -- | Wraps an 'Iteratee', counting the number of bytes consumed by it. + 102 countBytes :: (Monad m) => Iteratee m a -> Iteratee m (a, Int64) + 103 countBytes = go 0 + 104 where + 105 go !n iter = IterateeG $ f n iter + 106 + 107 f !n !iter ch@(Chunk ws) = do + 108 iterv <- runIter iter ch + 109 case iterv of + 110 Done x rest -> let !n' = n + m - len rest + 111 in return $! Done (x, n') rest + 112 Cont i err -> return $ Cont ((go $! n + m) i) err + 113 where + 114 m = fromIntegral $ S.length (unWrap ws) 115 - 116 f !n !iter stream = do - 117 iterv <- runIter iter stream - 118 case iterv of - 119 Done x rest -> return $ Done (x, n) rest - 120 Cont i err -> return $ Cont (go n i) err - 121 - 122 - 123 ------------------------------------------------------------------------------ - 124 -- | Buffers an iteratee. - 125 -- - 126 -- Our enumerators produce a lot of little strings; rather than spending all - 127 -- our time doing kernel context switches for 4-byte write() calls, we buffer - 128 -- the iteratee to send 8KB at a time. - 129 bufferIteratee :: (Monad m) => Enumerator m a - 130 bufferIteratee = return . go (D.empty,0) - 131 where - 132 blocksize = 8192 - 133 - 134 --go :: (DList ByteString, Int) -> Iteratee m a -> Iteratee m a - 135 go (!dl,!n) iter = IterateeG $! f (dl,n) iter - 136 - 137 --f :: (DList ByteString, Int) -> Iteratee m a -> Stream -> m (IterV m a) - 138 f _ !iter ch@(EOF (Just _)) = runIter iter ch - 139 f (!dl,_) !iter ch@(EOF Nothing) = do - 140 iterv <- runIter iter $ Chunk big - 141 case iterv of - 142 Done x rest -> return $ Done x rest - 143 Cont i (Just e) -> return $ Cont i (Just e) - 144 Cont i Nothing -> runIter i ch - 145 where - 146 big = toWrap $ L.fromChunks [S.concat $ D.toList dl] - 147 - 148 f (!dl,!n) iter (Chunk ws) = - 149 if n' > blocksize - 150 then do - 151 iterv <- runIter iter (Chunk big) - 152 case iterv of - 153 Done x rest -> return $ Done x rest - 154 Cont i (Just e) -> return $ Cont i (Just e) - 155 Cont i Nothing -> return $ Cont (go (D.empty,0) i) Nothing - 156 else return $ Cont (go (dl',n') iter) Nothing - 157 where - 158 s = S.concat $ L.toChunks $ fromWrap ws - 159 m = S.length s - 160 n' = n+m - 161 dl' = D.snoc dl s - 162 big = toWrap $ L.fromChunks [S.concat $ D.toList dl'] - 163 - 164 - 165 bUFSIZ :: Int - 166 bUFSIZ = 8192 - 167 - 168 - 169 -- | Creates a buffer to be passed into 'unsafeBufferIterateeWithBuffer'. - 170 mkIterateeBuffer :: IO (ForeignPtr CChar) - 171 mkIterateeBuffer = mallocPlainForeignPtrBytes bUFSIZ - 172 - 173 ------------------------------------------------------------------------------ - 174 -- | Buffers an iteratee, \"unsafely\". Here we use a fixed binary buffer which - 175 -- we'll re-use, meaning that if you hold on to any of the bytestring data - 176 -- passed into your iteratee (instead of, let's say, shoving it right out a - 177 -- socket) it'll get changed out from underneath you, breaking referential - 178 -- transparency. Use with caution! - 179 -- - 180 -- The IORef returned can be set to True to "cancel" buffering. We added this - 181 -- so that transfer-encoding: chunked (which needs its own buffer and therefore - 182 -- doesn't need /its/ output buffered) can switch the outer buffer off. - 183 -- - 184 unsafeBufferIteratee :: Iteratee IO a -> IO (Iteratee IO a, IORef Bool) - 185 unsafeBufferIteratee iter = do - 186 buf <- mkIterateeBuffer - 187 unsafeBufferIterateeWithBuffer buf iter - 188 - 189 - 190 ------------------------------------------------------------------------------ - 191 -- | Buffers an iteratee, \"unsafely\". Here we use a fixed binary buffer which - 192 -- we'll re-use, meaning that if you hold on to any of the bytestring data - 193 -- passed into your iteratee (instead of, let's say, shoving it right out a - 194 -- socket) it'll get changed out from underneath you, breaking referential - 195 -- transparency. Use with caution! - 196 -- - 197 -- This version accepts a buffer created by 'mkIterateeBuffer'. - 198 -- - 199 -- The IORef returned can be set to True to "cancel" buffering. We added this - 200 -- so that transfer-encoding: chunked (which needs its own buffer and therefore - 201 -- doesn't need /its/ output buffered) can switch the outer buffer off. - 202 -- - 203 unsafeBufferIterateeWithBuffer :: ForeignPtr CChar - 204 -> Iteratee IO a - 205 -> IO (Iteratee IO a, IORef Bool) - 206 unsafeBufferIterateeWithBuffer buf iteratee = do - 207 esc <- newIORef False - 208 return $! (start esc iteratee, esc) - 209 - 210 where - 211 start esc iter = IterateeG $! checkRef esc iter - 212 go bytesSoFar iter = - 213 {-# SCC "unsafeBufferIteratee/go" #-} - 214 IterateeG $! f bytesSoFar iter - 215 - 216 checkRef esc iter ch = do - 217 quit <- readIORef esc - 218 if quit - 219 then runIter iter ch - 220 else f 0 iter ch - 221 - 222 sendBuf n iter = - 223 {-# SCC "unsafeBufferIteratee/sendBuf" #-} - 224 withForeignPtr buf $ \ptr -> do - 225 s <- S.unsafePackCStringLen (ptr, n) - 226 runIter iter $ Chunk $ WrapBS s + 116 len (EOF _) = 0 + 117 len (Chunk s) = fromIntegral $ S.length (unWrap s) + 118 + 119 f !n !iter stream = do + 120 iterv <- runIter iter stream + 121 case iterv of + 122 Done x rest -> return $ Done (x, n) rest + 123 Cont i err -> return $ Cont (go n i) err + 124 + 125 + 126 ------------------------------------------------------------------------------ + 127 -- | Buffers an iteratee. + 128 -- + 129 -- Our enumerators produce a lot of little strings; rather than spending all + 130 -- our time doing kernel context switches for 4-byte write() calls, we buffer + 131 -- the iteratee to send 8KB at a time. + 132 -- + 133 -- The IORef returned can be set to True to "cancel" buffering. We added this + 134 -- so that transfer-encoding: chunked (which needs its own buffer and therefore + 135 -- doesn't need /its/ output buffered) can switch the outer buffer off. + 136 -- + 137 bufferIteratee :: Iteratee IO a -> IO (Iteratee IO a, IORef Bool) + 138 bufferIteratee iteratee = do + 139 esc <- newIORef False + 140 return $ (start esc iteratee, esc) + 141 + 142 where + 143 blocksize = 8192 + 144 + 145 start esc iter = IterateeG $! checkRef esc iter + 146 + 147 checkRef esc iter ch = do + 148 quit <- readIORef esc + 149 if quit + 150 then runIter iter ch + 151 else f (D.empty,0) iter ch + 152 + 153 --go :: (DList ByteString, Int) -> Iteratee m a -> Iteratee m a + 154 go (!dl,!n) iter = IterateeG $! f (dl,n) iter + 155 + 156 --f :: (DList ByteString, Int) -> Iteratee m a -> Stream -> m (IterV m a) + 157 f _ !iter ch@(EOF (Just _)) = runIter iter ch + 158 f (!dl,_) !iter ch@(EOF Nothing) = do + 159 iter' <- if S.null str + 160 then return iter + 161 else liftM liftI $ runIter iter $ Chunk big + 162 runIter iter' ch + 163 where + 164 str = S.concat $ D.toList dl + 165 big = WrapBS str + 166 + 167 f (!dl,!n) iter (Chunk (WrapBS s)) = + 168 if n' >= blocksize + 169 then do + 170 iterv <- runIter iter (Chunk big) + 171 case iterv of + 172 Done x rest -> return $ Done x rest + 173 Cont i (Just e) -> return $ Cont i (Just e) + 174 Cont i Nothing -> return $ Cont (go (D.empty,0) i) Nothing + 175 else return $ Cont (go (dl',n') iter) Nothing + 176 where + 177 m = S.length s + 178 n' = n+m + 179 dl' = D.snoc dl s + 180 big = WrapBS $ S.concat $ D.toList dl' + 181 + 182 + 183 bUFSIZ :: Int + 184 bUFSIZ = 8192 + 185 + 186 + 187 -- | Creates a buffer to be passed into 'unsafeBufferIterateeWithBuffer'. + 188 mkIterateeBuffer :: IO (ForeignPtr CChar) + 189 mkIterateeBuffer = mallocPlainForeignPtrBytes bUFSIZ + 190 + 191 ------------------------------------------------------------------------------ + 192 -- | Buffers an iteratee, \"unsafely\". Here we use a fixed binary buffer which + 193 -- we'll re-use, meaning that if you hold on to any of the bytestring data + 194 -- passed into your iteratee (instead of, let's say, shoving it right out a + 195 -- socket) it'll get changed out from underneath you, breaking referential + 196 -- transparency. Use with caution! + 197 -- + 198 -- The IORef returned can be set to True to "cancel" buffering. We added this + 199 -- so that transfer-encoding: chunked (which needs its own buffer and therefore + 200 -- doesn't need /its/ output buffered) can switch the outer buffer off. + 201 -- + 202 unsafeBufferIteratee :: Iteratee IO a -> IO (Iteratee IO a, IORef Bool) + 203 unsafeBufferIteratee iter = do + 204 buf <- mkIterateeBuffer + 205 unsafeBufferIterateeWithBuffer buf iter + 206 + 207 + 208 ------------------------------------------------------------------------------ + 209 -- | Buffers an iteratee, \"unsafely\". Here we use a fixed binary buffer which + 210 -- we'll re-use, meaning that if you hold on to any of the bytestring data + 211 -- passed into your iteratee (instead of, let's say, shoving it right out a + 212 -- socket) it'll get changed out from underneath you, breaking referential + 213 -- transparency. Use with caution! + 214 -- + 215 -- This version accepts a buffer created by 'mkIterateeBuffer'. + 216 -- + 217 -- The IORef returned can be set to True to "cancel" buffering. We added this + 218 -- so that transfer-encoding: chunked (which needs its own buffer and therefore + 219 -- doesn't need /its/ output buffered) can switch the outer buffer off. + 220 -- + 221 unsafeBufferIterateeWithBuffer :: ForeignPtr CChar + 222 -> Iteratee IO a + 223 -> IO (Iteratee IO a, IORef Bool) + 224 unsafeBufferIterateeWithBuffer buf iteratee = do + 225 esc <- newIORef False + 226 return $! (start esc iteratee, esc) 227 - 228 copy c@(EOF _) = c - 229 copy (Chunk (WrapBS s)) = Chunk $ WrapBS $ S.copy s - 230 - 231 f _ iter ch@(EOF (Just _)) = runIter iter ch - 232 - 233 f !n iter ch@(EOF Nothing) = - 234 if n == 0 - 235 then runIter iter ch - 236 else do - 237 iterv <- sendBuf n iter - 238 case iterv of - 239 Done x rest -> return $ Done x $ copy rest - 240 Cont i (Just e) -> return $ Cont i (Just e) - 241 Cont i Nothing -> runIter i ch - 242 - 243 f !n iter (Chunk (WrapBS s)) = do - 244 let m = S.length s - 245 if m+n > bUFSIZ - 246 then overflow n iter s m - 247 else copyAndCont n iter s m + 228 where + 229 start esc iter = IterateeG $! checkRef esc iter + 230 go bytesSoFar iter = + 231 {-# SCC "unsafeBufferIteratee/go" #-} + 232 IterateeG $! f bytesSoFar iter + 233 + 234 checkRef esc iter ch = do + 235 quit <- readIORef esc + 236 if quit + 237 then runIter iter ch + 238 else f 0 iter ch + 239 + 240 sendBuf n iter = + 241 {-# SCC "unsafeBufferIteratee/sendBuf" #-} + 242 withForeignPtr buf $ \ptr -> do + 243 s <- S.unsafePackCStringLen (ptr, n) + 244 runIter iter $ Chunk $ WrapBS s + 245 + 246 copy c@(EOF _) = c + 247 copy (Chunk (WrapBS s)) = Chunk $ WrapBS $ S.copy s 248 - 249 copyAndCont n iter s m = - 250 {-# SCC "unsafeBufferIteratee/copyAndCont" #-} do - 251 S.unsafeUseAsCStringLen s $ \(p,sz) -> - 252 withForeignPtr buf $ \bufp -> do - 253 let b' = plusPtr bufp n - 254 copyBytes b' p sz - 255 - 256 return $ Cont (go (n+m) iter) Nothing + 249 f _ iter ch@(EOF (Just _)) = runIter iter ch + 250 + 251 f !n iter ch@(EOF Nothing) = + 252 if n == 0 + 253 then runIter iter ch + 254 else do + 255 iter' <- liftM liftI $ sendBuf n iter + 256 runIter iter' ch 257 - 258 - 259 overflow n iter s m = - 260 {-# SCC "unsafeBufferIteratee/overflow" #-} do - 261 let rest = bUFSIZ - n - 262 let m2 = m - rest - 263 let (s1,s2) = S.splitAt rest s - 264 - 265 S.unsafeUseAsCStringLen s1 $ \(p,_) -> - 266 withForeignPtr buf $ \bufp -> do - 267 let b' = plusPtr bufp n - 268 copyBytes b' p rest - 269 - 270 iv <- sendBuf bUFSIZ iter - 271 case iv of - 272 Done x r -> return $ - 273 Done x (copy r `mappend` (Chunk $ WrapBS s2)) - 274 Cont i (Just e) -> return $ Cont i (Just e) - 275 Cont i Nothing -> do - 276 -- check the size of the remainder; if it's bigger than the - 277 -- buffer size then just send it - 278 if m2 >= bUFSIZ - 279 then do - 280 iv' <- runIter i (Chunk $ WrapBS s2) - 281 case iv' of - 282 Done x r -> return $ Done x (copy r) - 283 Cont i' (Just e) -> return $ Cont i' (Just e) - 284 Cont i' Nothing -> return $ Cont (go 0 i') Nothing - 285 else copyAndCont 0 i s2 m2 - 286 - 287 - 288 ------------------------------------------------------------------------------ - 289 -- | Enumerates a strict bytestring. - 290 enumBS :: (Monad m) => ByteString -> Enumerator m a - 291 enumBS bs = enumPure1Chunk $ WrapBS bs - 292 {-# INLINE enumBS #-} - 293 - 294 - 295 ------------------------------------------------------------------------------ - 296 -- | Enumerates a lazy bytestring. - 297 enumLBS :: (Monad m) => L.ByteString -> Enumerator m a - 298 enumLBS lbs = el chunks - 299 where - 300 el [] i = liftM liftI $ runIter i (EOF Nothing) - 301 el (x:xs) i = do - 302 i' <- liftM liftI $ runIter i (Chunk $ WrapBS x) - 303 el xs i' - 304 - 305 chunks = L.toChunks lbs - 306 - 307 - 308 ------------------------------------------------------------------------------ - 309 -- | Converts a lazy bytestring to a wrapped bytestring. - 310 toWrap :: L.ByteString -> WrappedByteString Word8 - 311 toWrap = WrapBS . S.concat . L.toChunks - 312 {-# INLINE toWrap #-} - 313 - 314 - 315 ------------------------------------------------------------------------------ - 316 -- | Converts a wrapped bytestring to a lazy bytestring. - 317 fromWrap :: WrappedByteString Word8 -> L.ByteString - 318 fromWrap = L.fromChunks . (:[]) . unWrap - 319 {-# INLINE fromWrap #-} - 320 + 258 f !n iter (Chunk (WrapBS s)) = do + 259 let m = S.length s + 260 if m+n > bUFSIZ + 261 then overflow n iter s m + 262 else copyAndCont n iter s m + 263 + 264 copyAndCont n iter s m = + 265 {-# SCC "unsafeBufferIteratee/copyAndCont" #-} do + 266 S.unsafeUseAsCStringLen s $ \(p,sz) -> + 267 withForeignPtr buf $ \bufp -> do + 268 let b' = plusPtr bufp n + 269 copyBytes b' p sz + 270 + 271 return $ Cont (go (n+m) iter) Nothing + 272 + 273 + 274 overflow n iter s m = + 275 {-# SCC "unsafeBufferIteratee/overflow" #-} do + 276 let rest = bUFSIZ - n + 277 let m2 = m - rest + 278 let (s1,s2) = S.splitAt rest s + 279 + 280 S.unsafeUseAsCStringLen s1 $ \(p,_) -> + 281 withForeignPtr buf $ \bufp -> do + 282 let b' = plusPtr bufp n + 283 copyBytes b' p rest + 284 + 285 iv <- sendBuf bUFSIZ iter + 286 case iv of + 287 Done x r -> return $ + 288 Done x (copy r `mappend` (Chunk $ WrapBS s2)) + 289 Cont i (Just e) -> return $ Cont i (Just e) + 290 Cont i Nothing -> do + 291 -- check the size of the remainder; if it's bigger than the + 292 -- buffer size then just send it + 293 if m2 >= bUFSIZ + 294 then do + 295 iv' <- runIter i (Chunk $ WrapBS s2) + 296 case iv' of + 297 Done x r -> return $ Done x (copy r) + 298 Cont i' (Just e) -> return $ Cont i' (Just e) + 299 Cont i' Nothing -> return $ Cont (go 0 i') Nothing + 300 else copyAndCont 0 i s2 m2 + 301 + 302 + 303 ------------------------------------------------------------------------------ + 304 -- | Enumerates a strict bytestring. + 305 enumBS :: (Monad m) => ByteString -> Enumerator m a + 306 enumBS bs = enumPure1Chunk $ WrapBS bs + 307 {-# INLINE enumBS #-} + 308 + 309 + 310 ------------------------------------------------------------------------------ + 311 -- | Enumerates a lazy bytestring. + 312 enumLBS :: (Monad m) => L.ByteString -> Enumerator m a + 313 enumLBS lbs = el chunks + 314 where + 315 el [] i = liftM liftI $ runIter i (EOF Nothing) + 316 el (x:xs) i = do + 317 i' <- liftM liftI $ runIter i (Chunk $ WrapBS x) + 318 el xs i' + 319 + 320 chunks = L.toChunks lbs 321 - 322 ------------------------------------------------------------------------------ - 323 -- | Reads n elements from a stream and applies the given iteratee to - 324 -- the stream of the read elements. Reads exactly n elements, and if - 325 -- the stream is short propagates an error. - 326 takeExactly :: (SC.StreamChunk s el, Monad m) => - 327 Int -> - 328 EnumeratorN s el s el m a - 329 takeExactly 0 iter = return iter - 330 takeExactly n' iter = - 331 if n' < 0 - 332 then takeExactly 0 iter - 333 else IterateeG (step n') - 334 where - 335 step n chk@(Chunk str) - 336 | SC.null str = return $ Cont (takeExactly n iter) Nothing - 337 | SC.length str < n = liftM (flip Cont Nothing) inner - 338 where inner = liftM (check (n - SC.length str)) (runIter iter chk) - 339 step n (Chunk str) = done (Chunk s1) (Chunk s2) - 340 where (s1, s2) = SC.splitAt n str - 341 step _n (EOF (Just e)) = return $ Cont undefined (Just e) - 342 step _n (EOF Nothing) = return $ Cont undefined (Just (Err "short write")) - 343 check n (Done x _) = drop n >> return (return x) - 344 check n (Cont x Nothing) = takeExactly n x - 345 check n (Cont _ (Just e)) = drop n >> throwErr e - 346 done s1 s2 = liftM (flip Done s2) (runIter iter s1 >>= checkIfDone return) - 347 - 348 - 349 ------------------------------------------------------------------------------ - 350 -- | Reads up to n elements from a stream and applies the given iteratee to the - 351 -- stream of the read elements. If more than n elements are read, propagates an - 352 -- error. - 353 takeNoMoreThan :: (SC.StreamChunk s el, Monad m) => - 354 Int -> - 355 EnumeratorN s el s el m a - 356 takeNoMoreThan n' iter = - 357 if n' < 0 - 358 then takeNoMoreThan 0 iter - 359 else IterateeG (step n') - 360 where - 361 step n chk@(Chunk str) - 362 | SC.null str = return $ Cont (takeNoMoreThan n iter) Nothing - 363 | SC.length str < n = liftM (flip Cont Nothing) inner - 364 | otherwise = done (Chunk s1) (Chunk s2) - 365 where inner = liftM (check (n - SC.length str)) (runIter iter chk) - 366 (s1, s2) = SC.splitAt n str - 367 - 368 step _n (EOF (Just e)) = return $ Cont undefined (Just e) - 369 step _n chk@(EOF Nothing) = do - 370 v <- runIter iter chk - 371 - 372 case v of - 373 (Done x s) -> return $ Done (return x) s - 374 (Cont _ (Just e)) -> return $ Cont undefined (Just e) - 375 (Cont _ Nothing) -> return $ Cont (throwErr $ Err "premature EOF") Nothing - 376 - 377 check _ v@(Done _ _) = return $ liftI v - 378 check n (Cont x Nothing) = takeNoMoreThan n x - 379 check _ (Cont _ (Just e)) = throwErr e - 380 - 381 done _ (EOF _) = error "impossible" - 382 done s1 s2@(Chunk s2') = do - 383 v <- runIter iter s1 - 384 case v of - 385 (Done x s') -> return $ Done (return x) (s' `mappend` s2) - 386 (Cont _ (Just e)) -> return $ Cont undefined (Just e) - 387 (Cont i Nothing) -> - 388 if SC.null s2' - 389 then return $ Cont (takeNoMoreThan 0 i) Nothing - 390 else return $ Cont undefined (Just $ Err "too many bytes") - 391 - 392 - 393 ------------------------------------------------------------------------------ - 394 enumFile :: FilePath -> Iteratee IO a -> IO (Iteratee IO a) - 395 - 396 #ifdef PORTABLE - 397 - 398 enumFile fp iter = do - 399 h <- liftIO $ openBinaryFile fp ReadMode - 400 i' <- enumHandle h iter - 401 return $ do - 402 x <- i' - 403 liftIO (hClose h) - 404 return x - 405 - 406 #else - 407 - 408 enumFile fp iter = do - 409 es <- (try $ - 410 liftM WrapBS $ - 411 unsafeMMapFile fp) :: IO (Either SomeException (WrappedByteString Word8)) + 322 + 323 ------------------------------------------------------------------------------ + 324 -- | Converts a lazy bytestring to a wrapped bytestring. + 325 toWrap :: L.ByteString -> WrappedByteString Word8 + 326 toWrap = WrapBS . S.concat . L.toChunks + 327 {-# INLINE toWrap #-} + 328 + 329 + 330 ------------------------------------------------------------------------------ + 331 -- | Converts a wrapped bytestring to a lazy bytestring. + 332 fromWrap :: WrappedByteString Word8 -> L.ByteString + 333 fromWrap = L.fromChunks . (:[]) . unWrap + 334 {-# INLINE fromWrap #-} + 335 + 336 + 337 ------------------------------------------------------------------------------ + 338 -- | Skip n elements of the stream, if there are that many + 339 -- This is the Int64 version of the drop function in the iteratee library + 340 drop' :: (SC.StreamChunk s el, Monad m) + 341 => Int64 + 342 -> IterateeG s el m () + 343 drop' 0 = return () + 344 drop' n = IterateeG step + 345 where + 346 step (Chunk str) + 347 | strlen <= n = return $ Cont (drop' (n - strlen)) Nothing + 348 where + 349 strlen = fromIntegral $ SC.length str + 350 step (Chunk str) = return $ Done () (Chunk (LL.drop (fromIntegral n) str)) + 351 step stream = return $ Done () stream + 352 + 353 + 354 ------------------------------------------------------------------------------ + 355 -- | Reads n elements from a stream and applies the given iteratee to + 356 -- the stream of the read elements. Reads exactly n elements, and if + 357 -- the stream is short propagates an error. + 358 takeExactly :: (SC.StreamChunk s el, Monad m) + 359 => Int64 + 360 -> EnumeratorN s el s el m a + 361 takeExactly 0 iter = return iter + 362 takeExactly n' iter = + 363 if n' < 0 + 364 then takeExactly 0 iter + 365 else IterateeG (step n') + 366 where + 367 step n chk@(Chunk str) + 368 | SC.null str = return $ Cont (takeExactly n iter) Nothing + 369 | strlen < n = liftM (flip Cont Nothing) inner + 370 | otherwise = done (Chunk s1) (Chunk s2) + 371 where + 372 strlen = fromIntegral $ SC.length str + 373 inner = liftM (check (n - strlen)) (runIter iter chk) + 374 (s1, s2) = SC.splitAt (fromIntegral n) str + 375 step _n (EOF (Just e)) = return $ Cont undefined (Just e) + 376 step _n (EOF Nothing) = return $ Cont undefined (Just (Err "short write")) + 377 check n (Done x _) = drop' n >> return (return x) + 378 check n (Cont x Nothing) = takeExactly n x + 379 check n (Cont _ (Just e)) = drop' n >> throwErr e + 380 done s1 s2 = liftM (flip Done s2) (runIter iter s1 >>= checkIfDone return) + 381 + 382 + 383 ------------------------------------------------------------------------------ + 384 -- | Reads up to n elements from a stream and applies the given iteratee to the + 385 -- stream of the read elements. If more than n elements are read, propagates an + 386 -- error. + 387 takeNoMoreThan :: (SC.StreamChunk s el, Monad m) + 388 => Int64 + 389 -> EnumeratorN s el s el m a + 390 takeNoMoreThan n' iter = + 391 if n' < 0 + 392 then takeNoMoreThan 0 iter + 393 else IterateeG (step n') + 394 where + 395 step n chk@(Chunk str) + 396 | SC.null str = return $ Cont (takeNoMoreThan n iter) Nothing + 397 | strlen < n = liftM (flip Cont Nothing) inner + 398 | otherwise = done (Chunk s1) (Chunk s2) + 399 where + 400 strlen = fromIntegral $ SC.length str + 401 inner = liftM (check (n - strlen)) (runIter iter chk) + 402 (s1, s2) = SC.splitAt (fromIntegral n) str + 403 + 404 step _n (EOF (Just e)) = return $ Cont undefined (Just e) + 405 step _n chk@(EOF Nothing) = do + 406 v <- runIter iter chk + 407 + 408 case v of + 409 (Done x s) -> return $ Done (return x) s + 410 (Cont _ (Just e)) -> return $ Cont undefined (Just e) + 411 (Cont _ Nothing) -> return $ Cont (throwErr $ Err "premature EOF") Nothing 412 - 413 case es of - 414 (Left e) -> return $ throwErr $ Err $ "IO error" ++ show e - 415 (Right s) -> liftM liftI $ runIter iter $ Chunk s - 416 - 417 #endif + 413 check _ v@(Done _ _) = return $ liftI v + 414 check n (Cont x Nothing) = takeNoMoreThan n x + 415 check _ (Cont _ (Just e)) = throwErr e + 416 + 417 done _ (EOF _) = error "impossible" + 418 done s1 s2@(Chunk s2') = do + 419 v <- runIter iter s1 + 420 case v of + 421 (Done x s') -> return $ Done (return x) (s' `mappend` s2) + 422 (Cont _ (Just e)) -> return $ Cont undefined (Just e) + 423 (Cont i Nothing) -> + 424 if SC.null s2' + 425 then return $ Cont (takeNoMoreThan 0 i) Nothing + 426 else return $ Cont undefined (Just $ Err "too many bytes") + 427 + 428 + 429 ------------------------------------------------------------------------------ + 430 enumFile :: FilePath -> Iteratee IO a -> IO (Iteratee IO a) + 431 + 432 #ifdef PORTABLE + 433 + 434 enumFile fp iter = do + 435 h <- liftIO $ openBinaryFile fp ReadMode + 436 i' <- enumHandle h iter + 437 return $ do + 438 x <- i' + 439 liftIO (hClose h) + 440 return x + 441 + 442 #else + 443 + 444 enumFile fp iter = do + 445 es <- (try $ + 446 liftM WrapBS $ + 447 unsafeMMapFile fp) :: IO (Either SomeException (WrappedByteString Word8)) + 448 + 449 case es of + 450 (Left e) -> return $ throwErr $ Err $ "IO error" ++ show e + 451 (Right s) -> liftM liftI $ runIter iter $ Chunk s + 452 + 453 #endif diff --git a/static/docs/snap-core-hpc/Snap.Util.FileServe.hs.html b/static/docs/snap-core-hpc/Snap.Util.FileServe.hs.html index 86d3166..a0c898e 100644 --- a/static/docs/snap-core-hpc/Snap.Util.FileServe.hs.html +++ b/static/docs/snap-core-hpc/Snap.Util.FileServe.hs.html @@ -240,7 +240,7 @@ 229 let mt = modificationTime filestat 230 maybe (return ()) (chkModificationTime mt) mbIfModified 231 - 232 let sz = fromEnum $ fileSize filestat + 232 let sz = fromIntegral $ fileSize filestat 233 lm <- liftIO $ formatHttpTime mt 234 235 modifyResponse $ setHeader "Last-Modified" lm diff --git a/static/docs/snap-core-hpc/hpc_index.html b/static/docs/snap-core-hpc/hpc_index.html index ec05bdf..f1c3cd3 100644 --- a/static/docs/snap-core-hpc/hpc_index.html +++ b/static/docs/snap-core-hpc/hpc_index.html @@ -11,13 +11,13 @@ 79%38/48
93%14/15
95%536/561
  module Snap.Internal.Routing -100%6/6
96%27/28
98%212/216
+100%9/9
92%35/38
94%302/320
  module Snap.Internal.Types 76%40/52
60%6/10
82%356/434
  module Snap.Iteratee -81%13/16
60%48/79
69%498/714
+70%12/17
58%48/82
68%514/752
  module Snap.Types - 0/0 - 0/0 - 0/0  @@ -29,5 +29,5 @@ 92%12/13
64%20/31
75%262/345
  Program Coverage Total
-81%116/143
71%119/167
83%2144/2557
+80%118/147
70%127/180
83%2250/2699
diff --git a/static/docs/snap-core-hpc/hpc_index_alt.html b/static/docs/snap-core-hpc/hpc_index_alt.html index 7e6ab1b..f7a3e2d 100644 --- a/static/docs/snap-core-hpc/hpc_index_alt.html +++ b/static/docs/snap-core-hpc/hpc_index_alt.html @@ -10,24 +10,24 @@   module Snap.Util.FileServe 87%7/8
100%4/4
97%280/287
-  module Snap.Internal.Routing -100%6/6
96%27/28
98%212/216
-   module Snap.Internal.Http.Types 79%38/48
93%14/15
95%536/561
+  module Snap.Internal.Routing +100%9/9
92%35/38
94%302/320
+   module Snap.Util.GZip 92%12/13
64%20/31
75%262/345
-  module Snap.Iteratee -81%13/16
60%48/79
69%498/714
-   module Snap.Internal.Types 76%40/52
60%6/10
82%356/434
+  module Snap.Iteratee +70%12/17
58%48/82
68%514/752
+   module Snap.Types - 0/0 - 0/0 - 0/0    Program Coverage Total
-81%116/143
71%119/167
83%2144/2557
+80%118/147
70%127/180
83%2250/2699
diff --git a/static/docs/snap-core-hpc/hpc_index_exp.html b/static/docs/snap-core-hpc/hpc_index_exp.html index c5b90ec..d879125 100644 --- a/static/docs/snap-core-hpc/hpc_index_exp.html +++ b/static/docs/snap-core-hpc/hpc_index_exp.html @@ -7,15 +7,15 @@ - - - + + + @@ -23,11 +23,11 @@ - + - +
moduleTop Level DefinitionsAlternativesExpressions
%covered / total%covered / total%covered / total
  module Snap.Internal.Routing100%6/6
96%27/28
98%212/216
  module Snap.Util.FileServe 87%7/8
100%4/4
97%280/287
  module Snap.Internal.Http.Types 79%38/48
93%14/15
95%536/561
  module Snap.Internal.Routing100%9/9
92%35/38
94%302/320
  module Snap.Internal.Types 76%40/52
60%6/10
82%356/434
92%12/13
64%20/31
75%262/345
  module Snap.Iteratee81%13/16
60%48/79
69%498/714
70%12/17
58%48/82
68%514/752
  module Snap.Types 0/0 0/0 0/0 
  Program Coverage Total81%116/143
71%119/167
83%2144/2557
80%118/147
70%127/180
83%2250/2699
diff --git a/static/docs/snap-core-hpc/hpc_index_fun.html b/static/docs/snap-core-hpc/hpc_index_fun.html index aa0c83e..9813b0f 100644 --- a/static/docs/snap-core-hpc/hpc_index_fun.html +++ b/static/docs/snap-core-hpc/hpc_index_fun.html @@ -8,7 +8,7 @@ - + @@ -16,18 +16,18 @@ - - - + + + - +
moduleTop Level DefinitionsAlternativesExpressions
%covered / total%covered / total%covered / total
  module Snap.Internal.Routing100%6/6
96%27/28
98%212/216
100%9/9
92%35/38
94%302/320
  module Snap.Util.GZip 92%12/13
64%20/31
75%262/345
  module Snap.Util.FileServe 87%7/8
100%4/4
97%280/287
  module Snap.Iteratee81%13/16
60%48/79
69%498/714
  module Snap.Internal.Http.Types 79%38/48
93%14/15
95%536/561
  module Snap.Internal.Types 76%40/52
60%6/10
82%356/434
  module Snap.Iteratee70%12/17
58%48/82
68%514/752
  module Snap.Types 0/0 0/0 0/0 
  Program Coverage Total81%116/143
71%119/167
83%2144/2557
80%118/147
70%127/180
83%2250/2699
diff --git a/static/docs/snap-server-hpc/Snap.Internal.Http.Parser.hs.html b/static/docs/snap-server-hpc/Snap.Internal.Http.Parser.hs.html index 0ae18da..8335912 100644 --- a/static/docs/snap-server-hpc/Snap.Internal.Http.Parser.hs.html +++ b/static/docs/snap-server-hpc/Snap.Internal.Http.Parser.hs.html @@ -12,431 +12,452 @@ 1 {-# LANGUAGE BangPatterns #-} 2 {-# LANGUAGE OverloadedStrings #-} 3 {-# LANGUAGE RankNTypes #-} - 4 - 5 module Snap.Internal.Http.Parser - 6 ( IRequest(..) - 7 , parseRequest - 8 , readChunkedTransferEncoding - 9 , parserToIteratee - 10 , parseCookie - 11 , parseUrlEncoded - 12 , writeChunkedTransferEncoding - 13 , strictize - 14 ) where - 15 + 4 {-# LANGUAGE PackageImports #-} + 5 + 6 module Snap.Internal.Http.Parser + 7 ( IRequest(..) + 8 , parseRequest + 9 , readChunkedTransferEncoding + 10 , parserToIteratee + 11 , parseCookie + 12 , parseUrlEncoded + 13 , writeChunkedTransferEncoding + 14 , strictize + 15 ) where 16 - 17 ------------------------------------------------------------------------------ - 18 import Control.Applicative - 19 import Control.Arrow (second) - 20 import Control.Monad (liftM) - 21 import Control.Monad.Trans - 22 import Data.Attoparsec hiding (many, Result(..)) - 23 import Data.Attoparsec.Iteratee - 24 import Data.Bits - 25 import Data.ByteString (ByteString) - 26 import qualified Data.ByteString as S - 27 import Data.ByteString.Internal (c2w, w2c) - 28 import qualified Data.ByteString.Lazy as L - 29 import qualified Data.ByteString.Nums.Careless.Hex as Cvt - 30 import Data.Char - 31 import Data.List (foldl') - 32 import Data.Int - 33 import Data.Iteratee.WrappedByteString - 34 import Data.Map (Map) - 35 import qualified Data.Map as Map - 36 import Data.Maybe (catMaybes) - 37 import qualified Data.Vector.Unboxed as Vec - 38 import Data.Vector.Unboxed (Vector) - 39 import Data.Word (Word8, Word64) - 40 import Foreign.C.Types - 41 import Foreign.ForeignPtr - 42 import Prelude hiding (take, takeWhile) - 43 ------------------------------------------------------------------------------ - 44 import Snap.Internal.Http.Types hiding (Enumerator) - 45 import Snap.Iteratee hiding (take, foldl', filter) - 46 - 47 + 17 + 18 ------------------------------------------------------------------------------ + 19 import Control.Applicative + 20 import Control.Arrow (second) + 21 import Control.Monad (liftM) + 22 import "monads-fd" Control.Monad.Trans + 23 import Data.Attoparsec hiding (many, Result(..)) + 24 import Data.Attoparsec.Iteratee + 25 import Data.Bits + 26 import Data.ByteString (ByteString) + 27 import qualified Data.ByteString as S + 28 import Data.ByteString.Internal (c2w, w2c) + 29 import qualified Data.ByteString.Lazy as L + 30 import qualified Data.ByteString.Nums.Careless.Hex as Cvt + 31 import Data.Char + 32 import Data.List (foldl') + 33 import Data.Int + 34 import Data.IORef + 35 import Data.Iteratee.WrappedByteString + 36 import Data.Map (Map) + 37 import qualified Data.Map as Map + 38 import Data.Maybe (catMaybes) + 39 import qualified Data.Vector.Unboxed as Vec + 40 import Data.Vector.Unboxed (Vector) + 41 import Data.Word (Word8, Word64) + 42 import Foreign.C.Types + 43 import Foreign.ForeignPtr + 44 import Prelude hiding (take, takeWhile) + 45 ------------------------------------------------------------------------------ + 46 import Snap.Internal.Http.Types hiding (Enumerator) + 47 import Snap.Iteratee hiding (take, foldl', filter) 48 - 49 ------------------------------------------------------------------------------ - 50 -- | an internal version of the headers part of an HTTP request - 51 data IRequest = IRequest - 52 { iMethod :: Method - 53 , iRequestUri :: ByteString - 54 , iHttpVersion :: (Int,Int) - 55 , iRequestHeaders :: [(ByteString, ByteString)] - 56 } - 57 - 58 instance Show IRequest where - 59 show (IRequest m u v r) = - 60 concat [ show m - 61 , " " - 62 , show u + 49 + 50 + 51 ------------------------------------------------------------------------------ + 52 -- | an internal version of the headers part of an HTTP request + 53 data IRequest = IRequest + 54 { iMethod :: Method + 55 , iRequestUri :: ByteString + 56 , iHttpVersion :: (Int,Int) + 57 , iRequestHeaders :: [(ByteString, ByteString)] + 58 } + 59 + 60 instance Show IRequest where + 61 show (IRequest m u v r) = + 62 concat [ show m 63 , " " - 64 , show v + 64 , show u 65 , " " - 66 , show r ] - 67 - 68 ------------------------------------------------------------------------------ - 69 parseRequest :: (Monad m) => Iteratee m (Maybe IRequest) - 70 parseRequest = parserToIteratee pRequest - 71 - 72 - 73 readChunkedTransferEncoding :: (Monad m) => Enumerator m a - 74 readChunkedTransferEncoding iter = do - 75 i <- chunkParserToEnumerator (parserToIteratee pGetTransferChunk) - 76 iter - 77 - 78 return i - 79 - 80 - 81 toHex :: Int64 -> ByteString - 82 toHex !i' = S.reverse s - 83 where - 84 !i = abs i' - 85 (!s,_) = S.unfoldrN 16 f (fromIntegral i) - 86 - 87 f :: Word64 -> Maybe (Word8, Word64) - 88 f d = if d == 0 - 89 then Nothing - 90 else Just (ch, theRest) - 91 - 92 where - 93 low4 = fromIntegral $ d .&. 0xf - 94 ch = if low4 >= 10 - 95 then c2w 'a' + low4 - 10 - 96 else c2w '0' + low4 - 97 theRest = (d .&. (complement 0xf)) `shiftR` 4 - 98 - 99 - 100 -- | Given an iteratee, produces a new one that wraps chunks sent to it with a - 101 -- chunked transfer-encoding. Example usage: - 102 -- - 103 -- FIXME: sample output no longer looks like this, we buffer now - 104 -- - 105 -- > > (writeChunkedTransferEncoding - 106 -- > (enumLBS (L.fromChunks ["foo","bar","quux"])) - 107 -- > stream2stream) >>= - 108 -- > run >>= - 109 -- > return . fromWrap - 110 -- > - 111 -- > Chunk "3\r\nfoo\r\n3\r\nbar\r\n4\r\nquux\r\n0\r\n\r\n" Empty - 112 -- - 113 writeChunkedTransferEncoding :: ForeignPtr CChar - 114 -> Enumerator IO a - 115 -> Enumerator IO a - 116 writeChunkedTransferEncoding buf enum it = do - 117 i' <- wrap it - 118 (i,_) <- unsafeBufferIterateeWithBuffer buf i' - 119 enum i - 120 - 121 where - 122 wrap iter = return $ IterateeG $ \s -> - 123 case s of - 124 (EOF Nothing) -> do - 125 v <- runIter iter (Chunk $ toWrap "0\r\n\r\n") - 126 i <- checkIfDone return v - 127 runIter i (EOF Nothing) - 128 (EOF e) -> return $ Cont undefined e - 129 (Chunk (WrapBS x)) -> do - 130 let n = S.length x - 131 if n == 0 - 132 then do - 133 i' <- wrap iter - 134 return $ Cont i' Nothing - 135 else do - 136 let o = S.concat [ toHex (toEnum n) - 137 , "\r\n" - 138 , x - 139 , "\r\n" ] - 140 v <- runIter iter (Chunk $ WrapBS o) - 141 i <- checkIfDone wrap v - 142 return $ Cont i Nothing - 143 - 144 - 145 chunkParserToEnumerator :: (Monad m) => - 146 Iteratee m (Maybe ByteString) - 147 -> Iteratee m a - 148 -> m (Iteratee m a) - 149 chunkParserToEnumerator getChunk client = return $ do - 150 mbB <- getChunk - 151 maybe (finishIt client) (sendBS client) mbB - 152 - 153 where - 154 sendBS iter s = do - 155 v <- lift $ runIter iter (Chunk $ toWrap $ L.fromChunks [s]) - 156 - 157 case v of - 158 (Done _ (EOF (Just e))) -> throwErr e - 159 - 160 (Done x _) -> return x - 161 - 162 (Cont _ (Just e)) -> throwErr e - 163 - 164 (Cont k Nothing) -> joinIM $ - 165 chunkParserToEnumerator getChunk k - 166 - 167 finishIt iter = do - 168 e <- lift $ sendEof iter - 169 - 170 case e of - 171 Left x -> throwErr x - 172 Right x -> return x + 66 , show v + 67 , " " + 68 , show r ] + 69 + 70 ------------------------------------------------------------------------------ + 71 parseRequest :: (Monad m) => Iteratee m (Maybe IRequest) + 72 parseRequest = parserToIteratee pRequest + 73 + 74 + 75 readChunkedTransferEncoding :: (Monad m) => + 76 Iteratee m a + 77 -> m (Iteratee m a) + 78 readChunkedTransferEncoding iter = do + 79 i <- chunkParserToEnumerator (parserToIteratee pGetTransferChunk) + 80 iter + 81 return i + 82 + 83 + 84 toHex :: Int64 -> ByteString + 85 toHex !i' = S.reverse s + 86 where + 87 !i = abs i' + 88 (!s,_) = S.unfoldrN 16 f (fromIntegral i) + 89 + 90 f :: Word64 -> Maybe (Word8, Word64) + 91 f d = if d == 0 + 92 then Nothing + 93 else Just (ch, theRest) + 94 + 95 where + 96 low4 = fromIntegral $ d .&. 0xf + 97 ch = if low4 >= 10 + 98 then c2w 'a' + low4 - 10 + 99 else c2w '0' + low4 + 100 theRest = (d .&. (complement 0xf)) `shiftR` 4 + 101 + 102 + 103 -- | Given an iteratee, produces a new one that wraps chunks sent to it with a + 104 -- chunked transfer-encoding. Example usage: + 105 -- + 106 -- FIXME: sample output no longer looks like this, we buffer now + 107 -- + 108 -- > > (writeChunkedTransferEncoding + 109 -- > (enumLBS (L.fromChunks ["foo","bar","quux"])) + 110 -- > stream2stream) >>= + 111 -- > run >>= + 112 -- > return . fromWrap + 113 -- > + 114 -- > Chunk "3\r\nfoo\r\n3\r\nbar\r\n4\r\nquux\r\n0\r\n\r\n" Empty + 115 -- + 116 + 117 writeChunkedTransferEncoding :: ForeignPtr CChar + 118 -> Enumerator IO a + 119 -> Enumerator IO a + 120 writeChunkedTransferEncoding buf enum it = do + 121 killwrap <- newIORef False + 122 --(out,_) <- bufferIteratee (ignoreEOF $ wrap killwrap it) + 123 (out,_) <- unsafeBufferIterateeWithBuffer buf + 124 (ignoreEOF $ wrap killwrap it) + 125 i <- enum out + 126 v <- runIter i (EOF Nothing) + 127 j <- checkIfDone return v + 128 writeIORef killwrap True + 129 w <- runIter j (Chunk (WrapBS "0\r\n\r\n")) + 130 checkIfDone return w + 131 + 132 where + 133 ignoreEOF iter = IterateeG $ \s -> + 134 case s of + 135 (EOF Nothing) -> return $ Cont iter Nothing + 136 _ -> do + 137 i <- runIter iter s >>= checkIfDone return + 138 return $ Cont (ignoreEOF i) Nothing + 139 + 140 wrap killwrap iter = IterateeG $ \s -> do + 141 quit <- readIORef killwrap + 142 + 143 if quit + 144 then runIter iter s + 145 else case s of + 146 (EOF Nothing) -> do + 147 --S.putStrLn "wrap: eof" + 148 return $ Cont iter Nothing + 149 + 150 (EOF e) -> return $ Cont undefined e + 151 (Chunk (WrapBS x)) -> do + 152 --S.putStrLn $ S.concat ["wrap: got ", x] + 153 let n = S.length x + 154 if n == 0 + 155 then do + 156 return $ Cont iter Nothing + 157 else do + 158 let o = S.concat [ toHex (toEnum n) + 159 , "\r\n" + 160 , x + 161 , "\r\n" ] + 162 i <- liftM liftI $ runIter iter (Chunk $ WrapBS o) + 163 return $ Cont (wrap killwrap i) Nothing + 164 + 165 + 166 chunkParserToEnumerator :: (Monad m) => + 167 Iteratee m (Maybe ByteString) + 168 -> Iteratee m a + 169 -> m (Iteratee m a) + 170 chunkParserToEnumerator getChunk client = return $ do + 171 mbB <- getChunk + 172 maybe (finishIt client) (sendBS client) mbB 173 - 174 sendEof iter = do - 175 v <- runIter iter (EOF Nothing) - 176 - 177 return $ case v of - 178 (Done _ (EOF (Just e))) -> Left e - 179 (Done x _) -> Right x - 180 (Cont _ (Just e)) -> Left e - 181 (Cont _ _) -> Left $ Err $ "divergent iteratee" - 182 - 183 - 184 ------------------------------------------------------------------------------ - 185 -- parse functions - 186 ------------------------------------------------------------------------------ - 187 - 188 -- theft alert: many of these routines adapted from Johan Tibell's hyena - 189 -- package - 190 - 191 -- | Parsers for different tokens in an HTTP request. - 192 sp, digit, letter :: Parser Word8 - 193 sp = word8 $ c2w ' ' - 194 digit = satisfy (isDigit . w2c) - 195 letter = satisfy (isAlpha . w2c) - 196 - 197 untilEOL :: Parser ByteString - 198 untilEOL = takeWhile notend - 199 where - 200 notend d = let c = w2c d in not $ c == '\r' || c == '\n' - 201 - 202 crlf :: Parser ByteString - 203 crlf = string "\r\n" + 174 where + 175 sendBS iter s = do + 176 v <- lift $ runIter iter (Chunk $ toWrap $ L.fromChunks [s]) + 177 + 178 case v of + 179 (Done _ (EOF (Just e))) -> throwErr e + 180 + 181 (Done x _) -> return x + 182 + 183 (Cont _ (Just e)) -> throwErr e + 184 + 185 (Cont k Nothing) -> joinIM $ + 186 chunkParserToEnumerator getChunk k + 187 + 188 finishIt iter = do + 189 e <- lift $ sendEof iter + 190 + 191 case e of + 192 Left x -> throwErr x + 193 Right x -> return x + 194 + 195 sendEof iter = do + 196 v <- runIter iter (EOF Nothing) + 197 + 198 return $ case v of + 199 (Done _ (EOF (Just e))) -> Left e + 200 (Done x _) -> Right x + 201 (Cont _ (Just e)) -> Left e + 202 (Cont _ _) -> Left $ Err $ "divergent iteratee" + 203 204 - 205 -- | Parser for zero or more spaces. - 206 spaces :: Parser [Word8] - 207 spaces = many sp + 205 ------------------------------------------------------------------------------ + 206 -- parse functions + 207 ------------------------------------------------------------------------------ 208 - 209 pSpaces :: Parser ByteString - 210 pSpaces = takeWhile (isSpace . w2c) + 209 -- theft alert: many of these routines adapted from Johan Tibell's hyena + 210 -- package 211 - 212 -- | Parser for the internal request data type. - 213 pRequest :: Parser (Maybe IRequest) - 214 pRequest = (Just <$> pRequest') <|> (endOfInput *> pure Nothing) - 215 - 216 pRequest' :: Parser IRequest - 217 pRequest' = IRequest - 218 <$> (option "" crlf *> pMethod) <* sp - 219 <*> pUri <* sp - 220 <*> pVersion <* crlf - 221 <*> pHeaders <* crlf + 212 -- | Parsers for different tokens in an HTTP request. + 213 sp, digit, letter :: Parser Word8 + 214 sp = word8 $ c2w ' ' + 215 digit = satisfy (isDigit . w2c) + 216 letter = satisfy (isAlpha . w2c) + 217 + 218 untilEOL :: Parser ByteString + 219 untilEOL = takeWhile notend + 220 where + 221 notend d = let c = w2c d in not $ c == '\r' || c == '\n' 222 - 223 -- note: the optional crlf is at the beginning because some older browsers - 224 -- send an extra crlf after a POST body + 223 crlf :: Parser ByteString + 224 crlf = string "\r\n" 225 - 226 - 227 -- | Parser for the request method. - 228 pMethod :: Parser Method - 229 pMethod = (OPTIONS <$ string "OPTIONS") - 230 <|> (GET <$ string "GET") - 231 <|> (HEAD <$ string "HEAD") - 232 <|> word8 (c2w 'P') *> ((POST <$ string "OST") <|> - 233 (PUT <$ string "UT")) - 234 <|> (DELETE <$ string "DELETE") - 235 <|> (TRACE <$ string "TRACE") - 236 <|> (CONNECT <$ string "CONNECT") - 237 - 238 -- | Parser for the request URI. - 239 pUri :: Parser ByteString - 240 pUri = takeWhile (not . isSpace . w2c) - 241 - 242 -- | Parser for the request's HTTP protocol version. - 243 pVersion :: Parser (Int, Int) - 244 pVersion = string "HTTP/" *> - 245 liftA2 (,) (digit' <* word8 (c2w '.')) digit' - 246 where - 247 digit' = fmap (digitToInt . w2c) digit - 248 - 249 fieldChars :: Parser ByteString - 250 fieldChars = takeWhile isFieldChar - 251 where - 252 isFieldChar c = (Vec.!) fieldCharTable (fromEnum c) - 253 - 254 fieldCharTable :: Vector Bool - 255 fieldCharTable = Vec.generate 256 f - 256 where - 257 f d = let c=toEnum d in (isDigit c) || (isAlpha c) || c == '-' || c == '_' + 226 -- | Parser for zero or more spaces. + 227 spaces :: Parser [Word8] + 228 spaces = many sp + 229 + 230 pSpaces :: Parser ByteString + 231 pSpaces = takeWhile (isSpace . w2c) + 232 + 233 -- | Parser for the internal request data type. + 234 pRequest :: Parser (Maybe IRequest) + 235 pRequest = (Just <$> pRequest') <|> (endOfInput *> pure Nothing) + 236 + 237 pRequest' :: Parser IRequest + 238 pRequest' = IRequest + 239 <$> (option "" crlf *> pMethod) <* sp + 240 <*> pUri <* sp + 241 <*> pVersion <* crlf + 242 <*> pHeaders <* crlf + 243 + 244 -- note: the optional crlf is at the beginning because some older browsers + 245 -- send an extra crlf after a POST body + 246 + 247 + 248 -- | Parser for the request method. + 249 pMethod :: Parser Method + 250 pMethod = (OPTIONS <$ string "OPTIONS") + 251 <|> (GET <$ string "GET") + 252 <|> (HEAD <$ string "HEAD") + 253 <|> word8 (c2w 'P') *> ((POST <$ string "OST") <|> + 254 (PUT <$ string "UT")) + 255 <|> (DELETE <$ string "DELETE") + 256 <|> (TRACE <$ string "TRACE") + 257 <|> (CONNECT <$ string "CONNECT") 258 - 259 - 260 -- | Parser for request headers. - 261 pHeaders :: Parser [(ByteString, ByteString)] - 262 pHeaders = many header - 263 where - 264 header = {-# SCC "pHeaders/header" #-} - 265 liftA2 (,) - 266 fieldName - 267 (word8 (c2w ':') *> spaces *> contents) - 268 - 269 fieldName = {-# SCC "pHeaders/fieldName" #-} - 270 liftA2 S.cons letter fieldChars - 271 - 272 contents = {-# SCC "pHeaders/contents" #-} - 273 liftA2 S.append - 274 (untilEOL <* crlf) - 275 (continuation <|> pure S.empty) - 276 - 277 isLeadingWS w = {-# SCC "pHeaders/isLeadingWS" #-} - 278 elem w wstab - 279 - 280 wstab = map c2w " \t" - 281 - 282 leadingWhiteSpace = {-# SCC "pHeaders/leadingWhiteSpace" #-} - 283 takeWhile1 isLeadingWS - 284 - 285 continuation = {-# SCC "pHeaders/continuation" #-} - 286 liftA2 S.cons - 287 (leadingWhiteSpace *> pure (c2w ' ')) - 288 contents - 289 - 290 - 291 pGetTransferChunk :: Parser (Maybe ByteString) - 292 pGetTransferChunk = do - 293 !hex <- liftM fromHex $ (takeWhile (isHexDigit . w2c)) - 294 takeTill ((== '\r') . w2c) - 295 crlf - 296 if hex <= 0 - 297 then return Nothing - 298 else do - 299 x <- take hex - 300 crlf - 301 return $ Just x - 302 where - 303 fromHex :: ByteString -> Int - 304 fromHex s = Cvt.hex (L.fromChunks [s]) - 305 - 306 - 307 ------------------------------------------------------------------------------ - 308 -- COOKIE PARSING - 309 ------------------------------------------------------------------------------ + 259 -- | Parser for the request URI. + 260 pUri :: Parser ByteString + 261 pUri = takeWhile (not . isSpace . w2c) + 262 + 263 -- | Parser for the request's HTTP protocol version. + 264 pVersion :: Parser (Int, Int) + 265 pVersion = string "HTTP/" *> + 266 liftA2 (,) (digit' <* word8 (c2w '.')) digit' + 267 where + 268 digit' = fmap (digitToInt . w2c) digit + 269 + 270 fieldChars :: Parser ByteString + 271 fieldChars = takeWhile isFieldChar + 272 where + 273 isFieldChar c = (Vec.!) fieldCharTable (fromEnum c) + 274 + 275 fieldCharTable :: Vector Bool + 276 fieldCharTable = Vec.generate 256 f + 277 where + 278 f d = let c=toEnum d in (isDigit c) || (isAlpha c) || c == '-' || c == '_' + 279 + 280 + 281 -- | Parser for request headers. + 282 pHeaders :: Parser [(ByteString, ByteString)] + 283 pHeaders = many header + 284 where + 285 header = {-# SCC "pHeaders/header" #-} + 286 liftA2 (,) + 287 fieldName + 288 (word8 (c2w ':') *> spaces *> contents) + 289 + 290 fieldName = {-# SCC "pHeaders/fieldName" #-} + 291 liftA2 S.cons letter fieldChars + 292 + 293 contents = {-# SCC "pHeaders/contents" #-} + 294 liftA2 S.append + 295 (untilEOL <* crlf) + 296 (continuation <|> pure S.empty) + 297 + 298 isLeadingWS w = {-# SCC "pHeaders/isLeadingWS" #-} + 299 elem w wstab + 300 + 301 wstab = map c2w " \t" + 302 + 303 leadingWhiteSpace = {-# SCC "pHeaders/leadingWhiteSpace" #-} + 304 takeWhile1 isLeadingWS + 305 + 306 continuation = {-# SCC "pHeaders/continuation" #-} + 307 liftA2 S.cons + 308 (leadingWhiteSpace *> pure (c2w ' ')) + 309 contents 310 - 311 -- these definitions try to mirror RFC-2068 (the HTTP/1.1 spec) and RFC-2109 - 312 -- (cookie spec): please point out any errors! - 313 - 314 {-# INLINE matchAll #-} - 315 matchAll :: [ Char -> Bool ] -> Char -> Bool - 316 matchAll x c = and $ map ($ c) x - 317 - 318 {-# INLINE isToken #-} - 319 isToken :: Char -> Bool - 320 isToken c = (Vec.!) tokenTable (fromEnum c) - 321 where - 322 tokenTable :: Vector Bool - 323 tokenTable = Vec.generate 256 (f . toEnum) - 324 - 325 f = matchAll [ isAscii - 326 , not . isControl - 327 , not . isSpace - 328 , not . flip elem [ '(', ')', '<', '>', '@', ',', ';' - 329 , ':', '\\', '\"', '/', '[', ']' - 330 , '?', '=', '{', '}' ] - 331 ] - 332 - 333 {-# INLINE isRFCText #-} - 334 isRFCText :: Char -> Bool - 335 isRFCText = not . isControl - 336 - 337 pToken :: Parser ByteString - 338 pToken = takeWhile (isToken . w2c) - 339 - 340 - 341 pQuotedString :: Parser ByteString - 342 pQuotedString = q *> quotedText <* q - 343 where - 344 quotedText = (S.concat . reverse) <$> f [] + 311 + 312 pGetTransferChunk :: Parser (Maybe ByteString) + 313 pGetTransferChunk = do + 314 !hex <- liftM fromHex $ (takeWhile (isHexDigit . w2c)) + 315 takeTill ((== '\r') . w2c) + 316 crlf + 317 if hex <= 0 + 318 then return Nothing + 319 else do + 320 x <- take hex + 321 crlf + 322 return $ Just x + 323 where + 324 fromHex :: ByteString -> Int + 325 fromHex s = Cvt.hex (L.fromChunks [s]) + 326 + 327 + 328 ------------------------------------------------------------------------------ + 329 -- COOKIE PARSING + 330 ------------------------------------------------------------------------------ + 331 + 332 -- these definitions try to mirror RFC-2068 (the HTTP/1.1 spec) and RFC-2109 + 333 -- (cookie spec): please point out any errors! + 334 + 335 {-# INLINE matchAll #-} + 336 matchAll :: [ Char -> Bool ] -> Char -> Bool + 337 matchAll x c = and $ map ($ c) x + 338 + 339 {-# INLINE isToken #-} + 340 isToken :: Char -> Bool + 341 isToken c = (Vec.!) tokenTable (fromEnum c) + 342 where + 343 tokenTable :: Vector Bool + 344 tokenTable = Vec.generate 256 (f . toEnum) 345 - 346 f soFar = do - 347 t <- takeWhile qdtext - 348 - 349 let soFar' = t:soFar - 350 - 351 -- RFC says that backslash only escapes for <"> - 352 choice [ string "\\\"" *> f ("\"" : soFar') - 353 , pure soFar' ] - 354 - 355 - 356 q = word8 $ c2w '\"' - 357 - 358 qdtext = matchAll [ isRFCText, (/= '\"'), (/= '\\') ] . w2c - 359 + 346 f = matchAll [ isAscii + 347 , not . isControl + 348 , not . isSpace + 349 , not . flip elem [ '(', ')', '<', '>', '@', ',', ';' + 350 , ':', '\\', '\"', '/', '[', ']' + 351 , '?', '=', '{', '}' ] + 352 ] + 353 + 354 {-# INLINE isRFCText #-} + 355 isRFCText :: Char -> Bool + 356 isRFCText = not . isControl + 357 + 358 pToken :: Parser ByteString + 359 pToken = takeWhile (isToken . w2c) 360 - 361 pCookies :: Parser [Cookie] - 362 pCookies = do - 363 -- grab kvps and turn to strict bytestrings - 364 kvps <- pAvPairs - 365 - 366 return $ map toCookie $ filter (not . S.isPrefixOf "$" . fst) kvps - 367 - 368 where - 369 toCookie (nm,val) = Cookie nm val Nothing Nothing Nothing - 370 - 371 - 372 -- unhelpfully, the spec mentions "old-style" cookies that don't have quotes - 373 -- around the value. wonderful. - 374 pWord :: Parser ByteString - 375 pWord = pQuotedString <|> (takeWhile ((/= ';') . w2c)) - 376 - 377 pAvPairs :: Parser [(ByteString, ByteString)] - 378 pAvPairs = do - 379 a <- pAvPair - 380 b <- many (pSpaces *> char ';' *> pSpaces *> pAvPair) - 381 - 382 return $ a:b - 383 - 384 pAvPair :: Parser (ByteString, ByteString) - 385 pAvPair = do - 386 key <- pToken <* pSpaces - 387 val <- option "" $ char '=' *> pSpaces *> pWord + 361 + 362 pQuotedString :: Parser ByteString + 363 pQuotedString = q *> quotedText <* q + 364 where + 365 quotedText = (S.concat . reverse) <$> f [] + 366 + 367 f soFar = do + 368 t <- takeWhile qdtext + 369 + 370 let soFar' = t:soFar + 371 + 372 -- RFC says that backslash only escapes for <"> + 373 choice [ string "\\\"" *> f ("\"" : soFar') + 374 , pure soFar' ] + 375 + 376 + 377 q = word8 $ c2w '\"' + 378 + 379 qdtext = matchAll [ isRFCText, (/= '\"'), (/= '\\') ] . w2c + 380 + 381 + 382 pCookies :: Parser [Cookie] + 383 pCookies = do + 384 -- grab kvps and turn to strict bytestrings + 385 kvps <- pAvPairs + 386 + 387 return $ map toCookie $ filter (not . S.isPrefixOf "$" . fst) kvps 388 - 389 return (key,val) - 390 - 391 parseCookie :: ByteString -> Maybe [Cookie] - 392 parseCookie = parseToCompletion pCookies - 393 - 394 ------------------------------------------------------------------------------ - 395 -- MULTIPART/FORMDATA - 396 ------------------------------------------------------------------------------ + 389 where + 390 toCookie (nm,val) = Cookie nm val Nothing Nothing Nothing + 391 + 392 + 393 -- unhelpfully, the spec mentions "old-style" cookies that don't have quotes + 394 -- around the value. wonderful. + 395 pWord :: Parser ByteString + 396 pWord = pQuotedString <|> (takeWhile ((/= ';') . w2c)) 397 - 398 parseUrlEncoded :: ByteString -> Map ByteString [ByteString] - 399 parseUrlEncoded s = foldl' (\m (k,v) -> Map.insertWith' (++) k [v] m) - 400 Map.empty - 401 decoded - 402 where - 403 breakApart = (second (S.drop 1)) . S.break (== (c2w '=')) - 404 - 405 parts :: [(ByteString,ByteString)] - 406 parts = map breakApart $ S.split (c2w '&') s - 407 - 408 urldecode = parseToCompletion pUrlEscaped + 398 pAvPairs :: Parser [(ByteString, ByteString)] + 399 pAvPairs = do + 400 a <- pAvPair + 401 b <- many (pSpaces *> char ';' *> pSpaces *> pAvPair) + 402 + 403 return $ a:b + 404 + 405 pAvPair :: Parser (ByteString, ByteString) + 406 pAvPair = do + 407 key <- pToken <* pSpaces + 408 val <- option "" $ char '=' *> pSpaces *> pWord 409 - 410 decodeOne (a,b) = do - 411 a' <- urldecode a - 412 b' <- urldecode b - 413 return (a',b') - 414 - 415 decoded = catMaybes $ map decodeOne parts - 416 - 417 - 418 ------------------------------------------------------------------------------ - 419 -- utility functions - 420 ------------------------------------------------------------------------------ - 421 - 422 strictize :: L.ByteString -> ByteString - 423 strictize = S.concat . L.toChunks - 424 - 425 ------------------------------------------------------------------------------ - 426 char :: Char -> Parser Word8 - 427 char = word8 . c2w - 428 + 410 return (key,val) + 411 + 412 parseCookie :: ByteString -> Maybe [Cookie] + 413 parseCookie = parseToCompletion pCookies + 414 + 415 ------------------------------------------------------------------------------ + 416 -- MULTIPART/FORMDATA + 417 ------------------------------------------------------------------------------ + 418 + 419 parseUrlEncoded :: ByteString -> Map ByteString [ByteString] + 420 parseUrlEncoded s = foldl' (\m (k,v) -> Map.insertWith' (++) k [v] m) + 421 Map.empty + 422 decoded + 423 where + 424 breakApart = (second (S.drop 1)) . S.break (== (c2w '=')) + 425 + 426 parts :: [(ByteString,ByteString)] + 427 parts = map breakApart $ S.split (c2w '&') s + 428 + 429 urldecode = parseToCompletion pUrlEscaped + 430 + 431 decodeOne (a,b) = do + 432 a' <- urldecode a + 433 b' <- urldecode b + 434 return (a',b') + 435 + 436 decoded = catMaybes $ map decodeOne parts + 437 + 438 + 439 ------------------------------------------------------------------------------ + 440 -- utility functions + 441 ------------------------------------------------------------------------------ + 442 + 443 strictize :: L.ByteString -> ByteString + 444 strictize = S.concat . L.toChunks + 445 + 446 ------------------------------------------------------------------------------ + 447 char :: Char -> Parser Word8 + 448 char = word8 . c2w + 449 diff --git a/static/docs/snap-server-hpc/Snap.Internal.Http.Server.LibevBackend.hs.html b/static/docs/snap-server-hpc/Snap.Internal.Http.Server.LibevBackend.hs.html index 50b00de..532d2a1 100644 --- a/static/docs/snap-server-hpc/Snap.Internal.Http.Server.LibevBackend.hs.html +++ b/static/docs/snap-server-hpc/Snap.Internal.Http.Server.LibevBackend.hs.html @@ -9,741 +9,817 @@ span.spaces { background: white }
-    1 {-# LANGUAGE BangPatterns #-}
-    2 {-# LANGUAGE DeriveDataTypeable #-}
-    3 {-# LANGUAGE ForeignFunctionInterface #-}
-    4 {-# LANGUAGE OverloadedStrings #-}
-    5 {-# LANGUAGE RankNTypes #-}
-    6 {-# LANGUAGE ScopedTypeVariables #-}
-    7 
-    8 module Snap.Internal.Http.Server.LibevBackend
-    9   ( Backend
-   10   , BackendTerminatedException
-   11   , Connection
-   12   , TimeoutException
-   13   , name
-   14   , debug
-   15   , bindIt
-   16   , new
-   17   , stop
-   18   , withConnection
-   19   , sendFile
-   20   , tickleTimeout
-   21   , getReadEnd
-   22   , getWriteEnd
-   23   , getRemoteAddr
-   24   , getRemotePort
-   25   , getLocalAddr
-   26   , getLocalPort
-   27   ) where
-   28 
-   29 ---------------------------
-   30 -- TODO: document module --
+    1 {-# LANGUAGE CPP #-}
+    2 {-# LANGUAGE BangPatterns #-}
+    3 {-# LANGUAGE DeriveDataTypeable #-}
+    4 {-# LANGUAGE ForeignFunctionInterface #-}
+    5 {-# LANGUAGE OverloadedStrings #-}
+    6 {-# LANGUAGE RankNTypes #-}
+    7 {-# LANGUAGE ScopedTypeVariables #-}
+    8 {-# LANGUAGE PackageImports #-}
+    9 
+   10 module Snap.Internal.Http.Server.LibevBackend
+   11   ( Backend
+   12   , BackendTerminatedException
+   13   , Connection
+   14   , TimeoutException
+   15   , name
+   16   , debug
+   17   , bindIt
+   18   , new
+   19   , stop
+   20   , withConnection
+   21   , sendFile
+   22   , tickleTimeout
+   23   , getReadEnd
+   24   , getWriteEnd
+   25   , getRemoteAddr
+   26   , getRemotePort
+   27   , getLocalAddr
+   28   , getLocalPort
+   29   ) where
+   30 
    31 ---------------------------
-   32 
-   33 ------------------------------------------------------------------------------
-   34 import           Control.Concurrent
-   35 import           Control.Exception
-   36 import           Control.Monad
-   37 import           Control.Monad.Trans
-   38 import           Data.ByteString (ByteString)
-   39 import           Data.ByteString.Internal (c2w, w2c)
-   40 import qualified Data.ByteString.Unsafe as B
-   41 import qualified Data.ByteString as B
-   42 import           Data.IORef
-   43 import           Data.Iteratee.WrappedByteString
-   44 import           Data.Set (Set)
-   45 import qualified Data.Set as Set
-   46 import           Data.Typeable
-   47 import           Foreign hiding (new)
-   48 import           Foreign.C.Error
-   49 import           Foreign.C.Types
-   50 import           GHC.Conc (forkOnIO)
-   51 import           Network.Libev
-   52 import           Network.Socket
-   53 import qualified Network.Socket.SendFile as SF
-   54 import           Prelude hiding (catch)
-   55 import           System.Timeout
-   56 ------------------------------------------------------------------------------
-   57 import           Snap.Iteratee
-   58 import           Snap.Internal.Debug
-   59 
-   60 
-   61 data Backend = Backend
-   62     { _acceptSocket      :: Socket
-   63     , _acceptFd          :: CInt
-   64     , _connectionQueue   :: Chan CInt
-   65     , _evLoop            :: EvLoopPtr
-   66     , _acceptIOCallback  :: FunPtr IoCallback
-   67     , _acceptIOObj       :: EvIoPtr
-   68 
-   69       -- FIXME: we don't need _loopThread
-   70     , _loopThread        :: MVar ThreadId
-   71     , _mutexCallbacks    :: (FunPtr MutexCallback, FunPtr MutexCallback)
-   72     , _loopLock          :: MVar ()
-   73     , _asyncCb           :: FunPtr AsyncCallback
-   74     , _asyncObj          :: EvAsyncPtr
-   75     , _killCb            :: FunPtr AsyncCallback
-   76     , _killObj           :: EvAsyncPtr
-   77     , _connectionThreads :: MVar (Set ThreadId)
-   78     , _backendCPU        :: Int
-   79     }
-   80 
-   81 
-   82 data Connection = Connection
-   83     { _backend             :: !Backend
-   84     , _socket              :: !Socket
-   85     , _socketFd            :: !CInt
-   86     , _remoteAddr          :: !ByteString
-   87     , _remotePort          :: !Int
-   88     , _localAddr           :: !ByteString
-   89     , _localPort           :: !Int
-   90     , _readAvailable       :: !(MVar ())
-   91     , _writeAvailable      :: !(MVar ())
-   92     , _timerObj            :: !EvTimerPtr
-   93     , _timerCallback       :: !(FunPtr TimerCallback)
-   94     , _readActive          :: !(IORef Bool)
-   95     , _writeActive         :: !(IORef Bool)
-   96     , _connReadIOObj       :: !EvIoPtr
-   97     , _connReadIOCallback  :: !(FunPtr IoCallback)
-   98     , _connWriteIOObj      :: !EvIoPtr
-   99     , _connWriteIOCallback :: !(FunPtr IoCallback)
-  100     , _connThread          :: !(MVar ThreadId)
-  101     }
-  102 
-  103 {-# INLINE name #-}
-  104 name :: ByteString
-  105 name = "libev"
-  106 
-  107 
-  108 sendFile :: Connection -> FilePath -> IO ()
-  109 sendFile c fp = do
-  110     withMVar lock $ \_ -> do
-  111       act <- readIORef $ _writeActive c
-  112       when act $ evIoStop loop io
-  113 
-  114     SF.sendFile s fp
-  115 
-  116     withMVar lock $ \_ -> do
-  117       tryPutMVar (_readAvailable c) ()
-  118       tryPutMVar (_writeAvailable c) ()
-  119       evIoStart loop io
-  120       writeIORef (_writeActive c) True
-  121       evAsyncSend loop asy
-  122 
-  123   where
-  124     s    = _socket c
-  125     io   = _connWriteIOObj c
-  126     b    = _backend c
-  127     loop = _evLoop b
-  128     lock = _loopLock b
-  129     asy  = _asyncObj b
-  130 
-  131 
-  132 bindIt :: ByteString         -- ^ bind address, or \"*\" for all
-  133        -> Int                -- ^ port to bind to
-  134        -> IO (Socket,CInt)
-  135 bindIt bindAddress bindPort = do
-  136     sock <- socket AF_INET Stream 0
-  137     addr <- getHostAddr bindPort bindAddress
-  138     setSocketOption sock ReuseAddr 1
-  139     bindSocket sock addr
-  140     listen sock 150
-  141     let sockFd = fdSocket sock
-  142     c_setnonblocking sockFd
-  143     return (sock, sockFd)
-  144 
-  145 
-  146 new :: (Socket,CInt)   -- ^ value you got from bindIt
-  147     -> Int             -- ^ cpu
-  148     -> IO Backend
-  149 new (sock,sockFd) cpu = do
-  150     connq <- newChan
-  151 
-  152     -- We'll try kqueue on OSX even though the libev docs complain that it's
-  153     -- "broken", in the hope that it works as expected for sockets
-  154     f  <- evRecommendedBackends
-  155     lp <- evLoopNew $ toEnum . fromEnum $ f .|. evbackend_kqueue
-  156 
-  157 
-  158     -- we'll be working multithreaded so we need to set up locking for the C
-  159     -- event loop struct
-  160     (mc1,mc2,looplock) <- setupLockingForLoop lp
-  161 
-  162     -- setup async callbacks -- these allow us to wake up the main loop
-  163     -- (normally blocked in c-land) from other threads
-  164     asyncObj <- mkEvAsync
-  165     asyncCB  <- mkAsyncCallback $ \_ _ _ -> do
-  166                             debug "async wakeup"
-  167                             return ()
-  168 
-  169     killObj <- mkEvAsync
-  170     killCB  <- mkAsyncCallback $ \_ _ _ -> do
-  171                             debug "async kill wakeup"
-  172                             evUnloop lp 2
-  173                             return ()
-  174 
-  175     evAsyncInit asyncObj asyncCB
-  176     evAsyncStart lp asyncObj
-  177     evAsyncInit killObj killCB
-  178     evAsyncStart lp killObj
-  179 
-  180     -- setup the accept callback; this watches for read readiness on the listen
-  181     -- port
-  182     accCB <- mkIoCallback $ acceptCallback sockFd connq
-  183     accIO <- mkEvIo
-  184     evIoInit accIO accCB sockFd ev_read
-  185     evIoStart lp accIO
-  186 
-  187     -- an MVar for the loop thread, and one to keep track of the set of active
-  188     -- threads
-  189     threadMVar <- newEmptyMVar
-  190     threadSetMVar <- newMVar Set.empty
-  191 
-  192     let b = Backend sock
-  193                     sockFd
-  194                     connq
-  195                     lp
-  196                     accCB
-  197                     accIO
-  198                     threadMVar
-  199                     (mc1,mc2)
-  200                     looplock
-  201                     asyncCB
-  202                     asyncObj
-  203                     killCB
-  204                     killObj
-  205                     threadSetMVar
-  206                     cpu
-  207 
-  208     tid <- forkOnIO cpu $ loopThread b
-  209     putMVar threadMVar tid
+   32 -- TODO: document module --
+   33 ---------------------------
+   34 
+   35 ------------------------------------------------------------------------------
+   36 import           Control.Concurrent
+   37 import           Control.Exception
+   38 import           Control.Monad
+   39 import "monads-fd" Control.Monad.Trans
+   40 import           Data.ByteString (ByteString)
+   41 import           Data.ByteString.Internal (c2w, w2c)
+   42 import qualified Data.ByteString.Unsafe as B
+   43 import qualified Data.ByteString as B
+   44 import           Data.DList (DList)
+   45 import qualified Data.DList as D
+   46 import           Data.IORef
+   47 import           Data.Iteratee.WrappedByteString
+   48 import qualified Data.List as List
+   49 import           Data.Set (Set)
+   50 import qualified Data.Set as Set
+   51 import           Data.Typeable
+   52 import           Foreign hiding (new)
+   53 import           Foreign.C.Error
+   54 import           Foreign.C.Types
+   55 import           GHC.Conc (forkOnIO)
+   56 import           Network.Libev
+   57 import           Network.Socket
+   58 import           Prelude hiding (catch)
+   59 import           System.Timeout
+   60 ------------------------------------------------------------------------------
+   61 import           Snap.Iteratee
+   62 import           Snap.Internal.Debug
+   63 
+   64 #if defined(HAS_SENDFILE)
+   65 import qualified System.SendFile as SF
+   66 import           System.Posix.IO
+   67 import           System.Posix.Types (Fd(..))
+   68 #endif
+   69 
+   70 data Backend = Backend
+   71     { _acceptSocket      :: !Socket
+   72     , _acceptFd          :: !CInt
+   73     , _connectionQueue   :: !(Chan CInt)
+   74     , _evLoop            :: !EvLoopPtr
+   75     , _acceptIOCallback  :: !(FunPtr IoCallback)
+   76     , _acceptIOObj       :: !EvIoPtr
+   77     , _mutexCallbacks    :: !(FunPtr MutexCallback, FunPtr MutexCallback)
+   78     , _loopLock          :: !(MVar ())
+   79     , _asyncCb           :: !(FunPtr AsyncCallback)
+   80     , _asyncObj          :: !EvAsyncPtr
+   81     , _killCb            :: !(FunPtr AsyncCallback)
+   82     , _killObj           :: !EvAsyncPtr
+   83     , _connectionThreads :: !(MVar (Set ThreadId))
+   84     , _connThreadEdits   :: !(IORef (DList (Set ThreadId -> Set ThreadId)))
+   85     , _connThreadId      :: !(MVar ThreadId)
+   86     , _connThreadIsDone  :: !(MVar ())
+   87     , _threadActivity    :: !(MVar ())
+   88     , _backendCPU        :: !Int
+   89     }
+   90 
+   91 
+   92 data Connection = Connection
+   93     { _backend             :: !Backend
+   94     , _socket              :: !Socket
+   95     , _socketFd            :: !CInt
+   96     , _remoteAddr          :: !ByteString
+   97     , _remotePort          :: !Int
+   98     , _localAddr           :: !ByteString
+   99     , _localPort           :: !Int
+  100     , _readAvailable       :: !(MVar ())
+  101     , _writeAvailable      :: !(MVar ())
+  102     , _timerObj            :: !EvTimerPtr
+  103     , _timerCallback       :: !(FunPtr TimerCallback)
+  104     , _readActive          :: !(IORef Bool)
+  105     , _writeActive         :: !(IORef Bool)
+  106     , _connReadIOObj       :: !EvIoPtr
+  107     , _connReadIOCallback  :: !(FunPtr IoCallback)
+  108     , _connWriteIOObj      :: !EvIoPtr
+  109     , _connWriteIOCallback :: !(FunPtr IoCallback)
+  110     , _connThread          :: !(MVar ThreadId)
+  111     }
+  112 
+  113 {-# INLINE name #-}
+  114 name :: ByteString
+  115 name = "libev"
+  116 
+  117 
+  118 sendFile :: Connection -> FilePath -> Int64 -> IO ()
+  119 #if defined(HAS_SENDFILE)
+  120 sendFile c fp sz = do
+  121 #else
+  122 sendFile c fp _ = do
+  123 #endif
+  124     withMVar lock $ \_ -> do
+  125       act <- readIORef $ _writeActive c
+  126       when act $ evIoStop loop io
+  127       writeIORef (_writeActive c) False
+  128       evAsyncSend loop asy
+  129 
+  130 #if defined(HAS_SENDFILE)
+  131     fd <- openFd fp ReadOnly Nothing defaultFileFlags
+  132     go fd 0 sz
+  133 #else
+  134     -- no need to count bytes
+  135     enumFile fp (getWriteEnd c) >>= run
+  136     return ()
+  137 #endif
+  138 
+  139     withMVar lock $ \_ -> do
+  140       tryTakeMVar $ _readAvailable c
+  141       tryTakeMVar $ _writeAvailable c
+  142       evAsyncSend loop asy
+  143 
+  144   where
+  145 #if defined(HAS_SENDFILE)
+  146     go fd off bytes
+  147       | bytes == 0 = return ()
+  148       | otherwise  = do
+  149             sent <- SF.sendFile sfd fd off bytes
+  150             if sent < bytes
+  151               then tickleTimeout c >> go fd (off+sent) (bytes-sent)
+  152               else return ()
+  153 
+  154     sfd  = Fd $ _socketFd c
+  155 #endif
+  156     io   = _connWriteIOObj c
+  157     b    = _backend c
+  158     loop = _evLoop b
+  159     lock = _loopLock b
+  160     asy  = _asyncObj b
+  161 
+  162 
+  163 bindIt :: ByteString         -- ^ bind address, or \"*\" for all
+  164        -> Int                -- ^ port to bind to
+  165        -> IO (Socket,CInt)
+  166 bindIt bindAddress bindPort = do
+  167     sock <- socket AF_INET Stream 0
+  168     addr <- getHostAddr bindPort bindAddress
+  169     setSocketOption sock ReuseAddr 1
+  170     bindSocket sock addr
+  171     listen sock 150
+  172     let sockFd = fdSocket sock
+  173     c_setnonblocking sockFd
+  174     return (sock, sockFd)
+  175 
+  176 
+  177 new :: (Socket,CInt)   -- ^ value you got from bindIt
+  178     -> Int             -- ^ cpu
+  179     -> IO Backend
+  180 new (sock,sockFd) cpu = do
+  181     connq <- newChan
+  182 
+  183     -- We'll try kqueue on OSX even though the libev docs complain that it's
+  184     -- "broken", in the hope that it works as expected for sockets
+  185     f  <- evRecommendedBackends
+  186     lp <- evLoopNew $ toEnum . fromEnum $ f .|. evbackend_kqueue
+  187 
+  188 
+  189     -- we'll be working multithreaded so we need to set up locking for the C
+  190     -- event loop struct
+  191     (mc1,mc2,looplock) <- setupLockingForLoop lp
+  192 
+  193     -- setup async callbacks -- these allow us to wake up the main loop
+  194     -- (normally blocked in c-land) from other threads
+  195     asyncObj <- mkEvAsync
+  196     asyncCB  <- mkAsyncCallback $ \_ _ _ -> do
+  197                             debug "async wakeup"
+  198                             return ()
+  199 
+  200     killObj <- mkEvAsync
+  201     killCB  <- mkAsyncCallback $ \_ _ _ -> do
+  202                             debug "async kill wakeup"
+  203                             evUnloop lp 2
+  204                             return ()
+  205 
+  206     evAsyncInit asyncObj asyncCB
+  207     evAsyncStart lp asyncObj
+  208     evAsyncInit killObj killCB
+  209     evAsyncStart lp killObj
   210 
-  211     debug $ "Backend.new: loop spawned"
-  212     return b
-  213 
-  214 
-  215 -- | Run evLoop in a thread
-  216 loopThread :: Backend -> IO ()
-  217 loopThread backend = do
-  218     debug $ "starting loop"
-  219     (ignoreException go) `finally` cleanup
-  220     debug $ "loop finished"
-  221   where
-  222     cleanup = do
-  223         debug $ "loopThread: cleaning up"
-  224         ignoreException $ freeBackend backend
-  225     lock    = _loopLock backend
-  226     loop    = _evLoop backend
-  227     go      = takeMVar lock >> block (evLoop loop 0)
-  228 
-  229 
-  230 acceptCallback :: CInt -> Chan CInt -> IoCallback
-  231 acceptCallback accFd chan _loopPtr _ioPtr _ = do
-  232     debug "inside acceptCallback"  
-  233     r <- c_accept accFd
-  234 
-  235     case r of
-  236       -- this (EWOULDBLOCK) shouldn't happen (we just got told it was ready!),
-  237       -- if it does (maybe the request got picked up by another thread) we'll
-  238       -- just bail out
-  239       -2 -> return ()
-  240       -1 -> debugErrno "Backend.acceptCallback:c_accept()"
-  241       fd -> do
-  242           debug $ "acceptCallback: accept()ed fd, writing to chan " ++ show fd
-  243           writeChan chan fd
-  244 
-  245 
-  246 ioReadCallback :: CInt -> IORef Bool -> MVar () -> IoCallback
-  247 ioReadCallback fd active ra _loopPtr _ioPtr _ = do
-  248     -- send notifications to the worker thread
-  249     debug $ "ioReadCallback: notification (" ++ show fd ++ ")"
-  250     tryPutMVar ra ()
-  251     debug $ "stopping ioReadCallback (" ++ show fd ++ ")"
-  252     evIoStop _loopPtr _ioPtr
-  253     writeIORef active False
-  254 
-  255 
-  256 ioWriteCallback :: CInt -> IORef Bool -> MVar () -> IoCallback
-  257 ioWriteCallback fd active wa _loopPtr _ioPtr _ = do
-  258     -- send notifications to the worker thread
-  259     debug $ "ioWriteCallback: notification (" ++ show fd ++ ")"
-  260     tryPutMVar wa ()
-  261     debug $ "stopping ioWriteCallback (" ++ show fd ++ ")"
-  262     evIoStop _loopPtr _ioPtr
-  263     writeIORef active False
-  264 
-  265 
-  266 seconds :: Int -> Int
-  267 seconds n = n * ((10::Int)^(6::Int))
-  268 
-  269 
-  270 stop :: Backend -> IO ()
-  271 stop b = ignoreException $ do
-  272     debug $ "Backend.stop"
-  273 
-  274     -- FIXME: what are we gonna do here?
-  275     --
-  276     -- 1. take the loop lock
-  277     -- 2. shut down the accept() callback
-  278     -- 3. stuff a poison pill (a bunch of -1 values should do) down the
-  279     --    connection queue so that withConnection knows to throw an exception
-  280     --    back up to its caller
-  281     -- 4. release the loop lock
-  282     -- 5. wait until all of the threads have finished, or until 10 seconds have
-  283     --    elapsed, whichever comes first
-  284     -- 6. take the loop lock
-  285     -- 7. call evUnloop and wake up the loop using evAsyncSend
-  286     -- 8. release the loop lock, the main loop thread should then free/clean
-  287     --    everything up (threads, connections, io objects, callbacks, etc)
-  288 
-  289     withMVar lock $ \_ -> do
-  290         evIoStop loop acceptObj
-  291         replicateM_ 10 $ writeChan connQ (-1)
-  292 
-  293     debug $ "Backend.stop: waiting at most 10 seconds for connection threads to die"
-  294     waitForThreads b $ seconds 10
-  295     debug $ "Backend.stop: all threads dead, unlooping"
-  296 
-  297     withMVar lock $ \_ -> do
-  298         -- FIXME: hlibev should export EVUNLOOP_ALL
-  299         evUnloop loop 2
-  300         evAsyncSend loop killObj
-  301 
-  302     debug $ "unloop sent"
-  303 
-  304 
-  305   where
-  306     loop           = _evLoop b
-  307     acceptObj      = _acceptIOObj b
-  308     killObj        = _killObj b
-  309     lock           = _loopLock b
-  310     connQ          = _connectionQueue b
-  311 
-  312 
-  313 
-  314 waitForThreads :: Backend -> Int -> IO ()
-  315 waitForThreads backend t = timeout t wait >> return ()
-  316   where
-  317     threadSet = _connectionThreads backend
-  318     wait = do
-  319         threads <- readMVar threadSet
-  320         if (Set.null threads)
-  321           then return ()
-  322           else threadDelay (seconds 1) >> wait
-  323 
-  324 
-  325 
-  326 getAddr :: SockAddr -> IO (ByteString, Int)
-  327 getAddr addr =
-  328     case addr of
-  329       SockAddrInet p ha -> do
-  330           s <- liftM (B.pack . map c2w) (inet_ntoa ha)
-  331           return (s, fromIntegral p)
-  332 
-  333       a -> throwIO $ AddressNotSupportedException (show a)
-  334 
-  335 
-  336 -- | throw a timeout exception to the handling thread -- it'll clean up
-  337 -- everything
-  338 timerCallback :: MVar ThreadId -> TimerCallback
-  339 timerCallback tmv _ _ _ = do
-  340     debug "timer callback"
-  341     tid <- readMVar tmv
-  342     throwTo tid TimeoutException
-  343 
-  344 
-  345 freeConnection :: Connection -> IO ()
-  346 freeConnection conn = ignoreException $ do
-  347     withMVar loopLock $ \_ -> block $ do
-  348         debug $ "freeConnection (" ++ show fd ++ ")"
-  349         c_close fd
-  350 
-  351         -- stop and free timer object
-  352         evTimerStop loop timerObj
-  353         freeEvTimer timerObj
-  354         freeTimerCallback timerCb
-  355 
-  356         -- stop and free i/o objects
-  357         evIoStop loop ioWrObj
-  358         freeEvIo ioWrObj
-  359         freeIoCallback ioWrCb
-  360 
-  361         evIoStop loop ioRdObj
-  362         freeEvIo ioRdObj
-  363         freeIoCallback ioRdCb
-  364 
-  365         -- remove the thread id from the backend set
-  366         tid <- readMVar threadMVar
-  367         modifyMVar_ tsetMVar $ \s -> do
-  368             let !s' = Set.delete tid s
-  369             return $! s'
+  211     -- setup the accept callback; this watches for read readiness on the listen
+  212     -- port
+  213     accCB <- mkIoCallback $ acceptCallback sockFd connq
+  214     accIO <- mkEvIo
+  215     evIoInit accIO accCB sockFd ev_read
+  216     evIoStart lp accIO
+  217 
+  218     -- thread set stuff
+  219     connThreadMVar <- newEmptyMVar
+  220     connSet        <- newMVar Set.empty
+  221     editsRef       <- newIORef D.empty
+  222     connThreadDone <- newEmptyMVar
+  223     threadActivity <- newMVar ()
+  224 
+  225     let b = Backend sock
+  226                     sockFd
+  227                     connq
+  228                     lp
+  229                     accCB
+  230                     accIO
+  231                     (mc1,mc2)
+  232                     looplock
+  233                     asyncCB
+  234                     asyncObj
+  235                     killCB
+  236                     killObj
+  237                     connSet
+  238                     editsRef
+  239                     connThreadMVar
+  240                     connThreadDone
+  241                     threadActivity
+  242                     cpu
+  243 
+  244     forkOnIO cpu $ loopThread b
+  245 
+  246     conntid <- forkOnIO cpu $ connTableSeqThread b
+  247     putMVar connThreadMVar conntid
+  248 
+  249     debug $ "Backend.new: loop spawned"
+  250     return b
+  251 
+  252 
+  253 -- | Run evLoop in a thread
+  254 loopThread :: Backend -> IO ()
+  255 loopThread backend = do
+  256     debug $ "starting loop"
+  257     (ignoreException go) `finally` cleanup
+  258     debug $ "loop finished"
+  259   where
+  260     cleanup = do
+  261         debug $ "loopThread: cleaning up"
+  262         ignoreException $ freeBackend backend
+  263     lock    = _loopLock backend
+  264     loop    = _evLoop backend
+  265     go      = takeMVar lock >> block (evLoop loop 0)
+  266 
+  267 
+  268 acceptCallback :: CInt -> Chan CInt -> IoCallback
+  269 acceptCallback accFd chan _loopPtr _ioPtr _ = do
+  270     debug "inside acceptCallback"
+  271     r <- c_accept accFd
+  272 
+  273     case r of
+  274       -- this (EWOULDBLOCK) shouldn't happen (we just got told it was ready!),
+  275       -- if it does (maybe the request got picked up by another thread) we'll
+  276       -- just bail out
+  277       -2 -> return ()
+  278       -1 -> debugErrno "Backend.acceptCallback:c_accept()"
+  279       fd -> do
+  280           debug $ "acceptCallback: accept()ed fd, writing to chan " ++ show fd
+  281           writeChan chan fd
+  282 
+  283 
+  284 ioReadCallback :: CInt -> IORef Bool -> MVar () -> IoCallback
+  285 ioReadCallback fd active ra _loopPtr _ioPtr _ = do
+  286     -- send notifications to the worker thread
+  287     debug $ "ioReadCallback: notification (" ++ show fd ++ ")"
+  288     tryPutMVar ra ()
+  289     debug $ "stopping ioReadCallback (" ++ show fd ++ ")"
+  290     evIoStop _loopPtr _ioPtr
+  291     writeIORef active False
+  292 
+  293 
+  294 ioWriteCallback :: CInt -> IORef Bool -> MVar () -> IoCallback
+  295 ioWriteCallback fd active wa _loopPtr _ioPtr _ = do
+  296     -- send notifications to the worker thread
+  297     debug $ "ioWriteCallback: notification (" ++ show fd ++ ")"
+  298     tryPutMVar wa ()
+  299     debug $ "stopping ioWriteCallback (" ++ show fd ++ ")"
+  300     evIoStop _loopPtr _ioPtr
+  301     writeIORef active False
+  302 
+  303 
+  304 seconds :: Int -> Int
+  305 seconds n = n * ((10::Int)^(6::Int))
+  306 
+  307 
+  308 stop :: Backend -> IO ()
+  309 stop b = ignoreException $ do
+  310     debug $ "Backend.stop"
+  311 
+  312     -- FIXME: what are we gonna do here?
+  313     --
+  314     -- 1. take the loop lock
+  315     -- 2. shut down the accept() callback
+  316     -- 3. stuff a poison pill (a bunch of -1 values should do) down the
+  317     --    connection queue so that withConnection knows to throw an exception
+  318     --    back up to its caller
+  319     -- 4. release the loop lock
+  320     -- 5. wait until all of the threads have finished, or until 10 seconds have
+  321     --    elapsed, whichever comes first
+  322     -- 6. take the loop lock
+  323     -- 7. call evUnloop and wake up the loop using evAsyncSend
+  324     -- 8. release the loop lock, the main loop thread should then free/clean
+  325     --    everything up (threads, connections, io objects, callbacks, etc)
+  326 
+  327     withMVar lock $ \_ -> do
+  328         evIoStop loop acceptObj
+  329         replicateM_ 10 $ writeChan connQ (-1)
+  330 
+  331     debug $ "Backend.stop: waiting at most 10 seconds for connection threads to die"
+  332     waitForThreads b $ seconds 10
+  333     debug $ "Backend.stop: all threads presumed dead, unlooping"
+  334 
+  335     withMVar lock $ \_ -> do
+  336         -- FIXME: hlibev should export EVUNLOOP_ALL
+  337         evUnloop loop 2
+  338         evAsyncSend loop killObj
+  339 
+  340     debug $ "unloop sent"
+  341 
+  342 
+  343   where
+  344     loop           = _evLoop b
+  345     acceptObj      = _acceptIOObj b
+  346     killObj        = _killObj b
+  347     lock           = _loopLock b
+  348     connQ          = _connectionQueue b
+  349 
+  350 
+  351 
+  352 waitForThreads :: Backend -> Int -> IO ()
+  353 waitForThreads backend t = timeout t wait >> return ()
+  354   where
+  355     threadSet = _connectionThreads backend
+  356     wait = do
+  357         threads <- readMVar threadSet
+  358         if (Set.null threads)
+  359           then return ()
+  360           else threadDelay (seconds 1) >> wait
+  361 
+  362 
+  363 
+  364 getAddr :: SockAddr -> IO (ByteString, Int)
+  365 getAddr addr =
+  366     case addr of
+  367       SockAddrInet p ha -> do
+  368           s <- liftM (B.pack . map c2w) (inet_ntoa ha)
+  369           return (s, fromIntegral p)
   370 
-  371         -- wake up the event loop so it can be apprised of the changes
-  372         evAsyncSend loop asyncObj
-  373 
-  374   where
-  375     backend    = _backend conn
-  376     tsetMVar   = _connectionThreads backend
-  377     loop       = _evLoop backend
-  378     loopLock   = _loopLock backend
-  379     asyncObj   = _asyncObj backend
-  380 
-  381     fd         = _socketFd conn
-  382     threadMVar = _connThread conn
-  383     ioWrObj    = _connWriteIOObj conn
-  384     ioWrCb     = _connWriteIOCallback conn
-  385     ioRdObj    = _connReadIOObj conn
-  386     ioRdCb     = _connReadIOCallback conn
-  387     timerObj   = _timerObj conn
-  388     timerCb    = _timerCallback conn
-  389 
+  371       a -> throwIO $ AddressNotSupportedException (show a)
+  372 
+  373 
+  374 -- | throw a timeout exception to the handling thread -- it'll clean up
+  375 -- everything
+  376 timerCallback :: MVar ThreadId -> TimerCallback
+  377 timerCallback tmv _ _ _ = do
+  378     debug "Backend.timerCallback: timed out"
+  379     tid <- readMVar tmv
+  380     throwTo tid TimeoutException
+  381 
+  382 
+  383 addThreadSetEdit :: Backend -> (Set ThreadId -> Set ThreadId) -> IO ()
+  384 addThreadSetEdit backend edit = do
+  385     atomicModifyIORef (_connThreadEdits backend) $ \els ->
+  386         (D.snoc els edit, ())
+  387 
+  388     tryPutMVar (_threadActivity backend) ()
+  389     return ()
   390 
-  391 ignoreException :: IO () -> IO ()
-  392 ignoreException = handle (\(_::SomeException) -> return ())
-  393 
-  394 
-  395 freeBackend :: Backend -> IO ()
-  396 freeBackend backend = ignoreException $ block $ do
-  397     -- note: we only get here after an unloop
+  391 
+  392 freeConnection :: Connection -> IO ()
+  393 freeConnection conn = ignoreException $ do
+  394     withMVar loopLock $ \_ -> block $ do
+  395         debug $ "freeConnection (" ++ show fd ++ ")"
+  396 
+  397         c_close fd
   398 
-  399     withMVar tsetMVar $ \set -> do
-  400         mapM_ killThread $ Set.toList set
-  401 
-  402     debug $ "Backend.freeBackend: wait at most 2 seconds for threads to die"
-  403     waitForThreads backend $ seconds 2
-  404 
-  405     debug $ "Backend.freeBackend: all threads dead"
-  406 
-  407     debug $ "Backend.freeBackend: destroying resources"
-  408     freeEvIo acceptObj
-  409     freeIoCallback acceptCb
-  410     c_close fd
-  411 
-  412     evAsyncStop loop asyncObj
-  413     freeEvAsync asyncObj
-  414     freeAsyncCallback asyncCb
-  415 
-  416     evAsyncStop loop killObj
-  417     freeEvAsync killObj
-  418     freeAsyncCallback killCb
-  419 
-  420     freeMutexCallback mcb1
-  421     freeMutexCallback mcb2
-  422 
-  423     evLoopDestroy loop
-  424     debug $ "Backend.freeBackend: resources destroyed"
-  425 
-  426   where
-  427     fd          = _acceptFd backend
-  428     acceptObj   = _acceptIOObj backend
-  429     acceptCb    = _acceptIOCallback backend
-  430     tsetMVar    = _connectionThreads backend
-  431     asyncObj    = _asyncObj backend
-  432     asyncCb     = _asyncCb backend
-  433     killObj     = _killObj backend
-  434     killCb      = _killCb backend
-  435     (mcb1,mcb2) = _mutexCallbacks backend
-  436     loop        = _evLoop backend
-  437 
+  399         -- stop and free timer object
+  400         evTimerStop loop timerObj
+  401         freeEvTimer timerObj
+  402         freeTimerCallback timerCb
+  403 
+  404         -- stop and free i/o objects
+  405         evIoStop loop ioWrObj
+  406         freeEvIo ioWrObj
+  407         freeIoCallback ioWrCb
+  408 
+  409         evIoStop loop ioRdObj
+  410         freeEvIo ioRdObj
+  411         freeIoCallback ioRdCb
+  412 
+  413         tid <- readMVar $ _connThread conn
+  414 
+  415         -- schedule the removal of the thread id from the backend set
+  416         addThreadSetEdit backend (Set.delete tid)
+  417 
+  418         -- wake up the event loop so it can be apprised of the changes
+  419         evAsyncSend loop asyncObj
+  420 
+  421   where
+  422     backend    = _backend conn
+  423     loop       = _evLoop backend
+  424     loopLock   = _loopLock backend
+  425     asyncObj   = _asyncObj backend
+  426 
+  427     fd         = _socketFd conn
+  428     ioWrObj    = _connWriteIOObj conn
+  429     ioWrCb     = _connWriteIOCallback conn
+  430     ioRdObj    = _connReadIOObj conn
+  431     ioRdCb     = _connReadIOCallback conn
+  432     timerObj   = _timerObj conn
+  433     timerCb    = _timerCallback conn
+  434 
+  435 
+  436 ignoreException :: IO () -> IO ()
+  437 ignoreException = handle (\(_::SomeException) -> return ())
   438 
-  439 -- | Note: proc gets run in the background
-  440 withConnection :: Backend -> Int -> (Connection -> IO ()) -> IO ()
-  441 withConnection backend cpu proc = go
+  439 
+  440 connTableSeqThread :: Backend -> IO ()
+  441 connTableSeqThread backend = loop `finally` putMVar threadDone ()
   442   where
-  443     threadProc conn = ignoreException (proc conn) `finally` freeConnection conn
-  444 
-  445     go = do
-  446         debug $ "withConnection: reading from chan"
-  447         fd   <- readChan $ _connectionQueue backend
-  448         debug $ "withConnection: got fd " ++ show fd
-  449 
-  450         -- if fd < 0 throw an exception here (because this only happens if stop
-  451         -- is called)
-  452         when (fd < 0) $ throwIO BackendTerminatedException
+  443     threadDone = _connThreadIsDone backend
+  444     editsRef   = _connThreadEdits backend
+  445     table      = _connectionThreads backend
+  446     activity   = _threadActivity backend
+  447 
+  448     loop = do
+  449         takeMVar activity
+  450 
+  451         -- grab the edits
+  452         edits <- atomicModifyIORef editsRef $ \t -> (D.empty, D.toList t)
   453 
-  454         sock <- mkSocket fd AF_INET Stream 0 Connected
-  455         peerName <- getPeerName sock
-  456         sockName <- getSocketName sock
-  457 
-  458         -- set_linger fd
-  459         c_setnonblocking fd
-  460 
-  461         (remoteAddr, remotePort) <- getAddr peerName
-  462         (localAddr, localPort) <- getAddr sockName
-  463 
-  464         let lp = _evLoop backend
-  465 
-  466         -- makes sense to assume the socket is read/write available when
-  467         -- opened; worst-case is we get EWOULDBLOCK
-  468         ra    <- newMVar ()
-  469         wa    <- newMVar ()
+  454         -- apply the edits
+  455         modifyMVar_ table $ \t -> block $ do
+  456                let !t' = List.foldl' (flip ($)) t edits
+  457                return t'
+  458 
+  459         -- zzz
+  460         threadDelay 1000000
+  461         loop
+  462 
+  463 
+  464 freeBackend :: Backend -> IO ()
+  465 freeBackend backend = ignoreException $ block $ do
+  466     -- note: we only get here after an unloop
+  467 
+  468     readMVar (_connThreadId backend) >>= killThread
+  469     takeMVar $ _connThreadIsDone backend
   470 
-  471         tmr   <- mkEvTimer
-  472         thrmv <- newEmptyMVar
-  473         tcb   <- mkTimerCallback $ timerCallback thrmv
-  474         evTimerInit tmr tcb 0 20.0
+  471     -- read edits and obtain final thread table
+  472     threads <- withMVar (_connectionThreads backend) $ \table -> do
+  473                    edits <- liftM D.toList $
+  474                             readIORef (_connThreadEdits backend)
   475 
-  476         readActive  <- newIORef True
-  477         writeActive <- newIORef True
+  476                    let !t = List.foldl' (flip ($)) table edits
+  477                    return $ Set.toList t
   478 
-  479         evioRead <- mkEvIo
-  480         ioReadCb <- mkIoCallback $ ioReadCallback fd readActive ra
-  481 
-  482         evioWrite <- mkEvIo
-  483         ioWriteCb <- mkIoCallback $ ioWriteCallback fd writeActive wa
-  484 
-  485         evIoInit evioRead ioReadCb fd ev_read
-  486         evIoInit evioWrite ioWriteCb fd ev_write
-  487 
-  488         -- take ev_loop lock, start timer and io watchers
-  489         withMVar (_loopLock backend) $ \_ -> do
-  490              evTimerAgain lp tmr
-  491              evIoStart lp evioRead
-  492              evIoStart lp evioWrite
-  493 
-  494              -- wakeup the loop thread so that these new watchers get
-  495              -- registered next time through the loop
-  496              evAsyncSend lp $ _asyncObj backend
+  479     mapM_ killThread threads
+  480 
+  481     debug $ "Backend.freeBackend: all threads killed"
+  482     debug $ "Backend.freeBackend: destroying resources"
+  483     freeEvIo acceptObj
+  484     freeIoCallback acceptCb
+  485     c_close fd
+  486 
+  487     evAsyncStop loop asyncObj
+  488     freeEvAsync asyncObj
+  489     freeAsyncCallback asyncCb
+  490 
+  491     evAsyncStop loop killObj
+  492     freeEvAsync killObj
+  493     freeAsyncCallback killCb
+  494 
+  495     freeMutexCallback mcb1
+  496     freeMutexCallback mcb2
   497 
-  498         let conn = Connection backend
-  499                               sock
-  500                               fd
-  501                               remoteAddr
-  502                               remotePort
-  503                               localAddr
-  504                               localPort
-  505                               ra
-  506                               wa
-  507                               tmr
-  508                               tcb
-  509                               readActive
-  510                               writeActive
-  511                               evioRead
-  512                               ioReadCb
-  513                               evioWrite
-  514                               ioWriteCb
-  515                               thrmv
-  516 
-  517 
-  518         tid <- forkOnIO cpu $ threadProc conn
-  519 
-  520         modifyMVar_ (_connectionThreads backend) $ ins tid
-  521         putMVar thrmv tid
-  522 
-  523       where
-  524         ins !thr !s = let !r = Set.insert thr s in return (r `seq` r)
-  525 
-  526 
-  527 data BackendTerminatedException = BackendTerminatedException
-  528    deriving (Typeable)
-  529 
-  530 instance Show BackendTerminatedException where
-  531     show BackendTerminatedException = "Backend terminated"
-  532 
-  533 instance Exception BackendTerminatedException
-  534 
-  535 
-  536 
-  537 data AddressNotSupportedException = AddressNotSupportedException String
-  538    deriving (Typeable)
-  539 
-  540 instance Show AddressNotSupportedException where
-  541     show (AddressNotSupportedException x) = "Address not supported: " ++ x
-  542 
-  543 instance Exception AddressNotSupportedException
-  544 
-  545 
-  546 getRemoteAddr :: Connection -> ByteString
-  547 getRemoteAddr = _remoteAddr
-  548 
-  549 getRemotePort :: Connection -> Int
-  550 getRemotePort = _remotePort
-  551 
-  552 getLocalAddr :: Connection -> ByteString
-  553 getLocalAddr = _localAddr
-  554 
-  555 getLocalPort :: Connection -> Int
-  556 getLocalPort = _localPort
-  557 
-  558 ------------------------------------------------------------------------------
-  559 
-  560 -- fixme: new function name
-  561 getHostAddr :: Int
-  562             -> ByteString
-  563             -> IO SockAddr
-  564 getHostAddr p s = do
-  565     h <- if s == "*"
-  566           then return iNADDR_ANY
-  567           else inet_addr (map w2c . B.unpack $ s)
-  568 
-  569     return $ SockAddrInet (fromIntegral p) h
-  570 
-  571 
-  572 
-  573 bLOCKSIZE :: Int
-  574 bLOCKSIZE = 8192
-  575 
-  576 --
-  577 -- About timeouts
-  578 --
-  579 -- It's not good enough to restart the timer from io(Read|Write)Callback,
-  580 -- because those seem to be edge-triggered. I've definitely had where after
-  581 -- 20 seconds they still weren't being re-awakened.
-  582 --
-  583 
-  584 data TimeoutException = TimeoutException
-  585    deriving (Typeable)
-  586 
-  587 instance Show TimeoutException where
-  588     show _ = "timeout"
-  589 
-  590 instance Exception TimeoutException
-  591 
-  592 tickleTimeout :: Connection -> IO ()
-  593 tickleTimeout conn = debug "Backend.tickleTimeout" >> evTimerAgain lp tmr
-  594   where
-  595     bk  = _backend conn
-  596     lp  = _evLoop bk
-  597     tmr = _timerObj conn
-  598 
-  599 recvData :: Connection -> Int -> IO ByteString
-  600 recvData conn n = do
-  601     dbg "entered"
-  602     allocaBytes n $ \cstr -> do
-  603     sz <- throwErrnoIfMinus1RetryMayBlock
-  604               "recvData"
-  605               (c_read fd cstr (toEnum n))
-  606               waitForLock
-  607 
-  608     -- we got activity, but don't do restart timer due to the
-  609     -- slowloris attack
-  610 
-  611     dbg $ "sz returned " ++ show sz
-  612 
-  613     if sz == 0
-  614       then return ""
-  615       else B.packCStringLen ((castPtr cstr),(fromEnum sz))
-  616 
-  617   where
-  618     io       = _connReadIOObj conn
-  619     bk       = _backend conn
-  620     active   = _readActive conn
-  621     lp       = _evLoop bk
-  622     looplock = _loopLock bk
-  623     async    = _asyncObj bk
-  624 
-  625     dbg s = debug $ "Backend.recvData(" ++ show (_socketFd conn) ++ "): " ++ s
-  626 
-  627     fd          = _socketFd conn
-  628     lock        = _readAvailable conn
-  629     waitForLock = do
-  630         dbg "start waitForLock"
-  631 
-  632         withMVar looplock $ \_ -> do
-  633             act <- readIORef active
-  634             if act
-  635               then dbg "read watcher already active, skipping"
-  636               else do
-  637                 dbg "starting watcher, sending async"
-  638                 evIoStart lp io
-  639                 writeIORef active True
-  640                 evAsyncSend lp async
-  641 
-  642         dbg "waitForLock: waiting for mvar"
-  643         takeMVar lock
-  644         dbg "waitForLock: took mvar"
-  645 
+  498     evLoopDestroy loop
+  499     debug $ "Backend.freeBackend: resources destroyed"
+  500 
+  501   where
+  502     fd          = _acceptFd backend
+  503     acceptObj   = _acceptIOObj backend
+  504     acceptCb    = _acceptIOCallback backend
+  505     asyncObj    = _asyncObj backend
+  506     asyncCb     = _asyncCb backend
+  507     killObj     = _killObj backend
+  508     killCb      = _killCb backend
+  509     (mcb1,mcb2) = _mutexCallbacks backend
+  510     loop        = _evLoop backend
+  511 
+  512 
+  513 -- | Note: proc gets run in the background
+  514 withConnection :: Backend -> Int -> (Connection -> IO ()) -> IO ()
+  515 withConnection backend cpu proc = go
+  516   where
+  517     threadProc conn = ignoreException (proc conn) `finally` freeConnection conn
+  518 
+  519     go = do
+  520         debug $ "withConnection: reading from chan"
+  521         fd   <- readChan $ _connectionQueue backend
+  522         debug $ "withConnection: got fd " ++ show fd
+  523 
+  524         -- if fd < 0 throw an exception here (because this only happens if stop
+  525         -- is called)
+  526         when (fd < 0) $ throwIO BackendTerminatedException
+  527 
+  528         sock <- mkSocket fd AF_INET Stream 0 Connected
+  529         peerName <- getPeerName sock
+  530         sockName <- getSocketName sock
+  531 
+  532         -- set_linger fd
+  533         c_setnonblocking fd
+  534 
+  535         (remoteAddr, remotePort) <- getAddr peerName
+  536         (localAddr, localPort) <- getAddr sockName
+  537 
+  538         let lp = _evLoop backend
+  539 
+  540         -- makes sense to assume the socket is read/write available when
+  541         -- opened; worst-case is we get EWOULDBLOCK
+  542         ra    <- newMVar ()
+  543         wa    <- newMVar ()
+  544 
+  545         tmr   <- mkEvTimer
+  546         thrmv <- newEmptyMVar
+  547         tcb   <- mkTimerCallback $ timerCallback thrmv
+  548         evTimerInit tmr tcb 0 20.0
+  549 
+  550         readActive  <- newIORef True
+  551         writeActive <- newIORef True
+  552 
+  553         evioRead <- mkEvIo
+  554         ioReadCb <- mkIoCallback $ ioReadCallback fd readActive ra
+  555 
+  556         evioWrite <- mkEvIo
+  557         ioWriteCb <- mkIoCallback $ ioWriteCallback fd writeActive wa
+  558 
+  559         evIoInit evioRead ioReadCb fd ev_read
+  560         evIoInit evioWrite ioWriteCb fd ev_write
+  561 
+  562         -- take ev_loop lock, start timer and io watchers
+  563         withMVar (_loopLock backend) $ \_ -> do
+  564              evTimerAgain lp tmr
+  565              evIoStart lp evioRead
+  566              evIoStart lp evioWrite
+  567 
+  568              -- wakeup the loop thread so that these new watchers get
+  569              -- registered next time through the loop
+  570              evAsyncSend lp $ _asyncObj backend
+  571 
+  572         let conn = Connection backend
+  573                               sock
+  574                               fd
+  575                               remoteAddr
+  576                               remotePort
+  577                               localAddr
+  578                               localPort
+  579                               ra
+  580                               wa
+  581                               tmr
+  582                               tcb
+  583                               readActive
+  584                               writeActive
+  585                               evioRead
+  586                               ioReadCb
+  587                               evioWrite
+  588                               ioWriteCb
+  589                               thrmv
+  590 
+  591 
+  592         tid <- forkOnIO cpu $ threadProc conn
+  593 
+  594         addThreadSetEdit backend (Set.insert tid)
+  595         putMVar thrmv tid
+  596 
+  597 
+  598 data BackendTerminatedException = BackendTerminatedException
+  599    deriving (Typeable)
+  600 
+  601 instance Show BackendTerminatedException where
+  602     show BackendTerminatedException = "Backend terminated"
+  603 
+  604 instance Exception BackendTerminatedException
+  605 
+  606 
+  607 
+  608 data AddressNotSupportedException = AddressNotSupportedException String
+  609    deriving (Typeable)
+  610 
+  611 instance Show AddressNotSupportedException where
+  612     show (AddressNotSupportedException x) = "Address not supported: " ++ x
+  613 
+  614 instance Exception AddressNotSupportedException
+  615 
+  616 
+  617 getRemoteAddr :: Connection -> ByteString
+  618 getRemoteAddr = _remoteAddr
+  619 
+  620 getRemotePort :: Connection -> Int
+  621 getRemotePort = _remotePort
+  622 
+  623 getLocalAddr :: Connection -> ByteString
+  624 getLocalAddr = _localAddr
+  625 
+  626 getLocalPort :: Connection -> Int
+  627 getLocalPort = _localPort
+  628 
+  629 ------------------------------------------------------------------------------
+  630 
+  631 -- fixme: new function name
+  632 getHostAddr :: Int
+  633             -> ByteString
+  634             -> IO SockAddr
+  635 getHostAddr p s = do
+  636     h <- if s == "*"
+  637           then return iNADDR_ANY
+  638           else inet_addr (map w2c . B.unpack $ s)
+  639 
+  640     return $ SockAddrInet (fromIntegral p) h
+  641 
+  642 
+  643 
+  644 bLOCKSIZE :: Int
+  645 bLOCKSIZE = 8192
   646 
-  647 sendData :: Connection -> ByteString -> IO ()
-  648 sendData conn bs = do
-  649     let len = B.length bs
-  650     dbg $ "entered w/ " ++ show len ++ " bytes"
-  651     written <- B.unsafeUseAsCString bs $ \cstr ->
-  652         throwErrnoIfMinus1RetryMayBlock
-  653                    "sendData"
-  654                    (c_write fd cstr (toEnum len))
-  655                    waitForLock
-  656 
-  657     -- we got activity, so restart timer
-  658     tickleTimeout conn
-  659 
-  660     let n = fromEnum written
-  661     let last10 = B.drop (n-10) $ B.take n bs
-  662 
-  663     dbg $ "wrote " ++ show written ++ " bytes, last 10='" ++ show last10 ++ "'"
-  664 
-  665     if n < len
-  666        then do
-  667          dbg $ "short write, need to write " ++ show (len-n) ++ " more bytes"
-  668          sendData conn $ B.drop n bs
-  669        else return ()
-  670 
-  671   where
-  672     io       = _connWriteIOObj conn
-  673     bk       = _backend conn
-  674     active   = _writeActive conn
-  675     lp       = _evLoop bk
-  676     looplock = _loopLock bk
-  677     async    = _asyncObj bk
-  678 
-  679     dbg s = debug $ "Backend.sendData(" ++ show (_socketFd conn) ++ "): " ++ s
-  680     fd          = _socketFd conn
-  681     lock        = _writeAvailable conn
-  682     waitForLock = do
-  683         dbg "waitForLock: starting"
-  684         withMVar looplock $ \_ -> do
-  685             act <- readIORef active
-  686             if act
-  687               then dbg "write watcher already running, skipping"
-  688               else do
-  689                 dbg "starting watcher, sending async event"
-  690                 evIoStart lp io
-  691                 writeIORef active True
-  692                 evAsyncSend lp async
-  693 
-  694         dbg "waitForLock: taking mvar"
-  695         takeMVar lock
-  696         dbg "waitForLock: took mvar"
-  697 
-  698 
-  699 getReadEnd :: Connection -> Enumerator IO a
-  700 getReadEnd = enumerate
-  701 
-  702 
-  703 getWriteEnd :: Connection -> Iteratee IO ()
-  704 getWriteEnd = writeOut
-  705 
-  706 
-  707 enumerate :: (MonadIO m) => Connection -> Enumerator m a
-  708 enumerate = loop
-  709   where
-  710     loop conn f = do
-  711         s <- liftIO $ recvData conn bLOCKSIZE
-  712         sendOne conn f s
-  713 
-  714     sendOne conn f s = do
-  715         v <- runIter f (if B.null s
-  716                          then EOF Nothing
-  717                          else Chunk $ WrapBS s)
-  718         case v of
-  719           r@(Done _ _)      -> return $ liftI r
-  720           (Cont k Nothing)  -> loop conn k
-  721           (Cont _ (Just e)) -> return $ throwErr e
-  722 
-  723 
-  724 writeOut :: (MonadIO m) => Connection -> Iteratee m ()
-  725 writeOut conn = IterateeG out
-  726   where
-  727     out c@(EOF _)   = return $ Done () c
-  728 
-  729     out (Chunk s) = do
-  730         let x = unWrap s
+  647 --
+  648 -- About timeouts
+  649 --
+  650 -- It's not good enough to restart the timer from io(Read|Write)Callback,
+  651 -- because those seem to be edge-triggered. I've definitely had where after
+  652 -- 20 seconds they still weren't being re-awakened.
+  653 --
+  654 
+  655 data TimeoutException = TimeoutException
+  656    deriving (Typeable)
+  657 
+  658 instance Show TimeoutException where
+  659     show _ = "timeout"
+  660 
+  661 instance Exception TimeoutException
+  662 
+  663 tickleTimeout :: Connection -> IO ()
+  664 tickleTimeout conn = do
+  665     debug "Backend.tickleTimeout"
+  666     withMVar (_loopLock bk) $ \_ -> evTimerAgain lp tmr
+  667 
+  668   where
+  669     bk  = _backend conn
+  670     lp  = _evLoop bk
+  671     tmr = _timerObj conn
+  672 
+  673 recvData :: Connection -> Int -> IO ByteString
+  674 recvData conn n = do
+  675     dbg "entered"
+  676     allocaBytes n $ \cstr -> do
+  677     sz <- throwErrnoIfMinus1RetryMayBlock
+  678               "recvData"
+  679               (c_read fd cstr (toEnum n))
+  680               waitForLock
+  681 
+  682     -- we got activity, but don't do restart timer due to the
+  683     -- slowloris attack
+  684 
+  685     dbg $ "sz returned " ++ show sz
+  686 
+  687     if sz == 0
+  688       then return ""
+  689       else B.packCStringLen ((castPtr cstr),(fromEnum sz))
+  690 
+  691   where
+  692     io       = _connReadIOObj conn
+  693     bk       = _backend conn
+  694     active   = _readActive conn
+  695     lp       = _evLoop bk
+  696     looplock = _loopLock bk
+  697     async    = _asyncObj bk
+  698 
+  699     dbg s = debug $ "Backend.recvData(" ++ show (_socketFd conn) ++ "): " ++ s
+  700 
+  701     fd          = _socketFd conn
+  702     lock        = _readAvailable conn
+  703     waitForLock = do
+  704         dbg "start waitForLock"
+  705 
+  706         withMVar looplock $ \_ -> do
+  707             act <- readIORef active
+  708             if act
+  709               then dbg "read watcher already active, skipping"
+  710               else do
+  711                 dbg "starting watcher, sending async"
+  712                 tryTakeMVar lock
+  713                 evIoStart lp io
+  714                 writeIORef active True
+  715                 evAsyncSend lp async
+  716 
+  717         dbg "waitForLock: waiting for mvar"
+  718         takeMVar lock
+  719         dbg "waitForLock: took mvar"
+  720 
+  721 
+  722 sendData :: Connection -> ByteString -> IO ()
+  723 sendData conn bs = do
+  724     let len = B.length bs
+  725     dbg $ "entered w/ " ++ show len ++ " bytes"
+  726     written <- B.unsafeUseAsCString bs $ \cstr ->
+  727         throwErrnoIfMinus1RetryMayBlock
+  728                    "sendData"
+  729                    (c_write fd cstr (toEnum len))
+  730                    waitForLock
   731 
-  732         liftIO $ sendData conn x
-  733 
-  734         return $ Cont (writeOut conn) Nothing
-  735 
+  732     -- we got activity, so restart timer
+  733     tickleTimeout conn
+  734 
+  735     let n = fromEnum written
+  736     let last10 = B.drop (n-10) $ B.take n bs
+  737 
+  738     dbg $ "wrote " ++ show written ++ " bytes, last 10='" ++ show last10 ++ "'"
+  739 
+  740     if n < len
+  741        then do
+  742          dbg $ "short write, need to write " ++ show (len-n) ++ " more bytes"
+  743          sendData conn $ B.drop n bs
+  744        else return ()
+  745 
+  746   where
+  747     io       = _connWriteIOObj conn
+  748     bk       = _backend conn
+  749     active   = _writeActive conn
+  750     lp       = _evLoop bk
+  751     looplock = _loopLock bk
+  752     async    = _asyncObj bk
+  753 
+  754     dbg s = debug $ "Backend.sendData(" ++ show (_socketFd conn) ++ "): " ++ s
+  755     fd          = _socketFd conn
+  756     lock        = _writeAvailable conn
+  757     waitForLock = do
+  758         dbg "waitForLock: starting"
+  759         withMVar looplock $ \_ -> do
+  760             act <- readIORef active
+  761             if act
+  762               then dbg "write watcher already running, skipping"
+  763               else do
+  764                 dbg "starting watcher, sending async event"
+  765                 tryTakeMVar lock
+  766                 evIoStart lp io
+  767                 writeIORef active True
+  768                 evAsyncSend lp async
+  769 
+  770         dbg "waitForLock: taking mvar"
+  771         takeMVar lock
+  772         dbg "waitForLock: took mvar"
+  773 
+  774 
+  775 getReadEnd :: Connection -> Enumerator IO a
+  776 getReadEnd = enumerate
+  777 
+  778 
+  779 getWriteEnd :: Connection -> Iteratee IO ()
+  780 getWriteEnd = writeOut
+  781 
+  782 
+  783 enumerate :: (MonadIO m) => Connection -> Enumerator m a
+  784 enumerate = loop
+  785   where
+  786     loop conn f = do
+  787         s <- liftIO $ recvData conn bLOCKSIZE
+  788         sendOne conn f s
+  789 
+  790     sendOne conn f s = do
+  791         v <- runIter f (if B.null s
+  792                          then EOF Nothing
+  793                          else Chunk $ WrapBS s)
+  794         case v of
+  795           r@(Done _ _)      -> return $ liftI r
+  796           (Cont k Nothing)  -> loop conn k
+  797           (Cont _ (Just e)) -> return $ throwErr e
+  798 
+  799 
+  800 writeOut :: (MonadIO m) => Connection -> Iteratee m ()
+  801 writeOut conn = IterateeG out
+  802   where
+  803     out c@(EOF _)   = return $ Done () c
+  804 
+  805     out (Chunk s) = do
+  806         let x = unWrap s
+  807 
+  808         liftIO $ sendData conn x
+  809 
+  810         return $ Cont (writeOut conn) Nothing
+  811 
 
 
diff --git a/static/docs/snap-server-hpc/Snap.Internal.Http.Server.hs.html b/static/docs/snap-server-hpc/Snap.Internal.Http.Server.hs.html index 3e0065d..8dcb814 100644 --- a/static/docs/snap-server-hpc/Snap.Internal.Http.Server.hs.html +++ b/static/docs/snap-server-hpc/Snap.Internal.Http.Server.hs.html @@ -29,652 +29,672 @@ 18 import qualified Data.ByteString.Lazy as L 19 import Data.ByteString.Internal (c2w, w2c) 20 import qualified Data.ByteString.Nums.Careless.Int as Cvt - 21 import Data.IORef - 22 import Data.List (foldl') - 23 import qualified Data.Map as Map - 24 import Data.Maybe (fromJust, catMaybes, fromMaybe) - 25 import Data.Monoid - 26 import Data.Version - 27 import Foreign.C.Types - 28 import Foreign.ForeignPtr - 29 import GHC.Conc - 30 import Prelude hiding (catch, show, Show) - 31 import qualified Prelude - 32 import System.PosixCompat.Files hiding (setFileSize) - 33 import System.Posix.Types (FileOffset) - 34 import Text.Show.ByteString hiding (runPut) - 35 ------------------------------------------------------------------------------ - 36 import System.FastLogger - 37 import Snap.Internal.Http.Types hiding (Enumerator) - 38 import Snap.Internal.Http.Parser - 39 import Snap.Iteratee hiding (foldl', head, take, FileOffset) - 40 import qualified Snap.Iteratee as I - 41 - 42 #ifdef LIBEV - 43 import qualified Snap.Internal.Http.Server.LibevBackend as Backend - 44 import Snap.Internal.Http.Server.LibevBackend (debug) - 45 #else - 46 import qualified Snap.Internal.Http.Server.SimpleBackend as Backend - 47 import Snap.Internal.Http.Server.SimpleBackend (debug) - 48 #endif - 49 - 50 import Snap.Internal.Http.Server.Date - 51 - 52 import qualified Paths_snap_server as V - 53 - 54 ------------------------------------------------------------------------------ - 55 -- | The handler has to return the request object because we have to clear the - 56 -- HTTP request body before we send the response. If the handler consumes the - 57 -- request body, it is responsible for setting @rqBody=return@ in the returned - 58 -- request (otherwise we will mess up reading the input stream). - 59 -- - 60 -- Note that we won't be bothering end users with this -- the details will be - 61 -- hidden inside the Snap monad - 62 type ServerHandler = (ByteString -> IO ()) - 63 -> Request - 64 -> Iteratee IO (Request,Response) - 65 - 66 type ServerMonad = StateT ServerState (Iteratee IO) - 67 - 68 data ServerState = ServerState - 69 { _forceConnectionClose :: Bool - 70 , _localHostname :: ByteString - 71 , _localAddress :: ByteString - 72 , _localPort :: Int - 73 , _remoteAddr :: ByteString - 74 , _remotePort :: Int - 75 , _logAccess :: Request -> Response -> IO () - 76 , _logError :: ByteString -> IO () - 77 } - 78 + 21 import Data.Int + 22 import Data.IORef + 23 import Data.List (foldl') + 24 import qualified Data.Map as Map + 25 import Data.Maybe (fromJust, catMaybes, fromMaybe) + 26 import Data.Monoid + 27 import Data.Version + 28 import Foreign.C.Types + 29 import Foreign.ForeignPtr + 30 import GHC.Conc + 31 import Prelude hiding (catch, show, Show) + 32 import qualified Prelude + 33 import System.PosixCompat.Files hiding (setFileSize) + 34 import System.Posix.Types (FileOffset) + 35 import Text.Show.ByteString hiding (runPut) + 36 ------------------------------------------------------------------------------ + 37 import System.FastLogger + 38 import Snap.Internal.Http.Types hiding (Enumerator) + 39 import Snap.Internal.Http.Parser + 40 import Snap.Iteratee hiding (foldl', head, take, FileOffset) + 41 import qualified Snap.Iteratee as I + 42 + 43 #ifdef LIBEV + 44 import qualified Snap.Internal.Http.Server.LibevBackend as Backend + 45 import Snap.Internal.Http.Server.LibevBackend (debug) + 46 #else + 47 import qualified Snap.Internal.Http.Server.SimpleBackend as Backend + 48 import Snap.Internal.Http.Server.SimpleBackend (debug) + 49 #endif + 50 + 51 import Snap.Internal.Http.Server.Date + 52 + 53 import qualified Paths_snap_server as V + 54 + 55 ------------------------------------------------------------------------------ + 56 -- | The handler has to return the request object because we have to clear the + 57 -- HTTP request body before we send the response. If the handler consumes the + 58 -- request body, it is responsible for setting @rqBody=return@ in the returned + 59 -- request (otherwise we will mess up reading the input stream). + 60 -- + 61 -- Note that we won't be bothering end users with this -- the details will be + 62 -- hidden inside the Snap monad + 63 type ServerHandler = (ByteString -> IO ()) + 64 -> Request + 65 -> Iteratee IO (Request,Response) + 66 + 67 type ServerMonad = StateT ServerState (Iteratee IO) + 68 + 69 data ServerState = ServerState + 70 { _forceConnectionClose :: Bool + 71 , _localHostname :: ByteString + 72 , _localAddress :: ByteString + 73 , _localPort :: Int + 74 , _remoteAddr :: ByteString + 75 , _remotePort :: Int + 76 , _logAccess :: Request -> Response -> IO () + 77 , _logError :: ByteString -> IO () + 78 } 79 - 80 ------------------------------------------------------------------------------ - 81 runServerMonad :: ByteString -- ^ local host name - 82 -> ByteString -- ^ local ip address - 83 -> Int -- ^ local port - 84 -> ByteString -- ^ remote ip address - 85 -> Int -- ^ remote port - 86 -> (Request -> Response -> IO ()) -- ^ access log function - 87 -> (ByteString -> IO ()) -- ^ error log function - 88 -> ServerMonad a -- ^ monadic action to run - 89 -> Iteratee IO a - 90 runServerMonad lh lip lp rip rp la le m = evalStateT m st - 91 where - 92 st = ServerState False lh lip lp rip rp la le - 93 + 80 + 81 ------------------------------------------------------------------------------ + 82 runServerMonad :: ByteString -- ^ local host name + 83 -> ByteString -- ^ local ip address + 84 -> Int -- ^ local port + 85 -> ByteString -- ^ remote ip address + 86 -> Int -- ^ remote port + 87 -> (Request -> Response -> IO ()) -- ^ access log function + 88 -> (ByteString -> IO ()) -- ^ error log function + 89 -> ServerMonad a -- ^ monadic action to run + 90 -> Iteratee IO a + 91 runServerMonad lh lip lp rip rp la le m = evalStateT m st + 92 where + 93 st = ServerState False lh lip lp rip rp la le 94 95 - 96 ------------------------------------------------------------------------------ - 97 -- input/output - 98 + 96 + 97 ------------------------------------------------------------------------------ + 98 -- input/output 99 - 100 ------------------------------------------------------------------------------ - 101 httpServe :: ByteString -- ^ bind address, or \"*\" for all - 102 -> Int -- ^ port to bind to - 103 -> ByteString -- ^ local hostname (server name) - 104 -> Maybe FilePath -- ^ path to the access log - 105 -> Maybe FilePath -- ^ path to the error log - 106 -> ServerHandler -- ^ handler procedure - 107 -> IO () - 108 httpServe bindAddress bindPort localHostname alogPath elogPath handler = - 109 withLoggers alogPath elogPath - 110 (\(alog, elog) -> spawnAll alog elog) - 111 - 112 where - 113 spawnAll alog elog = {-# SCC "httpServe/spawnAll" #-} do - 114 logE elog $ S.concat [ "Server.httpServe: START (" - 115 , Backend.name, ")"] - 116 let n = numCapabilities - 117 bracket (spawn n) - 118 (\xs -> do - 119 logE elog "Server.httpServe: SHUTDOWN" - 120 mapM_ (Backend.stop . fst) xs - 121 logE elog "Server.httpServe: BACKEND STOPPED") - 122 (runAll alog elog) - 123 + 100 + 101 ------------------------------------------------------------------------------ + 102 httpServe :: ByteString -- ^ bind address, or \"*\" for all + 103 -> Int -- ^ port to bind to + 104 -> ByteString -- ^ local hostname (server name) + 105 -> Maybe FilePath -- ^ path to the access log + 106 -> Maybe FilePath -- ^ path to the error log + 107 -> ServerHandler -- ^ handler procedure + 108 -> IO () + 109 httpServe bindAddress bindPort localHostname alogPath elogPath handler = + 110 withLoggers alogPath elogPath + 111 (\(alog, elog) -> spawnAll alog elog) + 112 + 113 where + 114 spawnAll alog elog = {-# SCC "httpServe/spawnAll" #-} do + 115 logE elog $ S.concat [ "Server.httpServe: START (" + 116 , Backend.name, ")"] + 117 let n = numCapabilities + 118 bracket (spawn n) + 119 (\xs -> do + 120 logE elog "Server.httpServe: SHUTDOWN" + 121 mapM_ (Backend.stop . fst) xs + 122 logE elog "Server.httpServe: BACKEND STOPPED") + 123 (runAll alog elog) 124 - 125 runAll alog elog xs = {-# SCC "httpServe/runAll" #-} do - 126 mapM_ f $ xs `zip` [0..] - 127 mapM_ (takeMVar . snd) xs - 128 where - 129 f ((backend,mvar),cpu) = - 130 forkOnIO cpu $ do - 131 labelMe $ map w2c $ S.unpack $ - 132 S.concat ["accThread ", l2s $ show cpu] - 133 (try $ (goooo alog elog backend cpu)) :: IO (Either SomeException ()) - 134 putMVar mvar () - 135 - 136 goooo alog elog backend cpu = - 137 {-# SCC "httpServe/goooo" #-} - 138 let loop = go alog elog backend cpu >> loop - 139 in loop - 140 - 141 maybeSpawnLogger = maybe (return Nothing) $ (liftM Just) . newLogger - 142 - 143 withLoggers afp efp = - 144 bracket (do alog <- maybeSpawnLogger afp - 145 elog <- maybeSpawnLogger efp - 146 return (alog, elog)) - 147 (\(alog, elog) -> do - 148 threadDelay 1000000 - 149 maybe (return ()) stopLogger alog - 150 maybe (return ()) stopLogger elog) - 151 - 152 labelMe :: String -> IO () - 153 labelMe s = do - 154 tid <- myThreadId - 155 labelThread tid s - 156 - 157 spawn n = do - 158 sock <- Backend.bindIt bindAddress bindPort - 159 backends <- mapM (Backend.new sock) $ [0..(n-1)] - 160 mvars <- replicateM n newEmptyMVar - 161 - 162 return (backends `zip` mvars) - 163 + 125 + 126 runAll alog elog xs = {-# SCC "httpServe/runAll" #-} do + 127 mapM_ f $ xs `zip` [0..] + 128 mapM_ (takeMVar . snd) xs + 129 where + 130 f ((backend,mvar),cpu) = + 131 forkOnIO cpu $ do + 132 labelMe $ map w2c $ S.unpack $ + 133 S.concat ["accThread ", l2s $ show cpu] + 134 (try $ (goooo alog elog backend cpu)) :: IO (Either SomeException ()) + 135 putMVar mvar () + 136 + 137 goooo alog elog backend cpu = + 138 {-# SCC "httpServe/goooo" #-} + 139 let loop = go alog elog backend cpu >> loop + 140 in loop + 141 + 142 maybeSpawnLogger = maybe (return Nothing) $ (liftM Just) . newLogger + 143 + 144 withLoggers afp efp = + 145 bracket (do alog <- maybeSpawnLogger afp + 146 elog <- maybeSpawnLogger efp + 147 return (alog, elog)) + 148 (\(alog, elog) -> do + 149 threadDelay 1000000 + 150 maybe (return ()) stopLogger alog + 151 maybe (return ()) stopLogger elog) + 152 + 153 labelMe :: String -> IO () + 154 labelMe s = do + 155 tid <- myThreadId + 156 labelThread tid s + 157 + 158 spawn n = do + 159 sock <- Backend.bindIt bindAddress bindPort + 160 backends <- mapM (Backend.new sock) $ [0..(n-1)] + 161 mvars <- replicateM n newEmptyMVar + 162 + 163 return (backends `zip` mvars) 164 - 165 runOne alog elog backend cpu = - 166 Backend.withConnection backend cpu $ \conn -> - 167 {-# SCC "httpServe/runOne" #-} do - 168 debug "Server.httpServe.runOne: entered" - 169 let readEnd = Backend.getReadEnd conn - 170 let writeEnd = Backend.getWriteEnd conn - 171 - 172 let raddr = Backend.getRemoteAddr conn - 173 let rport = Backend.getRemotePort conn - 174 let laddr = Backend.getLocalAddr conn - 175 let lport = Backend.getLocalPort conn - 176 - 177 runHTTP localHostname laddr lport raddr rport - 178 alog elog readEnd writeEnd - 179 (Backend.sendFile conn) - 180 (Backend.tickleTimeout conn) handler - 181 - 182 debug "Server.httpServe.runHTTP: finished" - 183 + 165 + 166 runOne alog elog backend cpu = + 167 Backend.withConnection backend cpu $ \conn -> + 168 {-# SCC "httpServe/runOne" #-} do + 169 debug "Server.httpServe.runOne: entered" + 170 let readEnd = Backend.getReadEnd conn + 171 let writeEnd = Backend.getWriteEnd conn + 172 + 173 let raddr = Backend.getRemoteAddr conn + 174 let rport = Backend.getRemotePort conn + 175 let laddr = Backend.getLocalAddr conn + 176 let lport = Backend.getLocalPort conn + 177 + 178 runHTTP localHostname laddr lport raddr rport + 179 alog elog readEnd writeEnd + 180 (Backend.sendFile conn) + 181 (Backend.tickleTimeout conn) handler + 182 + 183 debug "Server.httpServe.runHTTP: finished" 184 - 185 go alog elog backend cpu = runOne alog elog backend cpu - 186 `catches` - 187 [ Handler $ \(_ :: Backend.TimeoutException) -> return () - 188 - 189 , Handler $ \(e :: AsyncException) -> do - 190 logE elog $ - 191 S.concat [ "Server.httpServe.go: got async exception, " - 192 , "terminating:\n", bshow e ] - 193 throwIO e - 194 - 195 , Handler $ \(e :: Backend.BackendTerminatedException) -> do - 196 logE elog $ "Server.httpServe.go: got backend terminated, waiting for cleanup" - 197 throwIO e - 198 - 199 , Handler $ \(e :: IOException) -> do - 200 logE elog $ S.concat [ "Server.httpServe.go: got io exception: " - 201 , bshow e ] - 202 - 203 , Handler $ \(e :: SomeException) -> do - 204 logE elog $ S.concat [ "Server.httpServe.go: got someexception: " - 205 , bshow e ] ] - 206 - 207 ------------------------------------------------------------------------------ - 208 debugE :: (MonadIO m) => ByteString -> m () - 209 debugE s = debug $ "Server: " ++ (map w2c $ S.unpack s) - 210 + 185 + 186 go alog elog backend cpu = runOne alog elog backend cpu + 187 `catches` + 188 [ Handler $ \(_ :: Backend.TimeoutException) -> return () + 189 + 190 , Handler $ \(e :: AsyncException) -> do + 191 logE elog $ + 192 S.concat [ "Server.httpServe.go: got async exception, " + 193 , "terminating:\n", bshow e ] + 194 throwIO e + 195 + 196 , Handler $ \(e :: Backend.BackendTerminatedException) -> do + 197 logE elog $ "Server.httpServe.go: got backend terminated, waiting for cleanup" + 198 throwIO e + 199 + 200 , Handler $ \(e :: IOException) -> do + 201 logE elog $ S.concat [ "Server.httpServe.go: got io exception: " + 202 , bshow e ] + 203 + 204 , Handler $ \(e :: SomeException) -> do + 205 logE elog $ S.concat [ "Server.httpServe.go: got someexception: " + 206 , bshow e ] ] + 207 + 208 ------------------------------------------------------------------------------ + 209 debugE :: (MonadIO m) => ByteString -> m () + 210 debugE s = debug $ "Server: " ++ (map w2c $ S.unpack s) 211 - 212 ------------------------------------------------------------------------------ - 213 logE :: Maybe Logger -> ByteString -> IO () - 214 logE elog = maybe debugE (\l s -> debugE s >> logE' l s) elog - 215 - 216 logE' :: Logger -> ByteString -> IO () - 217 logE' logger s = (timestampedLogEntry s) >>= logMsg logger - 218 + 212 + 213 ------------------------------------------------------------------------------ + 214 logE :: Maybe Logger -> ByteString -> IO () + 215 logE elog = maybe debugE (\l s -> debugE s >> logE' l s) elog + 216 + 217 logE' :: Logger -> ByteString -> IO () + 218 logE' logger s = (timestampedLogEntry s) >>= logMsg logger 219 - 220 bshow :: (Prelude.Show a) => a -> ByteString - 221 bshow = toBS . Prelude.show - 222 - 223 ------------------------------------------------------------------------------ - 224 logA ::Maybe Logger -> Request -> Response -> IO () - 225 logA alog = maybe (\_ _ -> return ()) logA' alog - 226 - 227 logA' :: Logger -> Request -> Response -> IO () - 228 logA' logger req rsp = do - 229 let hdrs = rqHeaders req - 230 let host = rqRemoteAddr req - 231 let user = Nothing -- TODO we don't do authentication yet - 232 let (v, v') = rqVersion req - 233 let ver = S.concat [ "HTTP/", bshow v, ".", bshow v' ] - 234 let method = toBS $ Prelude.show (rqMethod req) - 235 let reql = S.intercalate " " [ method, rqURI req, ver ] - 236 let status = rspStatus rsp - 237 let cl = rspContentLength rsp - 238 let referer = maybe Nothing (Just . head) $ Map.lookup "referer" hdrs - 239 let userAgent = maybe "-" head $ Map.lookup "user-agent" hdrs - 240 - 241 msg <- combinedLogEntry host user reql status cl referer userAgent - 242 logMsg logger msg - 243 + 220 + 221 bshow :: (Prelude.Show a) => a -> ByteString + 222 bshow = toBS . Prelude.show + 223 + 224 ------------------------------------------------------------------------------ + 225 logA ::Maybe Logger -> Request -> Response -> IO () + 226 logA alog = maybe (\_ _ -> return ()) logA' alog + 227 + 228 logA' :: Logger -> Request -> Response -> IO () + 229 logA' logger req rsp = do + 230 let hdrs = rqHeaders req + 231 let host = rqRemoteAddr req + 232 let user = Nothing -- TODO we don't do authentication yet + 233 let (v, v') = rqVersion req + 234 let ver = S.concat [ "HTTP/", bshow v, ".", bshow v' ] + 235 let method = toBS $ Prelude.show (rqMethod req) + 236 let reql = S.intercalate " " [ method, rqURI req, ver ] + 237 let status = rspStatus rsp + 238 let cl = rspContentLength rsp + 239 let referer = maybe Nothing (Just . head) $ Map.lookup "referer" hdrs + 240 let userAgent = maybe "-" head $ Map.lookup "user-agent" hdrs + 241 + 242 msg <- combinedLogEntry host user reql status cl referer userAgent + 243 logMsg logger msg 244 - 245 ------------------------------------------------------------------------------ - 246 runHTTP :: ByteString -- ^ local host name - 247 -> ByteString -- ^ local ip address - 248 -> Int -- ^ local port - 249 -> ByteString -- ^ remote ip address - 250 -> Int -- ^ remote port - 251 -> Maybe Logger -- ^ access logger - 252 -> Maybe Logger -- ^ error logger - 253 -> Enumerator IO () -- ^ read end of socket - 254 -> Iteratee IO () -- ^ write end of socket - 255 -> (FilePath -> IO ()) -- ^ sendfile end - 256 -> IO () -- ^ timeout tickler - 257 -> ServerHandler -- ^ handler procedure - 258 -> IO () - 259 runHTTP lh lip lp rip rp alog elog - 260 readEnd writeEnd onSendFile tickle handler = - 261 go `catches` [ Handler $ \(e :: AsyncException) -> do - 262 throwIO e - 263 - 264 , Handler $ \(_ :: Backend.TimeoutException) -> return () - 265 - 266 , Handler $ \(e :: SomeException) -> - 267 logE elog $ S.concat [ logPrefix , bshow e ] ] - 268 - 269 where - 270 logPrefix = S.concat [ "[", rip, "]: error: " ] - 271 - 272 go = do - 273 buf <- mkIterateeBuffer - 274 let iter = runServerMonad lh lip lp rip rp (logA alog) (logE elog) $ - 275 httpSession writeEnd buf onSendFile tickle - 276 handler - 277 readEnd iter >>= run - 278 + 245 + 246 ------------------------------------------------------------------------------ + 247 runHTTP :: ByteString -- ^ local host name + 248 -> ByteString -- ^ local ip address + 249 -> Int -- ^ local port + 250 -> ByteString -- ^ remote ip address + 251 -> Int -- ^ remote port + 252 -> Maybe Logger -- ^ access logger + 253 -> Maybe Logger -- ^ error logger + 254 -> Enumerator IO () -- ^ read end of socket + 255 -> Iteratee IO () -- ^ write end of socket + 256 -> (FilePath -> Int64 -> IO ()) -- ^ sendfile end + 257 -> IO () -- ^ timeout tickler + 258 -> ServerHandler -- ^ handler procedure + 259 -> IO () + 260 runHTTP lh lip lp rip rp alog elog + 261 readEnd writeEnd onSendFile tickle handler = + 262 go `catches` [ Handler $ \(e :: AsyncException) -> do + 263 throwIO e + 264 + 265 , Handler $ \(_ :: Backend.TimeoutException) -> return () + 266 + 267 , Handler $ \(e :: SomeException) -> + 268 logE elog $ S.concat [ logPrefix , bshow e ] ] + 269 + 270 where + 271 logPrefix = S.concat [ "[", rip, "]: error: " ] + 272 + 273 go = do + 274 buf <- mkIterateeBuffer + 275 let iter = runServerMonad lh lip lp rip rp (logA alog) (logE elog) $ + 276 httpSession writeEnd buf onSendFile tickle + 277 handler + 278 readEnd iter >>= run 279 - 280 ------------------------------------------------------------------------------ - 281 sERVER_HEADER :: [ByteString] - 282 sERVER_HEADER = [S.concat ["Snap/", snapServerVersion]] - 283 - 284 snapServerVersion :: ByteString - 285 snapServerVersion = SC.pack $ showVersion $ V.version - 286 - 287 ------------------------------------------------------------------------------ - 288 logAccess :: Request -> Response -> ServerMonad () - 289 logAccess req rsp = gets _logAccess >>= (\l -> liftIO $ l req rsp) - 290 - 291 ------------------------------------------------------------------------------ - 292 logError :: ByteString -> ServerMonad () - 293 logError s = gets _logError >>= (\l -> liftIO $ l s) - 294 - 295 ------------------------------------------------------------------------------ - 296 -- | Runs an HTTP session. - 297 httpSession :: Iteratee IO () -- ^ write end of socket - 298 -> ForeignPtr CChar -- ^ iteratee buffer - 299 -> (FilePath -> IO ()) -- ^ sendfile continuation - 300 -> IO () -- ^ timeout tickler - 301 -> ServerHandler -- ^ handler procedure - 302 -> ServerMonad () - 303 httpSession writeEnd' ibuf onSendFile tickle handler = do - 304 - 305 (writeEnd, cancelBuffering) <- - 306 liftIO $ I.unsafeBufferIterateeWithBuffer ibuf writeEnd' - 307 - 308 let killBuffer = writeIORef cancelBuffering True - 309 - 310 liftIO $ debug "Server.httpSession: entered" - 311 mreq <- receiveRequest - 312 -- successfully got a request, so restart timer - 313 liftIO tickle - 314 - 315 case mreq of - 316 (Just req) -> do - 317 logerr <- gets _logError - 318 (req',rspOrig) <- lift $ handler logerr req - 319 let rspTmp = rspOrig { rspHttpVersion = rqVersion req } - 320 checkConnectionClose (rspHttpVersion rspTmp) (rspHeaders rspTmp) - 321 - 322 cc <- gets _forceConnectionClose - 323 let rsp = if cc - 324 then (setHeader "Connection" "close" rspTmp) - 325 else rspTmp - 326 - 327 - 328 liftIO $ debug "Server.httpSession: handled, skipping request body" - 329 srqEnum <- liftIO $ readIORef $ rqBody req' - 330 let (SomeEnumerator rqEnum) = srqEnum - 331 lift $ joinIM $ rqEnum skipToEof - 332 liftIO $ debug "Server.httpSession: request body skipped, sending response" + 280 + 281 ------------------------------------------------------------------------------ + 282 sERVER_HEADER :: [ByteString] + 283 sERVER_HEADER = [S.concat ["Snap/", snapServerVersion]] + 284 + 285 snapServerVersion :: ByteString + 286 snapServerVersion = SC.pack $ showVersion $ V.version + 287 + 288 ------------------------------------------------------------------------------ + 289 logAccess :: Request -> Response -> ServerMonad () + 290 logAccess req rsp = gets _logAccess >>= (\l -> liftIO $ l req rsp) + 291 + 292 ------------------------------------------------------------------------------ + 293 logError :: ByteString -> ServerMonad () + 294 logError s = gets _logError >>= (\l -> liftIO $ l s) + 295 + 296 ------------------------------------------------------------------------------ + 297 -- | Runs an HTTP session. + 298 httpSession :: Iteratee IO () -- ^ write end of socket + 299 -> ForeignPtr CChar -- ^ iteratee buffer + 300 -> (FilePath -> Int64 -> IO ()) -- ^ sendfile continuation + 301 -> IO () -- ^ timeout tickler + 302 -> ServerHandler -- ^ handler procedure + 303 -> ServerMonad () + 304 httpSession writeEnd' ibuf onSendFile tickle handler = do + 305 + 306 (writeEnd, cancelBuffering) <- + 307 liftIO $ I.unsafeBufferIterateeWithBuffer ibuf writeEnd' + 308 + 309 -- (writeEnd, cancelBuffering) <- liftIO $ I.bufferIteratee writeEnd' + 310 let killBuffer = writeIORef cancelBuffering True + 311 + 312 + 313 liftIO $ debug "Server.httpSession: entered" + 314 mreq <- receiveRequest + 315 -- successfully got a request, so restart timer + 316 liftIO tickle + 317 + 318 case mreq of + 319 (Just req) -> do + 320 liftIO $ debug $ "got request: " ++ + 321 Prelude.show (rqMethod req) ++ + 322 " " ++ SC.unpack (rqURI req) ++ + 323 " " ++ Prelude.show (rqVersion req) + 324 logerr <- gets _logError + 325 (req',rspOrig) <- lift $ handler logerr req + 326 let rspTmp = rspOrig { rspHttpVersion = rqVersion req } + 327 checkConnectionClose (rspHttpVersion rspTmp) (rspHeaders rspTmp) + 328 + 329 cc <- gets _forceConnectionClose + 330 let rsp = if cc + 331 then (setHeader "Connection" "close" rspTmp) + 332 else rspTmp 333 - 334 date <- liftIO getDateString - 335 let ins = (Map.insert "Date" [date] . Map.insert "Server" sERVER_HEADER) - 336 let rsp' = updateHeaders ins rsp - 337 (bytesSent,_) <- sendResponse rsp' writeEnd ibuf killBuffer onSendFile - 338 - 339 liftIO . debug $ "Server.httpSession: sent " ++ - 340 (Prelude.show bytesSent) ++ " bytes" - 341 - 342 maybe (logAccess req rsp') - 343 (\_ -> logAccess req $ setContentLength bytesSent rsp') - 344 (rspContentLength rsp') + 334 + 335 liftIO $ debug "Server.httpSession: handled, skipping request body" + 336 srqEnum <- liftIO $ readIORef $ rqBody req' + 337 let (SomeEnumerator rqEnum) = srqEnum + 338 lift $ joinIM $ rqEnum skipToEof + 339 liftIO $ debug "Server.httpSession: request body skipped, sending response" + 340 + 341 date <- liftIO getDateString + 342 let ins = (Map.insert "Date" [date] . Map.insert "Server" sERVER_HEADER) + 343 let rsp' = updateHeaders ins rsp + 344 (bytesSent,_) <- sendResponse rsp' writeEnd ibuf killBuffer onSendFile 345 - 346 if cc - 347 then return () - 348 else httpSession writeEnd ibuf onSendFile tickle handler - 349 - 350 Nothing -> return () - 351 - 352 ------------------------------------------------------------------------------ - 353 receiveRequest :: ServerMonad (Maybe Request) - 354 receiveRequest = do - 355 mreq <- {-# SCC "receiveRequest/parseRequest" #-} lift parseRequest + 346 liftIO . debug $ "Server.httpSession: sent " ++ + 347 (Prelude.show bytesSent) ++ " bytes" + 348 + 349 maybe (logAccess req rsp') + 350 (\_ -> logAccess req $ setContentLength bytesSent rsp') + 351 (rspContentLength rsp') + 352 + 353 if cc + 354 then return () + 355 else httpSession writeEnd' ibuf onSendFile tickle handler 356 - 357 case mreq of - 358 (Just ireq) -> do - 359 req' <- toRequest ireq - 360 setEnumerator req' - 361 req <- parseForm req' - 362 checkConnectionClose (rqVersion req) (rqHeaders req) - 363 return $ Just req - 364 - 365 Nothing -> return Nothing - 366 - 367 - 368 where - 369 -- check: did the client specify "transfer-encoding: chunked"? then we have - 370 -- to honor that. - 371 -- - 372 -- otherwise: check content-length header. if set: only take N bytes from - 373 -- the read end of the socket - 374 -- - 375 -- if no content-length and no chunked encoding, enumerate the entire - 376 -- socket and close afterwards - 377 setEnumerator :: Request -> ServerMonad () - 378 setEnumerator req = - 379 {-# SCC "receiveRequest/setEnumerator" #-} - 380 if isChunked - 381 then liftIO $ writeIORef (rqBody req) - 382 (SomeEnumerator readChunkedTransferEncoding) - 383 else maybe noContentLength hasContentLength mbCL - 384 - 385 where - 386 isChunked = maybe False - 387 ((== ["chunked"]) . map toCI) - 388 (Map.lookup "transfer-encoding" hdrs) - 389 - 390 hasContentLength :: Int -> ServerMonad () - 391 hasContentLength l = do - 392 liftIO $ writeIORef (rqBody req) - 393 (SomeEnumerator e) - 394 where - 395 e :: Enumerator IO a - 396 e = return . joinI . I.take l - 397 - 398 noContentLength :: ServerMonad () - 399 noContentLength = - 400 liftIO $ writeIORef (rqBody req) - 401 (SomeEnumerator $ return . joinI . I.take 0 ) - 402 - 403 - 404 hdrs = rqHeaders req - 405 mbCL = Map.lookup "content-length" hdrs >>= return . Cvt.int . head - 406 - 407 - 408 parseForm :: Request -> ServerMonad Request - 409 parseForm req = - 410 {-# SCC "receiveRequest/parseForm" #-} if doIt then getIt else return req - 411 where - 412 doIt = mbCT == Just "application/x-www-form-urlencoded" - 413 mbCT = liftM head $ Map.lookup "content-type" (rqHeaders req) + 357 Nothing -> return () + 358 + 359 ------------------------------------------------------------------------------ + 360 receiveRequest :: ServerMonad (Maybe Request) + 361 receiveRequest = do + 362 mreq <- {-# SCC "receiveRequest/parseRequest" #-} lift parseRequest + 363 + 364 case mreq of + 365 (Just ireq) -> do + 366 req' <- toRequest ireq + 367 setEnumerator req' + 368 req <- parseForm req' + 369 checkConnectionClose (rqVersion req) (rqHeaders req) + 370 return $ Just req + 371 + 372 Nothing -> return Nothing + 373 + 374 + 375 where + 376 -- check: did the client specify "transfer-encoding: chunked"? then we have + 377 -- to honor that. + 378 -- + 379 -- otherwise: check content-length header. if set: only take N bytes from + 380 -- the read end of the socket + 381 -- + 382 -- if no content-length and no chunked encoding, enumerate the entire + 383 -- socket and close afterwards + 384 setEnumerator :: Request -> ServerMonad () + 385 setEnumerator req = + 386 {-# SCC "receiveRequest/setEnumerator" #-} + 387 if isChunked + 388 then liftIO $ writeIORef (rqBody req) + 389 (SomeEnumerator readChunkedTransferEncoding) + 390 else maybe noContentLength hasContentLength mbCL + 391 + 392 where + 393 isChunked = maybe False + 394 ((== ["chunked"]) . map toCI) + 395 (Map.lookup "transfer-encoding" hdrs) + 396 + 397 hasContentLength :: Int -> ServerMonad () + 398 hasContentLength l = do + 399 liftIO $ writeIORef (rqBody req) + 400 (SomeEnumerator e) + 401 where + 402 e :: Enumerator IO a + 403 e = return . joinI . I.take l + 404 + 405 noContentLength :: ServerMonad () + 406 noContentLength = + 407 liftIO $ writeIORef (rqBody req) + 408 (SomeEnumerator $ return . joinI . I.take 0 ) + 409 + 410 + 411 hdrs = rqHeaders req + 412 mbCL = Map.lookup "content-length" hdrs >>= return . Cvt.int . head + 413 414 - 415 maximumPOSTBodySize :: Int - 416 maximumPOSTBodySize = 10*1024*1024 - 417 - 418 getIt :: ServerMonad Request - 419 getIt = {-# SCC "receiveRequest/parseForm/getIt" #-} do - 420 senum <- liftIO $ readIORef $ rqBody req - 421 let (SomeEnumerator enum) = senum - 422 let i = joinI $ takeNoMoreThan maximumPOSTBodySize stream2stream - 423 iter <- liftIO $ enum i - 424 body <- lift iter - 425 let newParams = parseUrlEncoded $ strictize $ fromWrap body - 426 liftIO $ writeIORef (rqBody req) - 427 (SomeEnumerator $ return . I.joinI . I.take 0) - 428 return $ req { rqParams = rqParams req `mappend` newParams } - 429 - 430 - 431 toRequest (IRequest method uri version kvps) = - 432 {-# SCC "receiveRequest/toRequest" #-} do - 433 localAddr <- gets _localAddress - 434 localPort <- gets _localPort - 435 remoteAddr <- gets _remoteAddr - 436 remotePort <- gets _remotePort - 437 localHostname <- gets _localHostname - 438 - 439 let (serverName, serverPort) = fromMaybe - 440 (localHostname, localPort) - 441 (liftM (parseHost . head) - 442 (Map.lookup "host" hdrs)) - 443 - 444 -- will override in "setEnumerator" - 445 enum <- liftIO $ newIORef $ SomeEnumerator return - 446 - 447 - 448 return $ Request serverName - 449 serverPort - 450 remoteAddr - 451 remotePort - 452 localAddr - 453 localPort - 454 localHostname - 455 isSecure - 456 hdrs - 457 enum - 458 mbContentLength - 459 method - 460 version - 461 cookies - 462 snapletPath - 463 pathInfo - 464 contextPath - 465 uri - 466 queryString - 467 params - 468 - 469 where - 470 snapletPath = "" -- TODO: snaplets in v0.2 - 471 - 472 dropLeadingSlash s = maybe s f mbS - 473 where - 474 f (a,s') = if a == c2w '/' then s' else s - 475 mbS = S.uncons s - 476 - 477 isSecure = False + 415 parseForm :: Request -> ServerMonad Request + 416 parseForm req = + 417 {-# SCC "receiveRequest/parseForm" #-} if doIt then getIt else return req + 418 where + 419 doIt = mbCT == Just "application/x-www-form-urlencoded" + 420 mbCT = liftM head $ Map.lookup "content-type" (rqHeaders req) + 421 + 422 maximumPOSTBodySize :: Int64 + 423 maximumPOSTBodySize = 10*1024*1024 + 424 + 425 getIt :: ServerMonad Request + 426 getIt = {-# SCC "receiveRequest/parseForm/getIt" #-} do + 427 senum <- liftIO $ readIORef $ rqBody req + 428 let (SomeEnumerator enum) = senum + 429 let i = joinI $ takeNoMoreThan maximumPOSTBodySize stream2stream + 430 iter <- liftIO $ enum i + 431 body <- lift iter + 432 let newParams = parseUrlEncoded $ strictize $ fromWrap body + 433 liftIO $ writeIORef (rqBody req) + 434 (SomeEnumerator $ return . I.joinI . I.take 0) + 435 return $ req { rqParams = rqParams req `mappend` newParams } + 436 + 437 + 438 toRequest (IRequest method uri version kvps) = + 439 {-# SCC "receiveRequest/toRequest" #-} do + 440 localAddr <- gets _localAddress + 441 localPort <- gets _localPort + 442 remoteAddr <- gets _remoteAddr + 443 remotePort <- gets _remotePort + 444 localHostname <- gets _localHostname + 445 + 446 let (serverName, serverPort) = fromMaybe + 447 (localHostname, localPort) + 448 (liftM (parseHost . head) + 449 (Map.lookup "host" hdrs)) + 450 + 451 -- will override in "setEnumerator" + 452 enum <- liftIO $ newIORef $ SomeEnumerator return + 453 + 454 + 455 return $ Request serverName + 456 serverPort + 457 remoteAddr + 458 remotePort + 459 localAddr + 460 localPort + 461 localHostname + 462 isSecure + 463 hdrs + 464 enum + 465 mbContentLength + 466 method + 467 version + 468 cookies + 469 snapletPath + 470 pathInfo + 471 contextPath + 472 uri + 473 queryString + 474 params + 475 + 476 where + 477 snapletPath = "" -- TODO: snaplets in v0.2 478 - 479 hdrs = toHeaders kvps - 480 - 481 mbContentLength = liftM (Cvt.int . head) $ - 482 Map.lookup "content-length" hdrs + 479 dropLeadingSlash s = maybe s f mbS + 480 where + 481 f (a,s') = if a == c2w '/' then s' else s + 482 mbS = S.uncons s 483 - 484 cookies = concat $ - 485 maybe [] - 486 (catMaybes . map parseCookie) - 487 (Map.lookup "cookie" hdrs) - 488 - 489 contextPath = "/" + 484 isSecure = False + 485 + 486 hdrs = toHeaders kvps + 487 + 488 mbContentLength = liftM (Cvt.int . head) $ + 489 Map.lookup "content-length" hdrs 490 - 491 parseHost h = (a, Cvt.int (S.drop 1 b)) - 492 where - 493 (a,b) = S.break (== (c2w ':')) h - 494 - 495 params = parseUrlEncoded queryString - 496 - 497 (pathInfo, queryString) = first dropLeadingSlash . second (S.drop 1) $ - 498 S.break (== (c2w '?')) uri - 499 - 500 - 501 ------------------------------------------------------------------------------ - 502 -- Response must be well-formed here - 503 sendResponse :: Response - 504 -> Iteratee IO a - 505 -> ForeignPtr CChar - 506 -> IO () - 507 -> (FilePath -> IO a) - 508 -> ServerMonad (Int,a) - 509 sendResponse rsp' writeEnd ibuf killBuffering onSendFile = do - 510 rsp <- fixupResponse rsp' - 511 let !headerString = mkHeaderString rsp - 512 - 513 (!x,!bs) <- case (rspBody rsp) of - 514 (Enum e) -> liftIO $ whenEnum headerString e - 515 (SendFile f) -> liftIO $ whenSendFile headerString rsp f - 516 - 517 return $! (bs,x) - 518 - 519 where - 520 whenEnum hs e = do - 521 let enum = enumBS hs >. e - 522 let hl = S.length hs - 523 (x,bs) <- liftIO $ enum (countBytes writeEnd) >>= run - 524 - 525 return (x, bs-hl) - 526 - 527 whenSendFile hs r f = do - 528 -- guaranteed to have a content length here. - 529 enumBS hs writeEnd >>= run + 491 cookies = concat $ + 492 maybe [] + 493 (catMaybes . map parseCookie) + 494 (Map.lookup "cookie" hdrs) + 495 + 496 contextPath = "/" + 497 + 498 parseHost h = (a, Cvt.int (S.drop 1 b)) + 499 where + 500 (a,b) = S.break (== (c2w ':')) h + 501 + 502 params = parseUrlEncoded queryString + 503 + 504 (pathInfo, queryString) = first dropLeadingSlash . second (S.drop 1) $ + 505 S.break (== (c2w '?')) uri + 506 + 507 + 508 ------------------------------------------------------------------------------ + 509 -- Response must be well-formed here + 510 sendResponse :: Response + 511 -> Iteratee IO a + 512 -> ForeignPtr CChar + 513 -> IO () + 514 -> (FilePath -> Int64 -> IO a) + 515 -> ServerMonad (Int64, a) + 516 sendResponse rsp' writeEnd ibuf killBuffering onSendFile = do + 517 rsp <- fixupResponse rsp' + 518 let !headerString = mkHeaderString rsp + 519 + 520 (!x,!bs) <- case (rspBody rsp) of + 521 (Enum e) -> liftIO $ whenEnum headerString e + 522 (SendFile f) -> liftIO $ whenSendFile headerString rsp f + 523 + 524 return $! (bs,x) + 525 + 526 where + 527 whenEnum hs e = do + 528 let enum = enumBS hs >. e + 529 let hl = fromIntegral $ S.length hs 530 - 531 let !cl = fromJust $ rspContentLength r - 532 x <- onSendFile f - 533 return (x, cl) + 531 (x,bs) <- liftIO $ enum (countBytes writeEnd) >>= run + 532 + 533 return (x, bs-hl) 534 - 535 (major,minor) = rspHttpVersion rsp' - 536 - 537 - 538 fmtHdrs hdrs = - 539 {-# SCC "fmtHdrs" #-} - 540 concat xs - 541 where - 542 xs = map f $ Map.toList hdrs - 543 - 544 f (k, ys) = map (g k) ys + 535 whenSendFile hs r f = do + 536 -- guaranteed to have a content length here. + 537 enumBS hs writeEnd >>= run + 538 + 539 let !cl = fromJust $ rspContentLength r + 540 x <- onSendFile f cl + 541 return (x, cl) + 542 + 543 (major,minor) = rspHttpVersion rsp' + 544 545 - 546 g k y = S.concat [ unCI k, ": ", y, "\r\n" ] - 547 - 548 - 549 noCL :: Response -> ServerMonad Response - 550 noCL r = - 551 {-# SCC "noCL" #-} - 552 do - 553 -- are we in HTTP/1.1? - 554 let sendChunked = (rspHttpVersion r) == (1,1) - 555 if sendChunked - 556 then do - 557 liftIO $ killBuffering - 558 let r' = setHeader "Transfer-Encoding" "chunked" r - 559 let e = writeChunkedTransferEncoding ibuf $ - 560 rspBodyToEnum $ rspBody r - 561 return $ r' { rspBody = Enum e } - 562 - 563 else do - 564 -- HTTP/1.0 and no content-length? We'll have to close the - 565 -- socket. - 566 modify $! \s -> s { _forceConnectionClose = True } - 567 return $ setHeader "Connection" "close" r - 568 - 569 - 570 hasCL :: Int -> Response -> ServerMonad Response - 571 hasCL cl r = - 572 {-# SCC "hasCL" #-} - 573 do - 574 -- set the content-length header - 575 let r' = setHeader "Content-Length" (l2s $ show cl) r - 576 let b = case (rspBody r') of - 577 (Enum e) -> Enum (i e) - 578 (SendFile f) -> SendFile f - 579 - 580 return $ r' { rspBody = b } - 581 - 582 where - 583 i :: Enumerator IO a -> Enumerator IO a - 584 i enum iter = enum (joinI $ takeExactly cl iter) - 585 - 586 - 587 setFileSize :: FilePath -> Response -> ServerMonad Response - 588 setFileSize fp r = - 589 {-# SCC "setFileSize" #-} - 590 do - 591 fs <- liftM fromEnum $ liftIO $ getFileSize fp - 592 return $ r { rspContentLength = Just fs } + 546 fmtHdrs hdrs = + 547 {-# SCC "fmtHdrs" #-} + 548 concat xs + 549 where + 550 xs = map f $ Map.toList hdrs + 551 + 552 f (k, ys) = map (g k) ys + 553 + 554 g k y = S.concat [ unCI k, ": ", y, "\r\n" ] + 555 + 556 + 557 noCL :: Response -> ServerMonad Response + 558 noCL r = + 559 {-# SCC "noCL" #-} + 560 do + 561 -- are we in HTTP/1.1? + 562 let sendChunked = (rspHttpVersion r) == (1,1) + 563 if sendChunked + 564 then do + 565 liftIO $ killBuffering + 566 let r' = setHeader "Transfer-Encoding" "chunked" r + 567 let e = writeChunkedTransferEncoding ibuf $ + 568 rspBodyToEnum $ rspBody r + 569 return $ r' { rspBody = Enum e } + 570 + 571 else do + 572 -- HTTP/1.0 and no content-length? We'll have to close the + 573 -- socket. + 574 modify $! \s -> s { _forceConnectionClose = True } + 575 return $ setHeader "Connection" "close" r + 576 + 577 + 578 hasCL :: Int64 -> Response -> ServerMonad Response + 579 hasCL cl r = + 580 {-# SCC "hasCL" #-} + 581 do + 582 -- set the content-length header + 583 let r' = setHeader "Content-Length" (l2s $ show cl) r + 584 let b = case (rspBody r') of + 585 (Enum e) -> Enum (i e) + 586 (SendFile f) -> SendFile f + 587 + 588 return $ r' { rspBody = b } + 589 + 590 where + 591 i :: Enumerator IO a -> Enumerator IO a + 592 i enum iter = enum (joinI $ takeExactly cl iter) 593 594 - 595 fixupResponse :: Response -> ServerMonad Response - 596 fixupResponse r = - 597 {-# SCC "fixupResponse" #-} + 595 setFileSize :: FilePath -> Response -> ServerMonad Response + 596 setFileSize fp r = + 597 {-# SCC "setFileSize" #-} 598 do - 599 let r' = updateHeaders (Map.delete "Content-Length") r - 600 r'' <- case (rspBody r') of - 601 (Enum _) -> return r' - 602 (SendFile f) -> setFileSize f r' - 603 case (rspContentLength r'') of - 604 Nothing -> noCL r'' - 605 (Just sz) -> hasCL sz r'' - 606 + 599 fs <- liftM fromIntegral $ liftIO $ getFileSize fp + 600 return $ r { rspContentLength = Just fs } + 601 + 602 + 603 handle304 :: Response -> Response + 604 handle304 r = setResponseBody (enumBS "") $ + 605 updateHeaders (Map.delete "Transfer-Encoding") $ + 606 setContentLength 0 r 607 - 608 bsshow = l2s . show - 609 - 610 - 611 mkHeaderString :: Response -> ByteString - 612 mkHeaderString r = - 613 {-# SCC "mkHeaderString" #-} - 614 S.concat $ concat [hl, hdr, eol] - 615 where - 616 hl = [ "HTTP/" - 617 , bsshow major - 618 , "." - 619 , bsshow minor - 620 , " " - 621 , bsshow $ rspStatus r - 622 , " " - 623 , rspStatusReason r - 624 , "\r\n" ] - 625 - 626 hdr = fmtHdrs $ headers r + 608 fixupResponse :: Response -> ServerMonad Response + 609 fixupResponse r = + 610 {-# SCC "fixupResponse" #-} + 611 do + 612 let r' = updateHeaders (Map.delete "Content-Length") r + 613 + 614 let code = rspStatus r' + 615 + 616 let r'' = if code == 204 || code == 304 + 617 then handle304 r' + 618 else r' + 619 + 620 r''' <- case (rspBody r'') of + 621 (Enum _) -> return r'' + 622 (SendFile f) -> setFileSize f r'' + 623 case (rspContentLength r''') of + 624 Nothing -> noCL r''' + 625 (Just sz) -> hasCL sz r''' + 626 627 - 628 eol = ["\r\n"] - 629 - 630 - 631 ------------------------------------------------------------------------------ - 632 checkConnectionClose :: (Int, Int) -> Headers -> ServerMonad () - 633 checkConnectionClose ver hdrs = - 634 -- For HTTP/1.1: - 635 -- if there is an explicit Connection: close, close the socket. - 636 -- For HTTP/1.0: - 637 -- if there is no explicit Connection: Keep-Alive, close the socket. - 638 if (ver == (1,1) && l == Just ["close"]) || - 639 (ver == (1,0) && l /= Just ["Keep-Alive"]) - 640 then modify $ \s -> s { _forceConnectionClose = True } - 641 else return () - 642 where - 643 l = liftM (map tl) $ Map.lookup "Connection" hdrs - 644 tl = S.map (c2w . toLower . w2c) - 645 - 646 - 647 ------------------------------------------------------------------------------ - 648 -- FIXME: whitespace-trim the values here. - 649 toHeaders :: [(ByteString,ByteString)] -> Headers - 650 toHeaders kvps = foldl' f Map.empty kvps' - 651 where - 652 kvps' = map (first toCI . second (:[])) kvps - 653 f m (k,v) = Map.insertWith' (flip (++)) k v m - 654 - 655 - 656 ------------------------------------------------------------------------------ - 657 getFileSize :: FilePath -> IO FileOffset - 658 getFileSize fp = liftM fileSize $ getFileStatus fp - 659 - 660 - 661 l2s :: L.ByteString -> S.ByteString - 662 l2s = S.concat . L.toChunks - 663 - 664 - 665 toBS :: String -> ByteString - 666 toBS = S.pack . map c2w + 628 bsshow = l2s . show + 629 + 630 + 631 mkHeaderString :: Response -> ByteString + 632 mkHeaderString r = + 633 {-# SCC "mkHeaderString" #-} + 634 S.concat $ concat [hl, hdr, eol] + 635 where + 636 hl = [ "HTTP/" + 637 , bsshow major + 638 , "." + 639 , bsshow minor + 640 , " " + 641 , bsshow $ rspStatus r + 642 , " " + 643 , rspStatusReason r + 644 , "\r\n" ] + 645 + 646 hdr = fmtHdrs $ headers r + 647 + 648 eol = ["\r\n"] + 649 + 650 + 651 ------------------------------------------------------------------------------ + 652 checkConnectionClose :: (Int, Int) -> Headers -> ServerMonad () + 653 checkConnectionClose ver hdrs = + 654 -- For HTTP/1.1: + 655 -- if there is an explicit Connection: close, close the socket. + 656 -- For HTTP/1.0: + 657 -- if there is no explicit Connection: Keep-Alive, close the socket. + 658 if (ver == (1,1) && l == Just ["close"]) || + 659 (ver == (1,0) && l /= Just ["Keep-Alive"]) + 660 then modify $ \s -> s { _forceConnectionClose = True } + 661 else return () + 662 where + 663 l = liftM (map tl) $ Map.lookup "Connection" hdrs + 664 tl = S.map (c2w . toLower . w2c) + 665 + 666 + 667 ------------------------------------------------------------------------------ + 668 -- FIXME: whitespace-trim the values here. + 669 toHeaders :: [(ByteString,ByteString)] -> Headers + 670 toHeaders kvps = foldl' f Map.empty kvps' + 671 where + 672 kvps' = map (first toCI . second (:[])) kvps + 673 f m (k,v) = Map.insertWith' (flip (++)) k v m + 674 + 675 + 676 ------------------------------------------------------------------------------ + 677 getFileSize :: FilePath -> IO FileOffset + 678 getFileSize fp = liftM fileSize $ getFileStatus fp + 679 + 680 + 681 l2s :: L.ByteString -> S.ByteString + 682 l2s = S.concat . L.toChunks + 683 + 684 + 685 toBS :: String -> ByteString + 686 toBS = S.pack . map c2w diff --git a/static/docs/snap-server-hpc/System.FastLogger.hs.html b/static/docs/snap-server-hpc/System.FastLogger.hs.html index 432c832..25260de 100644 --- a/static/docs/snap-server-hpc/System.FastLogger.hs.html +++ b/static/docs/snap-server-hpc/System.FastLogger.hs.html @@ -31,185 +31,186 @@ 20 import Data.ByteString.Internal (c2w) 21 import Data.DList (DList) 22 import qualified Data.DList as D - 23 import Data.IORef - 24 import Data.Maybe - 25 import Data.Serialize.Put - 26 import Prelude hiding (catch, show) - 27 import qualified Prelude - 28 import System.IO - 29 import Text.Show.ByteString hiding (runPut) - 30 - 31 import Snap.Internal.Http.Server.Date - 32 + 23 import Data.Int + 24 import Data.IORef + 25 import Data.Maybe + 26 import Data.Serialize.Put + 27 import Prelude hiding (catch, show) + 28 import qualified Prelude + 29 import System.IO + 30 import Text.Show.ByteString hiding (runPut) + 31 + 32 import Snap.Internal.Http.Server.Date 33 - 34 -- | Holds the state for a logger. - 35 data Logger = Logger - 36 { _queuedMessages :: !(IORef (DList ByteString)) - 37 , _dataWaiting :: !(MVar ()) - 38 , _loggerPath :: !(FilePath) - 39 , _loggingThread :: !(MVar ThreadId) } - 40 + 34 + 35 -- | Holds the state for a logger. + 36 data Logger = Logger + 37 { _queuedMessages :: !(IORef (DList ByteString)) + 38 , _dataWaiting :: !(MVar ()) + 39 , _loggerPath :: !(FilePath) + 40 , _loggingThread :: !(MVar ThreadId) } 41 - 42 -- | Creates a new logger, logging to the given file. If the file argument is - 43 -- \"-\", then log to stdout; if it's \"stderr\" then we log to stderr, - 44 -- otherwise we log to a regular file in append mode. The file is closed and - 45 -- re-opened every 15 minutes to facilitate external log rotation. - 46 newLogger :: FilePath -> IO Logger - 47 newLogger fp = do - 48 q <- newIORef D.empty - 49 dw <- newEmptyMVar - 50 th <- newEmptyMVar - 51 - 52 let lg = Logger q dw fp th - 53 - 54 tid <- forkIO $ loggingThread lg - 55 putMVar th tid - 56 - 57 return lg - 58 - 59 -- | Prepares a log message with the time prepended. - 60 timestampedLogEntry :: ByteString -> IO ByteString - 61 timestampedLogEntry msg = do - 62 timeStr <- getLogDateString - 63 - 64 return $! runPut $! do - 65 putWord8 $ c2w '[' - 66 putByteString timeStr - 67 putByteString "] " - 68 putByteString msg - 69 + 42 + 43 -- | Creates a new logger, logging to the given file. If the file argument is + 44 -- \"-\", then log to stdout; if it's \"stderr\" then we log to stderr, + 45 -- otherwise we log to a regular file in append mode. The file is closed and + 46 -- re-opened every 15 minutes to facilitate external log rotation. + 47 newLogger :: FilePath -> IO Logger + 48 newLogger fp = do + 49 q <- newIORef D.empty + 50 dw <- newEmptyMVar + 51 th <- newEmptyMVar + 52 + 53 let lg = Logger q dw fp th + 54 + 55 tid <- forkIO $ loggingThread lg + 56 putMVar th tid + 57 + 58 return lg + 59 + 60 -- | Prepares a log message with the time prepended. + 61 timestampedLogEntry :: ByteString -> IO ByteString + 62 timestampedLogEntry msg = do + 63 timeStr <- getLogDateString + 64 + 65 return $! runPut $! do + 66 putWord8 $ c2w '[' + 67 putByteString timeStr + 68 putByteString "] " + 69 putByteString msg 70 - 71 -- | Prepares a log message in \"combined\" format. - 72 combinedLogEntry :: ByteString -- ^ remote host - 73 -> Maybe ByteString -- ^ remote user - 74 -> ByteString -- ^ request line (up to you to ensure - 75 -- there are no quotes in here) - 76 -> Int -- ^ status code - 77 -> Maybe Int -- ^ num bytes sent - 78 -> Maybe ByteString -- ^ referer (up to you to ensure - 79 -- there are no quotes in here) - 80 -> ByteString -- ^ user agent (up to you to ensure - 81 -- there are no quotes in here) - 82 -> IO ByteString - 83 combinedLogEntry !host !mbUser !req !status !mbNumBytes !mbReferer !userAgent = do - 84 let user = fromMaybe "-" mbUser - 85 let numBytes = maybe "-" (\s -> strict $ show s) mbNumBytes - 86 let referer = maybe "-" (\s -> S.concat ["\"", s, "\""]) mbReferer - 87 - 88 timeStr <- getLogDateString - 89 - 90 let !p = [ host - 91 , " - " - 92 , user - 93 , " [" - 94 , timeStr - 95 , "] \"" - 96 , req - 97 , "\" " - 98 , strict $ show status - 99 , " " - 100 , numBytes - 101 , " " - 102 , referer - 103 , " \"" - 104 , userAgent - 105 , "\"" ] - 106 - 107 let !output = S.concat p - 108 - 109 return $! output - 110 + 71 + 72 -- | Prepares a log message in \"combined\" format. + 73 combinedLogEntry :: ByteString -- ^ remote host + 74 -> Maybe ByteString -- ^ remote user + 75 -> ByteString -- ^ request line (up to you to ensure + 76 -- there are no quotes in here) + 77 -> Int -- ^ status code + 78 -> Maybe Int64 -- ^ num bytes sent + 79 -> Maybe ByteString -- ^ referer (up to you to ensure + 80 -- there are no quotes in here) + 81 -> ByteString -- ^ user agent (up to you to ensure + 82 -- there are no quotes in here) + 83 -> IO ByteString + 84 combinedLogEntry !host !mbUser !req !status !mbNumBytes !mbReferer !userAgent = do + 85 let user = fromMaybe "-" mbUser + 86 let numBytes = maybe "-" (\s -> strict $ show s) mbNumBytes + 87 let referer = maybe "-" (\s -> S.concat ["\"", s, "\""]) mbReferer + 88 + 89 timeStr <- getLogDateString + 90 + 91 let !p = [ host + 92 , " - " + 93 , user + 94 , " [" + 95 , timeStr + 96 , "] \"" + 97 , req + 98 , "\" " + 99 , strict $ show status + 100 , " " + 101 , numBytes + 102 , " " + 103 , referer + 104 , " \"" + 105 , userAgent + 106 , "\"" ] + 107 + 108 let !output = S.concat p + 109 + 110 return $! output 111 - 112 where - 113 strict = S.concat . L.toChunks - 114 + 112 + 113 where + 114 strict = S.concat . L.toChunks 115 - 116 -- | Sends out a log message verbatim with a newline appended. Note: - 117 -- if you want a fancy log message you'll have to format it yourself - 118 -- (or use 'combinedLogEntry'). - 119 logMsg :: Logger -> ByteString -> IO () - 120 logMsg !lg !s = do - 121 let !s' = S.snoc s '\n' - 122 atomicModifyIORef (_queuedMessages lg) $ \d -> (D.snoc d s',()) - 123 tryPutMVar (_dataWaiting lg) () >> return () - 124 + 116 + 117 -- | Sends out a log message verbatim with a newline appended. Note: + 118 -- if you want a fancy log message you'll have to format it yourself + 119 -- (or use 'combinedLogEntry'). + 120 logMsg :: Logger -> ByteString -> IO () + 121 logMsg !lg !s = do + 122 let !s' = S.snoc s '\n' + 123 atomicModifyIORef (_queuedMessages lg) $ \d -> (D.snoc d s',()) + 124 tryPutMVar (_dataWaiting lg) () >> return () 125 - 126 loggingThread :: Logger -> IO () - 127 loggingThread (Logger queue notifier filePath _) = do - 128 initialize >>= go - 129 - 130 where - 131 openIt = if filePath == "-" - 132 then return stdout - 133 else if filePath == "stderr" - 134 then return stderr - 135 else openFile filePath AppendMode - 136 - 137 closeIt h = if filePath == "-" || filePath == "stderr" - 138 then return () - 139 else hClose h - 140 - 141 go (href, lastOpened) = - 142 (loop (href, lastOpened)) - 143 `catches` - 144 [ Handler $ \(_::AsyncException) -> killit (href, lastOpened) - 145 , Handler $ \(e::SomeException) -> do - 146 hPutStrLn stderr $ "logger got exception: " ++ Prelude.show e - 147 threadDelay 20000000 - 148 go (href, lastOpened) ] - 149 + 126 + 127 loggingThread :: Logger -> IO () + 128 loggingThread (Logger queue notifier filePath _) = do + 129 initialize >>= go + 130 + 131 where + 132 openIt = if filePath == "-" + 133 then return stdout + 134 else if filePath == "stderr" + 135 then return stderr + 136 else openFile filePath AppendMode + 137 + 138 closeIt h = if filePath == "-" || filePath == "stderr" + 139 then return () + 140 else hClose h + 141 + 142 go (href, lastOpened) = + 143 (loop (href, lastOpened)) + 144 `catches` + 145 [ Handler $ \(_::AsyncException) -> killit (href, lastOpened) + 146 , Handler $ \(e::SomeException) -> do + 147 hPutStrLn stderr $ "logger got exception: " ++ Prelude.show e + 148 threadDelay 20000000 + 149 go (href, lastOpened) ] 150 - 151 initialize = do - 152 lh <- openIt - 153 href <- newIORef lh - 154 t <- getCurrentDateTime - 155 tref <- newIORef t - 156 return (href, tref) - 157 + 151 + 152 initialize = do + 153 lh <- openIt + 154 href <- newIORef lh + 155 t <- getCurrentDateTime + 156 tref <- newIORef t + 157 return (href, tref) 158 - 159 killit (href, lastOpened) = do - 160 flushIt (href, lastOpened) - 161 h <- readIORef href - 162 closeIt h - 163 + 159 + 160 killit (href, lastOpened) = do + 161 flushIt (href, lastOpened) + 162 h <- readIORef href + 163 closeIt h 164 - 165 flushIt (!href, !lastOpened) = do - 166 dl <- atomicModifyIORef queue $ \x -> (D.empty,x) - 167 - 168 let !msgs = D.toList dl - 169 let !s = L.fromChunks msgs - 170 h <- readIORef href - 171 L.hPut h s - 172 hFlush h - 173 - 174 -- close the file every 15 minutes (for log rotation) - 175 t <- getCurrentDateTime - 176 old <- readIORef lastOpened - 177 - 178 if t-old > 900 - 179 then do - 180 closeIt h - 181 openIt >>= writeIORef href - 182 writeIORef lastOpened t - 183 else return () - 184 + 165 + 166 flushIt (!href, !lastOpened) = do + 167 dl <- atomicModifyIORef queue $ \x -> (D.empty,x) + 168 + 169 let !msgs = D.toList dl + 170 let !s = L.fromChunks msgs + 171 h <- readIORef href + 172 L.hPut h s + 173 hFlush h + 174 + 175 -- close the file every 15 minutes (for log rotation) + 176 t <- getCurrentDateTime + 177 old <- readIORef lastOpened + 178 + 179 if t-old > 900 + 180 then do + 181 closeIt h + 182 openIt >>= writeIORef href + 183 writeIORef lastOpened t + 184 else return () 185 - 186 loop !d = do - 187 -- wait on the notification mvar - 188 _ <- takeMVar notifier - 189 - 190 -- grab the queued messages and write them out - 191 flushIt d - 192 - 193 -- at least five seconds between log dumps - 194 threadDelay 5000000 - 195 loop d - 196 + 186 + 187 loop !d = do + 188 -- wait on the notification mvar + 189 _ <- takeMVar notifier + 190 + 191 -- grab the queued messages and write them out + 192 flushIt d + 193 + 194 -- at least five seconds between log dumps + 195 threadDelay 5000000 + 196 loop d 197 - 198 -- | Kills a logger thread, causing any unwritten contents to be - 199 -- flushed out to disk - 200 stopLogger :: Logger -> IO () - 201 stopLogger lg = withMVar (_loggingThread lg) killThread + 198 + 199 -- | Kills a logger thread, causing any unwritten contents to be + 200 -- flushed out to disk + 201 stopLogger :: Logger -> IO () + 202 stopLogger lg = withMVar (_loggingThread lg) killThread diff --git a/static/docs/snap-server-hpc/hpc_index.html b/static/docs/snap-server-hpc/hpc_index.html index 20c09e8..8c13096 100644 --- a/static/docs/snap-server-hpc/hpc_index.html +++ b/static/docs/snap-server-hpc/hpc_index.html @@ -11,20 +11,20 @@ 100%1/1
- 0/0 100%7/7
  module Snap.Internal.Http.Parser -100%35/35
57%12/21
93%601/641
+100%35/35
64%16/25
94%647/684
  module Snap.Internal.Http.Server -95%20/21
88%23/26
88%982/1112
+95%20/21
85%24/28
86%999/1160
  module Snap.Internal.Http.Server.Date 100%7/7
- 0/0 91%124/135
  module Snap.Internal.Http.Server.LibevBackend -86%31/36
45%11/24
74%789/1060
+81%31/38
41%10/24
70%809/1141
  module System.FastLogger 100%6/6
50%4/8
80%198/245
  Program Coverage Total
-94%100/106
63%50/79
84%2701/3200
+92%100/108
63%54/85
82%2784/3372
diff --git a/static/docs/snap-server-hpc/hpc_index_alt.html b/static/docs/snap-server-hpc/hpc_index_alt.html index 89be12d..81d0f8d 100644 --- a/static/docs/snap-server-hpc/hpc_index_alt.html +++ b/static/docs/snap-server-hpc/hpc_index_alt.html @@ -8,23 +8,23 @@ - + - + - - - - + + + + - +
moduleTop Level DefinitionsAlternativesExpressions
%covered / total%covered / total%covered / total
  module Snap.Internal.Http.Server95%20/21
88%23/26
88%982/1112
95%20/21
85%24/28
86%999/1160
  module Snap.Internal.Http.Parser100%35/35
57%12/21
93%601/641
100%35/35
64%16/25
94%647/684
  module System.FastLogger 100%6/6
50%4/8
80%198/245
  module Snap.Internal.Http.Server.LibevBackend86%31/36
45%11/24
74%789/1060
  module Snap.Internal.Http.Server.Date100%7/7
0/0 91%124/135
81%31/38
41%10/24
70%809/1141
  module Paths_snap_server 100%1/1
0/0 100%7/7
  module Snap.Internal.Http.Server.Date100%7/7
0/0 91%124/135
  Program Coverage Total94%100/106
63%50/79
84%2701/3200
92%100/108
63%54/85
82%2784/3372
diff --git a/static/docs/snap-server-hpc/hpc_index_exp.html b/static/docs/snap-server-hpc/hpc_index_exp.html index 94b519c..c373e2d 100644 --- a/static/docs/snap-server-hpc/hpc_index_exp.html +++ b/static/docs/snap-server-hpc/hpc_index_exp.html @@ -11,20 +11,20 @@ 100%1/1
- 0/0 100%7/7
  module Snap.Internal.Http.Parser -100%35/35
57%12/21
93%601/641
+100%35/35
64%16/25
94%647/684
  module Snap.Internal.Http.Server.Date 100%7/7
- 0/0 91%124/135
  module Snap.Internal.Http.Server -95%20/21
88%23/26
88%982/1112
+95%20/21
85%24/28
86%999/1160
  module System.FastLogger 100%6/6
50%4/8
80%198/245
  module Snap.Internal.Http.Server.LibevBackend -86%31/36
45%11/24
74%789/1060
+81%31/38
41%10/24
70%809/1141
  Program Coverage Total
-94%100/106
63%50/79
84%2701/3200
+92%100/108
63%54/85
82%2784/3372
diff --git a/static/docs/snap-server-hpc/hpc_index_fun.html b/static/docs/snap-server-hpc/hpc_index_fun.html index 24778f1..902dcb8 100644 --- a/static/docs/snap-server-hpc/hpc_index_fun.html +++ b/static/docs/snap-server-hpc/hpc_index_fun.html @@ -7,24 +7,24 @@ - - - + + + - + - + - + - +
moduleTop Level DefinitionsAlternativesExpressions
%covered / total%covered / total%covered / total
  module Snap.Internal.Http.Server.Date100%7/7
0/0 91%124/135
  module Paths_snap_server 100%1/1
0/0 100%7/7
  module Snap.Internal.Http.Server.Date100%7/7
0/0 91%124/135
  module System.FastLogger 100%6/6
50%4/8
80%198/245
  module Snap.Internal.Http.Parser100%35/35
57%12/21
93%601/641
100%35/35
64%16/25
94%647/684
  module Snap.Internal.Http.Server95%20/21
88%23/26
88%982/1112
95%20/21
85%24/28
86%999/1160
  module Snap.Internal.Http.Server.LibevBackend86%31/36
45%11/24
74%789/1060
81%31/38
41%10/24
70%809/1141
  Program Coverage Total94%100/106
63%50/79
84%2701/3200
92%100/108
63%54/85
82%2784/3372