1--------------------------------------------------------------------------------
2-- | This module provides a declarative DSL in which the user can specify the
3-- different rules used to run the compilers.
5-- The convention is to just list all items in the 'Rules' monad, routes and
8-- A typical usage example would be:
10-- > main = hakyll $ do
11-- > match "posts/*" $ do
12-- > route (setExtension "html")
13-- > compile someCompiler
14-- > match "css/*" $ do
16-- > compile compressCssCompiler
17{-# LANGUAGE GeneralizedNewtypeDeriving #-}
18{-# LANGUAGE OverloadedStrings #-}
19module Hakyll.Core.Rules
31--------------------------------------------------------------------------------
32import Control.Applicative ((<$>))
33import Control.Arrow (second)
34import Control.Monad.Reader (ask, local)
35import Control.Monad.State (get, put)
36import Control.Monad.Writer (tell)
37import Data.Monoid (mappend, mempty)
38import qualified Data.Set as S
41--------------------------------------------------------------------------------
42import Data.Binary (Binary)
43import Data.Typeable (Typeable)
46--------------------------------------------------------------------------------
47import Hakyll.Core.Compiler.Internal
48import Hakyll.Core.Identifier
49import Hakyll.Core.Identifier.Pattern
50import Hakyll.Core.Item
51import Hakyll.Core.Item.SomeItem
52import Hakyll.Core.Provider
53import Hakyll.Core.Routes
54import Hakyll.Core.Rules.Internal
55import Hakyll.Core.Writable
58--------------------------------------------------------------------------------
60tellRoute :: Routes -> Rules ()
61tellRoute route' = Rules $ tell $ RuleSet route' mempty mempty
64--------------------------------------------------------------------------------
65-- | Add a number of compilers
66tellCompilers :: (Binary a, Typeable a, Writable a)
67 => [(Identifier, Compiler (Item a))]
69tellCompilers compilers = Rules $ do
70 -- We box the compilers so they have a more simple type
71 let compilers' = map (second $ fmap SomeItem) compilers
72 tell $ RuleSet mempty compilers' mempty
75--------------------------------------------------------------------------------
77tellResources :: [Identifier]
79tellResources resources' = Rules $ tell $
80 RuleSet mempty mempty $ S.fromList resources'
83--------------------------------------------------------------------------------
84-- | Only compile/route items satisfying the given predicate
85match :: Pattern -> Rules b -> Rules b
86match pattern = Rules . local addPredicate . unRules
88 addPredicate env = env
89 { rulesPattern = rulesPattern env `mappend` pattern
93--------------------------------------------------------------------------------
94-- | Greate a group of compilers
95-- Imagine you have a page that you want to render, but you also want the raw
96-- content available on your site.
98-- > match "test.markdown" $ do
99-- > route $ setExtension "html"
100-- > compile pageCompiler
102-- > match "test.markdown" $ do
104-- > compile copyPageCompiler
106-- Will of course conflict! In this case, Hakyll will pick the first matching
107-- compiler (@pageCompiler@ in this case).
109-- In case you want to have them both, you can use the 'group' function to
110-- create a new group. For example,
112-- > match "test.markdown" $ do
113-- > route $ setExtension "html"
114-- > compile pageCompiler
117-- > match "test.markdown" $ do
119-- > compile copyPageCompiler
121-- This will put the compiler for the raw content in a separate group
122-- (@\"raw\"@), which causes it to be compiled as well.
123group :: String -> Rules a -> Rules a
124group g = Rules . local setVersion' . unRules
126 setVersion' env = env {rulesVersion = Just g}
129--------------------------------------------------------------------------------
130-- | Add a compilation rule to the rules.
132-- This instructs all resources to be compiled using the given compiler. When
133-- no resources match the current selection, nothing will happen. In this case,
134-- you might want to have a look at 'create'.
135compile :: (Binary a, Typeable a, Writable a)
136 => Compiler (Item a) -> Rules ()
139 tellCompilers [(id', compiler) | id' <- ids]
143--------------------------------------------------------------------------------
144-- | Add a compilation rule
146-- This sets a compiler for the given identifier. No resource is needed, since
147-- we are creating the item from scratch. This is useful if you want to create a
148-- page on your site that just takes content from other items -- but has no
149-- actual content itself. Note that the group of the given identifier is
150-- replaced by the group set via 'group' (or 'Nothing', if 'group' has not been
152create :: (Binary a, Typeable a, Writable a)
153 => Identifier -> Compiler (Item a) -> Rules ()
154create id' compiler = Rules $ do
155 version' <- rulesVersion <$> ask
156 let id'' = setVersion version' id'
157 unRules $ tellCompilers [(id'', compiler)]
160--------------------------------------------------------------------------------
163-- This adds a route for all items matching the current pattern.
164route :: Routes -> Rules ()
165route route' = Rules $ do
166 -- We want the route only to be applied if we match the current pattern and
168 pattern <- rulesPattern <$> ask
169 version' <- rulesVersion <$> ask
170 unRules $ tellRoute $ matchRoute
171 (pattern `mappend` fromVersion version') route'
174--------------------------------------------------------------------------------
175-- | Get a list of resources matching the current pattern. This will also set
176-- the correct group to the identifiers.
177resources :: Rules [Identifier]
178resources = Rules $ do
179 pattern <- rulesPattern <$> ask
180 provider <- rulesProvider <$> ask
181 g <- rulesVersion <$> ask
182 return $ filterMatches pattern $ map (setVersion g) $ resourceList provider
185--------------------------------------------------------------------------------
186-- | Generate a fresh Identifier with a given prefix
188freshIdentifier :: String -- ^ Prefix
189 -> Rules Identifier -- ^ Fresh identifier
190freshIdentifier prefix = Rules $ do
192 let index = rulesNextIdentifier state
193 id' = fromFilePath $ prefix ++ "/" ++ show index
194 put $ state {rulesNextIdentifier = index + 1}
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list