@@ -1,13 +1,19 @@
1−-- | This module provides a monadic DSL in which the user can specify the
2−-- different rules used to run the compilers
1+-- | This module provides a declarative DSL in which the user can specify the
2+-- different rules used to run the compilers.
3+--
4+-- The convention is to just list all items in the 'RulesM' monad, routes and
5+-- compilation rules.
6+--
7+-- A typical usage example would be:
8+--
9+-- > main = hakyll $ do
10+-- > route "posts/*" (setExtension "html")
11+-- > compile "posts/*" someCompiler
312--
413{-# LANGUAGE GeneralizedNewtypeDeriving, OverloadedStrings #-}
514module Hakyll.Core.Rules
6− ( CompileRule (..)
7− , RuleSet (..)
8− , RulesM
15+ ( RulesM
916 , Rules
10− , runRules
1117 , compile
1218 , create
1319 , route
@@ -15,12 +21,12 @@ module Hakyll.Core.Rules
1521 , metaCompileWith
1622 ) where
1723
18−import Control.Applicative (Applicative, (<$>))
19−import Control.Monad.Writer (WriterT, execWriterT, tell)
20−import Control.Monad.Reader (ReaderT, runReaderT, ask)
24+import Control.Applicative ((<$>))
25+import Control.Monad.Writer (tell)
26+import Control.Monad.Reader (ask)
2127import Control.Arrow (second, (>>>), arr, (>>^))
22−import Control.Monad.State (State, evalState, get, put)
23−import Data.Monoid (Monoid, mempty, mappend)
28+import Control.Monad.State (get, put)
29+import Data.Monoid (mempty)
2430
2531import Data.Typeable (Typeable)
2632import Data.Binary (Binary)
@@ -32,53 +38,7 @@ import Hakyll.Core.Compiler.Internal
3238import Hakyll.Core.Routes
3339import Hakyll.Core.CompiledItem
3440import Hakyll.Core.Writable
35−
36−-- | Output of a compiler rule
37−--
38−-- * The compiler will produce a simple item. This is the most common case.
39−--
40−-- * The compiler will produce more compilers. These new compilers need to be
41−-- added to the runtime if possible, since other items might depend upon them.
42−--
43−data CompileRule = CompileRule CompiledItem
44− | MetaCompileRule [(Identifier, Compiler () CompileRule)]
45−
46−-- | A collection of rules for the compilation process
47−--
48−data RuleSet = RuleSet
49− { rulesRoutes :: Routes
50− , rulesCompilers :: [(Identifier, Compiler () CompileRule)]
51− }
52−
53−instance Monoid RuleSet where
54− mempty = RuleSet mempty mempty
55− mappend (RuleSet r1 c1) (RuleSet r2 c2) =
56− RuleSet (mappend r1 r2) (mappend c1 c2)
57−
58−-- | Rule state
59−--
60−data RuleState = RuleState
61− { rulesMetaCompilerIndex :: Int
62− } deriving (Show)
63−
64−-- | The monad used to compose rules
65−--
66−newtype RulesM a = RulesM
67− { unRulesM :: ReaderT ResourceProvider (WriterT RuleSet (State RuleState)) a
68− } deriving (Monad, Functor, Applicative)
69−
70−-- | Simplification of the RulesM type; usually, it will not return any
71−-- result.
72−--
73−type Rules = RulesM ()
74−
75−-- | Run a Rules monad, resulting in a 'RuleSet'
76−--
77−runRules :: Rules -> ResourceProvider -> RuleSet
78−runRules rules provider =
79− evalState (execWriterT $ runReaderT (unRulesM rules) provider) state
80− where
81− state = RuleState {rulesMetaCompilerIndex = 0}
41+import Hakyll.Core.Rules.Internal
8242
8343-- | Add a route
8444--
@@ -95,10 +55,11 @@ tellCompilers compilers = RulesM $ tell $ RuleSet mempty $
9555 where
9656 boxCompiler = (>>> arr compiledItem >>> arr CompileRule)
9757
98−-- | Add a compilation rule
58+-- | Add a compilation rule to the rules.
9959--
10060-- This instructs all resources matching the given pattern to be compiled using
101−-- the given compiler
61+-- the given compiler. When no resources match the given pattern, nothing will
62+-- happen. In this case, you might want to have a look at 'create'.
10263--
10364compile :: (Binary a, Typeable a, Writable a)
10465 => Pattern -> Compiler () a -> Rules
@@ -108,18 +69,32 @@ compile pattern compiler = RulesM $ do
10869
10970-- | Add a compilation rule
11071--
111−-- This sets a compiler for the given identifier
72+-- This sets a compiler for the given identifier. No resource is needed, since
73+-- we are creating the item from scratch.
11274--
11375create :: (Binary a, Typeable a, Writable a)
11476 => Identifier -> Compiler () a -> Rules
11577create identifier compiler = tellCompilers [(identifier, compiler)]
11678
117−-- | Add a route
79+-- | Add a route.
80+--
81+-- This adds a route for all items matching the given pattern.
11882--
11983route :: Pattern -> Routes -> Rules
12084route pattern route' = tellRoute $ ifMatch pattern route'
12185
122−-- | Add a compiler that produces other compilers over time
86+-- | Apart from regular compilers, one is also able to specify metacompilers.
87+-- Metacompilers are a special class of compilers: they are compilers which
88+-- produce other compilers.
89+--
90+-- And indeed, we can see that the first argument to 'metaCompile' is a
91+-- 'Compiler' which produces a list of ('Identifier', 'Compiler') pairs. The
92+-- idea is simple: 'metaCompile' produces a list of compilers, and the
93+-- corresponding identifiers.
94+--
95+-- For simple hakyll systems, it is no need for this construction. More
96+-- formally, it is only needed when the content of one or more items determines
97+-- which items must be rendered.
12398--
12499metaCompile :: (Binary a, Typeable a, Writable a)
125100 => Compiler () [(Identifier, Compiler () a)]