robertodr / totaltrash.xyz
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
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
module Main where
import Control.Monad (liftM)
import qualified Data.Map as M
import Data.Monoid ((<>))
import Hakyll
import Hakyll.Web.Pandoc (defaultHakyllReaderOptions,
defaultHakyllWriterOptions,
writePandocWith)
import Hakyll.Web.Pandoc.Biblio (Biblio, readPandocBiblio)
import System.FilePath.Posix
import qualified Text.CSL as CSL
import Text.CSL.Pandoc (processCites)
import Text.Pandoc (Block (..), Pandoc (..))
import Text.Pandoc.Definition (Meta (..), MetaValue (..))
import Text.Pandoc.Options
import Text.Pandoc.Walk (walk)
import Text.Regex
import Text.Pandoc.Filter.Pyplot (plotTransform)
main :: IO ()
main = do
piHash <- readFile ".pijulinfo"
let totalTrashCtx = mkTotalTrashCtx piHash
hakyll $ do
match
("vendor/**" .||. "images/**" .||. "CNAME" .||. "favicon.png" .||.
"css/style.css" .||.
"keybase.txt" .||.
"googlebdd3afcf40d8a945.html" .||.
"robots.txt" .||.
"sitemap.xml") $ do
route idRoute
compile copyFileCompiler
match "templates/**" $ compile templateCompiler
match "assets/*.bib" $ compile biblioCompiler
match "assets/*.csl" $ compile cslCompiler
match "index.html" $ do
route idRoute
compile $ do
posts <- loadAll "blog/**" >>= recentFirst
let ctx = listField "blog" postCtx (return posts) <> totalTrashCtx
getResourceBody >>= applyAsTemplate ctx >>=
loadAndApplyTemplate "templates/default.html" ctx >>=
relativizeUrls
match "blog/**" $ do
route articleRoute
compile $
pandocBiblioCompiler' >>= saveSnapshot "content" >>=
loadAndApplyTemplate "templates/page.html" totalTrashCtx >>=
loadAndApplyTemplate "templates/default.html" totalTrashCtx >>=
relativizeUrls
create ["rss"] $ do
route idRoute
compile $ do
let feedCtx = defaultContext <> bodyField "description"
posts <- loadAllSnapshots "blog/**" "content" >>= recentFirst
renderRss totalTrashFeed feedCtx posts
totalTrashFeed :: FeedConfiguration
totalTrashFeed =
FeedConfiguration
{ feedTitle = "~totaltrash"
, feedDescription = "It's total trash."
, feedAuthorName = "Roberto Di Remigio"
, feedAuthorEmail = "roberto.diremigio@gmail.com"
, feedRoot = "totaltrash.xyz"
}
mkTotalTrashCtx :: String -> Context String
mkTotalTrashCtx hash = constField "long" hash
<> constField "short" (take 7 hash)
<> defaultContext
postCtx :: Context String
postCtx = dateField "date" "%Y-%m-%d" <> defaultContext
-- See here: https://github.com/jaspervdj/hakyll/issues/471#issuecomment-244540329
addLinkCitations (Pandoc meta a) =
let prevMap = unMeta meta
newMap = M.insert "link-citations" (MetaBool True) prevMap
newMeta = Meta newMap
in Pandoc newMeta a
readPandocBiblio' :: ReaderOptions
-> Item CSL
-> Item Biblio
-> Item String
-> Compiler (Item Pandoc)
readPandocBiblio' ropt csl biblio item = do
style <- unsafeCompiler $ CSL.readCSLFile Nothing . toFilePath . itemIdentifier $ csl
let Biblio refs = itemBody biblio
pandoc <- itemBody <$> readPandocWith ropt item
let pandoc' = processCites style refs (addLinkCitations pandoc)
return $ fmap (const pandoc') item
pandocBiblioCompiler' :: Compiler (Item String)
pandocBiblioCompiler' = do
csl <- load $ fromFilePath cslFileName
bib <- load $ fromFilePath bibFileName
writePandocWith wopt <$>
(traverse f =<< readPandocBiblio' ropt csl bib =<< getResourceBody)
where
cslFileName = "assets/journal-of-chemical-theory-and-computation.csl"
bibFileName = "assets/website.bib"
ropt =
defaultHakyllReaderOptions
{ readerExtensions =
enableExtension Ext_citations $
readerExtensions defaultHakyllReaderOptions
}
wopt =
defaultHakyllWriterOptions
{ writerTableOfContents = True
, writerTemplate = Just template
, writerTOCDepth = 4
, writerExtensions =
pandocExtensions <> (writerExtensions defaultHakyllWriterOptions)
, writerHTMLMathMethod = MathJax ""
}
f = (return . (shiftHeaders 1))
template =
"<div id='false_toc'>\n\
\ $if(toc)$\n\
\ <h2>Contents</h2>\n\
\ $toc$\n\
\ $endif$\n\
\</div>\n\
\$body$"
pandocMatplotlibCompiler :: Compiler (Item String)
pandocMatplotlibCompiler =
pandocCompilerWithTransformM
defaultHakyllReaderOptions
defaultHakyllWriterOptions
(unsafeCompiler . plotTransform)
articleRoute :: Routes
articleRoute = customRoute makeR
where
makeR i = shorten (toFilePath i) </> fileName (toFilePath i) ++ ".html"
fileName :: FilePath -> FilePath
fileName p = case (convertArticleFile . takeBaseName) p of
Just np -> np
Nothing -> error $ "[ERROR] wrong format: " ++ p
shorten = joinPath . splitPath . takeDirectory
convertArticleFile :: String -> Maybe String
convertArticleFile f = fmap last $ matchRegex articleRx f
articleRx :: Regex
articleRx = mkRegex "^([0-9]{4})\\-([0-9]{2})\\-([0-9]{2})\\-(.+)$"
shiftHeaders :: Int -> Pandoc -> Pandoc
shiftHeaders i p = walk go p
where
go (Header l a inl) = Header (l+i) a inl
go x = x