on master help sign in
Finish first tutorial... I think
commitcb79c45d040f38b6d49abf2298250c19e5d9cea7 authorJasper Van der Jeugt <m@jaspervdj.be> dateSat 15 Dec 2012, 18:17 (14 years ago) parente633df1
2 files changed+43−233
web/tutorials/02-basics.markdown+31−233 web/tutorials/03-compilers.markdown+12
web/tutorials/02-basics.markdown+31−233
@@ -86,248 +86,46 @@ more customization. You want to route `contact.markdown` to
8686customRoute $ reverse . toFilePath
8787```
8888
89+Basic compilers
90+---------------
91+
8992More information can be found in the [Routes] module.
9093
9194[Routes]: /reference/Hakyll-Core-Routes.html
9295
93−## Images
94−
95−Let's start of with the `images/haskell-logo.png` file, because the processing
96−of this file is very simple: it is simply copied to the output directory. Let's
97−look at the relevant lines in the `hakyll.hs` file:
98−
99−~~~~~{.haskell}
100−match "images/*" $ do
101− route idRoute
102− compile copyFileCompiler
103−~~~~~
104−
105−The first line specifies we will describe the process for compiling everything
106−in the `images/` folder: hakyll uses globs for this [^pattern].
107−
108−[^pattern]: A little caveat is that these globs are not `String`s but
109− `Pattern`s, so you need the `OverloadedStrings` extension.
110−
111−We can see two simple rules next: [route] and [compile].
112−
113−- [route] determines how the input file(s) get mapped to the output files.
114− [route] only deals with file names -- not with the actual content!
115−- [compile], on the other hand, determines how the file content is processed.
116−
117−[route]: /reference/Hakyll-Core-Rules.html#v:route
118−[compile]: /reference/Hakyll-Core-Rules.html#v:compile
119−
120−In this case, we select the [idRoute]: which means the file name will be kept
121−the same (`_site` will always be prepended automatically). This explains the
122−name of [idRoute]: much like the `id` function in Haskell, it also maps values
123−to themselves.
124−
125−[idRoute]: /reference/Hakyll-Core-Routes.html#v:idRoute
126−
127−For our compiler, we use [copyFileCompiler], meaning that we don't process the
128−content at all, we just copy the file.
129−
130−[copyFileCompiler]: /reference/Hakyll-Core-Writable-CopyFile.html#v:copyFileCompiler
131−
132−## CSS
133−
134−If we look at how the two CSS files are processed, we see something which looks
135−very familiar:
136−
137−~~~~~{.haskell}
138−match "css/*" $ do
139− route idRoute
140− compile compressCssCompiler
141−~~~~~
142−
143−Indeed, the only difference with the images is that have now chosen for
144−[compressCssCompiler] -- a compiler which *does* process the content. Let's have
145−a quick look at the type of [compressCssCompiler]:
146−
147−[compressCssCompiler]: /reference/Hakyll-Web-CompressCss.html#v:compressCssCompiler
148−
149−~~~~~{.haskell}
150−compressCssCompiler :: Compiler Resource String
151−~~~~~
152−
153−Intuitively, we can see this as a process which takes a `Resource` and produces
154−a `String`.
155−
156−- A `Resource` is simply the Hakyll representation of an item -- usually just a
157− file on the disk.
158−- The produced string is the processed CSS.
159−
160−We can wonder what Hakyll does with the resulting `String`. Well, it simply
161−writes this to the file specified in the `route`! As you can see, routes and
162−compilers work together to produce your site.
163−
164−## Templates
165−
166−Next, we can see that the templates are compiled:
167−
168−~~~~~{.haskell}
169−match "templates/*" $ compile templateCompiler
170−~~~~~
171−
172−Let's start with the basics: what is a template? An example template gives us a
173−good impression:
174−
175−~~~~~
176−<html>
177− <head>
178− <title>Hakyll Example - $$title$$</title>
179− </head>
180− <body>
181− <h1>$$title$$</h1>
182−
183− $$body$$
184− </body>
185−</html>
186−~~~~~
187−
188−A template is a text file to lay out some content. The content it lays out is
189−called a page -- we'll see that in the next section. The syntax for templates is
190−intentionally very simplistic. You can bind some content by referencing the name
191−of the content *field* by using `$$field$$`, and that's it.
192−
193−You might have noticed how we specify a compiler (`compile`), but we don't set
194−any `route`. Why is this?
195−
196−We need to compile the template because we will need it later. If we compile a
197−page later using `templates/default.html`, Hakyll needs to know what
198−`templates/default.html` is. Note that we could move template compilation to the
199−bottom of our code. The order doesn't matter -- Hakyll will determine that for
200−you. But if you don't compile `templates/default.html` as a template, Hakyll
201−will not be able to take it into account when deciding the compilation order.
96+The `compile` function determines how the content is produced for a certain
97+item. `compile` takes a value of the type `Compiler (Item a)`. Let's look at
98+some common examples:
20299
203−So, the `compile` needs to be there -- but why don't we set a `route` here?
204−Precisely because we don't want to our template to end up anywhere in our site
205−directory! We want to use it to lay out other items -- so we need to load
206−(compile) it, but we don't want to give it a real destination.
100+- `copyFileCompiler` is self-explanatory, the output is exactly the same as the
101+ input;
102+- `compressCssCompiler` performs some simple build-in compression
103+ transformations for CSS;
104+- `pandocCompiler` reads markdown, reStructuredText, or another input format and
105+ renders it as HTML (if you want to pass specific options to pandoc, use
106+ `pandocCompilerWith`).
207107
208−By using the `templates/*` pattern, we compile all templates in one go.
108+Compilers are very flexible: `Compiler` is a [Monad] and `Item` is a [Functor].
209109
210−## Pages
110+[Monad]: http://learnyouahaskell.com/a-fistful-of-monads
111+[Functor]: http://learnyouahaskell.com/functors-applicative-functors-and-monoids
211112
212−The code for pages looks suspiciously more complicated:
113+A good example to illustrate the `Monad` instance for `Compiler` is
213114
214−~~~~~~{.haskell}
215−match (list ["about.rst", "index.markdown", "code.lhs"]) $ do
216− route $ setExtension "html"
217− compile $ pageCompiler
218− >>> applyTemplateCompiler "templates/default.html"
219− >>> relativizeUrlsCompiler
220−~~~~~~
221−
222−But we'll see shortly that this actually fairly straightforward. Let's begin by
223−exploring what a *page* is.
224−
225−~~~~~~
226−---
227−title: Home
228−author: Jasper
229−---
230−
231−So, I decided to create a site using Hakyll and...
232−~~~~~~
233−
234−A page consists of two parts: a body, and metadata. As you can see above, the
235−syntax is not hard. The metadata part is completely optional, this is the same
236−page without metadata:
237−
238−~~~~~~
239−So, I decided to create a site using Hakyll and...
240−~~~~~~
241−
242−Hakyll supports a number of formats for the page body. Markdown, HTML and RST
243−are probably the most common. Hakyll will automatically guess the right format
244−if you use the right extension for your page.
245−
246−~~~~~~{.haskell}
247−match (list ["about.rst", "index.markdown", "code.lhs"]) $ do
248−~~~~~~
249−
250−We see a more complicated pattern here. Some sets of files cannot be described
251−easily by just one pattern, and here the [list] function can help us out. In
252−this case, we have three specific pages we want to compile.
253−
254−[list]: /reference/Hakyll-Core-Identifier-Pattern.html#v:list
255−
256−~~~~~~{.haskell}
257−route $ setExtension "html"
258−~~~~~~
259−
260−For our pages, we do not want to use `idRoute` -- after all, we want to generate
261−`.html` files, not `.markdown` files or something similar! The [setExtension]
262−route allows you to simply replace the extension of an item, which is what we
263−want here.
264−
265−[setExtension]: /reference/Hakyll-Core-Routes.html#v:setExtension
266−
267−~~~~~~{.haskell}
268−compile $ pageCompiler
269− >>> applyTemplateCompiler "templates/default.html"
270− >>> relativizeUrlsCompiler
271−~~~~~~
272−
273−How should we process these pages? [pageCompiler] is the default compiler for
274−pages. [pageCompiler] does a few things:
275−
276−- It parses the page into body and metadata
277−- It adds some extra metadata fields such as `$$url$$` and `$$path$$` (you
278− shouldn't worry about these for now)
279−- It fill in possible `$$key$$`'s in it's own body
280−- It renders the page using pandoc
281−
282−Which basically means that we end up with a `Page` that has the HTML content we
283−want as body. But we don't just want the plain content on our website -- we want
284−to decorate it with a template, for starters.
285−
286−[pageCompiler]: /reference/Hakyll-Web-Page.html#v:pageCompiler
287−
288−Different compilers can be chained in a pipeline-like way using Arrows. Arrows
289−form a complicated subject, but fortunately, most Hakyll users need not be
290−concerned with the details. If you are interested, you can find some information
291−on the [Understanding arrows] page -- but the only thing you really *need* to
292−know is that you can chain compilers using the `>>>` operator.
293−
294−[Understanding arrows]: http://en.wikibooks.org/wiki/Haskell/Understanding_arrows
295−
296−The `>>>` operator is a lot like a flipped function composition (`flip (.)`) in
297−Haskell, with the important difference that `>>>` is more general and works on
298−all Arrows -- including Hakyll compilers.
299−
300−Here, we apply three compilers sequentially:
301−
302−1. We load and render the page using `pageCompiler`
303−2. We apply the template we previously loaded using [applyTemplateCompiler]
304−3. We relativize the URL's on the page using [relativizeUrlsCompiler]
305−
306−[applyTemplateCompiler]: /reference/Hakyll-Web-Template.html#v:applyTemplateCompiler
307−[relativizeUrlsCompiler]: /reference/Hakyll-Web-RelativizeUrls.html#v:relativizeUrlsCompiler
308−
309−Relativizing URL's is a very handy feature. It means that we can just use
310−absolute URL's everywhere in our templates and code, e.g.:
311−
312−~~~~~{.haskell}
313−<link rel="stylesheet" type="text/css" href="/css/default.css" />
314−~~~~~
315−
316−Using the [relativizeUrlsCompiler], Hakyll will change this to:
317−
318−~~~~~{.haskell}
319−<link rel="stylesheet" type="text/css" href="css/default.css" />
320−~~~~~
321−
322−when we are compiling `index.html`, or
115+```haskell
116+relativizeUrls :: Item String -> Compiler (Item String)
117+```
323118
324−~~~~~{.haskell}
325−<link rel="stylesheet" type="text/css" href="../css/default.css" />
326−~~~~~
119+This compiler traverses your HTML and changes absolute URLs (e.g.
120+`/posts/foo.markdown` into relative ones: `../posts/foo.markdown`). This is
121+extremely useful if you want to deploy your site in a subdirectory (e.g.
122+`jaspervdj.be/hakyll` instead of `jaspervdj.be`). Combining this with the
123+`pandocCompiler` gives us:
327124
328−when we are compiling (some imaginary) `posts/foo.html`. So Hakyll will
329−translate this to a relative URL for each page. This means we can host our site
330−at `example.com` and `example.com/subdir` without changing a single line of
331−code.
125+```haskell
126+pandocCompiler >>= relativizeUrls :: Compiler (Item String)
127+```
332128
333−More tutorials are in the works...
129+For a real website, you probably also want to use templates in order to give
130+your pages produced by pandoc a nice layout. We tackle this in the next
131+tutorial.
web/tutorials/03-compilers.markdownnew file+12
@@ -0,0 +1,12 @@
1+---
2+title: Using and writing Compilers
3+author: Jasper Van der Jeugt
4+---
5+
6+Identifier, Item, Compiler
7+--------------------------
8+
9+Three important, related types are `Identifier`, `Item` and `Compiler`.
10+
11+- `Identifier` is a string-like value which uniquely identifies a single item
12+ for your webpage