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
|
-- | Module aimed to paginate web pages.
--
module Text.Hakyll.Paginate
( PaginateConfiguration (..)
, defaultPaginateConfiguration
, paginate
) where
import Control.Applicative ((<$>))
import Text.Hakyll.Context (Context)
import Text.Hakyll.CreateContext
import Text.Hakyll.HakyllAction
import Text.Hakyll.Util (link)
-- | A configuration for a pagination.
--
data PaginateConfiguration = PaginateConfiguration
{ -- | Label for the link to the previous page.
previousLabel :: String
, -- | Label for the link to the next page.
nextLabel :: String
, -- | Label for the link to the first page.
firstLabel :: String
, -- | Label for the link to the last page.
lastLabel :: String
}
-- | A simple default configuration for pagination.
--
defaultPaginateConfiguration :: PaginateConfiguration
defaultPaginateConfiguration = PaginateConfiguration
{ previousLabel = "Previous"
, nextLabel = "Next"
, firstLabel = "First"
, lastLabel = "Last"
}
-- | The most important function for pagination. This function operates on a
-- list of @Context@s (the pages), and basically just adds fields to them
-- by combining them with a custom page.
--
-- The following metadata fields will be added:
--
-- - @$previous@: A link to the previous page.
--
-- - @$next@: A link to the next page.
--
-- - @$first@: A link to the first page.
--
-- - @$last@: A link to the last page.
--
-- - @$index@: 1-based index of the current page.
--
-- - @$length@: Total number of pages.
--
-- When @$previous@ or @$next@ are not available, they will be just a label
-- without a link. The same goes for when we are on the first or last page for
-- @$first@ and @$last@.
--
paginate :: PaginateConfiguration
-> [HakyllAction () Context]
-> [HakyllAction () Context]
paginate configuration renderables = paginate' Nothing renderables (1 :: Int)
where
-- Create a link with a given label, taken from the configuration.
linkWithLabel f r = Right $ case actionUrl r of
Left l -> createSimpleHakyllAction $
link (f configuration) . ("$root/" ++) <$> l
Right _ -> error "No link found for pagination."
-- The main function that creates combined renderables by recursing over
-- the list of items.
paginate' _ [] _ = []
paginate' maybePrev (x:xs) index =
let (previous, first) = case maybePrev of
(Just r) -> ( linkWithLabel previousLabel r
, linkWithLabel firstLabel (head renderables) )
Nothing -> ( Left $ previousLabel configuration
, Left $ firstLabel configuration )
(next, last') = case xs of
(n:_) -> ( linkWithLabel nextLabel n
, linkWithLabel lastLabel (last renderables) )
[] -> ( Left $ nextLabel configuration
, Left $ lastLabel configuration )
customPage = createCustomPage ""
[ ("previous", previous)
, ("next", next)
, ("first", first)
, ("last", last')
, ("index", Left $ show index)
, ("length", Left $ show $ length renderables)
]
in (x `combine` customPage) : paginate' (Just x) xs (index + 1)
|