-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathCollections.hs
102 lines (89 loc) · 3.4 KB
/
Collections.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
module Collections
( Collections (..)
, buildCollections
, collectionContext
) where
import Hakyll
import Control.Applicative (liftA2)
import Data.Ord (comparing)
import Data.List (elemIndex, insertBy)
import Control.Monad (foldM)
import Data.Maybe (fromMaybe)
import Data.Monoid (mconcat)
import qualified Data.Map as M
import qualified Data.Set as S
data Collections = Collections
{ collMap :: [(String, [Identifier])]
, collMakeId :: String -> Identifier
, collDependency :: Dependency
} deriving (Show)
------ Building the collections map
buildCollWith :: MonadMetadata m
=> (Identifier -> m (Maybe (Int, String)))
-> Pattern
-> (String -> Identifier)
-> m Collections
buildCollWith f pattern makeId = do
ids <- getMatches pattern
collMap <- foldM addColl M.empty ids
let set' = S.fromList ids
let mapList = map (liftA2 (,) fst (map snd . snd)) $ M.toList collMap
return $ Collections mapList makeId (PatternDependency pattern set')
where
addColl collMap id' = do
maybeCollection <- f id'
let add (pos, coll) = insertCollEntryInOrder coll (pos, id') collMap
return $ maybe collMap add maybeCollection
insertCollEntryInOrder :: (Ord k, Ord a)
=> k -> (a,b)
-> M.Map k [(a,b)] -> M.Map k [(a,b)]
insertCollEntryInOrder key val oldMap = M.insert key newVal oldMap
where
newVal = maybe [val] id $ do
list <- M.lookup key oldMap
return $ insertBy (comparing fst) val list
buildCollections :: MonadMetadata m
=> Pattern
-> (String -> Identifier)
-> m Collections
buildCollections = buildCollWith getCollectionAndPos
-- swap order of pos and collection to fit name
getCollectionAndPos :: MonadMetadata m => Identifier -> m (Maybe (Int,String))
getCollectionAndPos identifier = do
metadata <- getMetadata identifier
return $ do
coll <- M.lookup "collection" metadata
pos <- M.lookup "part" metadata
return (read pos :: Int, coll)
--------------
offsetUrl :: (Int -> Int) -- offset function
-> Collections
-> Item a
-> Compiler FilePath
offsetUrl f colls i =
(offsetInCollection colls (itemIdentifier i) f) >>= url
where
url Nothing = fail $ "No next/prev page"
url (Just id') = (getRoute id') >>= process
process Nothing = fail $ "No URL for that page"
process (Just fp) = return $ toUrl fp
offsetInCollection :: MonadMetadata m
=> Collections
-> Identifier
-> (Int -> Int)
-> m (Maybe Identifier)
offsetInCollection colls identifier f = do
maybeCollection <- getCollectionAndPos identifier
return $ do
(pos, collection) <- maybeCollection
list <- M.lookup collection $ M.fromList (collMap colls)
list `indexList` (f $ pos - 1) -- Pos starts at 1
indexList :: [a] -> Int -> Maybe a
indexList xs n | n < 0 = Nothing
| n >= length xs = Nothing
| otherwise = Just (xs !! n)
collectionContext :: Collections -> Context String
collectionContext colls = mconcat
[ field "nextInCollection" $ offsetUrl (+1) colls
, field "prevInCollection" $ offsetUrl (+(-1)) colls
]