on master help sign in
"Allow" missing keys in templates
commitd61d7f19fc636f97e60f76b1ab0bd7a249cd96c3 authorJasper Van der Jeugt <m@jaspervdj.be> dateWed 23 Nov 2011, 15:24 (15 years ago) parente1687cb
2 files changed+50−17
src/Hakyll/Web/Template.hs+29−6 tests/Hakyll/Web/Template/Tests.hs+21−11
src/Hakyll/Web/Template.hs+29−6
@@ -44,10 +44,12 @@
4444module Hakyll.Web.Template
4545 ( Template
4646 , applyTemplate
47+ , applyTemplateWith
4748 , applySelf
4849 , templateCompiler
4950 , templateCompilerWith
5051 , applyTemplateCompiler
52+ , applyTemplateCompilerWith
5153 ) where
5254
5355import Control.Arrow
@@ -65,17 +67,29 @@ import Hakyll.Web.Template.Read
6567import Hakyll.Web.Page.Internal
6668
6769-- | Substitutes @$identifiers@ in the given @Template@ by values from the given
68−-- "Page". When a key is not found, it is left as it is. You can specify
69−-- the characters used to replace escaped dollars (@$$@) here.
70+-- "Page". When a key is not found, it is left as it is.
7071--
7172applyTemplate :: Template -> Page String -> Page String
72−applyTemplate template page =
73+applyTemplate = applyTemplateWith defaultMissingHandler
74+
75+-- | Default solution if a key is missing: render it again
76+defaultMissingHandler :: String -> String
77+defaultMissingHandler k = "$" ++ k ++ "$"
78+
79+-- | A version of 'applyTemplate' which allows you to give a fallback option,
80+-- which can produce the value for a key if it is missing.
81+--
82+applyTemplateWith :: (String -> String) -- ^ Fallback if key missing
83+ -> Template -- ^ Template to apply
84+ -> Page String -- ^ Input page
85+ -> Page String -- ^ Resulting page
86+applyTemplateWith missing template page =
7387 fmap (const $ substitute =<< unTemplate template) page
7488 where
7589 map' = toMap page
7690 substitute (Chunk chunk) = chunk
77− substitute (Key key) = fromMaybe ("$" ++ key ++ "$") $ M.lookup key map'
78− substitute (Escaped) = "$"
91+ substitute (Key key) = fromMaybe (missing key) $ M.lookup key map'
92+ substitute (Escaped) = "$"
7993
8094-- | Apply a page as it's own template. This is often very useful to fill in
8195-- certain keys like @$root@ and @$url@.
@@ -106,4 +120,13 @@ templateCompilerWith settings =
106120
107121applyTemplateCompiler :: Identifier Template -- ^ Template
108122 -> Compiler (Page String) (Page String) -- ^ Compiler
109−applyTemplateCompiler identifier = require identifier (flip applyTemplate)
123+applyTemplateCompiler = applyTemplateCompilerWith defaultMissingHandler
124+
125+-- | A version of 'applyTemplateCompiler' which allows you to pass a function
126+-- which is called for a key when it is missing.
127+--
128+applyTemplateCompilerWith :: (String -> String)
129+ -> Identifier Template
130+ -> Compiler (Page String) (Page String)
131+applyTemplateCompilerWith missing identifier =
132+ require identifier (flip $ applyTemplateWith missing)
tests/Hakyll/Web/Template/Tests.hs+21−11
@@ -16,29 +16,39 @@ import TestSuite.Util
1616tests :: [Test]
1717tests = fromAssertions "applyTemplate"
1818 -- Hakyll templates
19− [ applyTemplateAssertion readTemplate
19+ [ applyTemplateAssertion readTemplate applyTemplate
2020 "bar" "$foo$" [("foo", "bar")]
2121
22− , applyTemplateAssertion readTemplate
22+ , applyTemplateAssertion readTemplate applyTemplate
2323 "$ barqux" "$$ $foo$$bar$" [("foo", "bar"), ("bar", "qux")]
2424
25+ , applyTemplateAssertion readTemplate applyTemplate
26+ "$foo$" "$foo$" []
27+
2528 -- Hamlet templates
26− , applyTemplateAssertion readHamletTemplate
29+ , applyTemplateAssertion readHamletTemplate applyTemplate
2730 "<head><title>notice</title></head><body>A paragraph</body>"
2831 "<head\n\
2932 \ <title>#{title}\n\
3033 \<body\n\
3134 \ A paragraph\n"
3235 [("title", "notice")]
36+
37+ -- Missing keys
38+ , let missing "foo" = "bar"
39+ missing "bar" = "qux"
40+ missing x = reverse x
41+ in applyTemplateAssertion readTemplate (applyTemplateWith missing)
42+ "bar foo ver" "$foo$ $bar$ $rev$" [("bar", "foo")]
3343 ]
3444
3545-- | Utility function to create quick template tests
3646--
37−applyTemplateAssertion :: (String -> Template) -- ^ Template parser
38− -> String -- ^ Expected
39− -> String -- ^ Template
40− -> [(String, String)] -- ^ Page
41− -> Assertion -- ^ Resulting assertion
42−applyTemplateAssertion parser expected template page =
43− expected @=? pageBody (applyTemplate (parser template)
44− (fromMap $ M.fromList page))
47+applyTemplateAssertion :: (String -> Template)
48+ -> (Template -> Page String -> Page String)
49+ -> String
50+ -> String
51+ -> [(String, String)]
52+ -> Assertion
53+applyTemplateAssertion parser apply expected template page =
54+ expected @=? pageBody (apply (parser template) (fromMap $ M.fromList page))