@@ -0,0 +1,49 @@
1+module Hakyll.Web.Template
2+ ( Template
3+ , readTemplate
4+ , applyTemplate
5+ , applySelf
6+ ) where
7+
8+import Data.List (isPrefixOf)
9+import Data.Char (isAlphaNum)
10+import Data.Maybe (fromMaybe)
11+import qualified Data.Map as M
12+
13+import Hakyll.Web.Template.Internal
14+import Hakyll.Web.Page
15+
16+-- | Construct a @Template@ from a string.
17+--
18+readTemplate :: String -> Template
19+readTemplate = Template . readTemplate'
20+ where
21+ readTemplate' [] = []
22+ readTemplate' string
23+ | "$$" `isPrefixOf` string =
24+ EscapeCharacter : (readTemplate' $ drop 2 string)
25+ | "$" `isPrefixOf` string =
26+ let (key, rest) = span isAlphaNum $ drop 1 string
27+ in Identifier key : readTemplate' rest
28+ | otherwise =
29+ let (chunk, rest) = break (== '$') string
30+ in Chunk chunk : readTemplate' rest
31+
32+-- | Substitutes @$identifiers@ in the given @Template@ by values from the given
33+-- "Page". When a key is not found, it is left as it is. You can specify
34+-- the characters used to replace escaped dollars (@$$@) here.
35+--
36+applyTemplate :: Template -> Page String -> Page String
37+applyTemplate template page =
38+ fmap (const $ substitute =<< unTemplate template) page
39+ where
40+ substitute (Chunk chunk) = chunk
41+ substitute (Identifier key) =
42+ fromMaybe ('$' : key) $ M.lookup key $ toMap page
43+ substitute (EscapeCharacter) = "$"
44+
45+-- | Apply a page as it's own template. This is often very useful to fill in
46+-- certain keys like @$root@ and @$url@.
47+--
48+applySelf :: Page String -> Page String
49+applySelf page = applyTemplate (readTemplate $ pageBody page) page