@@ -0,0 +1,168 @@
1+---
2+title: How to write pages
3+what: elaborates a little on writing pages and templates
4+---
5+
6+## The structure of a Page
7+
8+The most important thing to realize is that a page is reduced to a `Context`,
9+and therefore is just a key-value mapping. Another example:
10+
11+ ---
12+ title: About
13+ author: Mia Wallace
14+ ---
15+ Hello there! This is
16+ a simple about page.
17+
18+This will produce the following mapping:
19+
20+- `$title`: About
21+- `$author`: Mia Wallace
22+- `$body`: Hello there! This is a simple about page.
23+
24+`$body` is the traditional name for the main body part of a page. If the page
25+has a `.markdown` extension for example, this would also be rendered by pandoc.
26+But pages are more flexible. The following is also a valid page:
27+
28+ Hello there! This is
29+ a simple about page.
30+
31+This will produce one key-value pair:
32+
33+- `$body`: Hello there! This is a simple about page.
34+
35+But Hakyll can do more than this. You can add extra sections, apart from the
36+body, and even leave out the body.
37+
38+ ---
39+ author: Vincent Vega
40+
41+ --- prelude
42+ A small introduction goes here. I can write *markdown*
43+ here, by the way. Well, assuming this page has a
44+ `.markdown` extension.
45+
46+ --- main
47+ I can write some more things here.
48+
49+ ---
50+ The body comes last, and is optional.
51+
52+This will produce the following:
53+
54+- `$author`: Vincent Vega
55+- `$prelude`: A small introduction goes here. I can write *markdown* here, by the
56+ way. Well, assuming this page has a `.markdown` extension.
57+- `$main`: I can write some more things here.
58+- `$body`: The body comes last, and is optional.
59+
60+The example from this tutorial (we will see later) uses this to build a
61+three-column system for the website, separating content from layout.
62+
63+## Combining Contexts
64+
65+Now you know that pages, and `Context`s in general, are basically nothing more
66+than key-values mappings, it is time to abuse this fact. There is another
67+way to create a `Context`, called `combine`.
68+
69+The type signature of the `combine` function does a pretty good job at
70+explaining it:
71+
72+~~~~~{.haskell}
73+combine :: HakyllAction () Context
74+ -> HakyllAction () Context
75+ -> HakyllAction () Context
76+~~~~~
77+
78+This means we can take two `Context`s values and combine them. This is
79+basically a `Map.union`: The result will contain all keys from both `Context`s,
80+with there corresponding values. If a key is present in both `Context`s, the
81+value from the first argument will be chosen. This is, for example, almost
82+always the case with the `$url` field (since almost all `Context`s have an url
83+in Hakyll).
84+
85+Combining two `Context`s, but overriding the `$url` is quite common, so there is
86+another function that helps us here:
87+
88+~~~~~{.haskell}
89+combineWithUrl :: FilePath
90+ -> HakyllAction () Context
91+ -> HakyllAction () Context
92+ -> HakyllAction () Context
93+~~~~~
94+
95+## The example
96+
97+Now that we have the tools, we'll get on to the example. This time, we'll
98+be making a more advanced brochure site. Here [is a zip file] containing the
99+source code for the tutorial.
100+
101+[is a zip file]: examples/morepages.zip
102+
103+Every page consists of three sections, originally named `section1`, `section2`
104+and `section3`. So our pages look more or less like this:
105+
106+ ---
107+ title: About
108+
109+ --- section1
110+ ## Mattis
111+ Nullam imperdiet sodales orci vitae molestie. Nunc...
112+
113+ --- section2
114+ ## Orci
115+ Vivamus eget mauris sit amet nulla laoreet lobortis.
116+ Nulla in...
117+
118+ --- section3
119+ ## Augue
120+ In urna ante, pulvinar et imperdiet nec, fermentum ac...
121+
122+The cool thing is we do not have to specify how these will be layed out. In our
123+template, we decide to use a simple three column system:
124+
125+~~~~~{.html}
126+<div class="column"> $section1 </div>
127+<div class="column"> $section2 </div>
128+<div class="column"> $section3 </div>
129+~~~~~
130+
131+The columns are then floated using css. So far so good, but what if we wanted
132+an additional text block on every page? An easy solution would be to add this
133+to the template, but then our layout-content separation idea will be broken
134+again. So we simply add to the template:
135+
136+~~~~~{.html}
137+<div class="footer"> $footer </div>
138+~~~~~
139+
140+And now we will use `combine` to put the footer on every page - so we need to
141+add the footer page to every `Context`. We write a small auxiliary function
142+that combines a given `Context` with the footer:
143+
144+~~~~~{.haskell}
145+withFooter = flip combine $ createPage "footer.markdown"
146+~~~~~
147+
148+Note that we use `flip` here - we want `footer.markdown` to be our second
149+argument. That is because Hakyll will take the `$url` from the first `Context`,
150+so all pages would be rendered to `footer.html` - obviously not what we want.
151+Now, were we previously wrote:
152+
153+~~~~~{.haskell}
154+render "about.markdown"
155+where render = renderChain ["templates/default.html"]
156+ . createPage
157+~~~~~
158+
159+We simply have to add our footer:
160+
161+~~~~~{.haskell}
162+render "about.markdown"
163+where render = renderChain ["templates/default.html"]
164+ . withFooter
165+ . createPage
166+~~~~~
167+
168+And now every page will include the footer.