on master help sign in
Added custom Template system. Highly experimental.
6bcad27Jasper Van der Jeugt
hakyll.cabal−1
@@ -24,7 +24,6 @@ library
24 ghc-options: -Wall
24 ghc-options: -Wall
25 hs-source-dirs: src/
25 hs-source-dirs: src/
26 build-depends: base >= 4 && < 5,
26 build-depends: base >= 4 && < 5,
27− template >= 0.1.1,
28 filepath >= 1.1,
27 filepath >= 1.1,
29 directory >= 1,
28 directory >= 1,
30 containers >= 0.1,
29 containers >= 0.1,
src/Network/Hakyll/SimpleServer.hs+1−1
@@ -48,7 +48,7 @@ instance Show Request where
48readRequest :: Handle -> Server Request
48readRequest :: Handle -> Server Request
49readRequest handle = do
49readRequest handle = do
50 requestLine <- liftIO $ hGetLine handle
50 requestLine <- liftIO $ hGetLine handle
51− let [method, uri, version] = map trim $ split " " requestLine
51+ let [method, uri, version] = map trim $ splitRegex " " requestLine
52 return $ Request { requestMethod = B.pack method
52 return $ Request { requestMethod = B.pack method
53 , requestURI = B.pack uri
53 , requestURI = B.pack uri
54 , requestVersion = B.pack version
54 , requestVersion = B.pack version
src/Text/Hakyll/CompressCSS.hs+5−5
@@ -3,7 +3,7 @@ module Text.Hakyll.CompressCSS
3 ) where
3 ) where
4
4
5import Data.List (isPrefixOf)
5import Data.List (isPrefixOf)
6−import Text.Hakyll.Regex (substitute)
6+import Text.Hakyll.Regex (substituteRegex)
7
7
8-- | Compress CSS to speed up your site.
8-- | Compress CSS to speed up your site.
9compressCSS :: String -> String
9compressCSS :: String -> String
@@ -13,13 +13,13 @@ compressCSS = compressSeparators
13
13
14-- | Compresses certain forms of separators.
14-- | Compresses certain forms of separators.
15compressSeparators :: String -> String
15compressSeparators :: String -> String
16−compressSeparators = substitute "; *}" "}"
16+compressSeparators = substituteRegex "; *}" "}"
17− . substitute " *([{};:]) *" "\\1"
17+ . substituteRegex " *([{};:]) *" "\\1"
18− . substitute ";;*" ";"
18+ . substituteRegex ";;*" ";"
19
19
20-- | Compresses all whitespace.
20-- | Compresses all whitespace.
21compressWhitespace :: String -> String
21compressWhitespace :: String -> String
22−compressWhitespace = substitute "[ \t\n][ \t\n]*" " "
22+compressWhitespace = substituteRegex "[ \t\n][ \t\n]*" " "
23
23
24-- | Function that strips CSS comments away.
24-- | Function that strips CSS comments away.
25stripComments :: String -> String
25stripComments :: String -> String
src/Text/Hakyll/Context.hs+14−12
@@ -1,20 +1,23 @@
1-- | Module containing various functions to manipulate contexts.
1-- | Module containing various functions to manipulate contexts.
2module Text.Hakyll.Context
2module Text.Hakyll.Context
3+ ( Context
3− ( ContextManipulation
4+ , ContextManipulation
4 , renderValue
5 , renderValue
5 , renderDate
6 , renderDate
6 ) where
7 ) where
7
8
8import qualified Data.Map as M
9import qualified Data.Map as M
9−import qualified Data.ByteString.Lazy.Char8 as B
10+import Data.Map (Map)
10
11
11import System.Locale (defaultTimeLocale)
12import System.Locale (defaultTimeLocale)
12import System.FilePath (takeFileName)
13import System.FilePath (takeFileName)
13−import Text.Template (Context)
14import Data.Time.Format (parseTime, formatTime)
14import Data.Time.Format (parseTime, formatTime)
15import Data.Time.Clock (UTCTime)
15import Data.Time.Clock (UTCTime)
16import Data.Maybe (fromMaybe)
16import Data.Maybe (fromMaybe)
17−import Text.Hakyll.Regex (substitute)
17+import Text.Hakyll.Regex (substituteRegex)
18+
19+-- | Type for a context.
20+type Context = Map String String
18
21
19-- | Type for context manipulating functions.
22-- | Type for context manipulating functions.
20type ContextManipulation = Context -> Context
23type ContextManipulation = Context -> Context
@@ -22,11 +25,11 @@ type ContextManipulation = Context -> Context
22-- | Do something with a value of a context.
25-- | Do something with a value of a context.
23renderValue :: String -- ^ Key of which the value should be copied.
26renderValue :: String -- ^ Key of which the value should be copied.
24 -> String -- ^ Key the value should be copied to.
27 -> String -- ^ Key the value should be copied to.
25− -> (B.ByteString -> B.ByteString) -- ^ Function to apply on the value.
28+ -> (String -> String) -- ^ Function to apply on the value.
26 -> ContextManipulation
29 -> ContextManipulation
27−renderValue src dst f context = case M.lookup (B.pack src) context of
30+renderValue src dst f context = case M.lookup src context of
28 Nothing -> context
31 Nothing -> context
29− (Just value) -> M.insert (B.pack dst) (f value) context
32+ (Just value) -> M.insert dst (f value) context
30
33
31-- | When the context has a key called `path` in a `yyyy-mm-dd-title.extension`
34-- | When the context has a key called `path` in a `yyyy-mm-dd-title.extension`
32-- format (default for pages), this function can render the date.
35-- format (default for pages), this function can render the date.
@@ -34,12 +37,11 @@ renderDate :: String -- ^ Key in which the rendered date should be placed.
34 -> String -- ^ Format to use on the date.
37 -> String -- ^ Format to use on the date.
35 -> String -- ^ Default value when the date cannot be parsed.
38 -> String -- ^ Default value when the date cannot be parsed.
36 -> ContextManipulation
39 -> ContextManipulation
37−renderDate key format defaultValue context =
40+renderDate key format defaultValue context = M.insert key value context
38− M.insert (B.pack key) (B.pack value) context
39 where value = fromMaybe defaultValue pretty
41 where value = fromMaybe defaultValue pretty
40− pretty = do filePath <- M.lookup (B.pack "path") context
42+ pretty = do filePath <- M.lookup "path" context
41− let dateString = substitute "^([0-9]*-[0-9]*-[0-9]*).*" "\\1"
43+ let dateString = substituteRegex "^([0-9]*-[0-9]*-[0-9]*).*" "\\1"
42− (takeFileName $ B.unpack filePath)
44+ (takeFileName filePath)
43 time <- parseTime defaultTimeLocale
45 time <- parseTime defaultTimeLocale
44 "%Y-%m-%d"
46 "%Y-%m-%d"
45 dateString :: Maybe UTCTime
47 dateString :: Maybe UTCTime
src/Text/Hakyll/Page.hs+17−22
@@ -8,7 +8,6 @@ module Text.Hakyll.Page
8
8
9import qualified Data.Map as M
9import qualified Data.Map as M
10import qualified Data.List as L
10import qualified Data.List as L
11−import qualified Data.ByteString.Lazy.Char8 as B
12import Data.Maybe (fromMaybe)
11import Data.Maybe (fromMaybe)
13
12
14import System.FilePath (FilePath, takeExtension)
13import System.FilePath (FilePath, takeExtension)
@@ -16,10 +15,10 @@ import System.IO
16
15
17import Text.Hakyll.File
16import Text.Hakyll.File
18import Text.Hakyll.Util (trim)
17import Text.Hakyll.Util (trim)
18+import Text.Hakyll.Context (Context)
19import Text.Hakyll.Renderable
19import Text.Hakyll.Renderable
20import Text.Pandoc
20import Text.Pandoc
21
21
22−import Text.Template (Context)
23
22
24-- | A Page is basically key-value mapping. Certain keys have special
23-- | A Page is basically key-value mapping. Certain keys have special
25-- meanings, like for example url, body and title.
24-- meanings, like for example url, body and title.
@@ -31,26 +30,22 @@ fromContext = Page
31
30
32-- | Obtain a value from a page. Will resturn an empty string when nothing is
31-- | Obtain a value from a page. Will resturn an empty string when nothing is
33-- found.
32-- found.
34−getValue :: String -> Page -> B.ByteString
33+getValue :: String -> Page -> String
35−getValue str (Page page) = fromMaybe B.empty $ M.lookup (B.pack str) page
34+getValue str (Page page) = fromMaybe [] $ M.lookup str page
36−
37−-- | Auxiliary function to pack a pair.
38−packPair :: (String, String) -> (B.ByteString, B.ByteString)
39−packPair (a, b) = (B.pack a, B.pack b)
40
35
41-- | Get the URL for a certain page. This should always be defined. If
36-- | Get the URL for a certain page. This should always be defined. If
42-- not, it will error.
37-- not, it will error.
43getPageURL :: Page -> String
38getPageURL :: Page -> String
44−getPageURL (Page page) = B.unpack $ fromMaybe (error "No page url") $ M.lookup (B.pack "url") page
39+getPageURL (Page page) = fromMaybe (error "No page url") $ M.lookup "url" page
45
40
46-- | Get the original page path.
41-- | Get the original page path.
47getPagePath :: Page -> String
42getPagePath :: Page -> String
48−getPagePath (Page page) = B.unpack $ fromMaybe (error "No page path") $ M.lookup (B.pack "path") page
43+getPagePath (Page page) = fromMaybe (error "No page path") $ M.lookup "path" page
49
44
50-- | Get the body for a certain page. When not defined, the body will be
45-- | Get the body for a certain page. When not defined, the body will be
51-- empty.
46-- empty.
52−getBody :: Page -> B.ByteString
47+getBody :: Page -> String
53−getBody (Page page) = fromMaybe B.empty $ M.lookup (B.pack "body") page
48+getBody (Page page) = fromMaybe [] $ M.lookup "body" page
54
49
55-- | The default writer options for pandoc rendering.
50-- | The default writer options for pandoc rendering.
56writerOptions :: WriterOptions
51writerOptions :: WriterOptions
@@ -86,13 +81,13 @@ cachePage page@(Page mapping) = do
86 makeDirectories destination
81 makeDirectories destination
87 handle <- openFile destination WriteMode
82 handle <- openFile destination WriteMode
88 hPutStrLn handle "---"
83 hPutStrLn handle "---"
89− mapM_ (writePair handle) $ M.toList $ M.delete (B.pack "body") mapping
84+ mapM_ (writePair handle) $ M.toList $ M.delete "body" mapping
90 hPutStrLn handle "---"
85 hPutStrLn handle "---"
91− B.hPut handle $ getBody page
86+ hPutStr handle $ getBody page
92 hClose handle
87 hClose handle
93− where writePair h (k, v) = B.hPut h k >>
88+ where writePair h (k, v) = hPutStr h k >>
94− B.hPut h (B.pack ": ") >>
89+ hPutStr h ": " >>
95− B.hPut h v >>
90+ hPutStr h v >>
96 hPutStrLn h ""
91 hPutStrLn h ""
97
92
98-- | Read a page from a file. Metadata is supported, and if the filename
93-- | Read a page from a file. Metadata is supported, and if the filename
@@ -114,13 +109,13 @@ readPage pagePath = do
114 else hGetContents handle >>= \b -> return ([], line ++ b)
109 else hGetContents handle >>= \b -> return ([], line ++ b)
115
110
116 -- Render file
111 -- Render file
117− let rendered = B.pack $ (renderFunction $ takeExtension path) body
112+ let rendered = (renderFunction $ takeExtension path) body
118 seq rendered $ hClose handle
113 seq rendered $ hClose handle
119 let page = fromContext $ M.fromList $
114 let page = fromContext $ M.fromList $
120− [ (B.pack "body", rendered)
115+ [ ("body", rendered)
121− , packPair ("url", url)
116+ , ("url", url)
122− , packPair ("path", pagePath)
117+ , ("path", pagePath)
123− ] ++ map packPair context
118+ ] ++ context
124
119
125 -- Cache if needed
120 -- Cache if needed
126 if getFromCache then return () else cachePage page
121 if getFromCache then return () else cachePage page
src/Text/Hakyll/Regex.hs+17−17
@@ -1,8 +1,8 @@
1-- | A module that exports a simple regex interface. This code is mostly copied
1-- | A module that exports a simple regex interface. This code is mostly copied
2-- from the regex-compat package at hackage.
2-- from the regex-compat package at hackage.
3module Text.Hakyll.Regex
3module Text.Hakyll.Regex
4− ( split
4+ ( splitRegex
5− , substitute
5+ , substituteRegex
6 ) where
6 ) where
7
7
8import Text.Regex.TDFA
8import Text.Regex.TDFA
@@ -13,10 +13,10 @@ matchRegexAll :: Regex -> String -> Maybe (String, String, String, [String])
13matchRegexAll p str = matchM p str
13matchRegexAll p str = matchM p str
14
14
15-- | Replaces every occurance of the given regexp with the replacement string.
15-- | Replaces every occurance of the given regexp with the replacement string.
16−subRegex :: Regex -- ^ Search pattern
16+subRegex :: Regex -- ^ Search pattern
17− -> String -- ^ Input string
17+ -> String -- ^ Input string
18− -> String -- ^ Replacement text
18+ -> String -- ^ Replacement text
19− -> String -- ^ Output string
19+ -> String -- ^ Output string
20subRegex _ "" _ = ""
20subRegex _ "" _ = ""
21subRegex regexp inp replacement =
21subRegex regexp inp replacement =
22 let -- bre matches a backslash then capture either a backslash or some digits
22 let -- bre matches a backslash then capture either a backslash or some digits
@@ -43,9 +43,9 @@ subRegex regexp inp replacement =
43
43
44-- | Splits a string based on a regular expression. The regular expression
44-- | Splits a string based on a regular expression. The regular expression
45-- should identify one delimiter.
45-- should identify one delimiter.
46−splitRegex :: Regex -> String -> [String]
46+splitRegex' :: Regex -> String -> [String]
47−splitRegex _ [] = []
47+splitRegex' _ [] = []
48−splitRegex delim strIn = loop strIn where
48+splitRegex' delim strIn = loop strIn where
49 loop str = case matchOnceText delim str of
49 loop str = case matchOnceText delim str of
50 Nothing -> [str]
50 Nothing -> [str]
51 Just (firstline, _, remainder) ->
51 Just (firstline, _, remainder) ->
@@ -54,13 +54,13 @@ splitRegex delim strIn = loop strIn where
54 else firstline : loop remainder
54 else firstline : loop remainder
55
55
56-- | Split a list at a certain element.
56-- | Split a list at a certain element.
57−split :: String -> String -> [String]
57+splitRegex :: String -> String -> [String]
58−split pattern = filter (not . null)
58+splitRegex pattern = filter (not . null)
59− . splitRegex (makeRegex pattern)
59+ . splitRegex' (makeRegex pattern)
60
60
61-- | Substitute a regex. Simplified interface.
61-- | Substitute a regex. Simplified interface.
62−substitute :: String -- ^ Pattern to replace (regex).
62+substituteRegex :: String -- ^ Pattern to replace (regex).
63− -> String -- ^ Replacement string.
63+ -> String -- ^ Replacement string.
64− -> String -- ^ Input string.
64+ -> String -- ^ Input string.
65− -> String -- ^ Result.
65+ -> String -- ^ Result.
66−substitute pattern replacement str = subRegex (makeRegex pattern) str replacement
66+substituteRegex pattern replacement str = subRegex (makeRegex pattern) str replacement
src/Text/Hakyll/Render.hs+29−15
@@ -10,15 +10,16 @@ module Text.Hakyll.Render
10 , css
10 , css
11 ) where
11 ) where
12
12
13−import Text.Template hiding (render)
14−import qualified Data.ByteString.Lazy.Char8 as B
15import qualified Data.Map as M
13import qualified Data.Map as M
14+import Data.List (isPrefixOf)
16import Control.Monad (unless, liftM, foldM)
15import Control.Monad (unless, liftM, foldM)
16+import Data.Char (isAlpha)
17+import Data.Maybe (fromMaybe)
17
18
18import System.Directory (copyFile)
19import System.Directory (copyFile)
19import System.IO
20import System.IO
20
21
21−import Text.Hakyll.Context (ContextManipulation)
22+import Text.Hakyll.Context (Context, ContextManipulation)
22import Text.Hakyll.Page
23import Text.Hakyll.Page
23import Text.Hakyll.Renderable
24import Text.Hakyll.Renderable
24import Text.Hakyll.File
25import Text.Hakyll.File
@@ -33,6 +34,19 @@ depends file dependencies action = do
33 valid <- isCacheValid (toDestination file) dependencies
34 valid <- isCacheValid (toDestination file) dependencies
34 unless valid action
35 unless valid action
35
36
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.
39+substitute :: String -> Context -> String
40+substitute [] _ = []
41+substitute string context
42+ | "$$" `isPrefixOf` string = "$$" ++ (substitute (tail tail') context)
43+ | "$" `isPrefixOf` string = substitute'
44+ | otherwise = (head string) : (substitute tail' context)
45+ where tail' = tail string
46+ (key, rest) = break (not . isAlpha) tail'
47+ replacement = fromMaybe ('$' : key) $ M.lookup key context
48+ substitute' = replacement ++ substitute rest context
49+
36-- | Render to a Page.
50-- | Render to a Page.
37render :: Renderable a
51render :: Renderable a
38 => FilePath -- ^ Template to use for rendering.
52 => FilePath -- ^ Template to use for rendering.
@@ -49,18 +63,18 @@ renderWith :: Renderable a
49 -> IO Page -- ^ The body of the result will contain the render.
63 -> IO Page -- ^ The body of the result will contain the render.
50renderWith manipulation templatePath renderable = do
64renderWith manipulation templatePath renderable = do
51 handle <- openFile templatePath ReadMode
65 handle <- openFile templatePath ReadMode
52− templateString <- liftM B.pack $ hGetContents handle
66+ templateString <- hGetContents handle
53 seq templateString $ hClose handle
67 seq templateString $ hClose handle
54 context <- liftM manipulation $ toContext renderable
68 context <- liftM manipulation $ toContext renderable
55 -- Ignore $root when substituting here. We will only replace that in the
69 -- Ignore $root when substituting here. We will only replace that in the
56 -- final render (just before writing).
70 -- final render (just before writing).
57− let contextIgnoringRoot = M.insert (B.pack "root") (B.pack "$root") context
71+ let contextIgnoringRoot = M.insert "root" "$root" context
58 body = substitute templateString contextIgnoringRoot
72 body = substitute templateString contextIgnoringRoot
59− return $ fromContext (M.insert (B.pack "body") body context)
73+ return $ fromContext (M.insert "body" body context)
60
74
61-- | Render each renderable with the given template, then concatenate the
75-- | Render each renderable with the given template, then concatenate the
62-- result.
76-- result.
63−renderAndConcat :: Renderable a => FilePath -> [a] -> IO B.ByteString
77+renderAndConcat :: Renderable a => FilePath -> [a] -> IO String
64renderAndConcat = renderAndConcatWith id
78renderAndConcat = renderAndConcatWith id
65
79
66-- | Render each renderable with the given template, then concatenate the
80-- | Render each renderable with the given template, then concatenate the
@@ -70,14 +84,14 @@ renderAndConcatWith :: Renderable a
70 => ContextManipulation
84 => ContextManipulation
71 -> FilePath
85 -> FilePath
72 -> [a]
86 -> [a]
73− -> IO B.ByteString
87+ -> IO String
74renderAndConcatWith manipulation templatePath renderables =
88renderAndConcatWith manipulation templatePath renderables =
75− foldM concatRender' B.empty renderables
89+ foldM concatRender' [] renderables
76− where concatRender' :: Renderable a => B.ByteString -> a -> IO B.ByteString
90+ where concatRender' :: Renderable a => String -> a -> IO String
77 concatRender' chunk renderable = do
91 concatRender' chunk renderable = do
78 rendered <- renderWith manipulation templatePath renderable
92 rendered <- renderWith manipulation templatePath renderable
79 let body = getBody rendered
93 let body = getBody rendered
80− return $ B.append chunk $ body
94+ return $ chunk ++ body
81
95
82-- | Chain a render action for a page with a number of templates. This will
96-- | Chain a render action for a page with a number of templates. This will
83-- also write the result to the site destination. This is the preferred way
97-- also write the result to the site destination. This is the preferred way
@@ -100,11 +114,11 @@ writePage :: Page -> IO ()
100writePage page = do
114writePage page = do
101 let destination = toDestination url
115 let destination = toDestination url
102 makeDirectories destination
116 makeDirectories destination
103− B.writeFile destination body
117+ writeFile destination body
104 where url = getURL page
118 where url = getURL page
105− -- Substitute $root here, just before writing.
119+          -- Substitute $root here, just before writing.
106− body = substitute (getBody page)
120+          body = substitute (getBody page)
107− (M.singleton (B.pack "root") (B.pack $ toRoot url))
121+                            (M.singleton "root" $ toRoot url)
108
122
109-- | Mark a certain file as static, so it will just be copied when the site is
123-- | Mark a certain file as static, so it will just be copied when the site is
110-- generated.
124-- generated.
src/Text/Hakyll/Renderable.hs+1−1
@@ -3,7 +3,7 @@ module Text.Hakyll.Renderable
3 ) where
3 ) where
4
4
5import System.FilePath (FilePath)
5import System.FilePath (FilePath)
6−import Text.Template (Context)
6+import Text.Hakyll.Context (Context)
7
7
8-- | A class for datatypes that can be rendered to pages.
8-- | A class for datatypes that can be rendered to pages.
9class Renderable a where
9class Renderable a where
src/Text/Hakyll/Renderables.hs+5−7
@@ -6,7 +6,6 @@ module Text.Hakyll.Renderables
6 ) where
6 ) where
7
7
8import System.FilePath (FilePath)
8import System.FilePath (FilePath)
9−import qualified Data.ByteString.Lazy.Char8 as B
10import qualified Data.Map as M
9import qualified Data.Map as M
11import Text.Hakyll.Page
10import Text.Hakyll.Page
12import Text.Hakyll.Renderable
11import Text.Hakyll.Renderable
@@ -16,13 +15,13 @@ import Text.Hakyll.File
16data CustomPage = CustomPage
15data CustomPage = CustomPage
17 { url :: String,
16 { url :: String,
18 dependencies :: [FilePath],
17 dependencies :: [FilePath],
19− mapping :: [(String, Either String (IO B.ByteString))]
18+ mapping :: [(String, Either String (IO String))]
20 }
19 }
21
20
22-- | Create a custom page.
21-- | Create a custom page.
23createCustomPage :: String -- ^ Destination of the page, relative to _site.
22createCustomPage :: String -- ^ Destination of the page, relative to _site.
24 -> [FilePath] -- ^ Dependencies of the page.
23 -> [FilePath] -- ^ Dependencies of the page.
25− -> [(String, Either String (IO B.ByteString))] -- ^ Key - value mapping for rendering.
24+ -> [(String, Either String (IO String))] -- ^ Key - value mapping for rendering.
26 -> CustomPage
25 -> CustomPage
27createCustomPage = CustomPage
26createCustomPage = CustomPage
28
27
@@ -30,10 +29,9 @@ instance Renderable CustomPage where
30 getDependencies = dependencies
29 getDependencies = dependencies
31 getURL = url
30 getURL = url
32 toContext page = do
31 toContext page = do
33− values <- mapM (either (return . B.pack) (>>= return) . snd) (mapping page)
32+ values <- mapM (either (return) (>>= return) . snd) (mapping page)
34− let keys = map (B.pack . fst) (mapping page)
35− return $ M.fromList $ [ (B.pack "url", B.pack $ url page)
33+ return $ M.fromList $ [ ("url", url page)
36− ] ++ zip keys values
34+ ] ++ zip (map fst $ mapping page) values
37
35
38-- | PagePath is a class that wraps a FilePath. This is used to render Pages
36-- | PagePath is a class that wraps a FilePath. This is used to render Pages
39-- without reading them first through use of caching.
37-- without reading them first through use of caching.
src/Text/Hakyll/Tags.hs+3−4
@@ -7,7 +7,6 @@ module Text.Hakyll.Tags
7 ) where
7 ) where
8
8
9import qualified Data.Map as M
9import qualified Data.Map as M
10−import qualified Data.ByteString.Lazy.Char8 as B
11import Data.List (intercalate)
10import Data.List (intercalate)
12import Control.Monad (foldM)
11import Control.Monad (foldM)
13
12
@@ -24,7 +23,7 @@ readTagMap :: [FilePath] -> IO (M.Map String [FilePath])
24readTagMap paths = foldM addPaths M.empty paths
23readTagMap paths = foldM addPaths M.empty paths
25 where addPaths current path = do
24 where addPaths current path = do
26 page <- readPage path
25 page <- readPage path
27− let tags = map trim $ split "," $ B.unpack $ getValue ("tags") page
26+ let tags = map trim $ splitRegex "," $ getValue ("tags") page
28 return $ foldr (\t -> M.insertWith (++) t [path]) current tags
27 return $ foldr (\t -> M.insertWith (++) t [path]) current tags
29
28
30-- | Render a tag cloud.
29-- | Render a tag cloud.
@@ -57,6 +56,6 @@ renderTagCloud tagMap urlFunction minSize maxSize =
57renderTagLinks :: (String -> String) -- ^ Function that produces an url for a tag.
56renderTagLinks :: (String -> String) -- ^ Function that produces an url for a tag.
58 -> ContextManipulation
57 -> ContextManipulation
59renderTagLinks urlFunction = renderValue "tags" "tags" renderTagLinks'
58renderTagLinks urlFunction = renderValue "tags" "tags" renderTagLinks'
60− where renderTagLinks' = B.pack . intercalate ", "
59+ where renderTagLinks' = intercalate ", "
61 . map (\t -> link t $ urlFunction t)
60 . map (\t -> link t $ urlFunction t)
62− . map trim . split "," . B.unpack
61+ . map trim . splitRegex ","
tests/Tests.hs+5−5
@@ -26,8 +26,8 @@ tests = [ testGroup "Util group" [ testProperty "trim length" prop_trim_length
26 , testCase "link 2" test_link2
26 , testCase "link 2" test_link2
27 ]
27 ]
28
28
29− , testGroup "Regex group" [ testCase "split 1" test_split1
29+ , testGroup "Regex group" [ testCase "splitRegex 1" test_split_regex1
30− , testCase "split 2" test_split2
30+ , testCase "splitRegex 2" test_split_regex2
31 ]
31 ]
32
32
33 , testGroup "CompressCSS group" [ testProperty "compressCSS length" prop_compress_css_length
33 , testGroup "CompressCSS group" [ testProperty "compressCSS length" prop_compress_css_length
@@ -71,9 +71,9 @@ test_strip_html3 = stripHTML "<b>Hakyll</b> is an <i>awesome</i> web framework <
71test_link1 = link "foo bar" "/foo/bar.html" @?= "<a href=\"/foo/bar.html\">foo bar</a>"
71test_link1 = link "foo bar" "/foo/bar.html" @?= "<a href=\"/foo/bar.html\">foo bar</a>"
72test_link2 = link "back home" "/" @?= "<a href=\"/\">back home</a>"
72test_link2 = link "back home" "/" @?= "<a href=\"/\">back home</a>"
73
73
74−-- Split test cases.
74+-- Split Regex test cases.
75−test_split1 = split "," "1,2,3" @?= ["1", "2", "3"]
75+test_split_regex1 = split "," "1,2,3" @?= ["1", "2", "3"]
76−test_split2 = split "," ",1,2," @?= ["1", "2"]
76+test_split_regex2 = split "," ",1,2," @?= ["1", "2"]
77
77
78-- CSS compression should always decrease the text length.
78-- CSS compression should always decrease the text length.
79prop_compress_css_length str = length str >= length (compressCSS str)
79prop_compress_css_length str = length str >= length (compressCSS str)