on master help sign in
Some changes to the regex interface, and version bump.
73f6b1aJasper Van der Jeugt
hakyll.cabal+4−2
@@ -1,5 +1,5 @@
1Name: hakyll
1Name: hakyll
2−Version: 0.4
2+Version: 0.4.1
3
3
4Synopsis: A simple static site generator library.
4Synopsis: A simple static site generator library.
5Description:
5Description:
@@ -30,7 +30,8 @@ library
30 containers >= 0.1,
30 containers >= 0.1,
31 bytestring >= 0.9 && < 0.9.2,
31 bytestring >= 0.9 && < 0.9.2,
32 pandoc >= 1,
32 pandoc >= 1,
33− regex-compat >= 0.92,
33+ regex-base >= 0.83,
34+ regex-tdfa >= 0.92,
34 network >= 2,
35 network >= 2,
35 mtl >= 1.1,
36 mtl >= 1.1,
36 old-locale >= 1,
37 old-locale >= 1,
@@ -45,4 +46,5 @@ library
45 Text.Hakyll.Util
46 Text.Hakyll.Util
46 Text.Hakyll.Tags
47 Text.Hakyll.Tags
47 Text.Hakyll.Context
48 Text.Hakyll.Context
49+ Text.Hakyll.Regex
48 Network.Hakyll.SimpleServer
50 Network.Hakyll.SimpleServer
src/Network/Hakyll/SimpleServer.hs+1
@@ -17,6 +17,7 @@ import qualified Data.ByteString.Char8 as B
17import qualified Data.Map as M
17import qualified Data.Map as M
18
18
19import Text.Hakyll.Util
19import Text.Hakyll.Util
20+import Text.Hakyll.Regex
20
21
21-- | Function to log from a chan.
22-- | Function to log from a chan.
22log :: Chan String -> IO ()
23log :: Chan String -> IO ()
src/Text/Hakyll/CompressCSS.hs+6−10
@@ -3,27 +3,23 @@ module Text.Hakyll.CompressCSS
3 ) where
3 ) where
4
4
5import Data.List (isPrefixOf)
5import Data.List (isPrefixOf)
6−import Text.Regex (subRegex, mkRegex)
6+import Text.Hakyll.Regex (substitute)
7−
8−-- | subRegex with arguments flipped for easy function composition.
9−subRegex' :: String -> String -> String -> String
10−subRegex' pattern replacement str = subRegex (mkRegex pattern) str replacement
11
7
12-- | Compress CSS to speed up your site.
8-- | Compress CSS to speed up your site.
13compressCSS :: String -> String
9compressCSS :: String -> String
14compressCSS = compressSeparators
10compressCSS = compressSeparators
15− . compressWhitespace
16 . stripComments
11 . stripComments
12+ . compressWhitespace
17
13
18-- | Compresses certain forms of separators.
14-- | Compresses certain forms of separators.
19compressSeparators :: String -> String
15compressSeparators :: String -> String
20−compressSeparators = subRegex' ";\\s*}" "}"
16+compressSeparators = substitute "; *}" "}"
21− . subRegex' "\\s*([{};:])\\s*" "\\1"
17+ . substitute " *([{};:]) *" "\\1"
22− . subRegex' ";;*" ";"
18+ . substitute ";;*" ";"
23
19
24-- | Compresses all whitespace.
20-- | Compresses all whitespace.
25compressWhitespace :: String -> String
21compressWhitespace :: String -> String
26−compressWhitespace = subRegex' "\\s\\s*" " "
22+compressWhitespace = substitute "[ \t\n][ \t\n]*" " "
27
23
28-- | Function that strips CSS comments away.
24-- | Function that strips CSS comments away.
29stripComments :: String -> String
25stripComments :: String -> String
src/Text/Hakyll/Context.hs+3−4
@@ -10,11 +10,11 @@ import qualified Data.ByteString.Lazy.Char8 as B
10
10
11import System.Locale (defaultTimeLocale)
11import System.Locale (defaultTimeLocale)
12import System.FilePath (takeFileName)
12import System.FilePath (takeFileName)
13−import Text.Regex (subRegex, mkRegex)
14import Text.Template (Context)
13import Text.Template (Context)
15import Data.Time.Format (parseTime, formatTime)
14import Data.Time.Format (parseTime, formatTime)
16import Data.Time.Clock (UTCTime)
15import Data.Time.Clock (UTCTime)
17import Data.Maybe (fromMaybe)
16import Data.Maybe (fromMaybe)
17+import Text.Hakyll.Regex (substitute)
18
18
19-- | Type for context manipulating functions.
19-- | Type for context manipulating functions.
20type ContextManipulation = Context -> Context
20type ContextManipulation = Context -> Context
@@ -38,9 +38,8 @@ renderDate key format defaultValue context =
38 M.insert (B.pack key) (B.pack value) context
38 M.insert (B.pack key) (B.pack value) context
39 where value = fromMaybe defaultValue pretty
39 where value = fromMaybe defaultValue pretty
40 pretty = do filePath <- M.lookup (B.pack "path") context
40 pretty = do filePath <- M.lookup (B.pack "path") context
41− let dateString = subRegex (mkRegex "^([0-9]*-[0-9]*-[0-9]*).*")
41+ let dateString = substitute "^([0-9]*-[0-9]*-[0-9]*).*" "\\1"
42− (takeFileName $ B.unpack filePath)
42+ (takeFileName $ B.unpack filePath)
43− "\\1"
44 time <- parseTime defaultTimeLocale
43 time <- parseTime defaultTimeLocale
45 "%Y-%m-%d"
44 "%Y-%m-%d"
46 dateString :: Maybe UTCTime
45 dateString :: Maybe UTCTime
src/Text/Hakyll/Regex.hsnew file+66
@@ -0,0 +1,66 @@
1+-- | A module that exports a simple regex interface. This code is mostly copied
2+-- from the regex-compat package at hackage.
3+module Text.Hakyll.Regex
4+ ( split
5+ , substitute
6+ ) where
7+
8+import Text.Regex.TDFA
9+
10+-- | Match a regular expression against a string, returning more information
11+-- about the match.
12+matchRegexAll :: Regex -> String -> Maybe (String, String, String, [String])
13+matchRegexAll p str = matchM p str
14+
15+-- | Replaces every occurance of the given regexp with the replacement string.
16+subRegex :: Regex -- ^ Search pattern
17+ -> String -- ^ Input string
18+ -> String -- ^ Replacement text
19+ -> String -- ^ Output string
20+subRegex _ "" _ = ""
21+subRegex regexp inp replacement =
22+ let -- bre matches a backslash then capture either a backslash or some digits
23+ bre = makeRegex "\\\\(\\\\|[0-9]+)"
24+ lookup' _ [] _ = []
25+ lookup' [] _ _ = []
26+ lookup' match' repl groups =
27+ case matchRegexAll bre repl of
28+ Nothing -> repl
29+ Just (lead, _, trail, bgroups) ->
30+ let newval =
31+ if (head bgroups) == "\\"
32+ then "\\"
33+ else let index :: Int
34+ index = (read (head bgroups)) - 1
35+ in if index == -1
36+ then match'
37+ else groups !! index
38+ in lead ++ newval ++ lookup' match' trail groups
39+ in case matchRegexAll regexp inp of
40+ Nothing -> inp
41+ Just (lead, match', trail, groups) ->
42+ lead ++ lookup' match' replacement groups ++ (subRegex regexp trail replacement)
43+
44+-- | Splits a string based on a regular expression. The regular expression
45+-- should identify one delimiter.
46+splitRegex :: Regex -> String -> [String]
47+splitRegex _ [] = []
48+splitRegex delim strIn = loop strIn where
49+ loop str = case matchOnceText delim str of
50+ Nothing -> [str]
51+ Just (firstline, _, remainder) ->
52+ if null remainder
53+ then [firstline,""]
54+ else firstline : loop remainder
55+
56+-- | Split a list at a certain element.
57+split :: String -> String -> [String]
58+split pattern = filter (not . null)
59+ . splitRegex (makeRegex pattern)
60+
61+-- | Substitute a regex. Simplified interface.
62+substitute :: String -- ^ Pattern to replace (regex).
63+ -> String -- ^ Replacement string.
64+ -> String -- ^ Input string.
65+ -> String -- ^ Result.
66+substitute pattern replacement str = subRegex (makeRegex pattern) str replacement
src/Text/Hakyll/Tags.hs+1
@@ -12,6 +12,7 @@ import Data.List (intercalate)
12import Control.Monad (foldM)
12import Control.Monad (foldM)
13
13
14import Text.Hakyll.Context (ContextManipulation, renderValue)
14import Text.Hakyll.Context (ContextManipulation, renderValue)
15+import Text.Hakyll.Regex
15import Text.Hakyll.Util
16import Text.Hakyll.Util
16import Text.Hakyll.Page
17import Text.Hakyll.Page
17import Control.Arrow (second)
18import Control.Arrow (second)
src/Text/Hakyll/Util.hs−7
@@ -1,12 +1,10 @@
1module Text.Hakyll.Util
1module Text.Hakyll.Util
2 ( trim
2 ( trim
3− , split
4 , stripHTML
3 , stripHTML
5 , link
4 , link
6 ) where
5 ) where
7
6
8import Data.Char (isSpace)
7import Data.Char (isSpace)
9−import Text.Regex (splitRegex, mkRegex)
10
8
11-- | Trim a string (drop spaces and tabs at both sides).
9-- | Trim a string (drop spaces and tabs at both sides).
12trim :: String -> String
10trim :: String -> String
@@ -23,11 +21,6 @@ stripHTML str = let (beforeTag, rest) = break (== '<') str
23 where tail' [] = []
21 where tail' [] = []
24 tail' xs = tail xs
22 tail' xs = tail xs
25
23
26−-- | Split a list at a certain element.
27−split :: String -> String -> [String]
28−split pattern = filter (not . null)
29− . splitRegex (mkRegex pattern)
30−
31-- | Make a HTML link.
24-- | Make a HTML link.
32--
25--
33-- > link "foo" "bar.html" == "<a href='bar.html'>foo</a>"
26-- > link "foo" "bar.html" == "<a href='bar.html'>foo</a>"
tests/Tests.hs+9−6
@@ -10,6 +10,7 @@ import qualified Data.ByteString.Lazy.Char8 as B
10
10
11import Text.Hakyll.CompressCSS
11import Text.Hakyll.CompressCSS
12import Text.Hakyll.Util
12import Text.Hakyll.Util
13+import Text.Hakyll.Regex
13import Text.Hakyll.Context
14import Text.Hakyll.Context
14import Text.Hakyll.File
15import Text.Hakyll.File
15
16
@@ -21,12 +22,14 @@ tests = [ testGroup "Util group" [ testProperty "trim length" prop_trim_length
21 , testCase "stripHTML 1" test_strip_html1
22 , testCase "stripHTML 1" test_strip_html1
22 , testCase "stripHTML 2" test_strip_html2
23 , testCase "stripHTML 2" test_strip_html2
23 , testCase "stripHTML 3" test_strip_html3
24 , testCase "stripHTML 3" test_strip_html3
24− , testCase "split 1" test_split1
25− , testCase "split 2" test_split2
26 , testCase "link 1" test_link1
25 , testCase "link 1" test_link1
27 , testCase "link 2" test_link2
26 , testCase "link 2" test_link2
28 ]
27 ]
29
28
29+ , testGroup "Regex group" [ testCase "split 1" test_split1
30+ , testCase "split 2" test_split2
31+ ]
32+
30 , testGroup "CompressCSS group" [ testProperty "compressCSS length" prop_compress_css_length
33 , testGroup "CompressCSS group" [ testProperty "compressCSS length" prop_compress_css_length
31 , testCase "compressCSS 1" test_compress_css1
34 , testCase "compressCSS 1" test_compress_css1
32 , testCase "compressCSS 2" test_compress_css2
35 , testCase "compressCSS 2" test_compress_css2
@@ -61,14 +64,14 @@ test_strip_html2 = stripHTML "text" @?= "text"
61test_strip_html3 = stripHTML "<b>Hakyll</b> is an <i>awesome</i> web framework <img src=\"foo.png\" />" @?=
64test_strip_html3 = stripHTML "<b>Hakyll</b> is an <i>awesome</i> web framework <img src=\"foo.png\" />" @?=
62 "Hakyll is an awesome web framework "
65 "Hakyll is an awesome web framework "
63
66
64−-- Split test cases.
65−test_split1 = split "," "1,2,3" @?= ["1", "2", "3"]
66−test_split2 = split "," ",1,2," @?= ["1", "2"]
67−
68-- Link test cases.
67-- Link test cases.
69test_link1 = link "foo bar" "/foo/bar.html" @?= "<a href=\"/foo/bar.html\">foo bar</a>"
68test_link1 = link "foo bar" "/foo/bar.html" @?= "<a href=\"/foo/bar.html\">foo bar</a>"
70test_link2 = link "back home" "/" @?= "<a href=\"/\">back home</a>"
69test_link2 = link "back home" "/" @?= "<a href=\"/\">back home</a>"
71
70
71+-- Split test cases.
72+test_split1 = split "," "1,2,3" @?= ["1", "2", "3"]
73+test_split2 = split "," ",1,2," @?= ["1", "2"]
74+
72-- CSS compression should always decrease the text length.
75-- CSS compression should always decrease the text length.
73prop_compress_css_length str = length str >= length (compressCSS str)
76prop_compress_css_length str = length str >= length (compressCSS str)
74
77