1
- {-# Language DeriveGeneric #-}
2
1
{-# Language ScopedTypeVariables #-}
3
2
{-# Language OverloadedStrings #-}
4
- {-# Language TemplateHaskell #-}
3
+ {-# Language ViewPatterns #-}
5
4
6
5
import Hakyll
7
6
import Control.Monad (filterM )
8
7
import Data.List (sortOn )
9
8
import Data.Ord (comparing )
10
9
11
- config :: Configuration
12
- config = defaultConfiguration
13
-
10
+ --------------------------------------------------------------------------------------------------------
11
+ -- MAIN GENERATION -------------------------------------------------------------------------------------
12
+ --------------------------------------------------------------------------------------------------------
14
13
main :: IO ()
15
- main = hakyllWith config $ do
14
+ main = hakyll $ do
15
+ -- statics ---------------------------------------------------------------------------------------------
16
16
match " assets/css/main.css" $ do
17
17
route idRoute
18
18
compile compressCssCompiler
@@ -21,88 +21,147 @@ main = hakyllWith config $ do
21
21
route idRoute
22
22
compile copyFileCompiler
23
23
24
+ -- home ------------------------------------------------------------------------------------------------
24
25
match " index.html" $ do
25
26
route idRoute
26
27
compile $ do
27
- sponsors <- sponsorsCtx defaultContext . sortOn itemIdentifier <$> loadAll " donations/sponsors/*.markdown"
28
+ sponsors <- sponsorsCtx . sortOn itemIdentifier <$> loadAll " donations/sponsors/*.markdown"
28
29
getResourceBody
29
30
>>= applyAsTemplate sponsors
30
31
>>= loadAndApplyTemplate " templates/boilerplate.html" sponsors
31
32
>>= relativizeUrls
32
33
33
- match " affiliates/*.markdown" $ compile pandocCompiler
34
-
34
+ -- sponsors --------------------------------------------------------------------------------------------
35
35
match " donations/sponsors/*.markdown" $ compile pandocCompiler
36
36
37
- match " affiliates/index.html" $ do
37
+ -- affiliates ------------------------------------------------------------------------------------------
38
+ match " affiliates/*.markdown" $ compile pandocCompiler
39
+ create [" affiliates/index.html" ] $ do
38
40
route idRoute
39
41
compile $ do
40
- affils <- affiliatesCtx . sortOn itemIdentifier <$> loadAll " affiliates /*.markdown"
41
- sponsors <- sponsorsCtx affils . sortOn itemIdentifier <$> loadAll " donations/sponsors /*.markdown"
42
+ sponsors <- sponsorsCtx . sortOn itemIdentifier <$> loadAll " donations/sponsors /*.markdown"
43
+ ctx <- affiliatesCtx . sortOn itemIdentifier <$> loadAll " affiliates /*.markdown"
42
44
43
- getResourceBody
44
- >>= applyAsTemplate sponsors
45
- >>= loadAndApplyTemplate " templates/boilerplate.html" sponsors
45
+ makeItem " "
46
+ >>= loadAndApplyTemplate " templates/affiliates/list.html " ctx
47
+ >>= loadAndApplyTemplate " templates/boilerplate.html" sponsors
46
48
>>= relativizeUrls
47
49
48
- match " **/index.html" $ do
50
+ -- projects --------------------------------------------------------------------------------------------
51
+ match " projects/*.markdown" $ compile pandocCompiler
52
+ create [" projects/index.html" ] $ do
49
53
route idRoute
50
54
compile $ do
51
- sponsors <- sponsorsCtx defaultContext . sortOn itemIdentifier <$> loadAll " donations/sponsors/*.markdown"
52
- getResourceBody
53
- >>= applyAsTemplate sponsors
54
- >>= loadAndApplyTemplate " templates/boilerplate.html" sponsors
55
+ sponsors <- sponsorsCtx . sortOn itemIdentifier <$> loadAll " donations/sponsors/*.markdown"
56
+ ctx <- projectsCtx . sortOn itemIdentifier <$> loadAll " projects/*.markdown"
57
+
58
+ makeItem " "
59
+ >>= loadAndApplyTemplate " templates/projects/list.html" ctx
60
+ >>= loadAndApplyTemplate " templates/boilerplate.html" sponsors
55
61
>>= relativizeUrls
56
62
57
- match " projects/*.markdown" $ compile pandocCompiler
63
+ -- news ------------------------------------------------------------------------------------------------
64
+ match " news/**.markdown" $ compile pandocCompiler
65
+ categories <- buildCategories " news/**.markdown" (fromCapture " news/categories/**.html" )
58
66
59
- create [" projects/index.html" ] $ do
67
+ tagsRules categories $ \ category catId -> compile $ do
68
+ news <- recentFirst =<< loadAll catId
69
+ let ctx =
70
+ listField " news" (newsWithCategoriesCtx categories) (pure news) <>
71
+ dateField " category" " %B %e, %Y" <>
72
+ defaultContext
73
+
74
+ makeItem " "
75
+ >>= loadAndApplyTemplate " templates/news/tile.html" ctx
76
+ >>= relativizeUrls
77
+
78
+ create [" news/index.html" ] $ do
60
79
route idRoute
61
80
compile $ do
62
- ctx <- projectsCtx . sortOn itemIdentifier <$> loadAll " projects/*.markdown"
63
- sponsors <- sponsorsCtx ctx . sortOn itemIdentifier <$> loadAll " donations/sponsors/*.markdown"
81
+ sponsors <- sponsorsCtx . sortOn itemIdentifier <$> loadAll " donations/sponsors/*.markdown"
82
+ newsWithCategories <- recentFirst =<< loadAll " news/categories/**.html"
83
+
84
+ let ctx =
85
+ listField " categories" defaultContext (return newsWithCategories) <>
86
+ defaultContext
64
87
65
88
makeItem " "
66
- >>= loadAndApplyTemplate " templates/projects /list.html" sponsors
89
+ >>= loadAndApplyTemplate " templates/news /list.html" ctx
67
90
>>= loadAndApplyTemplate " templates/boilerplate.html" sponsors
68
91
>>= relativizeUrls
69
92
93
+ -- templates -------------------------------------------------------------------------------------------
94
+ match " templates/*" $ compile templateBodyCompiler
70
95
match " templates/**" $ compile templateBodyCompiler
71
96
97
+
98
+ --------------------------------------------------------------------------------------------------------
99
+ -- CONTEXT ---------------------------------------------------------------------------------------------
100
+ --------------------------------------------------------------------------------------------------------
101
+
102
+ -- sponsors --------------------------------------------------------------------------------------------
103
+ -- | Partition sponsors into by level: monad, applicative, and functor
104
+ -- Sponsors are listed in the footer template, which means we need this
105
+ -- context for most pages.
106
+ sponsorsCtx :: [Item String ] -> Context String
107
+ sponsorsCtx sponsors =
108
+ listField " monads" defaultContext (ofMetadataField " level" " Monad" sponsors) <>
109
+ listField " applicatives" defaultContext (ofMetadataField " level" " Applicative" sponsors) <>
110
+ listField " functors" defaultContext (ofMetadataField " level" " Functor" sponsors) <>
111
+ defaultContext
112
+
113
+ -- affiliates ------------------------------------------------------------------------------------------
72
114
-- | Partition affiliates into affiliates and pending
73
115
affiliatesCtx :: [Item String ] -> Context String
74
- affiliatesCtx tuts =
75
- listField " affiliated" defaultContext (ofStatus " affiliated" tuts) <>
76
- listField " pending" defaultContext (ofStatus " pending" tuts) <>
116
+ affiliatesCtx affiliates =
117
+ listField " affiliated" defaultContext (ofMetadataField " status " " affiliated" affiliates) <>
118
+ listField " pending" defaultContext (ofMetadataField " status " " pending" affiliates) <>
77
119
defaultContext
78
120
121
+ -- projects --------------------------------------------------------------------------------------------
79
122
-- | Partition projects into : Ideation | Proposed | In Progress | Completed
80
123
projectsCtx :: [Item String ] -> Context String
81
- projectsCtx p =
82
- listField " ideas" defaultContext (ofStatus " ideation" p) <>
83
- listField " proposals" defaultContext (ofStatus " proposed" p) <>
84
- listField " inprogress" defaultContext (ofStatus " inprogress" p ) <>
85
- listField " completed" defaultContext (ofStatus " completed" p) <>
124
+ projectsCtx projects =
125
+ listField " ideas" defaultContext (ofMetadataField " status " " ideation" projects) <>
126
+ listField " proposals" defaultContext (ofMetadataField " status " " proposed" projects) <>
127
+ listField " inprogress" defaultContext (ofMetadataField " status " " inprogress" projects ) <>
128
+ listField " completed" defaultContext (ofMetadataField " status " " completed" projects) <>
86
129
defaultContext
87
130
88
- ofStatus :: String -> [Item String ] -> Compiler [Item String ]
89
- ofStatus v = filterM (\ item -> do
90
- mbStatus <- getMetadataField (itemIdentifier item) " status"
91
- return $ Just v == mbStatus
131
+ -- news ------------------------------------------------------------------------------------------------
132
+ -- | build group of news inside date of publishing (category)
133
+ newsWithCategoriesCtx :: Tags -> Context String
134
+ newsWithCategoriesCtx categories =
135
+ listField " categories" categoryCtx getAllCategories <>
136
+ defaultContext
137
+ where
138
+ getAllCategories :: Compiler [Item (String , [Identifier ])]
139
+ getAllCategories = pure . map buildItemFromTag $ tagsMap categories
140
+ where
141
+ buildItemFromTag :: (String , [Identifier ]) -> Item (String , [Identifier ])
142
+ buildItemFromTag c@ (name, _) = Item (tagsMakeId categories name) c
143
+ categoryCtx :: Context (String , [Identifier ])
144
+ categoryCtx =
145
+ listFieldWith " news" newsCtx getNews <>
146
+ metadataField <>
147
+ urlField " url" <>
148
+ pathField " path" <>
149
+ titleField " title" <>
150
+ missingField
151
+ where
152
+ getNews :: Item (String , [Identifier ]) -> Compiler [Item String ]
153
+ getNews (itemBody -> (_, ids)) = mapM load ids
154
+ newsCtx :: Context String
155
+ newsCtx = newsWithCategoriesCtx categories
156
+
157
+
158
+ --------------------------------------------------------------------------------------------------------
159
+ -- UTILS -----------------------------------------------------------------------------------------------
160
+ --------------------------------------------------------------------------------------------------------
161
+
162
+ -- | filter list of item string based on the given value to match on the given metadata field
163
+ ofMetadataField :: String -> String -> [Item String ] -> Compiler [Item String ]
164
+ ofMetadataField field value = filterM (\ item -> do
165
+ mbStatus <- getMetadataField (itemIdentifier item) field
166
+ return $ Just value == mbStatus
92
167
)
93
-
94
- -- | Partition sponsors into by level: monad, applicative, and functor
95
- -- Sponsors are listed in the footer template, which means we need this
96
- -- context for most pages. The first argument is another context so
97
- -- we can compose them together, and the usage site can pass in the
98
- -- context it is in.
99
- sponsorsCtx :: Context String -> [Item String ] -> Context String
100
- sponsorsCtx ctx sponsors =
101
- listField " monads" defaultContext (ofLevel " Monad" ) <>
102
- listField " applicatives" defaultContext (ofLevel " Applicative" ) <>
103
- listField " functors" defaultContext (ofLevel " Functor" ) <>
104
- ctx
105
- where
106
- ofLevel ty = filterM (\ item -> do
107
- mbLevel <- getMetadataField (itemIdentifier item) " level"
108
- return $ Just ty == mbLevel) sponsors
0 commit comments