@@ -5,16 +5,22 @@
5module Hakyll.Web.Template.Internal
5module Hakyll.Web.Template.Internal
6 ( Template (..)
6 ( Template (..)
7 , TemplateElement (..)
7 , TemplateElement (..)
11--------------------------------------------------------------------------------
12--------------------------------------------------------------------------------
12−import Control.Applicative (pure, (<$>), (<*>))
13+import Control.Applicative (pure, (<$), (<$>), (<*>), (<|>))
14+import Control.Monad (void)
13−import Data.Binary (Binary, get, getWord8, put, putWord8)
15+import Data.Binary (Binary, get, getWord8, put, putWord8)
14−import Data.Typeable (Typeable)
16+import Data.Typeable (Typeable)
17+import GHC.Exts (IsString (..))
18+import qualified Text.Parsec as P
19+import qualified Text.Parsec.String as P
17--------------------------------------------------------------------------------
22--------------------------------------------------------------------------------
23+import Hakyll.Core.Util.Parser
18import Hakyll.Core.Writable
24import Hakyll.Core.Writable
@@ -46,10 +52,10 @@ data TemplateElement
46--------------------------------------------------------------------------------
52--------------------------------------------------------------------------------
47instance Binary TemplateElement where
53instance Binary TemplateElement where
48 put (Chunk string) = putWord8 0 >> put string
54 put (Chunk string) = putWord8 0 >> put string
49− put (Key key) = putWord8 1 >> put key
55+ put (Key k) = putWord8 1 >> put k
50 put (Escaped) = putWord8 2
56 put (Escaped) = putWord8 2
51− put (If key t f) = putWord8 3 >> put key >> put t >> put f
57+ put (If k t f ) = putWord8 3 >> put k >> put t >> put f
52− put (For key b s) = putWord8 4 >> put key >> put b >> put s
58+ put (For k b s) = putWord8 4 >> put k >> put b >> put s
53 put (Partial p) = putWord8 5 >> put p
59 put (Partial p) = putWord8 5 >> put p
55 get = getWord8 >>= \tag -> case tag of
61 get = getWord8 >>= \tag -> case tag of
@@ -61,3 +67,84 @@ instance Binary TemplateElement where
61 5 -> Partial <$> get
67 5 -> Partial <$> get
62 _ -> error $
68 _ -> error $
63 "Hakyll.Web.Template.Internal: Error reading cached template"
69 "Hakyll.Web.Template.Internal: Error reading cached template"
72+--------------------------------------------------------------------------------
73+instance IsString Template where
74+ fromString = readTemplate
77+--------------------------------------------------------------------------------
78+readTemplate :: String -> Template
79+readTemplate input = case P.parse template "" input of
80+ Left err -> error $ "Cannot parse template: " ++ show err
84+--------------------------------------------------------------------------------
85+template :: P.Parser Template
86+template = Template <$>
87+ (P.many1 $ chunk <|> escaped <|> conditional <|> for <|> partial <|> key)
90+--------------------------------------------------------------------------------
91+chunk :: P.Parser TemplateElement
92+chunk = Chunk <$> (P.many1 $ P.noneOf "$")
95+--------------------------------------------------------------------------------
96+escaped :: P.Parser TemplateElement
97+escaped = Escaped <$ (P.try $ P.string "$$")
100+--------------------------------------------------------------------------------
101+conditional :: P.Parser TemplateElement
102+conditional = P.try $ do
103+ void $ P.string "$if("
105+ void $ P.string ")$"
106+ thenBranch <- template
107+ elseBranch <- P.optionMaybe $ P.try (P.string "$else$") >> template
108+ void $ P.string "$endif$"
109+ return $ If i thenBranch elseBranch
112+--------------------------------------------------------------------------------
113+for :: P.Parser TemplateElement
115+ void $ P.string "$for("
117+ void $ P.string ")$"
119+ sep <- P.optionMaybe $ P.try (P.string "$sep$") >> template
120+ void $ P.string "$endfor$"
121+ return $ For i body sep
124+--------------------------------------------------------------------------------
125+partial :: P.Parser TemplateElement
127+ void $ P.string "$partial("
129+ void $ P.string ")$"
133+--------------------------------------------------------------------------------
134+key :: P.Parser TemplateElement
142+--------------------------------------------------------------------------------
143+stringLiteral :: P.Parser String
148+ if x == '\\' then P.anyChar else return x