packages feed

yesod-examples 0.5.0.2 → 0.5.1

raw patch · 13 files changed

+184/−168 lines, 13 filesnew-component:exe:generalized-hamlet

Files

− hamlet/synopsis.lhs
@@ -1,73 +0,0 @@-----title: Synopsis - Hamlet-----\begin{code}-{-# LANGUAGE QuasiQuotes #-}--import Text.Hamlet-import qualified Data.ByteString.Lazy as L--data Person = Person-    { name :: String-    , age :: String-    , page :: PersonUrls-    , isMarried :: Bool-    , children :: [String]-    }-data PersonUrls = Homepage | PersonPage String--renderUrls :: PersonUrls -> [(String, String)] -> String-renderUrls Homepage _ = "/"-renderUrls (PersonPage name) _ = '/' : name--footer :: Hamlet url-footer = [$hamlet|-#footer Thank you, come again-|]--template :: Person -> Hamlet PersonUrls-template person = [$hamlet|-!!!-%html-    %head-        %title Hamlet Demo-    %body-        %h1 Information on $string.name.person$-        %p $string.name.person$ is $string.age.person$ years old.-        %h2-            $if isMarried.person-                Married-            $else-                Not married-        %ul-            $forall children.person child-                %li $string.child$-        %p-            %a!href=@page.person@ See the page.-        ^footer^-|]--main :: IO ()-main = do-    let person = Person-            { name = "Michael"-            , age = "twenty five & a half"-            , page = PersonPage "michael"-            , isMarried = True-            , children = ["Adam", "Ben", "Chris"]-            }-    L.putStrLn $ renderHamlet renderUrls $ template person-\end{code}--Outputs (new lines added for readability):-<code><pre>-    &lt;!DOCTYPE html&gt;-    &lt;html&gt;&lt;head&gt;&lt;title&gt;Hamlet Demo&lt;/title&gt;&lt;/head&gt;&lt;body&gt;-    &lt;h1&gt;Information on Michael&lt;/h1&gt;-    &lt;p&gt;Michael is twenty five &amp; a half years old.&lt;/p&gt;-    &lt;h2&gt;Married&lt;/h2&gt;-    &lt;ul&gt;&lt;li&gt;Adam&lt;/li&gt;&lt;li&gt;Ben&lt;/li&gt;&lt;li&gt;Chris&lt;/li&gt;&lt;/ul&gt;-    &lt;p&gt;&lt;a href="/michael"&gt;See the page.&lt;/a&gt;&lt;/p&gt;-    &lt;div id="footer"&gt;Thank you, come again&lt;/div&gt;-    &lt;/body&gt;&lt;/html&gt;-</pre></code>
− persistent/synopsis.lhs
@@ -1,41 +0,0 @@-----title: Synopsis - Persistent-----This example uses the sqlite backend for Persistent, since it can run in-memory and has no external dependencies.--> {-# LANGUAGE TypeFamilies, GeneralizedNewtypeDeriving, QuasiQuotes #-}->-> import Database.Persist.Sqlite-> import Control.Monad.IO.Class (liftIO)->-> mkPersist [$persist|Person->     name String Eq->     age Int update-> |]->-> main :: IO ()-> main = withSqliteConn ":memory:" $ runSqlConn go->-> go :: SqlPersist IO ()-> go = do->   runMigration $ migrate (undefined :: Person)->   key <- insert $ Person "Michael" 25->   liftIO $ print key->   p1 <- get key->   liftIO $ print p1->   update key [PersonAge 26]->   p2 <- get key->   liftIO $ print p2->   p3 <- selectList [PersonNameEq "Michael"] [] 0 0->   liftIO $ print p3->   delete key->   p4 <- selectList [PersonNameEq "Michael"] [] 0 0->   liftIO $ print p4--The output of the above is:--    PersonId 1-    Just (Person {personName = "Michael", personAge = 25})-    Just (Person {personName = "Michael", personAge = 26})-    [(PersonId 1,Person {personName = "Michael", personAge = 26})]-    []
+ synopsis/hamlet.lhs view
@@ -0,0 +1,70 @@+\begin{code}+{-# LANGUAGE QuasiQuotes #-}++import Text.Hamlet+import qualified Data.ByteString.Lazy as L++data Person = Person+    { name :: String+    , age :: String+    , page :: PersonUrls+    , isMarried :: Bool+    , children :: [String]+    }+data PersonUrls = Homepage | PersonPage String++renderUrls :: PersonUrls -> [(String, String)] -> String+renderUrls Homepage _ = "/"+renderUrls (PersonPage name) _ = '/' : name++footer :: Hamlet url+footer = [$hamlet|+#footer Thank you, come again+|]++template :: Person -> Hamlet PersonUrls+template person = [$hamlet|+!!!+%html+    %head+        %title Hamlet Demo+    %body+        %h1 Information on $string.name.person$+        %p $string.name.person$ is $string.age.person$ years old.+        %h2+            $if isMarried.person+                Married+            $else+                Not married+        %ul+            $forall children.person child+                %li $string.child$+        %p+            %a!href=@page.person@ See the page.+        ^footer^+|]++main :: IO ()+main = do+    let person = Person+            { name = "Michael"+            , age = "twenty five & a half"+            , page = PersonPage "michael"+            , isMarried = True+            , children = ["Adam", "Ben", "Chris"]+            }+    L.putStrLn $ renderHamlet renderUrls $ template person+\end{code}++Outputs (new lines added for readability):+<code><pre>+    &lt;!DOCTYPE html&gt;+    &lt;html&gt;&lt;head&gt;&lt;title&gt;Hamlet Demo&lt;/title&gt;&lt;/head&gt;&lt;body&gt;+    &lt;h1&gt;Information on Michael&lt;/h1&gt;+    &lt;p&gt;Michael is twenty five &amp; a half years old.&lt;/p&gt;+    &lt;h2&gt;Married&lt;/h2&gt;+    &lt;ul&gt;&lt;li&gt;Adam&lt;/li&gt;&lt;li&gt;Ben&lt;/li&gt;&lt;li&gt;Chris&lt;/li&gt;&lt;/ul&gt;+    &lt;p&gt;&lt;a href="/michael"&gt;See the page.&lt;/a&gt;&lt;/p&gt;+    &lt;div id="footer"&gt;Thank you, come again&lt;/div&gt;+    &lt;/body&gt;&lt;/html&gt;+</pre></code>
+ synopsis/persistent.lhs view
@@ -0,0 +1,38 @@+This example uses the sqlite backend for Persistent, since it can run in-memory and has no external dependencies.++> {-# LANGUAGE TypeFamilies, GeneralizedNewtypeDeriving, QuasiQuotes #-}+>+> import Database.Persist.Sqlite+> import Control.Monad.IO.Class (liftIO)+>+> mkPersist [$persist|Person+>     name String Eq+>     age Int update+> |]+>+> main :: IO ()+> main = withSqliteConn ":memory:" $ runSqlConn go+>+> go :: SqlPersist IO ()+> go = do+>   runMigration $ migrate (undefined :: Person)+>   key <- insert $ Person "Michael" 25+>   liftIO $ print key+>   p1 <- get key+>   liftIO $ print p1+>   update key [PersonAge 26]+>   p2 <- get key+>   liftIO $ print p2+>   p3 <- selectList [PersonNameEq "Michael"] [] 0 0+>   liftIO $ print p3+>   delete key+>   p4 <- selectList [PersonNameEq "Michael"] [] 0 0+>   liftIO $ print p4++The output of the above is:++<code><pre>PersonId 1+Just (Person {personName = "Michael", personAge = 25})+Just (Person {personName = "Michael", personAge = 26})+[(PersonId 1,Person {personName = "Michael", personAge = 26})]+[]</pre></code>
yesod-examples.cabal view
@@ -1,5 +1,5 @@ Name:                yesod-examples-Version:             0.5.0.2+Version:             0.5.1 Synopsis:            Example programs using the Yesod Web Framework. Description:         These are the same examples and tutorials found on the documentation site. Homepage:            http://docs.yesodweb.com/@@ -14,13 +14,10 @@ extra-source-files:  static/yesod/ajax/script.js,                      static/yesod/ajax/style.css -Executable helloworld-  Main-is:             yesod/helloworld.lhs-  Build-depends:       base >= 4 && < 5,-                       yesod >= 0.5.0.1 && < 0.6- Executable blog   Main-is:             yesod/tutorial/blog.lhs+  Build-depends:       base >= 4 && < 5,+                       yesod >= 0.5.0.1 && < 0.6  Executable ajax   Main-is:             yesod/tutorial/ajax.lhs@@ -43,6 +40,9 @@ Executable widgets   Main-is:             yesod/tutorial/widgets.lhs +Executable generalized-hamlet+  Main-is:             yesod/tutorial/generalized-hamlet.lhs+ Executable form   Main-is:             yesod/tutorial/form.lhs @@ -52,12 +52,12 @@                        persistent >= 0.2.0.1 && < 0.3  Executable persistent-synopsis-  Main-is:             persistent/synopsis.lhs+  Main-is:             synopsis/persistent.lhs   Build-depends:       transformers >= 0.2.1 && < 0.3,                        persistent-sqlite  Executable hamlet-synopsis-  Main-is:             hamlet/synopsis.lhs+  Main-is:             synopsis/hamlet.lhs   Build-depends:       hamlet  source-repository head
− yesod/helloworld.lhs
@@ -1,12 +0,0 @@-----title: Hello World -- Yesod-----The following will serve the text "Hello World!" on port 3000 as plain text.--> {-# LANGUAGE TypeFamilies, QuasiQuotes, TemplateHaskell #-}-> import Yesod-> data HelloWorld = HelloWorld-> mkYesod "HelloWorld" [$parseRoutes|/ Home GET|]-> instance Yesod HelloWorld where approot _ = ""-> getHome = return $ RepPlain $ toContent "Hello World!"-> main = basicHandler 3000 HelloWorld
yesod/tutorial/ajax.lhs view
@@ -1,16 +1,13 @@-----title: AJAX -- Tutorials -- Yesod-----We're going to write a very simple AJAX application. It will be a simple site with a few pages and a navbar; when you have Javascript, clicking on the links will load the pages via AJAX. Otherwise, it will use static HTML.+<p>We're going to write a very simple AJAX application. It will be a simple site with a few pages and a navbar; when you have Javascript, clicking on the links will load the pages via AJAX. Otherwise, it will use static HTML.</p> -We're going to use jQuery for the Javascript, though anything would work just fine. Also, the AJAX responses will be served as JSON. Let's get started.+<p>We're going to use jQuery for the Javascript, though anything would work just fine. Also, the AJAX responses will be served as JSON. Let's get started.</p>  > {-# LANGUAGE TypeFamilies, QuasiQuotes, TemplateHaskell #-} > import Yesod > import Yesod.Helpers.Static > import Data.Monoid (mempty) -Like the [blog tutorial](blog.html), we'll define some data first.+Like the blog example, we'll define some data first.  > data Page = Page >   { pageName :: String@@ -43,9 +40,9 @@ > /static            StaticR Static ajaxStatic > |] -That third line there is the syntax for a subsite: Static is the datatype for the subsite argument; siteStatic returns the site itself (parse, render and dispatch functions); and ajaxStatic gets the subsite argument from the master argument.+<p>That third line there is the syntax for a subsite: Static is the datatype for the subsite argument; siteStatic returns the site itself (parse, render and dispatch functions); and ajaxStatic gets the subsite argument from the master argument.</p> -Now, we'll define the Yesod instance. We'll still use a dummy approot value, but we're also going to define a default layout.+<p>Now, we'll define the Yesod instance. We'll still use a dummy approot value, but we're also going to define a default layout.</p>  > instance Yesod Ajax where >   approot _ = ""@@ -70,9 +67,9 @@ >       ^pageBody.content^ > |] -The Hamlet template refers to style_css and style_js; these were generated by the call to staticFiles above.  There's nothing Yesod-specific about the [style.css]($root/static/yesod/ajax/style.css) and [script.js]($root/static/yesod/ajax/script.js) files, so I won't describe them here.+<p>The Hamlet template refers to style_css and style_js; these were generated by the call to staticFiles above.  There's nothing Yesod-specific about the <a href="/static/yesod/ajax/style.css">style.css</a> and <a href="/static/yesod/ajax/script.js">script.js</a> files, so I won't describe them here.</p> -Now we need our handler functions. We'll have the homepage simply redirect to the first page, so:+<p>Now we need our handler functions. We'll have the homepage simply redirect to the first page, so:</p>  > getHomeR :: Handler () > getHomeR = do@@ -101,11 +98,11 @@ >       , ("content", jsonScalar $ pageContent page) >       ] -We first try and find the appropriate Page, returning a 404 if it's not there. We then use the applyLayoutJson function, which is really the heart of this example. It allows you an easy way to create responses that will be either HTML or JSON, and which use the default layout in the HTML responses. It takes four arguments: 1) the title of the HTML page, 2) some value, 3) a function from that value to a Hamlet value, and 4) a function from that value to a Json value.+<p>We first try and find the appropriate Page, returning a 404 if it's not there. We then use the applyLayoutJson function, which is really the heart of this example. It allows you an easy way to create responses that will be either HTML or JSON, and which use the default layout in the HTML responses. It takes four arguments: 1) the title of the HTML page, 2) some value, 3) a function from that value to a Hamlet value, and 4) a function from that value to a Json value.</p> -Under the scenes, the Json monad is really just using the Hamlet monad, so it gets all of the benefits thereof, namely interleaved IO and enumerator output. It is pretty straight-forward to generate JSON output by using the three functions jsonMap, jsonList and jsonMap. One thing to note: the input to jsonScalar must be HtmlContent; this helps avoid cross-site scripting attacks, by ensuring that any HTML entities will be escaped.+<p>Under the scenes, the Json monad is really just using the Hamlet monad, so it gets all of the benefits thereof, namely interleaved IO and enumerator output. It is pretty straight-forward to generate JSON output by using the three functions jsonMap, jsonList and jsonMap. One thing to note: the input to jsonScalar must be HtmlContent; this helps avoid cross-site scripting attacks, by ensuring that any HTML entities will be escaped.</p> -And now our typical main function. We need two parameters to build our Ajax value: the pages, and the static loader. We'll load up from a local directory.+<p>And now our typical main function. We need two parameters to build our Ajax value: the pages, and the static loader. We'll load up from a local directory.</p>  > main :: IO () > main = do
yesod/tutorial/blog.lhs view
@@ -1,9 +1,6 @@-----title: Blog -- Tutorials -- Yesod-----Well, just about every web framework I've seen starts with a blog tutorial- so here's mine! Actually, you'll see that this is actually a much less featureful blog than most, but gives a good introduction to Yesod basics. I recommend you start by [reading the terminology section]($root/yesod/terminology.html).+<p>Well, just about every web framework I've seen starts with a blog tutorial- so here's mine! Actually, you'll see that this is actually a much less featureful blog than most, but gives a good introduction to Yesod basics. I recommend you start by <a href="/book/basics.html">reading the basics chapter</a>.</p> -This file is literate Haskell, so we'll start off with our language pragmas and import statements. Basically every Yesod application will start off like this:+<p>This file is literate Haskell, so we'll start off with our language pragmas and import statements. Basically every Yesod application will start off like this:</p>  > {-# LANGUAGE TypeFamilies, QuasiQuotes, TemplateHaskell #-} > import Yesod
yesod/tutorial/form.lhs view
@@ -1,4 +1,4 @@-Forms can be a tedious part of web development since they require synchronization of code in many different areas: the HTML form declaration, parsing of the form and reconstructing a datatype from the raw values. The Yesod form library simplifies things greatly. We'll start off with a basic application.+<p>Forms can be a tedious part of web development since they require synchronization of code in many different areas: the HTML form declaration, parsing of the form and reconstructing a datatype from the raw values. The Yesod form library simplifies things greatly. We'll start off with a basic application.</p>   > {-# LANGUAGE TypeFamilies, QuasiQuotes, OverloadedStrings #-}@@ -25,15 +25,15 @@ > getRootR = do >     (res, wform, enctype) <- runFormGet $ personFormlet Nothing -We use runFormGet to bind to GET (query-string) parameters; we could also use runFormPost. The "Nothing" is the initial value of the form. You could also supply a "Just Person" value if you like. There is a three-tuple returned, containing the parsed value, the HTML form as a widget and the encoding type for the form.+<p>We use runFormGet to bind to GET (query-string) parameters; we could also use runFormPost. The "Nothing" is the initial value of the form. You could also supply a "Just Person" value if you like. There is a three-tuple returned, containing the parsed value, the HTML form as a widget and the encoding type for the form.</p> -We use a widget for the form since it allows embedding CSS and Javascript code in forms directly. This allows unobtrusive adding of rich Javascript controls like date pickers.+<p>We use a widget for the form since it allows embedding CSS and Javascript code in forms directly. This allows unobtrusive adding of rich Javascript controls like date pickers.</p>  >     defaultLayout $ do >         setTitle "Form Example" >         form <- extractBody wform -extractBody returns the HTML of a widget and "passes" all of the other declarations (the CSS, Javascript, etc) up to the parent widget. The rest of this is just standard Hamlet code and our main function.+<p>extractBody returns the HTML of a widget and "passes" all of the other declarations (the CSS, Javascript, etc) up to the parent widget. The rest of this is just standard Hamlet code and our main function.</p>  >         addBody [$hamlet| > %p Last result: $show.res$
+ yesod/tutorial/generalized-hamlet.lhs view
@@ -0,0 +1,51 @@+This example shows how generalized hamlet templates allow the creation of+different types of values. The key component here is the HamletValue typeclass.+Yesod has instances for:++* Html++* Hamlet url (= (url -> [(String, String)] -> String) -> Html)++* GWidget s m ()++This example uses all three. You are of course free in your own code to make+your own instances.++> {-# LANGUAGE QuasiQuotes, TypeFamilies #-}+> import Yesod+> data NewHamlet = NewHamlet+> mkYesod "NewHamlet" [$parseRoutes|/ RootR GET|]+> instance Yesod NewHamlet where approot _ = ""+> +> myHtml :: Html+> myHtml = [$hamlet|%p Just don't use any URLs in here!|]+>+> myInnerWidget :: Widget NewHamlet ()+> myInnerWidget = do+>     addBody [$hamlet|+>   #inner Inner widget+>   $myHtml$+> |]+>     addStyle [$cassius|+>#inner+>     color: red|]+> +> myPlainTemplate :: Hamlet NewHamletRoute+> myPlainTemplate = [$hamlet|+> %p+>     %a!href=@RootR@ Link to home+> |]+> +> myWidget :: Widget NewHamlet ()+> myWidget = [$hamlet|+>     %h1 Embed another widget+>     ^myInnerWidget^+>     %h1 Embed a Hamlet+>     ^addBody.myPlainTemplate^+> |]+> +> getRootR :: GHandler NewHamlet NewHamlet RepHtml+> getRootR = defaultLayout myWidget+> +> main :: IO ()+> main = basicHandler 3000 NewHamlet
yesod/tutorial/i18n.lhs view
@@ -1,7 +1,3 @@-----title: Multi-lingual -- Tutorials -- Yesod----- > {-# LANGUAGE QuasiQuotes #-} > {-# LANGUAGE TemplateHaskell #-} > {-# LANGUAGE TypeFamilies #-}
yesod/tutorial/pretty-yaml.lhs view
@@ -1,7 +1,4 @@-----title: Pretty YAML -- Tutorials -- Yesod-----This example uses the [data-object-yaml package](http://hackage.haskell.org/package/data-object-yaml) to display YAML files as cleaned-up HTML. If you've read through the other tutorials, this one should be easy to follow.+<p>This example uses the <a href="http://hackage.haskell.org/package/data-object-yaml">data-object-yaml package</a> to display YAML files as cleaned-up HTML. If you've read through the other tutorials, this one should be easy to follow.</p>  > {-# LANGUAGE TypeFamilies, QuasiQuotes, TemplateHaskell #-} 
yesod/tutorial/widgets.lhs view
@@ -1,7 +1,3 @@-----title: Widgets -- Tutorials -- Yesod----- > {-# LANGUAGE TypeFamilies, QuasiQuotes, OverloadedStrings #-} > import Yesod > import Yesod.Widget