@@ -35,17 +35,27 @@ depends file dependencies action = do
35 unless valid action
35 unless valid action
37-- | Substitutes `$identifiers` in the given string by values from the given
37-- | Substitutes `$identifiers` in the given string by values from the given
38−-- "Context". When a key is not found, it is left as it is.
38+-- "Context". When a key is not found, it is left as it is. You can here
39+-- specify the characters used to replace escaped dollars `$$`.
39−substitute :: String -> Context -> String
40+substitute :: String -> String -> Context -> String
40−substitute [] _ = []
41+substitute _ [] _ = []
41−substitute string context
42+substitute escaper string context
42− | "$$" `isPrefixOf` string = "$$" ++ (substitute (tail tail') context)
43+ | "$$" `isPrefixOf` string = escaper ++ substitute' (tail tail')
43− | "$" `isPrefixOf` string = substitute'
44+ | "$" `isPrefixOf` string = substituteKey
44− | otherwise = (head string) : (substitute tail' context)
45+ | otherwise = (head string) : (substitute' tail')
45 where tail' = tail string
46 where tail' = tail string
46 (key, rest) = break (not . isAlpha) tail'
47 (key, rest) = break (not . isAlpha) tail'
47 replacement = fromMaybe ('$' : key) $ M.lookup key context
48 replacement = fromMaybe ('$' : key) $ M.lookup key context
48− substitute' = replacement ++ substitute rest context
49+ substituteKey = replacement ++ substitute' rest
50+ substitute' str = substitute escaper str context
52+-- | "substitute" for use during a chain.
53+regularSubstitute :: String -> Context -> String
54+regularSubstitute = substitute "$$"
56+-- | "substitute" for the end of a chain (just before writing).
57+finalSubstitute :: String -> Context -> String
58+finalSubstitute = substitute "$"
50-- | Render to a Page.
60-- | Render to a Page.
51render :: Renderable a
61render :: Renderable a
@@ -69,7 +79,7 @@ renderWith manipulation templatePath renderable = do
69 -- Ignore $root when substituting here. We will only replace that in the
79 -- Ignore $root when substituting here. We will only replace that in the
70 -- final render (just before writing).
80 -- final render (just before writing).
71 let contextIgnoringRoot = M.insert "root" "$root" context
81 let contextIgnoringRoot = M.insert "root" "$root" context
72− body = substitute templateString contextIgnoringRoot
82+ body = regularSubstitute templateString contextIgnoringRoot
73 return $ fromContext (M.insert "body" body context)
83 return $ fromContext (M.insert "body" body context)
75-- | Render each renderable with the given template, then concatenate the
85-- | Render each renderable with the given template, then concatenate the
@@ -117,8 +127,8 @@ writePage page = do
117 writeFile destination body
127 writeFile destination body
118 where url = getURL page
128 where url = getURL page
119 -- Substitute $root here, just before writing.
129 -- Substitute $root here, just before writing.
120− body = substitute (getBody page)
130+ body = finalSubstitute (getBody page)
121− (M.singleton "root" $ toRoot url)
131+ (M.singleton "root" $ toRoot url)
123-- | Mark a certain file as static, so it will just be copied when the site is
133-- | Mark a certain file as static, so it will just be copied when the site is
124-- generated.
134-- generated.