on master help sign in
Add a simple static configuration
2c8d76cJasper Van der Jeugt
hakyll.cabal+1
@@ -54,6 +54,7 @@ library
54 Text.Hakyll.Util
54 Text.Hakyll.Util
55 Text.Hakyll.Tags
55 Text.Hakyll.Tags
56 Text.Hakyll.Feed
56 Text.Hakyll.Feed
57+ Text.Hakyll.Configurations.Static
57 other-modules: Paths_hakyll
58 other-modules: Paths_hakyll
58 Text.Hakyll.Internal.Cache
59 Text.Hakyll.Internal.Cache
59 Text.Hakyll.Internal.CompressCss
60 Text.Hakyll.Internal.CompressCss
src/Text/Hakyll/Configurations/Static.hsnew file+59
@@ -0,0 +1,59 @@
1+-- | Module for a simple static configuration of a website.
2+--
3+-- The configuration works like this:
4+--
5+-- * The @templates/@ directory should contain one template.
6+--
7+-- * Renderable files in the directory tree are rendered using this template.
8+--
9+-- * The @static/@ directory is copied entirely (if it exists).
10+--
11+-- * All files in the @css/@ directory are compressed.
12+--
13+module Text.Hakyll.Configurations.Static
14+ ( staticConfiguration
15+ ) where
16+
17+import Control.Applicative ((<$>))
18+import Control.Monad (filterM, forM_)
19+
20+import Text.Hakyll.File ( getRecursiveContents, inDirectory, inHakyllDirectory
21+ , directory )
22+import Text.Hakyll.Internal.FileType (isRenderableFile)
23+import Text.Hakyll.HakyllMonad (Hakyll, logHakyll)
24+import Text.Hakyll.Render (renderChain, css, static)
25+import Text.Hakyll.CreateContext (createPage)
26+
27+-- | A simple configuration for an entirely static website.
28+--
29+staticConfiguration :: Hakyll ()
30+staticConfiguration = do
31+ -- Find all files not in _site or _cache.
32+ files <- filterM isRenderableFile' =<< getRecursiveContents "."
33+
34+ -- Find a main template to use
35+ mainTemplate <- take 1 <$> getRecursiveContents templateDir
36+ logHakyll $ case mainTemplate of [] -> "Using no template"
37+ (x : _) -> "Using template " ++ x
38+
39+ -- Render all files using this template
40+ forM_ files $ renderChain mainTemplate . createPage
41+
42+ -- Render a static directory
43+ directory static staticDir
44+
45+ -- Render a css directory
46+ directory css cssDir
47+ where
48+ -- A file should have a renderable extension and not be in a hakyll
49+ -- directory, and not in a special directory.
50+ isRenderableFile' file = do
51+ inHakyllDirectory' <- inHakyllDirectory file
52+ return $ isRenderableFile file
53+ && not (any (inDirectory file) [templateDir, cssDir, staticDir])
54+ && not inHakyllDirectory'
55+
56+ -- Directories
57+ templateDir = "templates"
58+ cssDir = "css"
59+ staticDir = "static"
src/Text/Hakyll/File.hs+25−14
@@ -5,6 +5,7 @@ module Text.Hakyll.File
5 , toCache
5 , toCache
6 , toUrl
6 , toUrl
7 , toRoot
7 , toRoot
8+ , inDirectory
8 , inHakyllDirectory
9 , inHakyllDirectory
9 , removeSpaces
10 , removeSpaces
10 , makeDirectories
11 , makeDirectories
@@ -87,6 +88,15 @@ toRoot = emptyException . joinPath . map parent . splitPath
87 emptyException [] = "."
88 emptyException [] = "."
88 emptyException x = x
89 emptyException x = x
89
90
91+-- | Check if a file is in a given directory.
92+--
93+inDirectory :: FilePath -- ^ File path
94+ -> FilePath -- ^ Directory
95+ -> Bool -- ^ Result
96+inDirectory path dir = case splitDirectories path of
97+ [] -> False
98+ (x : _) -> x == dir
99+
90-- | Check if a file is in a Hakyll directory. With a Hakyll directory, we mean
100-- | Check if a file is in a Hakyll directory. With a Hakyll directory, we mean
91-- a directory that should be "ignored" such as the @_site@ or @_cache@
101-- a directory that should be "ignored" such as the @_site@ or @_cache@
92-- directory.
102-- directory.
@@ -101,11 +111,8 @@ toRoot = emptyException . joinPath . map parent . splitPath
101--
111--
102inHakyllDirectory :: FilePath -> Hakyll Bool
112inHakyllDirectory :: FilePath -> Hakyll Bool
103inHakyllDirectory path =
113inHakyllDirectory path =
104− or <$> mapM (liftM inDirectory . askHakyll) [siteDirectory, cacheDirectory]
114+ or <$> mapM (liftM (inDirectory path) . askHakyll)
105− where
115+ [siteDirectory, cacheDirectory]
106− inDirectory dir = case splitDirectories path of
107− [] -> False
108− (x : _) -> x == dir
109
116
110-- | Swaps spaces for '-'.
117-- | Swaps spaces for '-'.
111removeSpaces :: FilePath -> FilePath
118removeSpaces :: FilePath -> FilePath
@@ -123,17 +130,21 @@ makeDirectories path = liftIO $ createDirectoryIfMissing True dir
123
130
124-- | Get all contents of a directory. Note that files starting with a dot (.)
131-- | Get all contents of a directory. Note that files starting with a dot (.)
125-- will be ignored.
132-- will be ignored.
133+--
126getRecursiveContents :: FilePath -> Hakyll [FilePath]
134getRecursiveContents :: FilePath -> Hakyll [FilePath]
127getRecursiveContents topdir = do
135getRecursiveContents topdir = do
136+ topdirExists <- liftIO $ doesDirectoryExist topdir
137+ if topdirExists
128− names <- liftIO $ getDirectoryContents topdir
138+ then do names <- liftIO $ getDirectoryContents topdir
129− let properNames = filter isProper names
139+ let properNames = filter isProper names
130− paths <- forM properNames $ \name -> do
140+ paths <- forM properNames $ \name -> do
131− let path = topdir </> name
141+ let path = topdir </> name
132− isDirectory <- liftIO $ doesDirectoryExist path
142+ isDirectory <- liftIO $ doesDirectoryExist path
133− if isDirectory
143+ if isDirectory
134− then getRecursiveContents path
144+ then getRecursiveContents path
135− else return [path]
145+ else return [normalise path]
136− return (concat paths)
146+ return (concat paths)
147+ else return []
137 where
148 where
138 isProper = not . (== '.') . head
149 isProper = not . (== '.') . head
139
150
src/Text/Hakyll/HakyllAction.hs+1−3
@@ -12,9 +12,7 @@ module Text.Hakyll.HakyllAction
12import Control.Arrow
12import Control.Arrow
13import Control.Category
13import Control.Category
14import Control.Monad ((<=<), unless)
14import Control.Monad ((<=<), unless)
15−import Control.Monad.Reader (liftIO)
16import Prelude hiding ((.), id)
15import Prelude hiding ((.), id)
17−import System.IO (hPutStrLn, stderr)
18
16
19import Text.Hakyll.File (toDestination, isFileMoreRecent)
17import Text.Hakyll.File (toDestination, isFileMoreRecent)
20import Text.Hakyll.HakyllMonad
18import Text.Hakyll.HakyllMonad
@@ -65,7 +63,7 @@ runHakyllActionIfNeeded action = do
65 Right _ -> error "No url when checking dependencies."
63 Right _ -> error "No url when checking dependencies."
66 destination <- toDestination url
64 destination <- toDestination url
67 valid <- isFileMoreRecent destination $ actionDependencies action
65 valid <- isFileMoreRecent destination $ actionDependencies action
68− unless valid $ do liftIO $ hPutStrLn stderr $ "Rendering " ++ destination
66+ unless valid $ do logHakyll $ "Rendering " ++ destination
69 runHakyllAction action
67 runHakyllAction action
70
68
71-- | Chain a number of @HakyllAction@ computations.
69-- | Chain a number of @HakyllAction@ computations.
src/Text/Hakyll/HakyllMonad.hs+8
@@ -5,11 +5,14 @@ module Text.Hakyll.HakyllMonad
5 , Hakyll
5 , Hakyll
6 , askHakyll
6 , askHakyll
7 , getAdditionalContext
7 , getAdditionalContext
8+ , logHakyll
8 ) where
9 ) where
9
10
11+import Control.Monad.Trans (liftIO)
10import Control.Monad.Reader (ReaderT, ask)
12import Control.Monad.Reader (ReaderT, ask)
11import Control.Monad (liftM)
13import Control.Monad (liftM)
12import qualified Data.Map as M
14import qualified Data.Map as M
15+import System.IO (hPutStrLn, stderr)
13
16
14import Text.Pandoc (ParserState, WriterOptions)
17import Text.Pandoc (ParserState, WriterOptions)
15
18
@@ -65,3 +68,8 @@ getAdditionalContext :: HakyllConfiguration -> Context
65getAdditionalContext configuration =
68getAdditionalContext configuration =
66 let (Context c) = additionalContext configuration
69 let (Context c) = additionalContext configuration
67 in Context $ M.insert "absolute" (absoluteUrl configuration) c
70 in Context $ M.insert "absolute" (absoluteUrl configuration) c
71+
72+-- | Write some log information.
73+--
74+logHakyll :: String -> Hakyll ()
75+logHakyll = liftIO . hPutStrLn stderr