on master help sign in
WIP
commitf0af2a3b79ea7eea3f521f79fd903f9023ec85df authorJasper Van der Jeugt <m@jaspervdj.be> dateTue 13 Nov 2012, 17:31 (14 years ago) parentd2e913f
16 files changed+324−543
hakyll.cabal+1−1 src/Hakyll.hs−2 src/Hakyll/Core/Compiler.hs+76−332 src/Hakyll/Core/Compiler/Internal.hs+22−11 src/Hakyll/Core/Compiler/Require.hs+63 src/Hakyll/Core/Runtime.hs+11−9 src/Hakyll/Core/UnixFilter.hs+39−30 src/Hakyll/Core/Writable/CopyFile.hs+11−10 src/Hakyll/Core/Writable/WritableTuple.hs−37 src/Hakyll/Web/CompressCss.hs+31−22 src/Hakyll/Web/Page.hs+6−9 src/Hakyll/Web/Pandoc.hs+20−31 src/Hakyll/Web/Pandoc/Biblio.hs+29−30 src/Hakyll/Web/Pandoc/FileType.hs+3−3 src/Hakyll/Web/Template/Context.hs+6−8 src/Hakyll/Web/Urls/Relativize.hs+6−8
hakyll.cabal+1−1
@@ -108,7 +108,6 @@ Library
108108 Hakyll.Core.Util.String
109109 Hakyll.Core.Writable
110110 Hakyll.Core.Writable.CopyFile
111− Hakyll.Core.Writable.WritableTuple
112111 Hakyll.Main
113112 Hakyll.Web.CompressCss
114113 -- Hakyll.Web.Feed
@@ -129,6 +128,7 @@ Library
129128 Other-Modules:
130129 Hakyll.Core.CompiledItem
131130 Hakyll.Core.Compiler.Internal
131+ Hakyll.Core.Compiler.Require
132132 Hakyll.Core.DirectedGraph
133133 Hakyll.Core.DirectedGraph.Dot
134134 Hakyll.Core.ResourceProvider.Internal
src/Hakyll.hs−2
@@ -18,7 +18,6 @@ module Hakyll
1818 , module Hakyll.Core.Util.String
1919 , module Hakyll.Core.Writable
2020 , module Hakyll.Core.Writable.CopyFile
21− , module Hakyll.Core.Writable.WritableTuple
2221 , module Hakyll.Main
2322 , module Hakyll.Web.CompressCss
2423 -- , module Hakyll.Web.Feed
@@ -52,7 +51,6 @@ import Hakyll.Core.Util.File
5251import Hakyll.Core.Util.String
5352import Hakyll.Core.Writable
5453import Hakyll.Core.Writable.CopyFile
55−import Hakyll.Core.Writable.WritableTuple
5654import Hakyll.Main
5755import Hakyll.Web.CompressCss
5856-- import Hakyll.Web.Feed
src/Hakyll/Core/Compiler.hs+76−332
@@ -1,97 +1,8 @@
1−-- | A Compiler manages targets and dependencies between targets
2−--
3−-- The most distinguishing property of a 'Compiler' is that it is an Arrow. A
4−-- compiler of the type @Compiler a b@ is simply a compilation phase which takes
5−-- an @a@ as input, and produces a @b@ as output.
6−--
7−-- Compilers are chained using the '>>>' arrow operation. If we have a compiler
8−--
9−-- > getResourceString :: Compiler Resource String
10−--
11−-- which reads the resource, and a compiler
12−--
13−-- > readPage :: Compiler String (Page String)
14−--
15−-- we can chain these two compilers to get a
16−--
17−-- > (getResourceString >>> readPage) :: Compiler Resource (Page String)
18−--
19−-- Most compilers can be created by combining smaller compilers using '>>>'.
20−--
21−-- More advanced constructions are also possible using arrow, and sometimes
22−-- these are needed. For a good introduction to arrow, you can refer to
23−--
24−-- <http://en.wikibooks.org/wiki/Haskell/Understanding_arrows>
25−--
26−-- A construction worth writing a few paragraphs about here are the 'require'
27−-- functions. Different variants of this function are exported here, but they
28−-- all serve more or less the same goal.
29−--
30−-- When you use only '>>>' to chain your compilers, you get a linear pipeline --
31−-- it is not possible to add extra items from other compilers along the way.
32−-- This is where the 'require' functions come in.
33−--
34−-- This function allows you to reference other items, which are then added to
35−-- the pipeline. Let's look at this crappy ASCII illustration which represents
36−-- a pretty common scenario:
37−--
38−-- > read resource >>> pandoc render >>> layout >>> relativize URL's
39−-- >
40−-- > @templates/fancy.html@
41−--
42−-- We want to construct a pipeline of compilers to go from our resource to a
43−-- proper webpage. However, the @layout@ compiler takes more than just the
44−-- rendered page as input: it needs the @templates/fancy.html@ template as well.
45−--
46−-- This is an example of where we need the @require@ function. We can solve
47−-- this using a construction that looks like:
48−--
49−-- > ... >>> pandoc render >>> require >>> layout >>> ...
50−-- > |
51−-- > @templates/fancy.html@ ------/
52−--
53−-- This illustration can help us understand the type signature of 'require'.
54−--
55−-- > require :: (Binary a, Typeable a, Writable a)
56−-- > => Identifier a
57−-- > -> (b -> a -> c)
58−-- > -> Compiler b c
59−--
60−-- Let's look at it in detail:
61−--
62−-- > (Binary a, Typeable a, Writable a)
63−--
64−-- These are constraints for the @a@ type. @a@ (the template) needs to have
65−-- certain properties for it to be required.
66−--
67−-- > Identifier a
68−--
69−-- This is simply @templates/fancy.html@: the 'Identifier' of the item we want
70−-- to 'require', in other words, the name of the item we want to add to the
71−-- pipeline somehow.
72−--
73−-- > (b -> a -> c)
74−--
75−-- This is a function given by the user, specifying /how/ the two items shall be
76−-- merged. @b@ is the output of the previous compiler, and @a@ is the item we
77−-- just required -- the template. This means @c@ will be the final output of the
78−-- 'require' combinator.
79−--
80−-- > Compiler b c
81−--
82−-- Indeed, we have now constructed a compiler which takes a @b@ and produces a
83−-- @c@. This means that we have a linear pipeline again, thanks to the 'require'
84−-- function. So, the 'require' function actually helps to reduce to complexity
85−-- of Hakyll applications!
86−--
87−-- Note that require will fetch a previously compiled item: in our example of
88−-- the type @a@. It is /very/ important that the compiler which produced this
89−-- value, produced the right type as well!
90−--
91−{-# LANGUAGE GeneralizedNewtypeDeriving, ScopedTypeVariables #-}
1+--------------------------------------------------------------------------------
2+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
3+{-# LANGUAGE ScopedTypeVariables #-}
924module Hakyll.Core.Compiler
935 ( Compiler
94− , runCompiler
956 , getIdentifier
967 , getRoute
978 , getRouteFor
@@ -99,95 +10,52 @@ module Hakyll.Core.Compiler
9910 , getResourceString
10011 , getResourceLBS
10112 , getResourceWith
102− , fromDependency
103− , require_
10413 , require
105− , requireA
106− , requireAll_
10714 , requireAll
108− , requireAllA
10915 , cached
11016 , unsafeCompiler
111− , traceShowCompiler
17+ , logCompiler
11218 , timedCompiler
113− , byPattern
114− , byExtension
11519 ) where
11620
117−import Prelude hiding ((.), id)
118−import Control.Arrow ((>>>), (&&&), arr, first)
119−import Control.Applicative ((<$>), (*>))
120−import Control.Exception (SomeException, handle)
121−import Control.Monad.Reader (ask)
122−import Control.Monad.Trans (liftIO)
123−import Control.Monad.Error (throwError)
124−import Control.Category (Category, (.), id)
125−import Data.List (find)
126−import System.Environment (getProgName)
127−import System.FilePath (takeExtension)
12821
129−import Data.Binary (Binary)
130−import Data.Typeable (Typeable)
131−import Data.ByteString.Lazy (ByteString)
132−
133−import Hakyll.Core.Identifier
134−import Hakyll.Core.Identifier.Pattern
135−import Hakyll.Core.CompiledItem
136−import Hakyll.Core.Writable
137−import Hakyll.Core.ResourceProvider
138−import Hakyll.Core.Compiler.Internal
139−import Hakyll.Core.Store (Store)
140−import Hakyll.Core.Routes
141−import Hakyll.Core.Logger
142−import qualified Hakyll.Core.Store as Store
143−
144−-- | Run a compiler, yielding the resulting target and it's dependencies. This
145−-- version of 'runCompilerJob' also stores the result
146−--
147−runCompiler :: Compiler CompiledItem -- ^ Compiler to run
148− -> Identifier () -- ^ Target identifier
149− -> ResourceProvider -- ^ Resource provider
150− -> [Identifier ()] -- ^ Universe
151− -> Routes -- ^ Route
152− -> Store -- ^ Store
153− -> Bool -- ^ Was the resource modified?
154− -> Logger -- ^ Logger
155− -> IO (Throwing CompiledItem) -- ^ Resulting item
156−runCompiler compiler id' provider universe routes store modified logger = do
157− -- Run the compiler job
158− result <- handle (\(e :: SomeException) -> return $ Left $ show e) $
159− runCompilerJob compiler id' provider universe routes store modified
160− logger
22+--------------------------------------------------------------------------------
23+import Control.Applicative ((<$>))
24+import Data.Binary (Binary)
25+import Data.ByteString.Lazy (ByteString)
26+import Data.Typeable (Typeable)
27+import Prelude hiding (id, (.))
28+import System.Environment (getProgName)
16129
162− -- Inspect the result
163− case result of
164− -- In case we compiled an item, we will store a copy in the cache first,
165− -- before we return control. This makes sure the compiled item can later
166− -- be accessed by e.g. require.
167− Right (CompiledItem x) ->
168− Store.set store ["Hakyll.Core.Compiler.runCompiler", show id'] x
16930
170− -- Otherwise, we do nothing here
171− _ -> return ()
31+--------------------------------------------------------------------------------
32+import Hakyll.Core.Compiler.Internal
33+import Hakyll.Core.Compiler.Require
34+import Hakyll.Core.Identifier
35+import Hakyll.Core.Logger
36+import Hakyll.Core.ResourceProvider
37+import Hakyll.Core.Routes
38+import qualified Hakyll.Core.Store as Store
39+import Hakyll.Core.Writable
17240
173− return result
17441
42+--------------------------------------------------------------------------------
17543-- | Get the identifier of the item that is currently being compiled
176−--
177−getIdentifier :: Compiler (Identifier b)
178−getIdentifier = fromJob $ const $ CompilerM $
179− castIdentifier . compilerIdentifier <$> ask
44+getIdentifier :: Compiler Identifier
45+getIdentifier = compilerIdentifier <$> compilerAsk
46+
18047
48+--------------------------------------------------------------------------------
18149-- | Get the route we are using for this item
182−--
18350getRoute :: Compiler (Maybe FilePath)
184−getRoute = getIdentifier >>> getRouteFor
51+getRoute = getIdentifier >>= getRouteFor
18552
53+
54+--------------------------------------------------------------------------------
18655-- | Get the route for a specified item
187−--
188−getRouteFor :: Compiler (Identifier a -> Maybe FilePath)
189−getRouteFor = fromJob $ \identifier -> CompilerM $ do
190− routes <- compilerRoutes <$> ask
56+getRouteFor :: Identifier -> Compiler (Maybe FilePath)
57+getRouteFor identifier = do
58+ routes <- compilerRoutes <$> compilerAsk
19159 return $ runRoutes routes identifier
19260
19361
@@ -197,7 +65,6 @@ getResourceBody :: Compiler String
19765getResourceBody = getResourceWith resourceBody
19866
19967
200−
20168--------------------------------------------------------------------------------
20269-- | Get the resource we are compiling as a string
20370getResourceString :: Compiler String
@@ -213,188 +80,65 @@ getResourceLBS = getResourceWith $ const resourceLBS
21380
21481--------------------------------------------------------------------------------
21582-- | Overloadable function for 'getResourceString' and 'getResourceLBS'
216−getResourceWith :: (ResourceProvider -> Identifier a -> IO b) -> Compiler b
217−getResourceWith reader = fromJob $ \_ -> CompilerM $ do
218− provider <- compilerResourceProvider <$> ask
219− r <- compilerIdentifier <$> ask
220− let filePath = toFilePath r
221− if resourceExists provider r
222− then liftIO $ reader provider $ castIdentifier r
223− else throwError $ error' filePath
224− where
225− error' id' = "Hakyll.Core.Compiler.getResourceWith: resource "
226− ++ show id' ++ " not found"
227−
228−-- | Auxiliary: get a dependency
229−--
230−getDependency :: (Binary a, Writable a, Typeable a)
231− => Identifier a -> CompilerM a
232−getDependency id' = CompilerM $ do
233− store <- compilerStore <$> ask
234− result <- liftIO $
235− Store.get store ["Hakyll.Core.Compiler.runCompiler", show id']
236− case result of
237− Store.NotFound -> throwError notFound
238− Store.WrongType e r -> throwError $ wrongType e r
239− Store.Found x -> return x
240− where
241− notFound =
242− "Hakyll.Core.Compiler.getDependency: " ++ show id' ++ " was " ++
243− "not found in the cache, the cache might be corrupted or " ++
244− "the item you are referring to might not exist"
245− wrongType e r =
246− "Hakyll.Core.Compiler.getDependency: " ++ show id' ++ " was found " ++
247− "in the cache, but does not have the right type: expected " ++ show e ++
248− " but got " ++ show r
249−
250−-- | Variant of 'require' which drops the current value
251−--
252−require_ :: (Binary a, Typeable a, Writable a)
253− => Identifier a
254− -> Compiler a
255−require_ identifier =
256− fromDependency identifier >>> fromJob (const $ getDependency identifier)
257−
258−-- | Require another target. Using this function ensures automatic handling of
259−-- dependencies
260−--
261−{-
262−require :: (Binary a, Typeable a, Writable a)
263− => Identifier a
264− -> (b -> a -> c)
265− -> Compiler b c
266−require identifier = requireA identifier . arr . uncurry
267−
268−-- | Arrow-based variant of 'require'
269−--
270−requireA :: (Binary a, Typeable a, Writable a)
271− => Identifier a
272− -> Compiler (b, a) c
273− -> Compiler b c
274−requireA identifier = (id &&& require_ identifier >>>)
275−-}
276−
277−-- | Variant of 'requireAll' which drops the current value
278−--
279−requireAll_ :: (Binary a, Typeable a, Writable a)
280− => Pattern a
281− -> Compiler [a]
282−requireAll_ pattern = fromDependencies (const getDeps) *> fromJob requireAll_'
83+getResourceWith :: (ResourceProvider -> Identifier -> IO a) -> Compiler a
84+getResourceWith reader = do
85+ provider <- compilerProvider <$> compilerAsk
86+ id' <- compilerIdentifier <$> compilerAsk
87+ let filePath = toFilePath id'
88+ if resourceExists provider id'
89+ then compilerUnsafeIO $ reader provider id'
90+ else compilerThrow $ error' filePath
28391 where
284− getDeps = map castIdentifier . filterMatches pattern . map castIdentifier
285− requireAll_' = const $ CompilerM $ do
286− deps <- getDeps . compilerUniverse <$> ask
287− mapM (unCompilerM . getDependency) deps
92+ error' fp = "Hakyll.Core.Compiler.getResourceWith: resource " ++
93+ show fp ++ " not found"
28894
289−-- | Require a number of targets. Using this function ensures automatic handling
290−-- of dependencies
291−--
292−{-
293−requireAll :: (Binary a, Typeable a, Writable a)
294− => Pattern a
295− -> (b -> [a] -> c)
296− -> Compiler b c
297−requireAll pattern = requireAllA pattern . arr . uncurry
298−
299−-- | Arrow-based variant of 'requireAll'
300−--
301−requireAllA :: (Binary a, Typeable a, Writable a)
302− => Pattern a
303− -> Compiler (b, [a]) c
304− -> Compiler b c
305−requireAllA pattern = (id &&& requireAll_ pattern >>>)
306−-}
30795
96+--------------------------------------------------------------------------------
30897cached :: (Binary a, Typeable a, Writable a)
30998 => String
31099 -> Compiler a
311100 -> Compiler a
312−cached name (Compiler d j) = Compiler d $ CompilerM $ do
313− logger <- compilerLogger <$> ask
314− identifier <- castIdentifier . compilerIdentifier <$> ask
315− store <- compilerStore <$> ask
316− modified <- compilerResourceModified <$> ask
317− progName <- liftIO getProgName
318− report logger $ "Checking cache: " ++ if modified then "modified" else "OK"
101+cached name compiler = do
102+ logger <- compilerLogger <$> compilerAsk
103+ id' <- compilerIdentifier <$> compilerAsk
104+ store <- compilerStore <$> compilerAsk
105+ provider <- compilerProvider <$> compilerAsk
106+ modified <- compilerUnsafeIO $ resourceModified provider id'
107+ compilerUnsafeIO $ report logger $
108+ "Checking cache: " ++ if modified then "modified" else "OK"
319109 if modified
320− then do v <- unCompilerM $ j ()
321− liftIO $ Store.set store [name, show identifier] v
322− return v
323− else do v <- liftIO $ Store.get store [name, show identifier]
324− case v of Store.Found v' -> return v'
325− _ -> throwError (error' progName)
110+ then do
111+ x <- compiler
112+ compilerUnsafeIO $ Store.set store [name, show id'] x
113+ return x
114+ else do
115+ x <- compilerUnsafeIO $ Store.get store [name, show id']
116+ progName <- compilerUnsafeIO getProgName
117+ case x of Store.Found x' -> return x'
118+ _ -> compilerThrow (error' progName)
326119 where
327120 error' progName =
328121 "Hakyll.Core.Compiler.cached: Cache corrupt! " ++
329122 "Try running: " ++ progName ++ " clean"
330123
331−-- | Create an unsafe compiler from a function in IO
332−--
333−unsafeCompiler :: (a -> IO b) -- ^ Function to lift
334− -> Compiler (a -> b) -- ^ Resulting compiler
335−unsafeCompiler f = fromJob $ CompilerM . liftIO . f
336124
337−-- | Compiler for debugging purposes
338−--
339−traceShowCompiler :: Show a => Compiler a a
340−traceShowCompiler = fromJob $ \x -> CompilerM $ do
341− logger <- compilerLogger <$> ask
342− report logger $ show x
343− return x
125+--------------------------------------------------------------------------------
126+unsafeCompiler :: IO a -> Compiler a
127+unsafeCompiler = compilerUnsafeIO
344128
345−-- | Log and time a compiler
346−--
347−timedCompiler :: String -- ^ Message
348− -> Compiler a b -- ^ Compiler to time
349− -> Compiler a b -- ^ Resulting compiler
350−timedCompiler msg (Compiler d j) = Compiler d $ \x -> CompilerM $ do
351− logger <- compilerLogger <$> ask
352− timed logger msg $ unCompilerM $ j x
353129
354−-- | Choose a compiler by identifier
355−--
356−-- For example, assume that most content files need to be compiled
357−-- normally, but a select few need an extra step in the pipeline:
358−--
359−-- > compile $ pageCompiler >>> byPattern id
360−-- > [ ("projects.md", addProjectListCompiler)
361−-- > , ("sitemap.md", addSiteMapCompiler)
362−-- > ]
363−--
364−byPattern :: Compiler a b -- ^ Default compiler
365− -> [(Pattern (), Compiler a b)] -- ^ Choices
366− -> Compiler a b -- ^ Resulting compiler
367−byPattern defaultCompiler choices = Compiler deps job
368− where
369− -- Lookup the compiler, give an error when it is not found
370− lookup' identifier = maybe defaultCompiler snd $
371− find (\(p, _) -> matches p identifier) choices
372− -- Collect the dependencies of the choice
373− deps = do
374− identifier <- castIdentifier . dependencyIdentifier <$> ask
375− compilerDependencies $ lookup' identifier
376− -- Collect the job of the choice
377− job x = CompilerM $ do
378− identifier <- castIdentifier . compilerIdentifier <$> ask
379− unCompilerM $ compilerJob (lookup' identifier) x
130+--------------------------------------------------------------------------------
131+-- | Compiler for debugging purposes
132+logCompiler :: String -> Compiler ()
133+logCompiler msg = do
134+ logger <- compilerLogger <$> compilerAsk
135+ compilerUnsafeIO $ report logger msg
380136
381−-- | Choose a compiler by extension
382−--
383−-- Example:
384−--
385−-- > match "css/*" $ do
386−-- > route $ setExtension "css"
387−-- > compile $ byExtension (error "Not a (S)CSS file")
388−-- > [ (".css", compressCssCompiler)
389−-- > , (".scss", sass)
390−-- > ]
391−--
392−-- This piece of code will select the @compressCssCompiler@ for @.css@ files,
393−-- and the @sass@ compiler (defined elsewhere) for @.scss@ files.
394−--
395−byExtension :: Compiler a b -- ^ Default compiler
396− -> [(String, Compiler a b)] -- ^ Choices
397− -> Compiler a b -- ^ Resulting compiler
398−byExtension defaultCompiler = byPattern defaultCompiler . map (first extPattern)
399− where
400− extPattern c = predicate $ (== c) . takeExtension . toFilePath
137+
138+--------------------------------------------------------------------------------
139+-- | Log and time a compiler
140+timedCompiler :: String -- ^ Message
141+ -> Compiler a -- ^ Compiler to time
142+ -> Compiler a -- ^ Resulting compiler
143+timedCompiler msg compiler = Compiler $ \r ->
144+ timed (compilerLogger r) msg $ unCompiler compiler r
src/Hakyll/Core/Compiler/Internal.hs+22−11
@@ -5,19 +5,21 @@
55module Hakyll.Core.Compiler.Internal
66 ( CompilerRead (..)
77 , CompilerResult (..)
8− , Compiler
8+ , Compiler (..)
99 , runCompiler
1010 , compilerTell
1111 , compilerAsk
1212 , compilerThrow
1313 , compilerCatch
1414 , compilerResult
15+ , compilerUnsafeIO
1516 ) where
1617
1718
1819--------------------------------------------------------------------------------
1920import Control.Applicative (Alternative (..),
2021 Applicative (..))
22+import Control.Exception (SomeException, handle)
2123import Data.Monoid (mappend, mempty)
2224
2325
@@ -34,19 +36,17 @@ import Hakyll.Core.Store
3436-- | Environment in which a compiler runs
3537data CompilerRead = CompilerRead
3638 { -- | Target identifier
37− compilerIdentifier :: Identifier
39+ compilerIdentifier :: Identifier
3840 , -- | Resource provider
39− compilerResourceProvider :: ResourceProvider
41+ compilerProvider :: ResourceProvider
4042 , -- | List of all known identifiers
41− compilerUniverse :: [Identifier]
43+ compilerUniverse :: [Identifier]
4244 , -- | Site routes
43− compilerRoutes :: Routes
45+ compilerRoutes :: Routes
4446 , -- | Compiler store
45− compilerStore :: Store
46− , -- | Flag indicating if the underlying resource was modified
47− compilerResourceModified :: Bool
47+ compilerStore :: Store
4848 , -- | Logger
49− compilerLogger :: Logger
49+ compilerLogger :: Logger
5050 }
5151
5252
@@ -111,7 +111,10 @@ instance Applicative Compiler where
111111
112112--------------------------------------------------------------------------------
113113runCompiler :: Compiler a -> CompilerRead -> IO (CompilerResult a)
114−runCompiler = unCompiler
114+runCompiler compiler read' = handle handler $ unCompiler compiler read'
115+ where
116+ handler :: SomeException -> IO (CompilerResult a)
117+ handler e = return $ CompilerError $ show e
115118
116119
117120--------------------------------------------------------------------------------
@@ -128,7 +131,7 @@ compilerAsk = Compiler $ \r -> return $ CompilerDone r mempty
128131
129132
130133--------------------------------------------------------------------------------
131−compilerTell :: [Dependency] -> Compiler ()
134+compilerTell :: CompilerWrite -> Compiler ()
132135compilerTell deps = Compiler $ \_ -> return $ CompilerDone () deps
133136{-# INLINE compilerTell #-}
134137
@@ -154,3 +157,11 @@ compilerCatch (Compiler x) f = Compiler $ \r -> do
154157compilerResult :: CompilerResult a -> Compiler a
155158compilerResult x = Compiler $ \_ -> return x
156159{-# INLINE compilerResult #-}
160+
161+
162+--------------------------------------------------------------------------------
163+compilerUnsafeIO :: IO a -> Compiler a
164+compilerUnsafeIO io = Compiler $ \_ -> do
165+ x <- io
166+ return $ CompilerDone x mempty
167+{-# INLINE compilerUnsafeIO #-}
src/Hakyll/Core/Compiler/Require.hsnew file+63
@@ -0,0 +1,63 @@
1+--------------------------------------------------------------------------------
2+module Hakyll.Core.Compiler.Require
3+ ( save
4+ , require
5+ , requireAll
6+ ) where
7+
8+
9+--------------------------------------------------------------------------------
10+import Control.Applicative ((<$>))
11+import Data.Binary (Binary)
12+import Data.Typeable
13+
14+
15+--------------------------------------------------------------------------------
16+import Hakyll.Core.Compiler.Internal
17+import Hakyll.Core.Dependencies
18+import Hakyll.Core.Identifier
19+import Hakyll.Core.Identifier.Pattern
20+import Hakyll.Core.Store (Store)
21+import qualified Hakyll.Core.Store as Store
22+
23+
24+--------------------------------------------------------------------------------
25+save :: (Binary a, Typeable a) => Store -> Identifier -> a -> IO ()
26+save store identifier x = Store.set store (key identifier) x
27+
28+
29+--------------------------------------------------------------------------------
30+require :: (Binary a, Typeable a) => Identifier -> Compiler a
31+require id' = do
32+ store <- compilerStore <$> compilerAsk
33+
34+ compilerTell [Identifier id']
35+ compilerResult $ CompilerRequire id' $ do
36+ result <- compilerUnsafeIO $ Store.get store (key id')
37+ case result of
38+ Store.NotFound -> compilerThrow notFound
39+ Store.WrongType e r -> compilerThrow $ wrongType e r
40+ Store.Found x -> return x
41+ where
42+ notFound =
43+ "Hakyll.Core.Compiler.Require.require: " ++ show id' ++ " was " ++
44+ "not found in the cache, the cache might be corrupted or " ++
45+ "the item you are referring to might not exist"
46+ wrongType e r =
47+ "Hakyll.Core.Compiler.Require.require: " ++ show id' ++ " was found " ++
48+ "in the cache, but does not have the right type: expected " ++ show e ++
49+ " but got " ++ show r
50+
51+
52+--------------------------------------------------------------------------------
53+requireAll :: (Binary a, Typeable a) => Pattern -> Compiler [a]
54+requireAll pattern = do
55+ universe <- compilerUniverse <$> compilerAsk
56+ let matching = filterMatches pattern universe
57+ compilerTell [Pattern pattern matching]
58+ mapM require matching
59+
60+
61+--------------------------------------------------------------------------------
62+key :: Identifier -> [String]
63+key identifier = ["Hakyll.Core.Compiler.Require", show identifier]
src/Hakyll/Core/Runtime.hs+11−9
@@ -23,6 +23,7 @@ import System.FilePath ((</>))
2323--------------------------------------------------------------------------------
2424import Hakyll.Core.CompiledItem
2525import Hakyll.Core.Compiler.Internal
26+import Hakyll.Core.Compiler.Require
2627import Hakyll.Core.Configuration
2728import Hakyll.Core.Dependencies
2829import Hakyll.Core.Identifier
@@ -159,16 +160,14 @@ chase trail id'
159160 config <- runtimeConfiguration <$> ask
160161
161162 section logger $ "Processing " ++ show id'
162− isModified <- liftIO $ resourceModified provider id'
163163 let compiler = todo M.! id'
164164 read' = CompilerRead
165− { compilerIdentifier = id'
166− , compilerResourceProvider = provider
167− , compilerUniverse = map fst universe
168− , compilerRoutes = routes
169− , compilerStore = store
170− , compilerResourceModified = isModified
171− , compilerLogger = logger
165+ { compilerIdentifier = id'
166+ , compilerProvider = provider
167+ , compilerUniverse = map fst universe
168+ , compilerRoutes = routes
169+ , compilerStore = store
170+ , compilerLogger = logger
172171 }
173172
174173 result <- timed logger "Compiling" $ liftIO $ runCompiler compiler read'
@@ -177,7 +176,7 @@ chase trail id'
177176 CompilerError e -> throwError e
178177
179178 -- Huge success
180− CompilerDone compiled facts -> do
179+ CompilerDone (CompiledItem compiled) facts -> do
181180 -- Write if necessary
182181 case runRoutes routes id' of
183182 Nothing -> return ()
@@ -186,6 +185,9 @@ chase trail id'
186185 liftIO $ makeDirectories path
187186 liftIO $ write path compiled
188187
188+ -- Save! (For require)
189+ liftIO $ save store id' compiled
190+
189191 -- Update state
190192 modify $ \s -> s
191193 { runtimeDone = S.insert id' (runtimeDone s)
src/Hakyll/Core/UnixFilter.hs+39−30
@@ -1,29 +1,32 @@
1+--------------------------------------------------------------------------------
12-- | A Compiler that supports unix filters.
2−--
33module Hakyll.Core.UnixFilter
44 ( unixFilter
55 , unixFilterLBS
66 ) where
77
8−import Control.Concurrent (forkIO)
9−import System.Posix.Process (executeFile, forkProcess)
10−import System.Posix.IO ( dupTo, createPipe, stdInput
11− , stdOutput, closeFd, fdToHandle
12− )
13−import System.IO ( Handle, hPutStr, hClose, hGetContents
14− , hSetEncoding, localeEncoding
15− )
168
17−import Data.ByteString.Lazy (ByteString)
9+--------------------------------------------------------------------------------
10+import Control.Concurrent (forkIO)
11+import Data.ByteString.Lazy (ByteString)
1812import qualified Data.ByteString.Lazy as LB
13+import System.IO (Handle, hClose, hGetContents, hPutStr,
14+ hSetEncoding, localeEncoding)
15+import System.Posix.IO (closeFd, createPipe, dupTo, fdToHandle,
16+ stdInput, stdOutput)
17+import System.Posix.Process (executeFile, forkProcess)
18+
19+
20+--------------------------------------------------------------------------------
21+import Hakyll.Core.Compiler
1922
20−import Hakyll.Core.Compiler
2123
24+--------------------------------------------------------------------------------
2225-- | Use a unix filter as compiler. For example, we could use the 'rev' program
2326-- as a compiler.
2427--
25−-- > rev :: Compiler Resource String
26−-- > rev = getResourceString >>> unixFilter "rev" []
28+-- > rev :: Compiler String
29+-- > rev = getResourceString >>= unixFilter "rev" []
2730--
2831-- A more realistic example: one can use this to call, for example, the sass
2932-- compiler on CSS files. More information about sass can be found here:
@@ -34,12 +37,13 @@ import Hakyll.Core.Compiler
3437--
3538-- > match "style.scss" $ do
3639-- > route $ setExtension "css"
37−-- > compile $ getResourceString >>> unixFilter "sass" ["-s", "--scss"]
38−-- > >>> arr compressCss
39−--
40−unixFilter :: String -- ^ Program name
41− -> [String] -- ^ Program args
42− -> Compiler String String -- ^ Resulting compiler
40+-- > compile $ getResourceString >>=
41+-- > unixFilter "sass" ["-s", "--scss"] >>=
42+-- > compressCssCompiler
43+unixFilter :: String -- ^ Program name
44+ -> [String] -- ^ Program args
45+ -> String -- ^ Program input
46+ -> Compiler String -- ^ Program output
4347unixFilter = unixFilterWith writer reader
4448 where
4549 writer handle input = do
@@ -49,30 +53,35 @@ unixFilter = unixFilterWith writer reader
4953 hSetEncoding handle localeEncoding
5054 hGetContents handle
5155
56+
57+--------------------------------------------------------------------------------
5258-- | Variant of 'unixFilter' that should be used for binary files
5359--
5460-- > match "music.wav" $ do
5561-- > route $ setExtension "ogg"
56−-- > compile $ getResourceLBS >>> unixFilter "oggenc" ["-"]
57−--
58−unixFilterLBS :: String -- ^ Program name
59− -> [String] -- ^ Program args
60− -> Compiler ByteString ByteString -- ^ Resulting compiler
62+-- > compile $ getResourceLBS >>= unixFilter "oggenc" ["-"]
63+unixFilterLBS :: String -- ^ Program name
64+ -> [String] -- ^ Program args
65+ -> ByteString -- ^ Program input
66+ -> Compiler ByteString -- ^ Program output
6167unixFilterLBS = unixFilterWith LB.hPutStr LB.hGetContents
6268
69+
70+--------------------------------------------------------------------------------
6371-- | Overloaded compiler
64−--
6572unixFilterWith :: (Handle -> i -> IO ()) -- ^ Writer
6673 -> (Handle -> IO o) -- ^ Reader
6774 -> String -- ^ Program name
6875 -> [String] -- ^ Program args
69− -> Compiler i o -- ^ Resulting compiler
70−unixFilterWith writer reader programName args =
76+ -> i -- ^ Program input
77+ -> Compiler o -- ^ Program output
78+unixFilterWith writer reader programName args input =
7179 timedCompiler ("Executing external program " ++ programName) $
72− unsafeCompiler $ unixFilterIO writer reader programName args
80+ unsafeCompiler $ unixFilterIO writer reader programName args input
81+
7382
83+--------------------------------------------------------------------------------
7484-- | Internally used function
75−--
7685unixFilterIO :: (Handle -> i -> IO ())
7786 -> (Handle -> IO o)
7887 -> String
@@ -83,7 +92,7 @@ unixFilterIO writer reader programName args input = do
8392 -- Create pipes
8493 (stdinRead, stdinWrite) <- createPipe
8594 (stdoutRead, stdoutWrite) <- createPipe
86−
95+
8796 -- Fork the child
8897 _ <- forkProcess $ do
8998 -- Copy our pipes over the regular stdin/stdout
src/Hakyll/Core/Writable/CopyFile.hs+11−10
@@ -1,6 +1,7 @@
11--------------------------------------------------------------------------------
22-- | Exports simple compilers to just copy files
3−{-# LANGUAGE GeneralizedNewtypeDeriving, DeriveDataTypeable #-}
3+{-# LANGUAGE DeriveDataTypeable #-}
4+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
45module Hakyll.Core.Writable.CopyFile
56 ( CopyFile (..)
67 , copyFileCompiler
@@ -8,16 +9,16 @@ module Hakyll.Core.Writable.CopyFile
89
910
1011--------------------------------------------------------------------------------
11−import Control.Arrow ((>>^))
12−import System.Directory (copyFile)
13−import Data.Typeable (Typeable)
14−import Data.Binary (Binary)
12+import Control.Applicative ((<$>))
13+import Data.Binary (Binary)
14+import Data.Typeable (Typeable)
15+import System.Directory (copyFile)
1516
1617
1718--------------------------------------------------------------------------------
18−import Hakyll.Core.Writable
19−import Hakyll.Core.Compiler
20−import Hakyll.Core.Identifier
19+import Hakyll.Core.Compiler
20+import Hakyll.Core.Identifier
21+import Hakyll.Core.Writable
2122
2223
2324--------------------------------------------------------------------------------
@@ -32,5 +33,5 @@ instance Writable CopyFile where
3233
3334
3435--------------------------------------------------------------------------------
35−copyFileCompiler :: Compiler a CopyFile
36−copyFileCompiler = getIdentifier >>^ CopyFile . toFilePath
36+copyFileCompiler :: Compiler CopyFile
37+copyFileCompiler = CopyFile . toFilePath <$> getIdentifier
src/Hakyll/Core/Writable/WritableTuple.hsdeleted−37
@@ -1,37 +0,0 @@
1−-- | This module exposes a writable type 'WritableTuple' which is a simple
2−-- newtype wrapper around a tuple.
3−--
4−-- The idea is that, given a tuple @(a, b)@, @a@ is the value you actually want
5−-- to save to the disk, and @b@ is some additional info that you /don't/ want to
6−-- save, but that you need later, for example in a 'require' clause.
7−--
8−{-# LANGUAGE GeneralizedNewtypeDeriving, DeriveDataTypeable #-}
9−module Hakyll.Core.Writable.WritableTuple
10− ( WritableTuple (..)
11− , writableTupleFst
12− , writableTupleSnd
13− , writableTupleCompiler
14− ) where
15−
16−import Control.Arrow (arr)
17−
18−import Data.Typeable (Typeable)
19−import Data.Binary (Binary)
20−
21−import Hakyll.Core.Writable
22−import Hakyll.Core.Compiler
23−
24−newtype WritableTuple a b = WritableTuple {unWritableTuple :: (a, b)}
25− deriving (Show, Eq, Ord, Binary, Typeable)
26−
27−instance Writable a => Writable (WritableTuple a b) where
28− write dst (WritableTuple (x, _)) = write dst x
29−
30−writableTupleFst :: WritableTuple a b -> a
31−writableTupleFst = fst . unWritableTuple
32−
33−writableTupleSnd :: WritableTuple a b -> b
34−writableTupleSnd = snd . unWritableTuple
35−
36−writableTupleCompiler :: Compiler (a, b) (WritableTuple a b)
37−writableTupleCompiler = arr WritableTuple
src/Hakyll/Web/CompressCss.hs+31−22
@@ -1,50 +1,59 @@
1+--------------------------------------------------------------------------------
12-- | Module used for CSS compression. The compression is currently in a simple
23-- state, but would typically reduce the number of bytes by about 25%.
3−--
44module Hakyll.Web.CompressCss
55 ( compressCssCompiler
66 , compressCss
77 ) where
88
9−import Data.Char (isSpace)
10−import Data.List (isPrefixOf)
11−import Control.Arrow ((>>^))
129
13−import Hakyll.Core.Compiler
14−import Hakyll.Core.Util.String
10+--------------------------------------------------------------------------------
11+import Control.Applicative ((<$>))
12+import Data.Char (isSpace)
13+import Data.List (isPrefixOf)
1514
15+
16+--------------------------------------------------------------------------------
17+import Hakyll.Core.Compiler
18+import Hakyll.Core.Util.String
19+
20+
21+--------------------------------------------------------------------------------
1622-- | Compiler form of 'compressCss'
17−--
18−compressCssCompiler :: Compiler a String
19−compressCssCompiler = getResourceString >>^ compressCss
23+compressCssCompiler :: Compiler String
24+compressCssCompiler = compressCss <$> getResourceString
25+
2026
27+--------------------------------------------------------------------------------
2128-- | Compress CSS to speed up your site.
22−--
2329compressCss :: String -> String
24−compressCss = compressSeparators
25− . stripComments
26− . compressWhitespace
30+compressCss = compressSeparators . stripComments . compressWhitespace
2731
32+
33+--------------------------------------------------------------------------------
2834-- | Compresses certain forms of separators.
29−--
3035compressSeparators :: String -> String
31−compressSeparators = replaceAll "; *}" (const "}")
32− . replaceAll " *([{};:]) *" (take 1 . dropWhile isSpace)
33− . replaceAll ";+" (const ";")
36+compressSeparators =
37+ replaceAll "; *}" (const "}") .
38+ replaceAll " *([{};:]) *" (take 1 . dropWhile isSpace) .
39+ replaceAll ";+" (const ";")
40+
3441
42+--------------------------------------------------------------------------------
3543-- | Compresses all whitespace.
36−--
3744compressWhitespace :: String -> String
3845compressWhitespace = replaceAll "[ \t\n\r]+" (const " ")
3946
47+
48+--------------------------------------------------------------------------------
4049-- | Function that strips CSS comments away.
41−--
4250stripComments :: String -> String
4351stripComments [] = []
4452stripComments str
4553 | isPrefixOf "/*" str = stripComments $ eatComments $ drop 2 str
4654 | otherwise = head str : stripComments (drop 1 str)
4755 where
48− eatComments str' | null str' = []
49− | isPrefixOf "*/" str' = drop 2 str'
50− | otherwise = eatComments $ drop 1 str'
56+ eatComments str'
57+ | null str' = []
58+ | isPrefixOf "*/" str' = drop 2 str'
59+ | otherwise = eatComments $ drop 1 str'
src/Hakyll/Web/Page.hs+6−9
@@ -58,9 +58,6 @@ module Hakyll.Web.Page
5858
5959
6060--------------------------------------------------------------------------------
61−import Control.Arrow (arr, (>>>))
62−import Control.Category (id)
63−import Prelude hiding (id)
6461import Text.Pandoc (Pandoc, ParserState, WriterOptions)
6562
6663
@@ -72,14 +69,14 @@ import Hakyll.Web.Pandoc
7269
7370--------------------------------------------------------------------------------
7471-- | Read a page (do not render it)
75−readPageCompiler :: Compiler () Page
72+readPageCompiler :: Compiler Page
7673readPageCompiler = getResourceBody
7774{-# DEPRECATED readPageCompiler "Use getResourceBody" #-}
7875
7976
8077--------------------------------------------------------------------------------
8178-- | Read a page render using pandoc
82−pageCompiler :: Compiler () Page
79+pageCompiler :: Compiler Page
8380pageCompiler =
8481 pageCompilerWith defaultHakyllParserState defaultHakyllWriterOptions
8582
@@ -87,7 +84,7 @@ pageCompiler =
8784--------------------------------------------------------------------------------
8885-- | A version of 'pageCompiler' which allows you to specify your own pandoc
8986-- options
90−pageCompilerWith :: ParserState -> WriterOptions -> Compiler () Page
87+pageCompilerWith :: ParserState -> WriterOptions -> Compiler Page
9188pageCompilerWith state options = pageCompilerWithPandoc state options id
9289
9390
@@ -96,9 +93,9 @@ pageCompilerWith state options = pageCompilerWithPandoc state options id
9693-- pandoc transformation for the content
9794pageCompilerWithPandoc :: ParserState -> WriterOptions
9895 -> (Pandoc -> Pandoc)
99− -> Compiler () Page
96+ -> Compiler Page
10097pageCompilerWithPandoc state options f = cached cacheName $
101− readPageCompiler >>> pageReadPandocWith state >>>
102− arr (writePandocWith options . f)
98+ readPageCompiler >>= pageReadPandocWith state >>=
99+ return . writePandocWith options . f
103100 where
104101 cacheName = "Hakyll.Web.Page.pageCompilerWithPandoc"
src/Hakyll/Web/Pandoc.hs+20−31
@@ -10,7 +10,6 @@ module Hakyll.Web.Pandoc
1010 -- * Functions working on pages/compilers
1111 , pageReadPandoc
1212 , pageReadPandocWith
13− , pageReadPandocWithA
1413 , pageRenderPandoc
1514 , pageRenderPandocWith
1615
@@ -21,37 +20,34 @@ module Hakyll.Web.Pandoc
2120
2221
2322--------------------------------------------------------------------------------
24−import Control.Arrow ((&&&), (***), (>>>), (>>^))
25−import Control.Category (id)
23+import Control.Applicative ((<$>))
2624import Data.Maybe (fromMaybe)
27−import Prelude hiding (id)
2825import Text.Pandoc
2926
3027
3128--------------------------------------------------------------------------------
3229import Hakyll.Core.Compiler
3330import Hakyll.Core.Identifier
34−import Hakyll.Core.Util.Arrow
3531import Hakyll.Web.Page.Internal
3632import Hakyll.Web.Pandoc.FileType
3733
3834
3935--------------------------------------------------------------------------------
4036-- | Read a string using pandoc, with the default options
41−readPandoc :: FileType -- ^ Determines how parsing happens
42− -> Maybe (Identifier a) -- ^ Optional, for better error messages
43− -> Page -- ^ String to read
44− -> Pandoc -- ^ Resulting document
37+readPandoc :: FileType -- ^ Determines how parsing happens
38+ -> Maybe Identifier -- ^ Optional, for better error messages
39+ -> Page -- ^ String to read
40+ -> Pandoc -- ^ Resulting document
4541readPandoc = readPandocWith defaultHakyllParserState
4642
4743
4844--------------------------------------------------------------------------------
4945-- | Read a string using pandoc, with the supplied options
50−readPandocWith :: ParserState -- ^ Parser options
51− -> FileType -- ^ Determines parsing method
52− -> Maybe (Identifier a) -- ^ Optional, for better error messages
53− -> Page -- ^ String to read
54− -> Pandoc -- ^ Resulting document
46+readPandocWith :: ParserState -- ^ Parser options
47+ -> FileType -- ^ Determines parsing method
48+ -> Maybe Identifier -- ^ Optional, for better error messages
49+ -> Page -- ^ String to read
50+ -> Pandoc -- ^ Resulting document
5551readPandocWith state fileType' id' = case fileType' of
5652 Html -> readHtml state
5753 LaTeX -> readLaTeX state
@@ -82,38 +78,31 @@ writePandocWith = writeHtmlString
8278
8379--------------------------------------------------------------------------------
8480-- | Read the resource using pandoc
85−pageReadPandoc :: Compiler Page Pandoc
81+pageReadPandoc :: Page -> Compiler Pandoc
8682pageReadPandoc = pageReadPandocWith defaultHakyllParserState
8783
8884
8985--------------------------------------------------------------------------------
9086-- | Read the resource using pandoc
91−pageReadPandocWith :: ParserState -> Compiler Page Pandoc
92−pageReadPandocWith state = constA state &&& id >>> pageReadPandocWithA
93−
94−
95−--------------------------------------------------------------------------------
96−-- | Read the resource using pandoc. This is a (rarely needed) variant, which
97−-- comes in very useful when the parser state is the result of some arrow.
98−pageReadPandocWithA :: Compiler (ParserState, Page) Pandoc
99−pageReadPandocWithA =
100− id *** id &&& getIdentifier &&& getFileType >>^ pageReadPandocWithA'
101− where
102− pageReadPandocWithA' (s, (p, (i, t))) = readPandocWith s t (Just i) p
87+pageReadPandocWith :: ParserState -> Page -> Compiler Pandoc
88+pageReadPandocWith state page = do
89+ identifier <- getIdentifier
90+ fileType' <- getFileType
91+ return $ readPandocWith state fileType' (Just identifier) page
10392
10493
10594--------------------------------------------------------------------------------
10695-- | Render the resource using pandoc
107−pageRenderPandoc :: Compiler Page Page
96+pageRenderPandoc :: Page -> Compiler Page
10897pageRenderPandoc =
10998 pageRenderPandocWith defaultHakyllParserState defaultHakyllWriterOptions
11099
111100
112101--------------------------------------------------------------------------------
113102-- | Render the resource using pandoc
114−pageRenderPandocWith :: ParserState -> WriterOptions -> Compiler Page Page
115−pageRenderPandocWith state options =
116− pageReadPandocWith state >>^ writePandocWith options
103+pageRenderPandocWith :: ParserState -> WriterOptions -> Page -> Compiler Page
104+pageRenderPandocWith state options page =
105+ writePandocWith options <$> pageReadPandocWith state page
117106
118107
119108--------------------------------------------------------------------------------
src/Hakyll/Web/Pandoc/Biblio.hs+29−30
@@ -7,7 +7,9 @@
77-- refer to these files when you use 'pageReadPandocBiblio'. This function also
88-- takes a parser state for completeness -- you can use
99-- 'defaultHakyllParserState' if you're unsure.
10−{-# LANGUAGE Arrows, DeriveDataTypeable, GeneralizedNewtypeDeriving #-}
10+{-# LANGUAGE Arrows #-}
11+{-# LANGUAGE DeriveDataTypeable #-}
12+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
1113module Hakyll.Web.Pandoc.Biblio
1214 ( CSL
1315 , cslCompiler
@@ -18,21 +20,20 @@ module Hakyll.Web.Pandoc.Biblio
1820
1921
2022--------------------------------------------------------------------------------
21−import Control.Applicative ((<$>))
22−import Control.Arrow (arr, returnA, (>>>))
23−import Data.Typeable (Typeable)
24−import Data.Binary (Binary (..))
25−import Text.Pandoc (Pandoc, ParserState (..))
26−import Text.Pandoc.Biblio (processBiblio)
27−import qualified Text.CSL as CSL
23+import Control.Applicative ((<$>))
24+import Data.Binary (Binary (..))
25+import Data.Typeable (Typeable)
26+import qualified Text.CSL as CSL
27+import Text.Pandoc (Pandoc, ParserState (..))
28+import Text.Pandoc.Biblio (processBiblio)
2829
2930
3031--------------------------------------------------------------------------------
31−import Hakyll.Core.Compiler
32−import Hakyll.Core.Identifier
33−import Hakyll.Core.Writable
34−import Hakyll.Web.Page
35−import Hakyll.Web.Pandoc
32+import Hakyll.Core.Compiler
33+import Hakyll.Core.Identifier
34+import Hakyll.Core.Writable
35+import Hakyll.Web.Page
36+import Hakyll.Web.Pandoc
3637
3738
3839--------------------------------------------------------------------------------
@@ -41,8 +42,8 @@ newtype CSL = CSL FilePath
4142
4243
4344--------------------------------------------------------------------------------
44−cslCompiler :: Compiler () CSL
45−cslCompiler = getIdentifier >>> arr (CSL . toFilePath)
45+cslCompiler :: Compiler CSL
46+cslCompiler = CSL . toFilePath <$> getIdentifier
4647
4748
4849--------------------------------------------------------------------------------
@@ -61,26 +62,24 @@ instance Writable Biblio where
6162
6263
6364--------------------------------------------------------------------------------
64−biblioCompiler :: Compiler () Biblio
65−biblioCompiler = getIdentifier >>>
66− arr toFilePath >>> unsafeCompiler CSL.readBiblioFile >>> arr Biblio
65+biblioCompiler :: Compiler Biblio
66+biblioCompiler = do
67+ filePath <- toFilePath <$> getIdentifier
68+ unsafeCompiler $ Biblio <$> CSL.readBiblioFile filePath
6769
6870
6971--------------------------------------------------------------------------------
7072pageReadPandocBiblio :: ParserState
71− -> Identifier CSL
72− -> Identifier Biblio
73− -> Compiler Page Pandoc
74−pageReadPandocBiblio state csl refs = proc page -> do
75− CSL csl' <- require_ csl -< ()
76− Biblio refs' <- require_ refs -< ()
73+ -> CSL
74+ -> Biblio
75+ -> Page
76+ -> Compiler Pandoc
77+pageReadPandocBiblio state (CSL csl) (Biblio refs) page = do
7778 -- We need to know the citation keys, add then *before* actually parsing the
7879 -- actual page. If we don't do this, pandoc won't even consider them
7980 -- citations!
80− let cits = map CSL.refId refs'
81+ let cits = map CSL.refId refs
8182 state' = state {stateCitations = stateCitations state ++ cits}
82− pandoc <- pageReadPandocWithA -< (state', page)
83− pandoc' <- unsafeCompiler processBiblio' -< (csl', refs', pandoc)
84− returnA -< pandoc'
85− where
86− processBiblio' (c, r, p) = processBiblio c Nothing r p
83+ pandoc <- pageReadPandocWith state' page
84+ pandoc' <- unsafeCompiler $ processBiblio csl Nothing refs pandoc
85+ return pandoc'
src/Hakyll/Web/Pandoc/FileType.hs+3−3
@@ -8,7 +8,7 @@ module Hakyll.Web.Pandoc.FileType
88
99
1010--------------------------------------------------------------------------------
11−import Control.Arrow ((>>^))
11+import Control.Applicative ((<$>))
1212import System.FilePath (takeExtension)
1313
1414
@@ -62,5 +62,5 @@ fileType = fileType' . takeExtension
6262
6363--------------------------------------------------------------------------------
6464-- | Get the file type for the current file
65−getFileType :: Compiler a FileType
66−getFileType = getIdentifier >>^ fileType . toFilePath
65+getFileType :: Compiler FileType
66+getFileType = fileType . toFilePath <$> getIdentifier
src/Hakyll/Web/Template/Context.hs+6−8
@@ -26,16 +26,14 @@ import Hakyll.Web.Urls
2626
2727
2828--------------------------------------------------------------------------------
29−type Context a = Compiler (String, (Identifier a, a)) String
29+type Context a = String -> Identifier -> a -> Compiler String
3030
3131
3232--------------------------------------------------------------------------------
33−field :: String -> Compiler (Identifier a, a) String -> Context a
34−field key value = arr checkKey >>> (empty ||| value)
35− where
36− checkKey (k, x)
37− | k /= key = Left ()
38− | otherwise = Right x
33+field :: String -> (Identifier -> a -> Compiler String) -> Context a
34+field key value k' id' x
35+ | k' == key = value id' x
36+ | otherwise = empty
3937
4038
4139--------------------------------------------------------------------------------
@@ -51,7 +49,7 @@ defaultContext =
5149
5250--------------------------------------------------------------------------------
5351bodyField :: String -> Context Page
54−bodyField key = field key $ arr snd
52+bodyField key = field key $ \_ x -> return x
5553
5654
5755--------------------------------------------------------------------------------
src/Hakyll/Web/Urls/Relativize.hs+6−8
@@ -21,10 +21,7 @@ module Hakyll.Web.Urls.Relativize
2121
2222
2323--------------------------------------------------------------------------------
24−import Control.Arrow ((&&&), (>>^))
25−import Control.Category (id)
2624import Data.List (isPrefixOf)
27−import Prelude hiding (id)
2825
2926
3027--------------------------------------------------------------------------------
@@ -36,11 +33,12 @@ import Hakyll.Web.Urls
3633--------------------------------------------------------------------------------
3734-- | Compiler form of 'relativizeUrls' which automatically picks the right root
3835-- path
39−relativizeUrlsCompiler :: Compiler Page Page
40−relativizeUrlsCompiler = getRoute &&& id >>^ uncurry relativize
41− where
42− relativize Nothing = id
43− relativize (Just r) = relativizeUrls $ toSiteRoot r
36+relativizeUrlsCompiler :: Page -> Compiler Page
37+relativizeUrlsCompiler page = do
38+ route <- getRoute
39+ return $ case route of
40+ Nothing -> page
41+ Just r -> relativizeUrls (toSiteRoot r) page
4442
4543
4644--------------------------------------------------------------------------------