scratch/output/Scratch/en/blog/Yesod-tutorial-for-newbies/index.html

610 lines
27 KiB
HTML
Raw Normal View History

2011-12-29 16:05:05 +00:00
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="fr" xml:lang="fr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="keywords" content="yesod, haskell, programming, web">
<link rel="shortcut icon" type="image/x-icon" href="/Scratch/img/favicon.ico" />
<link rel="stylesheet" type="text/css" href="/Scratch/assets/css/main.css" />
<link rel="stylesheet" type="text/css" href="/Scratch/css/twilight.css" />
<link rel="stylesheet" type="text/css" href="/Scratch/css/idc.css" />
<link rel="alternate" type="application/rss+xml" title="RSS" href="http://feeds.feedburner.com/yannespositocomen"/>
<link rel="alternate" lang="fr" xml:lang="fr" title="Tutoriel Yesod pour les nuls" type="text/html" hreflang="fr" href="/Scratch/fr/blog/Yesod-tutorial-for-newbies/" />
<link rel="alternate" lang="en" xml:lang="en" title="Yesod tutorial for newbies" type="text/html" hreflang="en" href="/Scratch/en/blog/Yesod-tutorial-for-newbies/" />
<script type="text/javascript" src="/Scratch/js/jquery-1.3.1.min.js"></script>
<script type="text/javascript" src="/Scratch/js/jquery.cookie.js"></script>
<script type="text/javascript" src="/Scratch/js/index.js"></script>
<!--[if lt IE 9]>
<script src="http://ie7-js.googlecode.com/svn/version/2.1(beta4)/IE9.js"></script>
<![endif]-->
<title>Yesod tutorial for newbies</title>
</head>
<body lang="en" class="article">
<script type="text/javascript">// <![CDATA[
document.write('<div id="blackpage"><img src="/Scratch/img/loading.gif" alt="loading..."/></div>');
// ]]>
</script>
<div id="content">
<div id="choix">
<div class="return"><a href="#entete">&darr; Menu &darr;</a></div>
<div id="choixlang">
<a href="/Scratch/fr/blog/Yesod-tutorial-for-newbies/" onclick="setLanguage('fr')">en Français</a>
</div>
<div class="flush"></div>
</div>
<div id="titre">
<h1>
Yesod tutorial for newbies
</h1>
</div>
<div class="flush"></div>
<div class="flush"></div>
<div id="afterheader">
<div class="corps">
<p><img alt="Title image" src="/Scratch/img/blog/Yesod-tutorial-for-newbies/warp-benchmark.png" /></p>
<div class="intro">
<p><span class="sc"><abbr title="Too long; didn't read">tl;dr</abbr>: </span> A simple yesod tutorial. You shouldnt need to know Haskell very well. </p>
<blockquote>
<ul id="markdown-toc">
<li><a href="#install">Install</a></li>
<li><a href="#initialization">Initialization</a></li>
<li><a href="#configure-git">Configure git</a></li>
<li><a href="#a-last-point">A last point</a></li>
2012-01-02 14:39:00 +00:00
<li><a href="#protected-echo">Protected echo</a> <ul>
<li><a href="#secure">Secure?</a></li>
</ul>
</li>
2011-12-30 16:14:57 +00:00
<li><a href="#cleaning-up">Cleaning up</a> <ul>
<li><a href="#separate-handlers">Separate handlers</a></li>
<li><a href="#use-datatext-instead-of-string">Use <code>Data.Text</code> instead of <code>String</code></a></li>
<li><a href="#use-a-new-template-file">Use a new template file</a></li>
</ul>
</li>
2011-12-29 16:05:05 +00:00
<li><a href="#protected-input">Protected input</a></li>
</ul>
</blockquote>
</div>
2012-01-02 14:39:00 +00:00
<p>Do you want the best technology to handle your new web application?
Me too. After searching a lot, it appears you should choose Haskell.
Why? </p>
2011-12-29 16:05:05 +00:00
2012-01-02 14:39:00 +00:00
<ul>
<li><a href="http://www.yesodweb.com/blog/2011/03/preliminary-warp-cross-language-benchmarks">Extremely fast</a>.</li>
<li>Secure by nature. Many typical programming bug are hard to make in Haskell.</li>
<li>High abstraction level. </li>
<li>Handle asynchronous request better than any other system (better than node.js for example).</li>
<li>Done to be parallelized. Thanks to purity.</li>
</ul>
2011-12-29 16:05:05 +00:00
2012-01-02 14:39:00 +00:00
<p>Technically speaking, Haskell seems perfect for web development.
The only drawback you can found for Haskell certainly wont be technical but social. Like the difficulty to grasp Haskell, the few number of developer, etc…</p>
<p>But if you are here, lets pretend, the most important is the technical aspect.
You want the best of the best system to make your new web application.</p>
<p>Instead of reinvent the wheel, we should choose a web framework in Haskell.
Actually there are three choices:</p>
2011-12-29 16:05:05 +00:00
<ol>
<li><a href="http://happstack.com">Happstack</a></li>
<li><a href="http://snapframework.com">Snap</a></li>
<li><a href="http://yesodweb.com">Yesod</a></li>
</ol>
2012-01-02 14:39:00 +00:00
<p>I dont think there is a real winner between these three framework.
The choice I made for yesod is highly subjective.
I had the feeling yesod help the newcomers the most.
It also appears the yesod developer are the most active.
But as I said before, I might be wrong has it was only feeling.</p>
2011-12-29 16:05:05 +00:00
2012-01-02 14:39:00 +00:00
<p>Now, what this article is all about?
A missing tutorial in the yesod documentation.
The goal is to go as straight as possible to the best practice.</p>
2011-12-29 16:05:05 +00:00
2012-01-02 14:39:00 +00:00
<p>Youll then first install, initialize and configure your first yesod project.
Then a 5 minutes yesod tutorial to heat up and verify the awesomeness of yesod.
Then we clean up the 5 minutes tutorial to use the best practices.</p>
2011-12-29 16:05:05 +00:00
<h2 id="install">Install</h2>
2012-01-02 14:39:00 +00:00
<p>First you need to install <a href="http://www.haskell.org">Haskell</a>. The recommended way to do this is to download the <a href="http://www.haskell.org/platform">Haskell Platform</a>.</p>
2011-12-29 16:05:05 +00:00
2012-01-02 14:39:00 +00:00
<p>Then you need to install yesod.</p>
2011-12-29 16:05:05 +00:00
<pre class="twilight">
<span class="Keyword">&gt;</span> cabal update
<span class="Keyword">&gt;</span> cabal install yesod cabal-dev
</pre>
<p>That is all. It should take some time to
do this as cabal will download all
package and then compile them.</p>
<h2 id="initialization">Initialization</h2>
2012-01-02 14:39:00 +00:00
<p>Open a terminal and type:</p>
2011-12-29 16:05:05 +00:00
<pre class="twilight">
<span class="Keyword">&gt;</span> yesod init
</pre>
2012-01-02 14:39:00 +00:00
<p>Enter your name, name the project <code>yosog</code> and the name of the Foundation as <code>Yosog</code>, then choose <code>sqlite</code>.
Perfect. Now you can start the development cycle:</p>
2011-12-29 16:05:05 +00:00
<pre class="twilight">
<span class="Keyword">&gt;</span> cd yosog
<span class="Keyword">&gt;</span> cabal-dev install <span class="Keyword">&amp;&amp;</span> yesod --dev devel
</pre>
2012-01-02 14:39:00 +00:00
<p>This will compile the entire project. Be patient it could take some time.
Once finished a server is launched and you could visit it by clicking this link:</p>
2011-12-29 16:05:05 +00:00
<p><a href="http://localhost:3000"><code>http://localhost:3000</code></a></p>
2012-01-02 14:39:00 +00:00
<p>Congratulation! Yesod works.</p>
<blockquote>
<p>Note: if something is messed up use the following command line:
&lt;pre class="twilight"&gt;
<span class="Keyword">&gt;</span> <span class="Constant">\r</span>m -rf dist/* <span class="Keyword">;</span> cabal-dev install <span class="Keyword">&amp;&amp;</span> yesod dev devel
<span class="Keyword">&gt;</span> </p>
</blockquote>
<p>&lt;/pre&gt;</p>
<p>Until the end of the tutorial, use another terminal and let this one open in a corner to see what occurs.</p>
2011-12-29 16:05:05 +00:00
<h2 id="configure-git">Configure git</h2>
2012-01-02 14:39:00 +00:00
<p>This step is not mandatory for a tutorial, but I wanted to jump directly in good practice. There are many different choice of CVS, but for this tutorial Ill use <code>git</code>.</p>
2011-12-29 16:05:05 +00:00
2012-01-02 14:39:00 +00:00
<p>Copy this <code>.gitignore</code> file into the <code>yosog</code> folder.</p>
2011-12-29 16:05:05 +00:00
<div class="code"><div class="file"><a href="/Scratch/en/blog/Yesod-tutorial-for-newbies/code/.gitignore"> &#x27A5; .gitignore </a></div><div class="withfile">
<pre class="twilight">
cabal-dev
dist
.static-cache
static/tmp
*.sqlite3
</pre>
</div></div>
<p>Then initialize your git repository:</p>
<pre class="twilight">
<span class="Keyword">&gt;</span> git init .
<span class="Keyword">&gt;</span> git add .
<span class="Keyword">&gt;</span> git commit -a -m <span class="String"><span class="String">&quot;</span>Initial yesod commit<span class="String">&quot;</span></span>
</pre>
2012-01-02 14:39:00 +00:00
<p>Now we are almost ready to start.</p>
2011-12-29 16:05:05 +00:00
<h2 id="a-last-point">A last point</h2>
2012-01-02 14:39:00 +00:00
<p>Until here it was just an installation, an initialization and a configuration.</p>
2011-12-29 16:05:05 +00:00
2012-01-02 14:39:00 +00:00
<p>We have a directory containing a bunch of files and
we have a local web server that listen the port 3000.</p>
2011-12-29 16:05:05 +00:00
<p>If we modify a file inside this directory, yesod should try
2012-01-02 14:39:00 +00:00
to recompile as fast as possible the site.
This way, you should see the modification you do.</p>
2011-12-29 16:05:05 +00:00
<p>Instead of explaining the role of every file,
lets get straight to the point.</p>
<p>Inside the <code>yosog</code> the important files/directories for this tutorial are:</p>
<ol>
<li><code>config/routes</code></li>
<li><code>Handler/</code></li>
<li><code>templates/</code></li>
<li><code>config/models</code></li>
</ol>
<p>Obviously:</p>
<ul>
<li><code>config/routes</code> is where youll configure the map URL → Code.</li>
<li><code>Handler/</code> contains the files that will contain the code called when a URL is accessed.</li>
<li><code>templates/</code> contains HTML, JS and CSS templates. </li>
<li><code>config/models</code> is where youll configure the persistent objects (database tables).</li>
</ul>
2012-01-02 14:39:00 +00:00
<p>Also note until here we dont even typed any line of Haskell.
It is now time to start the interesting stuff.</p>
2011-12-29 16:05:05 +00:00
<h2 id="protected-echo">Protected echo</h2>
2012-01-02 14:39:00 +00:00
<p>To verify the quality of the security of the yesod framework, lets make a minimal echo application.</p>
2011-12-29 16:05:05 +00:00
<p>Our goal:</p>
2012-01-02 14:39:00 +00:00
<p>Make a server that when accessed <code>/echo/</code><em>[some text]</em> should return a web page containing “some text” inside an <code>h1</code> bloc.</p>
<p>For example, accessing <a href="http://localhost:3000/echo/some%20text"><code>http://localhost:3000/echo/some%20text</code></a>, should display “some text” in an %html web page.</p>
<p>First, we must declare URL of the form /echo/… are meaningful.</p>
2011-12-29 16:05:05 +00:00
<p>Lets take a look at the file <code>config/routes</code>:</p>
<pre class="twilight">
/static StaticR Static getStatic
/auth AuthR Auth getAuth
/favicon.ico FaviconR GET
/robots.txt RobotsR GET
/ RootR GET
</pre>
<p>We want to add a route of the form <code>/echo/[anything]</code> somehow and do some action with this.
We add the following:</p>
<pre>
/echo/#String EchoR GET
</pre>
<p>This line contains three elements: the <span class="sc">url</span> pattern, a handler name, an HTTP method.
I am not particularly fan of the big R in the end of handler names.
2012-01-02 14:39:00 +00:00
But this is the standard convention, then lets use it.</p>
2011-12-29 16:05:05 +00:00
2012-01-02 14:39:00 +00:00
<p>If you save <code>config/routes</code>, you should see your terminal in which you launched <code>yesod devel</code> activate and certainly displaying an error message.</p>
2011-12-29 16:05:05 +00:00
<pre>
Application.hs:31:1: Not in scope: `getEchoR'
</pre>
<p>Why? Simply because we didnt written the code for the handler <code>EchoR</code>.
Now, lets do this. Edit the file <code>Handler/Root.hs</code> and append this:</p>
<pre class="twilight">
<span class="Entity">getEchoR</span>&nbsp;:: <span class="Constant">String</span> &rarr; <span class="Constant">Handler</span> <span class="Constant">RepHtml</span>
getEchoR theText = <span class="Keyword">do</span>
defaultLayout $ <span class="Keyword">do</span>
[whamlet|&lt;h1&gt;#{theText}|]
</pre>
2012-01-02 14:39:00 +00:00
<p>Dont worry if you find all of this a bit cryptic.
This is normal when learning a new framework.
In short it just declare a function named getEchoR with one argument (<code>theText</code>) of type String.
When this function is called, it return a “Handler RepHtml” whatever it is.
But mainly this will encapsulate our expected result inside an HTML text.</p>
2011-12-29 16:05:05 +00:00
<p>After saving the file, you should see yesod recompile the application.
2012-01-02 14:39:00 +00:00
When the compilation is finished youll see the message: <code>Starting devel application</code>.</p>
<p>Now you can visit: <a href="http://localhost:3000/echo/Yesod%20rocks!"><code>http://localhost:3000/echo/Yesod%20rocks!</code></a></p>
2011-12-29 16:05:05 +00:00
<p>TADA! It works.</p>
2012-01-02 14:39:00 +00:00
<h3 id="secure">Secure?</h3>
<p>Lets try to attack our website by entering a text with special characters:</p>
2011-12-29 16:05:05 +00:00
2011-12-30 16:14:57 +00:00
<p><a href="http://localhost:3000/echo/&lt;a&gt;I'm &lt;script&gt;alert(&quot;Bad!&quot;);"><code>http://localhost:3000/echo/&lt;a&gt;I'm &lt;script&gt;alert("Bad!");</code></a></p>
2011-12-29 16:05:05 +00:00
2012-01-02 14:39:00 +00:00
<p>All should work better than expected.</p>
2011-12-29 16:05:05 +00:00
<p>The special characters are protected for us.
2012-01-02 14:39:00 +00:00
If you have a malicious user, he could not hide some bad script inside his login name for example.</p>
2011-12-29 16:05:05 +00:00
<p>This is a direct consequence of <em>type safety</em>.
The URL string is put inside a URL type.
Then the interesting part in the URL is put inside a String type. To pass from URL type to String type some transformation are made. For example, replace all “<code>%20</code>” by space characters.
Then to show the String inside an HTML document, the string is put inside an HTML type. Some transformations occurs like replace “<code>&lt;</code>” by “<code>&amp;lt;</code>”.
Thanks to yesod, most of tedious string transformation job is done for us.</p>
<pre class="twilight">
<span class="String"><span class="String">&quot;</span>http://localhost:3000/echo/some%20text&lt;a&gt;<span class="String">&quot;</span></span>&nbsp;:: URL
<span class="String"><span class="String">&quot;</span>some text&lt;a&gt;<span class="String">&quot;</span></span> &nbsp;:: String
<span class="String"><span class="String">&quot;</span>some text &amp;lt;a&amp;gt;<span class="String">&quot;</span></span> &nbsp;:: HTML
</pre>
<p>That was the first very minimal example, and we already
verified Yesod protect us from many common errors.</p>
2012-01-02 14:39:00 +00:00
<p>Then not only Yesod is fast, it is also relatively secure.</p>
2011-12-30 16:14:57 +00:00
<h2 id="cleaning-up">Cleaning up</h2>
2011-12-29 16:05:05 +00:00
2011-12-30 16:14:57 +00:00
<p>This first example was nice, but for simplicity reason we didnt used best practices.</p>
2011-12-29 16:05:05 +00:00
2011-12-30 16:14:57 +00:00
<p>First we will separate the handler code into different files.
2012-01-02 14:39:00 +00:00
After that we will use <code>Data.Text</code> instead of <code>String</code>.
Finally well use a template file to better separate our view.</p>
2011-12-29 16:05:05 +00:00
2011-12-30 16:14:57 +00:00
<h3 id="separate-handlers">Separate handlers</h3>
2011-12-29 16:05:05 +00:00
2011-12-30 16:14:57 +00:00
<p>In a first time create a new file <code>Handler/Echo.hs</code> containing:</p>
<pre class="twilight">
<span class="Keyword">module</span> <span class="Constant">Handler</span>.<span class="Constant">Echo</span> <span class="Keyword">where</span>
<span class="Keyword">import</span> <span class="Constant">Import</span>
<span class="Entity">getEchoR</span>&nbsp;:: <span class="Constant">String</span> &rarr; <span class="Constant">Handler</span> <span class="Constant">RepHtml</span>
getEchoR theText = <span class="Keyword">do</span>
defaultLayout $ <span class="Keyword">do</span>
[whamlet|&lt;h1&gt;#{theText}|]
</pre>
<p>Do not forget to remove the getEchoR function inside the <code>Handler/Root.hs</code> file.</p>
<p>We must declare the file inside the cabal configuration file <code>yosog.cabal</code>. Just after <code>Handler.Root</code> add:</p>
<pre>
Handler.Echo
</pre>
<p>We must also declare the new Handler module inside <code>Application.hs</code>.
Just after the “<code>import Handler.Root</code>”, add:</p>
<pre class="twilight">
<span class="Keyword">import</span> <span class="Constant">Handler</span>.<span class="Constant">Echo</span>
</pre>
<h3 id="use-datatext-instead-of-string">Use <code>Data.Text</code> instead of <code>String</code></h3>
<p>Now our handler is separated in another file.</p>
<p>But we used <code>String</code> but it is a good practice to use <code>Data.Text</code> instead.</p>
<p>To declare we will use <code>Data.Text</code> we modify the file <code>Foundation.hs</code>.
Add an import directive just after the last one:</p>
<pre class="twilight">
import Data.Text
</pre>
<p>And also we must modify <code>config/routes</code> and our handler accordingly. Replace <code>#String</code> by <code>#Text</code> in <code>config/routes</code>:</p>
<pre>
/echo/#Text EchoR GET
</pre>
<p>And do the same in <code>Handler/Echo.hs</code>:</p>
<div class="code"><div class="file"><a href="/Scratch/en/blog/Yesod-tutorial-for-newbies/code/Echo.hs"> &#x27A5; Echo.hs </a></div><div class="withfile">
<pre class="twilight">
<span class="Keyword">module</span> <span class="Constant">Handler</span>.<span class="Constant">Echo</span> <span class="Keyword">where</span>
<span class="Keyword">import</span> <span class="Constant">Import</span>
<span class="Entity">getEchoR</span>&nbsp;:: <span class="Constant">Text</span> &rarr; <span class="Constant">Handler</span> <span class="Constant">RepHtml</span>
getEchoR theText = <span class="Keyword">do</span>
defaultLayout $ <span class="Keyword">do</span>
[whamlet|&lt;h1&gt;#{theText}|]
</pre>
</div></div>
<h3 id="use-a-new-template-file">Use a new template file</h3>
<p>The last thing to change in order to do things like in
a real project is to use another template file.</p>
<p>Just create a new file <code>template/echo.hamlet</code> containing:</p>
<div class="code"><div class="file"><a href="/Scratch/en/blog/Yesod-tutorial-for-newbies/code/echo.hamlet"> &#x27A5; echo.hamlet </a></div><div class="withfile">
<pre class="twilight">
&lt;h1&gt; #{theText}
</pre>
</div></div>
<p>and modify the handler <code>Handler/Echo.hs</code>:</p>
<pre class="twilight">
<span class="Entity">getEchoR</span>&nbsp;:: <span class="Constant">Text</span> &rarr; <span class="Constant">Handler</span> <span class="Constant">RepHtml</span>
getEchoR theText = <span class="Keyword">do</span>
defaultLayout $ <span class="Keyword">do</span>
$(widgetFile <span class="String"><span class="String">&quot;</span>echo<span class="String">&quot;</span></span>)
</pre>
2011-12-29 16:05:05 +00:00
2012-01-02 14:39:00 +00:00
<p>At this point our code is clean.
Handler are grouped, we use <code>Data.Text</code> and our views are in templates.
It is now time to make a slightly more complex example.</p>
2011-12-29 16:05:05 +00:00
<h2 id="protected-input">Protected input</h2>
2012-01-02 14:39:00 +00:00
<p>Lets make another minimal application.
You should see a form containing a Text Field and a validation button.
When you click, the next page present you the content you entered in the field.</p>
<p>First, add a new route:</p>
<pre class="twilight">
/new NewR GET POST
</pre>
<p>This time the path /new will accept GET and POST requests. Add the corresponding new Handler file:</p>
<div class="code"><div class="file"><a href="/Scratch/en/blog/Yesod-tutorial-for-newbies/code/New.hs"> &#x27A5; New.hs </a></div><div class="withfile">
<pre class="twilight">
<span class="Keyword">module</span> <span class="Constant">Handler</span>.<span class="Constant">New</span> <span class="Keyword">where</span>
<span class="Keyword">import</span> <span class="Constant">Import</span>
<span class="Entity">getNewR</span>&nbsp;:: <span class="Constant">Handler</span> <span class="Constant">RepHtml</span>
getNewR = <span class="Keyword">do</span>
defaultLayout $ <span class="Keyword">do</span>
$(widgetFile <span class="String"><span class="String">&quot;</span>new<span class="String">&quot;</span></span>)
<span class="Entity">postNewR</span>&nbsp;:: <span class="Constant">Handler</span> <span class="Constant">RepHtml</span>
postNewR = <span class="Keyword">do</span>
postedText &larr; runInputPost $ ireq textField <span class="String"><span class="String">&quot;</span>content<span class="String">&quot;</span></span>
defaultLayout $ <span class="Keyword">do</span>
$(widgetFile <span class="String"><span class="String">&quot;</span>posted<span class="String">&quot;</span></span>)
</pre>
</div></div>
<p>Dont forget to declare it inside <code>yosog.cabal</code> and <code>Application.hs</code>.</p>
<p>The only new thing here is the line that get the POST parameter named “content”.
If you want to know more detail about it and form in general you can take look at <a href="http://www.yesodweb.com/book/forms">the yesod book</a>.</p>
<p>Create the two corresponding templates:</p>
<div class="code"><div class="file"><a href="/Scratch/en/blog/Yesod-tutorial-for-newbies/code/new.hamlet"> &#x27A5; new.hamlet </a></div><div class="withfile">
<pre class="twilight">
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">h1</span><span class="MetaTagAll">&gt;</span></span> Enter your text
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">form</span> <span class="MetaTagAll">method</span>=<span class="MetaTagAll">post</span> <span class="MetaTagAll">action</span>=@<span class="EmbeddedSource">{NewR}</span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagInline"><span class="MetaTagInline">&lt;</span><span class="MetaTagInline">input</span> <span class="MetaTagInline">type</span>=<span class="MetaTagInline">text</span> <span class="MetaTagInline">name</span>=<span class="MetaTagInline">content</span><span class="MetaTagInline">&gt;</span></span>
<span class="MetaTagInline"><span class="MetaTagInline">&lt;</span><span class="MetaTagInline">input</span> <span class="MetaTagInline">type</span>=<span class="MetaTagInline">submit</span><span class="MetaTagInline">&gt;</span></span>
</pre>
</div></div>
<div class="code"><div class="file"><a href="/Scratch/en/blog/Yesod-tutorial-for-newbies/code/posted.hamlet"> &#x27A5; posted.hamlet </a></div><div class="withfile">
<pre class="twilight">
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">h1</span><span class="MetaTagAll">&gt;</span></span>You've just posted
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">p</span><span class="MetaTagAll">&gt;</span></span>#<span class="EmbeddedSource">{postedText}</span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">hr</span><span class="MetaTagAll">&gt;</span></span>
<span class="MetaTagAll"><span class="MetaTagAll">&lt;</span><span class="MetaTagAll">p</span><span class="MetaTagAll">&gt;</span></span><span class="MetaTagInline"><span class="MetaTagInline">&lt;</span><span class="MetaTagInline">a</span> <span class="MetaTagInline">href</span>=@<span class="EmbeddedSource">{NewR}</span><span class="MetaTagInline">&gt;</span></span>Get back
</pre>
</div></div>
<p>And that is all.</p>
2011-12-29 16:05:05 +00:00
<hr />
<div style="background-color: #800; color: #FFF; font-weight: bold; border: 2px solid #300; box-shadow: 0 0 60px #300 inset;padding-left: 2em;">
<h2 style="margin: 0 auto; text-align: center">TODO</h2>
<ul>
<li> Display something, show it is protected.
</li><li> Make the same as before, but with an input.
</li><li> Create a minimal blog system.
</li><li> Change template to html5 boilerplate.
</li><li> Use Authentification.
</li>
</ul>
</div>
</div>
<div id="choixrss">
<a id="rss" href="http://feeds.feedburner.com/yannespositocomen">
Subscribe
</a>
</div>
<script type="text/javascript">
$(document).ready(function(){
$('#comment').hide();
$('#clickcomment').click(showComments);
});
function showComments() {
$('#comment').show();
$('#clickcomment').fadeOut();
}
document.write('<div id="clickcomment">Comments</div>');
</script>
<div class="flush"></div>
<div class="corps" id="comment">
<h2 class="first">comments</h2>
<noscript>
You must enable javascript to comment.
</noscript>
<script type="text/javascript">
var idcomments_acct = 'a307f0044511ff1b5cfca573fc0a52e7';
var idcomments_post_id = '/Scratch/en/blog/Yesod-tutorial-for-newbies/';
var idcomments_post_url = 'http://yannesposito.com/Scratch/en/blog/Yesod-tutorial-for-newbies/';
</script>
<span id="IDCommentsPostTitle" style="display:none"></span>
<script type='text/javascript' src='/Scratch/js/genericCommentWrapperV2.js'></script>
</div>
<div id="entete" class="corps_spaced">
<div id="liens">
<ul><li><a href="/Scratch/en/">Home</a></li>
<li><a href="/Scratch/en/blog/">Blog</a></li>
<li><a href="/Scratch/en/softwares/">Softwares</a></li>
<li><a href="/Scratch/en/about/">About</a></li></ul>
</div>
<div class="flush"></div>
<hr/>
<div id="next_before_articles">
<div id="previous_articles">
previous entries
<div class="previous_article">
<a href="/Scratch/en/blog/SVG-and-m4-fractals/"><span class="nicer">«</span>&nbsp;Increase the power of deficient languages.</a>
</div>
<div class="previous_article">
<a href="/Scratch/en/blog/Yesod-excellent-ideas/"><span class="nicer">«</span>&nbsp;Yesod excellent ideas</a>
</div>
<div class="previous_article">
<a href="/Scratch/en/blog/programming-language-experience/"><span class="nicer">«</span>&nbsp;Programming Language Experience</a>
</div>
</div>
<div id="next_articles">
next entries
</div>
<div class="flush"></div>
</div>
</div>
<div id="bottom">
<div>
<a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Copyright ©, Yann Esposito</a>
</div>
<div id="lastmod">
Created: 12/28/2011
2012-01-02 14:39:00 +00:00
Modified: 12/30/2011
2011-12-29 16:05:05 +00:00
</div>
<div>
Entirely done with
<a href="http://www.vim.org">Vim</a>
and
<a href="http://nanoc.stoneship.org">nanoc</a>
</div>
<div>
<a href="/Scratch/en/validation/">Validation</a>
<a href="http://validator.w3.org/check?uri=referer"> [xhtml] </a>
.
<a href="http://jigsaw.w3.org/css-validator/check/referer?profile=css3"> [css] </a>
.
<a href="http://validator.w3.org/feed/check.cgi?url=http%3A//yannesposito.com/Scratch/en/blog/feed/feed.xml">[rss]</a>
</div>
</div>
<div class="clear"></div>
</div>
</body>
</html>