on master help sign in
Hamlet support (experimental)
69ca425Jasper Van der Jeugt
hakyll.cabal+5−2
@@ -38,8 +38,9 @@ library
38 mtl == 1.*,
38 mtl == 1.*,
39 old-locale == 1.*,
39 old-locale == 1.*,
40 old-time == 1.*,
40 old-time == 1.*,
41− time == 1.*,
41+ time >= 1.2,
42− binary >= 0.5
42+ binary >= 0.5,
43+ hamlet == 0.4.2
43 exposed-modules: Network.Hakyll.SimpleServer
44 exposed-modules: Network.Hakyll.SimpleServer
44 Text.Hakyll
45 Text.Hakyll
45 Text.Hakyll.Context
46 Text.Hakyll.Context
@@ -61,3 +62,5 @@ library
61 Text.Hakyll.Internal.FileType
62 Text.Hakyll.Internal.FileType
62 Text.Hakyll.Internal.Page
63 Text.Hakyll.Internal.Page
63 Text.Hakyll.Internal.Template
64 Text.Hakyll.Internal.Template
65+ Text.Hakyll.Internal.Template.Template
66+ Text.Hakyll.Internal.Template.Hamlet
src/Text/Hakyll.hs+2
@@ -23,6 +23,7 @@ import System.Directory (doesDirectoryExist, removeDirectoryRecursive)
23import System.Time (getClockTime)
23import System.Time (getClockTime)
24
24
25import Text.Pandoc
25import Text.Pandoc
26+import Text.Hamlet (defaultHamletSettings)
26
27
27import Network.Hakyll.SimpleServer (simpleServer)
28import Network.Hakyll.SimpleServer (simpleServer)
28import Text.Hakyll.HakyllMonad
29import Text.Hakyll.HakyllMonad
@@ -59,6 +60,7 @@ defaultHakyllConfiguration absoluteUrl' = HakyllConfiguration
59 , previewMode = BuildOnRequest
60 , previewMode = BuildOnRequest
60 , pandocParserState = defaultPandocParserState
61 , pandocParserState = defaultPandocParserState
61 , pandocWriterOptions = defaultPandocWriterOptions
62 , pandocWriterOptions = defaultPandocWriterOptions
63+ , hamletSettings = defaultHamletSettings
62 }
64 }
63
65
64-- | Main function to run Hakyll with the default configuration. The
66-- | Main function to run Hakyll with the default configuration. The
src/Text/Hakyll/HakyllMonad.hs+3
@@ -15,6 +15,7 @@ import qualified Data.Map as M
15import System.IO (hPutStrLn, stderr)
15import System.IO (hPutStrLn, stderr)
16
16
17import Text.Pandoc (ParserState, WriterOptions)
17import Text.Pandoc (ParserState, WriterOptions)
18+import Text.Hamlet (HamletSettings)
18
19
19import Text.Hakyll.Context (Context (..))
20import Text.Hakyll.Context (Context (..))
20
21
@@ -48,6 +49,8 @@ data HakyllConfiguration = HakyllConfiguration
48 pandocParserState :: ParserState
49 pandocParserState :: ParserState
49 , -- | Pandoc writer options
50 , -- | Pandoc writer options
50 pandocWriterOptions :: WriterOptions
51 pandocWriterOptions :: WriterOptions
52+ , -- | Hamlet settings (if you use hamlet for templates)
53+ hamletSettings :: HamletSettings
51 }
54 }
52
55
53-- | Simplified @ask@ function for the Hakyll monad stack.
56-- | Simplified @ask@ function for the Hakyll monad stack.
src/Text/Hakyll/Internal/Template.hs+12−26
@@ -10,8 +10,6 @@ module Text.Hakyll.Internal.Template
10import Control.Applicative ((<$>))
10import Control.Applicative ((<$>))
11import Data.List (isPrefixOf)
11import Data.List (isPrefixOf)
12import Data.Char (isAlphaNum)
12import Data.Char (isAlphaNum)
13−import Data.Binary
14−import Control.Monad (liftM, liftM2)
15import Data.Maybe (fromMaybe)
13import Data.Maybe (fromMaybe)
16import System.FilePath ((</>))
14import System.FilePath ((</>))
17import qualified Data.Map as M
15import qualified Data.Map as M
@@ -20,13 +18,8 @@ import Text.Hakyll.Context (Context (..))
20import Text.Hakyll.HakyllMonad (Hakyll)
18import Text.Hakyll.HakyllMonad (Hakyll)
21import Text.Hakyll.Internal.Cache
19import Text.Hakyll.Internal.Cache
22import Text.Hakyll.Internal.Page
20import Text.Hakyll.Internal.Page
23−
24−-- | Datatype used for template substitutions.
25−data Template = Chunk String Template
21+import Text.Hakyll.Internal.Template.Template
26− | Identifier String Template
22+import Text.Hakyll.Internal.Template.Hamlet
27− | EscapeCharacter Template
28− | End
29− deriving (Show, Read, Eq)
30
23
31-- | Construct a @Template@ from a string.
24-- | Construct a @Template@ from a string.
32fromString :: String -> Template
25fromString :: String -> Template
@@ -48,14 +41,20 @@ readTemplate path = do
48 if isCacheMoreRecent'
41 if isCacheMoreRecent'
49 then getFromCache fileName
42 then getFromCache fileName
50 else do
43 else do
51− page <- unContext <$> readPage path
44+ template <- if isHamletRTFile path
52− let body = fromMaybe (error $ "No body in template " ++ fileName)
45+ then readHamletTemplate
53− (M.lookup "body" page)
46+ else readDefaultTemplate
54− template = fromString body
55 storeInCache template fileName
47 storeInCache template fileName
56 return template
48 return template
57 where
49 where
58 fileName = "templates" </> path
50 fileName = "templates" </> path
51+ readDefaultTemplate = do
52+ page <- unContext <$> readPage path
53+ let body = fromMaybe (error $ "No body in template " ++ fileName)
54+ (M.lookup "body" page)
55+ return $ fromString body
56+
57+ readHamletTemplate = fromHamletRT <$> readHamletRT path
59
58
60-- | Substitutes @$identifiers@ in the given @Template@ by values from the given
59-- | Substitutes @$identifiers@ in the given @Template@ by values from the given
61-- "Context". When a key is not found, it is left as it is. You can specify
60-- "Context". When a key is not found, it is left as it is. You can specify
@@ -80,16 +79,3 @@ regularSubstitute = substitute "$$"
80-- escaped characters.
79-- escaped characters.
81finalSubstitute :: Template -> Context -> String
80finalSubstitute :: Template -> Context -> String
82finalSubstitute = substitute "$"
81finalSubstitute = substitute "$"
83−
84−instance Binary Template where
85− put (Chunk string template) = put (0 :: Word8) >> put string >> put template
86− put (Identifier key template) = put (1 :: Word8) >> put key >> put template
87− put (EscapeCharacter template) = put (2 :: Word8) >> put template
88− put (End) = put (3 :: Word8)
89−
90− get = do tag <- getWord8
91− case tag of 0 -> liftM2 Chunk get get
92− 1 -> liftM2 Identifier get get
93− 2 -> liftM EscapeCharacter get
94− 3 -> return End
95− _ -> error "Error reading template"
src/Text/Hakyll/Internal/Template/Hamlet.hsnew file+44
@@ -0,0 +1,44 @@
1+-- | Support for Hamlet templates in Hakyll.
2+--
3+module Text.Hakyll.Internal.Template.Hamlet
4+ ( isHamletRTFile
5+ , readHamletRT
6+ , fromHamletRT
7+ ) where
8+
9+import Data.List (intercalate)
10+import Control.Monad.Trans (liftIO)
11+import System.FilePath (takeExtension)
12+
13+import Text.Hamlet.RT
14+
15+import Text.Hakyll.Internal.Template.Template
16+import Text.Hakyll.HakyllMonad (Hakyll, askHakyll, hamletSettings)
17+
18+-- | Determine if a file is a hamlet template by extension.
19+--
20+isHamletRTFile :: FilePath -> Bool
21+isHamletRTFile fileName = takeExtension fileName `elem` [".hamlet", ".hml"]
22+
23+-- | Read a 'HamletRT' by file name.
24+--
25+readHamletRT :: FilePath -- ^ Filename of the template
26+ -> Hakyll HamletRT -- ^ Resulting hamlet template
27+readHamletRT fileName = do
28+ settings <- askHakyll hamletSettings
29+ string <- liftIO $ readFile fileName
30+ liftIO $ parseHamletRT settings string
31+
32+
33+-- | Convert a 'HamletRT' to a 'Template'
34+--
35+fromHamletRT :: HamletRT -- ^ Hamlet runtime template
36+ -> Template -- ^ Hakyll template
37+fromHamletRT (HamletRT sd) = fromSimpleDoc sd
38+ where
39+ fromSimpleDoc :: [SimpleDoc] -> Template
40+ fromSimpleDoc [] = End
41+ fromSimpleDoc (SDRaw chunk : xs) = Chunk chunk $ fromSimpleDoc xs
42+ fromSimpleDoc (SDVar vars : xs) =
43+ Identifier (intercalate "." vars) $ fromSimpleDoc xs
44+ fromSimpleDoc (_ : xs) = fromSimpleDoc xs -- Unsupported elements
src/Text/Hakyll/Internal/Template/Template.hsnew file+31
@@ -0,0 +1,31 @@
1+-- | Module containing the template data structure.
2+--
3+module Text.Hakyll.Internal.Template.Template
4+ ( Template (..)
5+ ) where
6+
7+import Control.Monad (liftM, liftM2)
8+import Data.Word (Word8)
9+
10+import Data.Binary (Binary, get, put, getWord8)
11+
12+-- | Datatype used for template substitutions.
13+--
14+data Template = Chunk String Template
15+ | Identifier String Template
16+ | EscapeCharacter Template
17+ | End
18+ deriving (Show, Read, Eq)
19+
20+instance Binary Template where
21+ put (Chunk string template) = put (0 :: Word8) >> put string >> put template
22+ put (Identifier key template) = put (1 :: Word8) >> put key >> put template
23+ put (EscapeCharacter template) = put (2 :: Word8) >> put template
24+ put (End) = put (3 :: Word8)
25+
26+ get = do tag <- getWord8
27+ case tag of 0 -> liftM2 Chunk get get
28+ 1 -> liftM2 Identifier get get
29+ 2 -> liftM EscapeCharacter get
30+ 3 -> return End
31+ _ -> error "Error reading template"