summaryrefslogtreecommitdiff
path: root/src/Hakyll/Core/Route.hs
blob: f3f0b7ffed64dabd2e3cfefb71ca46ceb6bfbe02 (plain)
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
-- | Once a target is compiled, the user usually wants to save it to the disk.
-- This is where the 'Route' type comes in; it determines where a certain target
-- should be written.
--
-- When a route is applied (using 'runRoute'), it either returns a 'Just'
-- 'FilePath' (meaning the target should be written to that file path), or
-- 'Nothing' (meaning this target should not be written anywhere).
--
module Hakyll.Core.Route
    ( Route
    , runRoute
    , idRoute
    , setExtension
    , ifMatch
    ) where

import Data.Monoid (Monoid, mempty, mappend)
import Control.Monad (mplus)
import System.FilePath (replaceExtension)

import Hakyll.Core.Identifier
import Hakyll.Core.Identifier.Pattern

-- | Type used for a route
--
newtype Route = Route {unRoute :: Identifier -> Maybe FilePath}

instance Monoid Route where
    mempty = Route $ const Nothing
    mappend (Route f) (Route g) = Route $ \id' -> f id' `mplus` g id'

-- | Apply a route to an identifier
--
runRoute :: Route -> Identifier -> Maybe FilePath
runRoute = unRoute

-- | A route that uses the identifier as filepath. For example, the target with
-- ID @foo\/bar@ will be written to the file @foo\/bar@.
--
idRoute :: Route
idRoute = Route $ Just . toFilePath

-- | Set (or replace) the extension of a route.
--
-- Example:
--
-- > runRoute (setExtension "html") "foo/bar"
--
-- Result:
--
-- > Just "foo/bar.html"
--
-- Example:
--
-- > runRoute (setExtension "html") "posts/the-art-of-trolling.markdown"
--
-- Result:
--
-- > Just "posts/the-art-of-trolling.html"
--
setExtension :: String -> Route
setExtension extension = Route $ fmap (`replaceExtension` extension)
                               . unRoute idRoute

-- | Modify a route: apply the route if the identifier matches the given
-- pattern, fail otherwise.
--
ifMatch :: Pattern -> Route -> Route
ifMatch pattern (Route route) = Route $ \id' ->
    if doesMatch pattern id' then route id'
                             else Nothing