on master help sign in
Merge branch 'master' into type-safe-identifiers
e2cce1bJasper Van der Jeugt
examples/README.markdownnew file+14
@@ -0,0 +1,14 @@
1+Hakyll examples
2+===============
3+
4+In order of increasing complexity:
5+
6+ brochure/ A very simple brochure site
7+ morepages/ Slightly more complicated brochure site with partials
8+ simpleblog/ A simple blog
9+ feedblog/ Adds an RSS feed to the simple blog
10+ tagblog/ Adds tags to the simple blog
11+
12+In no real category:
13+
14+ hakyll/ The hakyll website (some custom pandoc options)
src/Hakyll/Core/Compiler.hs+6
@@ -93,6 +93,7 @@ module Hakyll.Core.Compiler
93 ( Compiler
93 ( Compiler
94 , runCompiler
94 , runCompiler
95 , getIdentifier
95 , getIdentifier
96+ , getResource
96 , getRoute
97 , getRoute
97 , getRouteFor
98 , getRouteFor
98 , getResourceString
99 , getResourceString
@@ -175,6 +176,11 @@ getIdentifier :: Compiler a (Identifier b)
175getIdentifier = fromJob $ const $ CompilerM $
176getIdentifier = fromJob $ const $ CompilerM $
176 castIdentifier . compilerIdentifier <$> ask
177 castIdentifier . compilerIdentifier <$> ask
177
178
179+-- | Get the resource that is currently being compiled
180+--
181+getResource :: Compiler a Resource
182+getResource = getIdentifier >>> arr fromIdentifier
183+
178-- | Get the route we are using for this item
184-- | Get the route we are using for this item
179--
185--
180getRoute :: Compiler a (Maybe FilePath)
186getRoute :: Compiler a (Maybe FilePath)
src/Hakyll/Core/Logger.hs+8−7
@@ -13,7 +13,7 @@ module Hakyll.Core.Logger
13
13
14import Control.Monad (forever)
14import Control.Monad (forever)
15import Control.Monad.Trans (MonadIO, liftIO)
15import Control.Monad.Trans (MonadIO, liftIO)
16−import Control.Applicative ((<$>), (<*>))
16+import Control.Applicative (pure, (<$>), (<*>))
17import Control.Concurrent (forkIO)
17import Control.Concurrent (forkIO)
18import Control.Concurrent.Chan.Strict (Chan, newChan, readChan, writeChan)
18import Control.Concurrent.Chan.Strict (Chan, newChan, readChan, writeChan)
19import Control.Concurrent.MVar.Strict (MVar, newEmptyMVar, takeMVar, putMVar)
19import Control.Concurrent.MVar.Strict (MVar, newEmptyMVar, takeMVar, putMVar)
@@ -24,15 +24,16 @@ import Data.Time (getCurrentTime, diffUTCTime)
24-- | Logger structure. Very complicated.
24-- | Logger structure. Very complicated.
25--
25--
26data Logger = Logger
26data Logger = Logger
27− { loggerChan :: Chan (Maybe String) -- Nothing marks the end
27+ { loggerChan :: Chan (Maybe String) -- ^ Nothing marks the end
28− , loggerSync :: MVar () -- Used for sync on quit
28+ , loggerSync :: MVar () -- ^ Used for sync on quit
29+ , loggerSink :: String -> IO () -- ^ Out sink
29 }
30 }
30
31
31-- | Create a new logger
32-- | Create a new logger
32--
33--
33−makeLogger :: IO Logger
34+makeLogger :: (String -> IO ()) -> IO Logger
34−makeLogger = do
35+makeLogger sink = do
35− logger <- Logger <$> newChan <*> newEmptyMVar
36+ logger <- Logger <$> newChan <*> newEmptyMVar <*> pure sink
36 _ <- forkIO $ loggerThread logger
37 _ <- forkIO $ loggerThread logger
37 return logger
38 return logger
38 where
39 where
@@ -42,7 +43,7 @@ makeLogger = do
42 -- Stop: sync
43 -- Stop: sync
43 Nothing -> putMVar (loggerSync logger) ()
44 Nothing -> putMVar (loggerSync logger) ()
44 -- Print and continue
45 -- Print and continue
45− Just m -> putStrLn m
46+ Just m -> loggerSink logger m
46
47
47-- | Flush the logger (blocks until flushed)
48-- | Flush the logger (blocks until flushed)
48--
49--
src/Hakyll/Core/Resource/Provider/Dummy.hs+5−3
@@ -7,15 +7,17 @@ module Hakyll.Core.Resource.Provider.Dummy
7import Data.Map (Map)
7import Data.Map (Map)
8import qualified Data.Map as M
8import qualified Data.Map as M
9
9
10−import qualified Data.ByteString.Lazy.Char8 as LBC
10+import qualified Data.Text.Lazy as TL
11+import qualified Data.Text.Lazy.Encoding as TL
12+import Data.ByteString.Lazy (ByteString)
11
13
12import Hakyll.Core.Resource
14import Hakyll.Core.Resource
13import Hakyll.Core.Resource.Provider
15import Hakyll.Core.Resource.Provider
14
16
15-- | Create a dummy 'ResourceProvider'
17-- | Create a dummy 'ResourceProvider'
16--
18--
17−dummyResourceProvider :: Map String String -> IO ResourceProvider
19+dummyResourceProvider :: Map String ByteString -> IO ResourceProvider
18dummyResourceProvider vfs = makeResourceProvider
20dummyResourceProvider vfs = makeResourceProvider
19 (map Resource (M.keys vfs))
21 (map Resource (M.keys vfs))
22+ (return . TL.unpack . TL.decodeUtf8 . (vfs M.!) . unResource)
20 (return . (vfs M.!) . unResource)
23 (return . (vfs M.!) . unResource)
21− (return . LBC.pack . (vfs M.!) . unResource)
src/Hakyll/Core/Run.hs+1−1
@@ -37,7 +37,7 @@ import Hakyll.Core.Logger
37--
37--
38run :: HakyllConfiguration -> Rules -> IO RuleSet
38run :: HakyllConfiguration -> Rules -> IO RuleSet
39run configuration rules = do
39run configuration rules = do
40− logger <- makeLogger
40+ logger <- makeLogger putStrLn
41
41
42 section logger "Initialising"
42 section logger "Initialising"
43 store <- timed logger "Creating store" $
43 store <- timed logger "Creating store" $
tests/Hakyll/Core/Store/Tests.hs+5−4
@@ -15,6 +15,7 @@ import qualified Test.HUnit as H
15
15
16import Hakyll.Core.Identifier
16import Hakyll.Core.Identifier
17import Hakyll.Core.Store
17import Hakyll.Core.Store
18+import TestSuite.Util
18
19
19tests :: [Test]
20tests :: [Test]
20tests =
21tests =
@@ -28,7 +29,7 @@ simpleSetGet = monadicIO $ do
28 identifier <- parseIdentifier . unFileName <$> pick arbitrary
29 identifier <- parseIdentifier . unFileName <$> pick arbitrary
29 FileName name <- pick arbitrary
30 FileName name <- pick arbitrary
30 value <- pick arbitrary
31 value <- pick arbitrary
31− store <- run $ makeStore "_store"
32+ store <- run $ makeStoreTest
32 run $ storeSet store name identifier (value :: String)
33 run $ storeSet store name identifier (value :: String)
33 value' <- run $ storeGet store name identifier
34 value' <- run $ storeGet store name identifier
34 assert $ Found value == value'
35 assert $ Found value == value'
@@ -38,16 +39,16 @@ persistentSetGet = monadicIO $ do
38 identifier <- parseIdentifier . unFileName <$> pick arbitrary
39 identifier <- parseIdentifier . unFileName <$> pick arbitrary
39 FileName name <- pick arbitrary
40 FileName name <- pick arbitrary
40 value <- pick arbitrary
41 value <- pick arbitrary
41− store1 <- run $ makeStore "_store"
42+ store1 <- run $ makeStoreTest
42 run $ storeSet store1 name identifier (value :: String)
43 run $ storeSet store1 name identifier (value :: String)
43 -- Now Create another store from the same dir to test persistence
44 -- Now Create another store from the same dir to test persistence
44− store2 <- run $ makeStore "_store"
45+ store2 <- run $ makeStoreTest
45 value' <- run $ storeGet store2 name identifier
46 value' <- run $ storeGet store2 name identifier
46 assert $ Found value == value'
47 assert $ Found value == value'
47
48
48wrongType :: H.Assertion
49wrongType :: H.Assertion
49wrongType = do
50wrongType = do
50− store <- makeStore "_store"
51+ store <- makeStoreTest
51 -- Store a string and try to fetch an int
52 -- Store a string and try to fetch an int
52 storeSet store "foo" "bar" ("qux" :: String)
53 storeSet store "foo" "bar" ("qux" :: String)
53 value <- storeGet store "foo" "bar" :: IO (StoreGet Int)
54 value <- storeGet store "foo" "bar" :: IO (StoreGet Int)
tests/Hakyll/Core/UnixFilter/Tests.hsnew file+50
@@ -0,0 +1,50 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+module Hakyll.Core.UnixFilter.Tests
3+ where
4+
5+import Control.Arrow ((>>>))
6+import qualified Data.Map as M
7+
8+import Test.Framework (Test)
9+import Test.Framework.Providers.HUnit (testCase)
10+import qualified Test.HUnit as H
11+import qualified Data.Text.Lazy as TL
12+import qualified Data.Text.Lazy.Encoding as TL
13+
14+import Hakyll.Core.Compiler
15+import Hakyll.Core.Resource.Provider.Dummy
16+import Hakyll.Core.UnixFilter
17+import TestSuite.Util
18+
19+tests :: [Test]
20+tests =
21+ [ testCase "unixFilter rev" unixFilterRev
22+ ]
23+
24+unixFilterRev :: H.Assertion
25+unixFilterRev = do
26+ provider <- dummyResourceProvider $ M.singleton "foo" $
27+ TL.encodeUtf8 $ TL.pack text
28+ output <- runCompilerJobTest compiler "foo" provider ["foo"]
29+ H.assert $ rev text == lines output
30+ where
31+ compiler = getResource >>> getResourceString >>> unixFilter "rev" []
32+ rev = map reverse . lines
33+
34+text :: String
35+text = unlines
36+ [ "Статья 18"
37+ , ""
38+ , "Каждый человек имеет право на свободу мысли, совести и религии; это"
39+ , "право включает свободу менять свою религию или убеждения и свободу"
40+ , "исповедовать свою религию или убеждения как единолично, так и сообща с"
41+ , "другими, публичным или частным порядком в учении, богослужении и"
42+ , "выполнении религиозных и ритуальных обрядов."
43+ , ""
44+ , "Статья 19"
45+ , ""
46+ , "Каждый человек имеет право на свободу убеждений и на свободное выражение"
47+ , "их; это право включает свободу беспрепятственно придерживаться своих"
48+ , "убеждений и свободу искать, получать и распространять информацию и идеи"
49+ , "любыми средствами и независимо от государственных границ."
50+ ]
tests/TestSuite.hs+3
@@ -7,6 +7,7 @@ import qualified Hakyll.Core.Identifier.Tests
7import qualified Hakyll.Core.Routes.Tests
7import qualified Hakyll.Core.Routes.Tests
8import qualified Hakyll.Core.Rules.Tests
8import qualified Hakyll.Core.Rules.Tests
9import qualified Hakyll.Core.Store.Tests
9import qualified Hakyll.Core.Store.Tests
10+import qualified Hakyll.Core.UnixFilter.Tests
10import qualified Hakyll.Web.Page.Tests
11import qualified Hakyll.Web.Page.Tests
11import qualified Hakyll.Web.Page.Metadata.Tests
12import qualified Hakyll.Web.Page.Metadata.Tests
12import qualified Hakyll.Web.RelativizeUrls.Tests
13import qualified Hakyll.Web.RelativizeUrls.Tests
@@ -25,6 +26,8 @@ main = defaultMain
25 Hakyll.Core.Rules.Tests.tests
26 Hakyll.Core.Rules.Tests.tests
26 , testGroup "Hakyll.Core.Store.Tests"
27 , testGroup "Hakyll.Core.Store.Tests"
27 Hakyll.Core.Store.Tests.tests
28 Hakyll.Core.Store.Tests.tests
29+ , testGroup "Hakyll.Core.UnixFilter.Tests"
30+ Hakyll.Core.UnixFilter.Tests.tests
28 , testGroup "Hakyll.Web.Page.Tests"
31 , testGroup "Hakyll.Web.Page.Tests"
29 Hakyll.Web.Page.Tests.tests
32 Hakyll.Web.Page.Tests.tests
30 , testGroup "Hakyll.Web.Page.Metadata.Tests"
33 , testGroup "Hakyll.Web.Page.Metadata.Tests"
tests/TestSuite/Util.hs+28
@@ -2,15 +2,43 @@
2--
2--
3module TestSuite.Util
3module TestSuite.Util
4 ( fromAssertions
4 ( fromAssertions
5+ , makeStoreTest
6+ , runCompilerJobTest
5 ) where
7 ) where
6
8
9+import Data.Monoid (mempty)
10+
7import Test.Framework
11import Test.Framework
8import Test.Framework.Providers.HUnit
12import Test.Framework.Providers.HUnit
9import Test.HUnit hiding (Test)
13import Test.HUnit hiding (Test)
10
14
15+import Hakyll.Core.Compiler.Internal
16+import Hakyll.Core.Identifier
17+import Hakyll.Core.Logger
18+import Hakyll.Core.Resource.Provider
19+import Hakyll.Core.Store
20+
11fromAssertions :: String -- ^ Name
21fromAssertions :: String -- ^ Name
12 -> [Assertion] -- ^ Cases
22 -> [Assertion] -- ^ Cases
13 -> [Test] -- ^ Result tests
23 -> [Test] -- ^ Result tests
14fromAssertions name = zipWith testCase names
24fromAssertions name = zipWith testCase names
15 where
25 where
16 names = map (\n -> name ++ " [" ++ show n ++ "]") [1 :: Int ..]
26 names = map (\n -> name ++ " [" ++ show n ++ "]") [1 :: Int ..]
27+
28+-- | Create a store for testing
29+--
30+makeStoreTest :: IO Store
31+makeStoreTest = makeStore "_store"
32+
33+-- | Testing for 'runCompilerJob'
34+--
35+runCompilerJobTest :: Compiler () a
36+ -> Identifier
37+ -> ResourceProvider
38+ -> [Identifier]
39+ -> IO a
40+runCompilerJobTest compiler id' provider uni = do
41+ store <- makeStoreTest
42+ logger <- makeLogger $ const $ return ()
43+ Right x <- runCompilerJob compiler id' provider uni mempty store True logger
44+ return x