-
Notifications
You must be signed in to change notification settings - Fork 2
/
site.hs
234 lines (199 loc) · 8.47 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
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
--------------------------------------------------------------------------------
{-# LANGUAGE OverloadedStrings #-}
import Data.Monoid (mappend, mconcat, (<>))
import Data.Maybe (fromMaybe)
import Hakyll
import Text.Pandoc (WriterOptions (..), HTMLMathMethod (MathJax))
import Text.Pandoc.Options
import qualified Data.Set as S
--------------------------------------------------------------------------------
main :: IO ()
main = hakyll $ do
match "images/*" $ do
route idRoute
compile copyFileCompiler
match "css/*" $ do
route idRoute
compile compressCssCompiler
match "js/*" $ do
route idRoute
compile copyFileCompiler
match "data/*" $ do
route idRoute
compile copyFileCompiler
match (fromList ["about.markdown", "contact.markdown", "blogroll.markdown", "404.md"]) $ do
route $ setExtension "html"
compile $ pandocCompiler
>>= loadAndApplyTemplate "templates/default.html" defaultContext
>>= relativizeUrls
-- build up tags
tags <- buildTags postsGlob (fromCapture "tags/*.html")
tagsRules tags $ \tag pattern -> do
route idRoute
compile $ do
posts <- recentFirst =<< loadAll pattern
let ctx = constField "title" ("Posts tagged \"" ++ tag ++ "\"")
`mappend` listField "posts" postCtx (return posts)
`mappend` defaultContext
makeItem ""
>>= loadAndApplyTemplate "templates/tag.html" ctx
>>= loadAndApplyTemplate "templates/default.html" ctx
>>= relativizeUrls
-- build up categories
categories <- buildCategories postsGlob (fromCapture "categories/*.html")
tagsRules categories $ \tag pattern -> do
route idRoute
compile $ do
posts <- recentFirst =<< loadAll pattern
let ctx = constField "title" ("Posts in category \"" ++ tag ++ "\"")
`mappend` listField "posts" postCtx (return posts)
`mappend` defaultContext
makeItem ""
>>= loadAndApplyTemplate "templates/tag.html" ctx
>>= loadAndApplyTemplate "templates/default.html" ctx
>>= relativizeUrls
match postsGlob $ do
route $ setExtension "html"
compile $ postCompiler
>>= saveSnapshot "teaser"
>>= loadAndApplyTemplate "templates/post.html" (postCtxWithTags tags categories)
>>= applyFilter postFilters
>>= saveSnapshot "content"
>>= loadAndApplyTemplate "templates/default.html" (postCtxWithTags tags categories <> metaKeywordContext <> metaDescriptionContext)
>>= relativizeUrls
{-match "drafts/*" $ do-}
{-route $ setExtension "html"-}
{-compile $ pandocMathCompiler-}
{->>= loadAndApplyTemplate "templates/post.html" (postCtxWithTags tags categories)-}
{->>= applyFilter postFilters-}
{->>= loadAndApplyTemplate "templates/default.html" (postCtxWithTags tags categories)-}
{->>= relativizeUrls-}
match "posts/**.stan" $ version "raw" $ do
route idRoute
compile copyFileCompiler
match "posts/**.Rmd" $ version "raw" $ do
route idRoute
compile copyFileCompiler
match "posts/**.svg" $ version "raw" $ do
route idRoute
compile copyFileCompiler
match "posts/**.jp*g" $ version "raw" $ do
route idRoute
compile copyFileCompiler
match "posts/**.png" $ version "raw" $ do
route idRoute
compile copyFileCompiler
match "posts/**.lhs" $ version "raw" $ do
route idRoute
compile getResourceBody
create ["archive.html"] $ do
route idRoute
compile $ do
posts <- recentFirst =<< loadAll (postsGlob .&&. hasNoVersion)
let archiveCtx = mconcat
[
listField "posts" postCtx (return posts)
, constField "title" "Archives"
, defaultContext
]
makeItem ""
>>= loadAndApplyTemplate "templates/archive.html" archiveCtx
>>= loadAndApplyTemplate "templates/default.html" archiveCtx
>>= relativizeUrls
match "index.html" $ do
route idRoute
compile $ do
posts <- fmap (take 5) . recentFirst =<< loadAll (postsGlob .&&. hasNoVersion)
let indexCtx = mconcat
[ constField "title" "Home"
, listField "posts" (teaserField "teaser" "teaser" <> postCtx) (return posts)
, defaultContext
]
getResourceBody
>>= applyAsTemplate indexCtx
>>= loadAndApplyTemplate "templates/default.html" indexCtx
>>= relativizeUrls
match "templates/*" $ compile templateCompiler
create ["atom.xml"] $ do
route idRoute
compile $ do
let feedCtx = postCtx `mappend` bodyField "description"
posts <- fmap (take 10) . recentFirst =<< loadAllSnapshots (postsGlob .&&. hasNoVersion) "content"
renderAtom myFeedConfiguration feedCtx posts
--------------------------------------------------------------------------------
postsGlob = "posts/**.md" :: Pattern
postCtx :: Context String
postCtx = mconcat
[ dateField "date" "%e %B, %Y"
, constField "author" "Brian"
, defaultContext
]
postCtxWithTags :: Tags -> Tags -> Context String
postCtxWithTags tags cats = mconcat
[
tagsField "tags" tags
, categoryField "cat" cats
, postCtx
]
postWriterOptions :: WriterOptions
postWriterOptions = defaultHakyllWriterOptions {
writerExtensions = newExtensions
, writerHTMLMathMethod = MathJax ""
, writerHtml5 = True
}
where
mathExtensions = [ Ext_tex_math_dollars
, Ext_tex_math_double_backslash
, Ext_latex_macros
]
defaultExtensions = writerExtensions defaultHakyllWriterOptions
newExtensions = foldr S.insert defaultExtensions mathExtensions
postWriterOptionsToc :: WriterOptions
postWriterOptionsToc = postWriterOptions{
writerTableOfContents = True
, writerTOCDepth = 2
, writerTemplate = Just "$if(toc)$<div id=\"toc\">$toc$</div>$endif$\n$body$"
}
postCompiler = do
ident <- getUnderlying
toc <- getMetadataField ident "withtoc"
let writerSettings = case toc of
Just "true" -> postWriterOptionsToc
Just "yes" -> postWriterOptionsToc
Just _ -> postWriterOptions
Nothing -> postWriterOptions
pandocCompilerWith defaultHakyllReaderOptions writerSettings
----------------------------------------------------------------------------------
applyFilter :: (Monad m, Functor f) => (String -> String) -> f String -> m (f String)
applyFilter g fs = return . fmap g $ fs
preFilters :: String -> String
preFilters = noAtxLhs
postFilters :: String -> String
postFilters = mathjaxFix
mathjaxFix = replaceAll "><span class=\"math" (" class=\"mathjaxWide\"" ++)
noAtxLhs = replaceAll "^#" (" "++)
metaKeywordContext :: Context String
-- can be reached using $metaKeywords$ in the templates
-- Use the current item (markdown file)
metaKeywordContext = field "keywords" $ \item -> do
-- tags contains the content of the "tags" metadata
-- inside the item (understand the source)
tags <- getMetadataField (itemIdentifier item) "tags"
return $ fromMaybe "" tags
metaDescriptionContext :: Context String
-- can be reached using $metaKeywords$ in the templates
-- Use the current item (markdown file)
metaDescriptionContext = field "tldr" $ \item -> do
-- tags contains the content of the "tags" metadata
-- inside the item (understand the source)
tldr <- getMetadataField (itemIdentifier item) "tldr"
return $ fromMaybe "" tldr
----------------------------------------------------------------------------------
myFeedConfiguration :: FeedConfiguration
myFeedConfiguration = FeedConfiguration
{ feedTitle = "Brian Callander"
, feedDescription = "Lots of exercise solutions to statistics books, some data analyses, and a bit of running."
, feedAuthorName = "Brian Callander"
, feedAuthorEmail = "briancallander+blog@gmail.com"
, feedRoot = "http://www.briancallander.com"
}