on master help sign in
Added a category tutorial.
commit340b87899dfd1b4cc223777991593444be76ad02 authorJasper Van der Jeugt <jaspervdj@gmail.com> dateFri 29 Jan 2010, 18:36 (17 years ago) parentc49cc9a
5 files changed+97−4
examples/categoryblog/hakyll.hs+4−4 examples/hakyll/css/default.css+6 examples/hakyll/images/tutorial6-categories.png examples/hakyll/images/tutorial6-tags.png examples/hakyll/tutorial6.markdown+87
examples/categoryblog/hakyll.hs+4−4
@@ -2,12 +2,11 @@ module Main where
22
33import Text.Hakyll (hakyll)
44import Text.Hakyll.Render
5−import Text.Hakyll.Tags (readCategoryMap)
6−import Text.Hakyll.File (getRecursiveContents, directory, removeSpaces)
5+import Text.Hakyll.Tags (TagMap, readCategoryMap)
6+import Text.Hakyll.File (getRecursiveContents, directory, removeSpaces, sortByBaseName)
77import Text.Hakyll.Renderables (createPagePath, createCustomPage, createListingWith, createListing)
88import Text.Hakyll.Context (ContextManipulation, renderDate)
99import Text.Hakyll.Util (link)
10−import Data.List (sort)
1110import Data.Map (toList)
1211import Control.Monad (mapM_, liftM, (<=<))
1312import Data.Either (Either(..))
@@ -17,7 +16,7 @@ main = hakyll $ do
1716 directory css "css"
1817
1918 -- Find all post paths.
20− postPaths <- liftM (reverse . sort) $ getRecursiveContents "posts"
19+ postPaths <- liftM (reverse . sortByBaseName) $ getRecursiveContents "posts"
2120 let renderablePosts = map createPagePath postPaths
2221
2322 -- Read category map.
@@ -54,6 +53,7 @@ main = hakyll $ do
5453
5554 categoryToURL category = "$root/categories/" ++ removeSpaces category ++ ".html"
5655
56+ categoryList :: TagMap -> String
5757 categoryList = uncurry categoryListItem <=< toList
5858
5959 categoryListItem category posts = "<li>" ++ link category (categoryToURL category)
examples/hakyll/css/default.css+6
@@ -83,6 +83,12 @@ div.column p {
8383 padding-right: 15px;
8484}
8585
86+img {
87+ display: block;
88+ margin: 10px auto 10px auto;
89+ border: none;
90+}
91+
8692ul {
8793 list-style-type: square;
8894 padding-left: 1em;
examples/hakyll/images/tutorial6-categories.pngnew file

Binary file not shown.

examples/hakyll/images/tutorial6-tags.pngnew file

Binary file not shown.

examples/hakyll/tutorial6.markdownnew file+87
@@ -0,0 +1,87 @@
1+---
2+title: Tutorial (Part VI)
3+what: explains how to use categories instead of tags
4+---
5+
6+## Categories
7+
8+Most people familiar with "tags" will also know the concept "categories".
9+
10+![Tags illustration]($root/images/tutorial6-tags.png)
11+
12+In fact, tags are harder to implement because they have to be represented as a
13+many-to-many relation, and categories are a simple 1-to-many relation.
14+
15+![Tags illustration]($root/images/tutorial6-categories.png)
16+
17+This is also the reason you can "simulate" categories using tags. In this
18+tutorial we will adapt the blog to use categories instead of tags. Here is
19+[a zip file](examples/categoryblog.zip) containing the files used in this
20+tutorial.
21+
22+## Reading Categories
23+
24+Tags are located in the `tags` metadata field. Since one post can only belong
25+in one category, a different approach was chosen here. The category of a post
26+is determined by the subfolder it is in. Here you see the directory layout for
27+our posts using categories:
28+
29+ posts
30+ |-- coding
31+ | |-- 2009-11-05-a-first-post.markdown
32+ | |-- 2009-11-28-a-third-post.markdown
33+ | `-- 2009-12-04-this-blog-aint-dead.markdown
34+ `-- random
35+ |-- 2009-11-10-another-post.markdown
36+ `-- 2009-12-23-almost-christmas.markdown
37+
38+Because we find all our posts in different subdirectories, sorting them is a
39+little harder: we still want them sorted by date, so it boils down to sorting
40+them by "base name". I hope it does not surprise you Hakyll provides a function
41+for that:
42+
43+~~~~~{.haskell}
44+postPaths <- liftM (reverse . sortByBaseName)
45+ (getRecursiveContents "posts")
46+~~~~~
47+
48+Now, we can use the `readCategoryMap` function instead of `readTagMap`, which
49+has the same signature, but assigns categories based on the folders the posts
50+are in.
51+
52+~~~~~{.haskell}
53+categoryMap <- readCategoryMap "categoryMap" renderablePosts
54+~~~~~
55+
56+The rest of the `hakyll.hs` is very similar to the one in the previous
57+tutorial, except we want to render a category list instead of a tag cloud.
58+
59+## Rendering a category list
60+
61+Because rendering a category list is quite easy, and it would be hard to
62+write a "general" function for this, hakyll does not provide such a function -
63+but it is not hard to write. First, we write an auxiliary function that produces
64+a list item for one category:
65+
66+~~~~~{.haskell}
67+categoryListItem category posts =
68+ "<li>" ++ link category (categoryToURL category)
69+ ++ " - " ++ show (length posts) ++ " items.</li>"
70+~~~~~
71+
72+This is nothing more that some string concatenation. The function that applies
73+this on every element in the `TagMap` is more interesting:
74+
75+~~~~~{.haskell}
76+categoryList :: TagMap -> String
77+categoryList = uncurry categoryListItem <=< toList
78+~~~~~
79+
80+This function might seem a little harder to understand, and figuring out how it
81+works is left as an exercise for the reader[^1].
82+
83+[^1]: Hint: `>>=` is `concatMap` in the list monad.
84+
85+We then add this to our index page, and we are done. Feel free to hack around
86+with the source code. If you still have questions, feel free to ask them at the
87+[google discussion group](http://groups.google.com/group/hakyll).