From 699bd0011e9771cd5c03c65aec0ec79656c475a1 Mon Sep 17 00:00:00 2001 From: Jasper Van der Jeugt Date: Fri, 8 Jan 2010 12:41:58 +0100 Subject: [PATCH] Added tagblog example (tutorial coming up). --- examples/rssblog/hakyll.hs | 6 ++ examples/tagblog/css/default.css | 17 +++++ examples/tagblog/hakyll.hs | 69 +++++++++++++++++++ examples/tagblog/index.html | 14 ++++ examples/tagblog/posts.html | 4 ++ .../posts/2009-11-05-a-first-post.markdown | 21 ++++++ .../posts/2009-11-10-another-post.markdown | 15 ++++ .../posts/2009-11-28-a-third-post.markdown | 19 +++++ .../2009-12-04-this-blog-aint-dead.markdown | 12 ++++ .../2009-12-23-almost-christmas.markdown | 13 ++++ examples/tagblog/templates/default.html | 22 ++++++ examples/tagblog/templates/post.html | 5 ++ examples/tagblog/templates/postitem.html | 4 ++ examples/tagblog/templates/rss.xml | 9 +++ examples/tagblog/templates/rssitem.xml | 5 ++ src/Text/Hakyll/File.hs | 18 ++++- src/Text/Hakyll/Tags.hs | 3 +- 17 files changed, 253 insertions(+), 3 deletions(-) create mode 100644 examples/tagblog/css/default.css create mode 100644 examples/tagblog/hakyll.hs create mode 100644 examples/tagblog/index.html create mode 100644 examples/tagblog/posts.html create mode 100644 examples/tagblog/posts/2009-11-05-a-first-post.markdown create mode 100644 examples/tagblog/posts/2009-11-10-another-post.markdown create mode 100644 examples/tagblog/posts/2009-11-28-a-third-post.markdown create mode 100644 examples/tagblog/posts/2009-12-04-this-blog-aint-dead.markdown create mode 100644 examples/tagblog/posts/2009-12-23-almost-christmas.markdown create mode 100644 examples/tagblog/templates/default.html create mode 100644 examples/tagblog/templates/post.html create mode 100644 examples/tagblog/templates/postitem.html create mode 100644 examples/tagblog/templates/rss.xml create mode 100644 examples/tagblog/templates/rssitem.xml diff --git a/examples/rssblog/hakyll.hs b/examples/rssblog/hakyll.hs index 7ed1b8e..a0984c8 100644 --- a/examples/rssblog/hakyll.hs +++ b/examples/rssblog/hakyll.hs @@ -16,6 +16,12 @@ main = hakyll $ do postPaths <- liftM (reverse . sort) $ getRecursiveContents "posts" let renderablePosts = map createPagePath postPaths + -- Render index, including recent posts. + let recentPosts = renderAndConcat "templates/postitem.html" $ take 3 renderablePosts + renderChain ["index.html", "templates/default.html"] $ + createCustomPage "index.html" ("templates/postitem.html" : take 3 postPaths) + [("title", Left "Home"), ("posts", Right recentPosts)] + -- Render all posts list. let postItems = renderAndConcat "templates/postitem.html" $ renderablePosts renderChain ["posts.html", "templates/default.html"] $ diff --git a/examples/tagblog/css/default.css b/examples/tagblog/css/default.css new file mode 100644 index 0000000..9ed2b01 --- /dev/null +++ b/examples/tagblog/css/default.css @@ -0,0 +1,17 @@ +body { + width: 600px; + margin: 0px auto 0px auto; +} + +div#navigation { + text-align: center; + border-bottom: 4px solid black; +} + +div#navigation a { + color: white; + text-decoration: none; + background-color: black; + padding: 3px 10px 3px 10px; + margin: 0px 10px 0px 10px; +} diff --git a/examples/tagblog/hakyll.hs b/examples/tagblog/hakyll.hs new file mode 100644 index 0000000..330ba3b --- /dev/null +++ b/examples/tagblog/hakyll.hs @@ -0,0 +1,69 @@ +module Main where + +import Text.Hakyll (hakyll) +import Text.Hakyll.Render +import Text.Hakyll.Tags (readTagMap, renderTagCloud, renderTagLinks) +import Text.Hakyll.File (getRecursiveContents, directory, removeSpaces) +import Text.Hakyll.Renderables (createPagePath, createCustomPage) +import Text.Hakyll.Context (ContextManipulation, renderDate) +import Data.List (sort) +import Data.Map (toList) +import Control.Monad (mapM_, liftM) +import Data.Either (Either(..)) + +main = hakyll $ do + -- Static directory. + directory css "css" + + -- Find all post paths. + postPaths <- liftM (reverse . sort) $ getRecursiveContents "posts" + let renderablePosts = map createPagePath postPaths + + -- Read tag map. + tagMap <- readTagMap postPaths + + -- Render all posts list. + renderPostList "posts.html" "All posts" postPaths + + -- Render post list per tag + mapM_ (\(tag, posts) -> renderPostList (tagToURL tag) ("Posts tagged " ++ tag) posts) + (toList tagMap) + + -- Render index, including recent posts. + let recentPosts = renderAndConcatWith postManipulation + "templates/postitem.html" + (take 3 renderablePosts) + renderChain ["index.html", "templates/default.html"] $ + createCustomPage "index.html" ("templates/postitem.html" : take 3 postPaths) + [("title", Left "Home"), ("posts", Right recentPosts)] + + -- Render all posts. + mapM_ (renderChainWith postManipulation + ["templates/post.html" + ,"templates/default.html" + ]) renderablePosts + + -- Render rss feed + let recentRSSItems = renderAndConcat "templates/rssitem.xml" $ take 3 renderablePosts + let rssPage = createCustomPage "rss.xml" + ("templates/postitem.html" : take 3 postPaths) + [("items", Right recentRSSItems)] + renderChain ["templates/rss.xml"] rssPage + + -- Render index. + renderChain ["templates/default.html"] $ createPagePath "index.html" + + where postManipulation :: ContextManipulation + postManipulation = renderDate "date" "%B %e, %Y" "Date unknown" + . renderTagLinks tagToURL + + tagToURL tag = "/tags/" ++ removeSpaces tag ++ ".html" + + renderPostList url title posts = do + let postItems = renderAndConcatWith postManipulation + "templates/postitem.html" + (map createPagePath posts) + customPage = createCustomPage url + ("templates/postitem.html" : posts) + [("title", Left title), ("posts", Right postItems)] + renderChain ["posts.html", "templates/default.html"] customPage diff --git a/examples/tagblog/index.html b/examples/tagblog/index.html new file mode 100644 index 0000000..e628bd6 --- /dev/null +++ b/examples/tagblog/index.html @@ -0,0 +1,14 @@ +
+

Recent posts

+ + All posts... +
+ +
+

About

+

+ This is a sample blog for educational purposes. +

+
diff --git a/examples/tagblog/posts.html b/examples/tagblog/posts.html new file mode 100644 index 0000000..ef86c40 --- /dev/null +++ b/examples/tagblog/posts.html @@ -0,0 +1,4 @@ +

$title

+ diff --git a/examples/tagblog/posts/2009-11-05-a-first-post.markdown b/examples/tagblog/posts/2009-11-05-a-first-post.markdown new file mode 100644 index 0000000..c010832 --- /dev/null +++ b/examples/tagblog/posts/2009-11-05-a-first-post.markdown @@ -0,0 +1,21 @@ +--- +title: A first post +author: Julius Caesar +tags: caesar, random crap +--- +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus pretium leo +adipiscing lectus iaculis lobortis. Vivamus scelerisque velit dignissim metus +gravida sit amet dapibus ligula tempor. Quisque sit amet viverra nunc. +Suspendisse cursus elementum ante, ut venenatis nisi dictum eu. Nulla diam +ligula, eleifend in varius quis, malesuada a nibh. Vivamus consequat +pellentesque erat non blandit. Nunc sit amet eros vel massa semper ullamcorper +quis iaculis magna. Vestibulum ullamcorper urna sit amet est elementum +pulvinar. Vestibulum consequat lacus ac quam hendrerit tincidunt. Praesent +bibendum vehicula diam, nec sagittis risus tempus a. Nulla quis odio sit amet +odio vehicula cursus ut id odio. Curabitur semper magna euismod magna mollis +venenatis. Nunc eget eleifend velit. Mauris sed posuere sem. Fusce id nunc +nisi, a aliquam orci. Suspendisse laoreet justo non enim laoreet eget consequat +velit porttitor. Aenean faucibus sodales metus at tincidunt. Donec vestibulum +leo pulvinar erat auctor ac ultrices massa euismod. Phasellus blandit cursus +magna, eget lacinia mi lobortis sed. Suspendisse ultricies enim ligula, vel +scelerisque mauris. diff --git a/examples/tagblog/posts/2009-11-10-another-post.markdown b/examples/tagblog/posts/2009-11-10-another-post.markdown new file mode 100644 index 0000000..a79ca88 --- /dev/null +++ b/examples/tagblog/posts/2009-11-10-another-post.markdown @@ -0,0 +1,15 @@ +--- +title: Another post +author: Marcus Tullius Cicero +tags: cicero, random crap +--- +Vestibulum in ultrices urna. Etiam tempor enim dui, nec malesuada elit. Donec +tempor ligula et quam volutpat quis fermentum eros congue. Sed ut pulvinar sem. +Sed aliquam ipsum id purus sollicitudin vulputate. Cras et mauris dui, vel +hendrerit leo. Ut metus ipsum, fermentum ac malesuada id, tempus pharetra quam. +Donec diam felis, consequat ac scelerisque cursus, gravida non lectus. Sed +faucibus elit dapibus diam elementum id varius nisi tristique. Proin consequat +faucibus neque in aliquam. Vestibulum ligula odio, pulvinar vel hendrerit +vitae, egestas ut nibh. Praesent ut velit elit, in consequat dolor. Praesent +sem enim, commodo in gravida sed, adipiscing vel eros. Lorem ipsum dolor sit +amet, consectetur adipiscing elit. Proin non aliquam nunc. diff --git a/examples/tagblog/posts/2009-11-28-a-third-post.markdown b/examples/tagblog/posts/2009-11-28-a-third-post.markdown new file mode 100644 index 0000000..a3e99aa --- /dev/null +++ b/examples/tagblog/posts/2009-11-28-a-third-post.markdown @@ -0,0 +1,19 @@ +--- +title: A third post +author: Publius Ovidius Naso +tags: epic fail, ovidius +--- +Pellentesque tempor blandit elit, vel ultricies arcu congue egestas. Fusce +vitae rutrum nisl. Fusce id mauris libero, a venenatis tellus. Fusce iaculis, +lorem et ornare molestie, mauris risus mollis nisi, non fermentum lacus lacus +sit amet ipsum. Praesent lobortis ullamcorper dolor, eget convallis ligula +dignissim a. Suspendisse nulla nisi, congue et pharetra vel, convallis non +libero. Ut a nulla ipsum. Phasellus cursus velit id neque viverra ut +pellentesque justo posuere. Curabitur laoreet enim et velit tempor consectetur. +Donec eu pretium urna. Suspendisse vitae nisi at metus vestibulum aliquam in +sit amet nisl. Donec convallis lacinia odio, vestibulum molestie nunc feugiat +a. Suspendisse vehicula, sapien id aliquet consectetur, sem sapien ullamcorper +arcu, scelerisque porttitor elit ipsum posuere ligula. Nulla at velit eu metus +tincidunt auctor ut sit amet enim. Donec placerat dapibus nisi id facilisis. +Maecenas pellentesque pulvinar auctor. Curabitur gravida quam sit amet purus +consectetur blandit. diff --git a/examples/tagblog/posts/2009-12-04-this-blog-aint-dead.markdown b/examples/tagblog/posts/2009-12-04-this-blog-aint-dead.markdown new file mode 100644 index 0000000..bdaa87f --- /dev/null +++ b/examples/tagblog/posts/2009-12-04-this-blog-aint-dead.markdown @@ -0,0 +1,12 @@ +--- +title: This blog ain't dead +author: Marcus Antonius +tags: epic fail, antonius +--- +Etiam non felis aliquet tellus dictum vestibulum. Aliquam accumsan mauris non +lacus ultricies nec lacinia enim rhoncus. Curabitur vel tortor massa, elementum +tincidunt elit. Maecenas venenatis luctus arcu ut ullamcorper. Donec interdum +dolor eu enim tristique vel vehicula risus mollis. Nunc nec tortor quam. Nulla +a mauris arcu. Phasellus venenatis tortor vel odio tincidunt consequat. Integer +venenatis nibh vitae lectus laoreet eu feugiat nunc pretium. Integer nec turpis +metus, in fermentum lorem. diff --git a/examples/tagblog/posts/2009-12-23-almost-christmas.markdown b/examples/tagblog/posts/2009-12-23-almost-christmas.markdown new file mode 100644 index 0000000..2e16426 --- /dev/null +++ b/examples/tagblog/posts/2009-12-23-almost-christmas.markdown @@ -0,0 +1,13 @@ +--- +title: Almost Christmas! +author: Publius Vergilius Maro +tags: christmas, random crap +--- +Morbi tincidunt eleifend ante, eu gravida ante rutrum vel. Nunc bibendum nulla +tellus, eget egestas sapien. Nam rhoncus interdum libero, eget congue orci +imperdiet eu. Quisque pellentesque fringilla urna, ac venenatis ante ultricies +et. Pellentesque habitant morbi tristique senectus et netus et malesuada fames +ac turpis egestas. Mauris eleifend sagittis ultrices. Quisque ultrices accumsan +nisl, sed pellentesque metus porta vitae. Nulla facilisi. In et nibh tincidunt +mi volutpat pellentesque vitae nec sapien. Integer massa ipsum, pellentesque in +elementum at, cursus sit amet diam. diff --git a/examples/tagblog/templates/default.html b/examples/tagblog/templates/default.html new file mode 100644 index 0000000..21429fa --- /dev/null +++ b/examples/tagblog/templates/default.html @@ -0,0 +1,22 @@ + + + + + SimpleBlog - $title + + + + +

SimpleBlog - $title

+ + + $body + + diff --git a/examples/tagblog/templates/post.html b/examples/tagblog/templates/post.html new file mode 100644 index 0000000..8ecb87d --- /dev/null +++ b/examples/tagblog/templates/post.html @@ -0,0 +1,5 @@ +

$title

+by $author on $date +
Tagged as: $tags.
+ +$body diff --git a/examples/tagblog/templates/postitem.html b/examples/tagblog/templates/postitem.html new file mode 100644 index 0000000..a14687b --- /dev/null +++ b/examples/tagblog/templates/postitem.html @@ -0,0 +1,4 @@ +
  • + $title + - $date - by $author +
  • diff --git a/examples/tagblog/templates/rss.xml b/examples/tagblog/templates/rss.xml new file mode 100644 index 0000000..be918af --- /dev/null +++ b/examples/tagblog/templates/rss.xml @@ -0,0 +1,9 @@ + + + + The SimpleBlog + http://example.com + Simple blog in hakyll + $items + + diff --git a/examples/tagblog/templates/rssitem.xml b/examples/tagblog/templates/rssitem.xml new file mode 100644 index 0000000..48573d2 --- /dev/null +++ b/examples/tagblog/templates/rssitem.xml @@ -0,0 +1,5 @@ + + $title + http://example.com/$url + $title by $author + diff --git a/src/Text/Hakyll/File.hs b/src/Text/Hakyll/File.hs index 0c803e1..400d156 100644 --- a/src/Text/Hakyll/File.hs +++ b/src/Text/Hakyll/File.hs @@ -4,6 +4,7 @@ module Text.Hakyll.File ( toDestination , toCache , toURL + , removeSpaces , makeDirectories , getRecursiveContents , havingExtension @@ -15,18 +16,31 @@ import System.Directory import System.FilePath import Control.Monad +-- | Auxiliary function to remove pathSeparators form the start. We don't deal +-- with absolute paths here. +removeLeadingSeparator :: FilePath -> FilePath +removeLeadingSeparator [] = [] +removeLeadingSeparator p@(x:xs) | x `elem` pathSeparators = xs + | otherwise = p + -- | Convert a relative filepath to a filepath in the destination (_site). toDestination :: FilePath -> FilePath -toDestination path = "_site" path +toDestination path = "_site" (removeLeadingSeparator path) -- | Convert a relative filepath to a filepath in the cache (_cache). toCache :: FilePath -> FilePath -toCache path = "_cache" path +toCache path = "_cache" (removeLeadingSeparator path) -- | Get the url for a given page. toURL :: FilePath -> FilePath toURL = flip addExtension ".html" . dropExtension +-- | Swaps spaces for '-'. +removeSpaces :: FilePath -> FilePath +removeSpaces = map swap + where swap ' ' = '-' + swap x = x + -- | Given a path to a file, try to make the path writable by making -- all directories on the path. makeDirectories :: FilePath -> IO () diff --git a/src/Text/Hakyll/Tags.hs b/src/Text/Hakyll/Tags.hs index c64d566..ea9ee87 100644 --- a/src/Text/Hakyll/Tags.hs +++ b/src/Text/Hakyll/Tags.hs @@ -56,5 +56,6 @@ renderTagCloud tagMap urlFunction minSize maxSize = renderTagLinks :: (String -> String) -- ^ Function that produces an url for a tag. -> ContextManipulation renderTagLinks urlFunction = renderValue "tags" "tags" renderTagLinks' - where renderTagLinks' = B.pack . intercalate ", " . map urlFunction + where renderTagLinks' = B.pack . intercalate ", " + . map (\t -> link t $ urlFunction t) . map trim . split "," . B.unpack