-
Notifications
You must be signed in to change notification settings - Fork 0
/
site.hs
200 lines (154 loc) · 6.33 KB
/
site.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
{-# LANGUAGE OverloadedStrings #-}
----------------------------------------------------------------------
--
-- my hakyll blog assembled together using many other people's blog scripts
--
----------------------------------------------------------------------
import Data.Monoid (mappend, (<>))
import Hakyll
import qualified Data.Set as S
import Data.List
import Data.Char (toLower)
import Text.Pandoc.Options
import Control.Monad
-- Deploy command
config :: Configuration
config = defaultConfiguration
{ deployCommand = "rsync -avz -e ssh --exclude 'drafts' --safe-links ./_site/ [email protected]:www/blog/"}
-- Pandoc + Math options
pandocMathCompiler =
let mathExtensions = [Ext_tex_math_dollars, Ext_tex_math_double_backslash,
Ext_latex_macros]
defaultExtensions = writerExtensions defaultHakyllWriterOptions
newExtensions = foldr S.insert defaultExtensions mathExtensions
writerOptions = defaultHakyllWriterOptions {
writerExtensions = newExtensions,
writerHTMLMathMethod = MathJax ""
}
in pandocCompilerWith defaultHakyllReaderOptions writerOptions
-- nonDrafts :: (MonadMetadata m, Functor m) => [Item a] -> m [Item a]
-- nonDrafts = return . filter f
-- where
-- f = not . isPrefixOf "drafts/" . show . itemIdentifier
-- recentFirstNonDrafts :: (MonadMetadata m, Functor m) => [Item a] -> m [Item a]
-- recentFirstNonDrafts items = do
-- nondrafts <- nonDrafts items
-- recentFirst nondrafts
main :: IO ()
main = hakyllWith config $ do
-- templates
match "templates/*" $ compile templateCompiler
-- static stuff
match "images/*" $ do
route idRoute
compile copyFileCompiler
match "css/*" $ do
route idRoute
compile compressCssCompiler
-- special invariable pages
match (fromList ["about.markdown"]) $ do
route $ setExtension "html"
compile $ pandocCompiler
>>= loadAndApplyTemplate "templates/default.html" defaultContext
>>= relativizeUrls
-- tags init
tags <- buildTags "posts/*" (fromCapture "tag/*")
-- posts
match ("posts/*.md" .||. "posts/*.markdown") $ do
route $ setExtension "html"
compile $ pandocMathCompiler
>>= loadAndApplyTemplate "templates/post-body.html" (postCtx tags)
>>= saveSnapshot "content"
>>= loadAndApplyTemplate "templates/post.html" (postCtx tags)
>>= relativizeUrls
-- tags
tagsRules tags $ \tag pattern -> do
let title = "Posts with label " ++ " ‘" ++ tag ++ "’"
route tagRoute
compile $ do
posts <- recentFirst =<< loadAll (pattern .&&. hasNoVersion)
let tagCtx =
constField "title" title <>
listField "posts" (postCtx tags) (return posts) <>
defaultContext
makeItem ""
>>= loadAndApplyTemplate "templates/tag.html" tagCtx
>>= loadAndApplyTemplate "templates/default.html" tagCtx
>>= relativizeUrls
create ["tags/index.html"] $ do
route idRoute
compile $ do
cloud <- renderTagCloud 80 300 tags
let cloudCtx =
constField "title" "Tag cloud" <>
constField "cloud" cloud <>
defaultContext
makeItem ""
>>= loadAndApplyTemplate "templates/tagcloud.html" cloudCtx
>>= loadAndApplyTemplate "templates/default.html" cloudCtx
>>= relativizeUrls
-- drafts
match ("drafts/*.md" .||. "drafts/*.markdown") $ do
route $ setExtension "html"
compile $ pandocMathCompiler
>>= loadAndApplyTemplate "templates/post-body.html" (postCtx tags)
>>= loadAndApplyTemplate "templates/draft.html" (postCtx tags)
>>= relativizeUrls
-- archive page
create ["archive.html"] $ do
route idRoute
compile $ do
posts <- recentFirst =<< loadAllSnapshots "posts/*" "content"
let archiveCtx =
listField "posts" (postCtx tags) (return posts) `mappend`
constField "title" "Archives" `mappend`
defaultContext
makeItem ""
>>= loadAndApplyTemplate "templates/archive.html" archiveCtx
>>= loadAndApplyTemplate "templates/default.html" archiveCtx
>>= relativizeUrls
-- blog pages, including the main one
pag <- buildPaginateWith grouper "posts/*" makeId
paginateRules pag $ \pageNum pattern -> do
route idRoute
compile $ do
posts <- recentFirst =<< loadAllSnapshots pattern "content"
let paginateCtx = paginateContext pag pageNum
ctx =
constField "title" ("Blog Archive - Page " ++ (show pageNum)) <>
listField "posts" (teaserCtx tags) (return posts) <>
paginateCtx <>
defaultContext
makeItem ""
>>= loadAndApplyTemplate "templates/blogpage.html" ctx
>>= loadAndApplyTemplate "templates/default.html" ctx
>>= relativizeUrls
-- Contexts
postCtx :: Tags -> Context String
postCtx tags = mconcat
[
dateField "date" "%B %e, %Y"
, tagsField "tags" tags
, defaultContext
]
teaserCtx tags = teaserField "teaser" "content" `mappend` (postCtx tags)
-- tag route
replaceWithDash :: Char -> Char
replaceWithDash c =
if c == '.' || c == ' '
then '-'
else c
adjustLink = (filter (not . (== '/'))) . (map (toLower . replaceWithDash))
tagRoute :: Routes
tagRoute =
setExtension ".html" `composeRoutes`
gsubRoute "." adjustLink `composeRoutes`
gsubRoute "/" (const "") `composeRoutes`
gsubRoute "^tag" (const "tag/") `composeRoutes`
gsubRoute "-html" (const "/index.html")
-- pagination
grouper :: MonadMetadata m => [Identifier] -> m [[Identifier]]
grouper ids = (liftM (paginateEvery 4) . sortRecentFirst) ids
makeId :: PageNumber -> Identifier
makeId pageNum = if pageNum == 1 then "index.html"
else fromFilePath $ "page/" ++ (show pageNum) ++ "/index.html"