@@ -8,14 +8,12 @@ module Hakyll.Web.CompressCss
88
99
1010--------------------------------------------------------------------------------
11−import Data.Char (isSpace)
1211import Data.List (isPrefixOf)
1312
1413
1514--------------------------------------------------------------------------------
1615import Hakyll.Core.Compiler
1716import Hakyll.Core.Item
18−import Hakyll.Core.Util.String
1917
2018
2119--------------------------------------------------------------------------------
@@ -33,27 +31,55 @@ compressCss = compressSeparators . stripComments . compressWhitespace
3331--------------------------------------------------------------------------------
3432-- | Compresses certain forms of separators.
3533compressSeparators :: String -> String
36−compressSeparators =
37− replaceAll "; *}" (const "}") .
38− replaceAll " *([{};]) *" (take 1 . dropWhile isSpace) .
39− replaceAll ";+" (const ";")
40−
34+compressSeparators [] = []
35+compressSeparators str
36+ | isConstant = head str : retainConstants compressSeparators (head str) (drop 1 str)
37+ | stripFirst = compressSeparators (drop 1 str)
38+ | stripSecond = compressSeparators (head str : (drop 2 str))
39+ | otherwise = head str : compressSeparators (drop 1 str)
40+ where
41+ isConstant = or $ map (isOfPrefix str) ["\"", "'"]
42+ stripFirst = or $ map (isOfPrefix str) [" ", " {", " }", " :", ";;", ";}"]
43+ stripSecond = or $ map (isOfPrefix str) ["{ ", "} ", ": ", "; "]
4144
4245--------------------------------------------------------------------------------
4346-- | Compresses all whitespace.
4447compressWhitespace :: String -> String
45−compressWhitespace = replaceAll "[ \t\n\r]+" (const " ")
46−
48+compressWhitespace [] = []
49+compressWhitespace str
50+ | isConstant = head str : retainConstants compressWhitespace (head str) (drop 1 str)
51+ | replaceOne = compressWhitespace (' ' : (drop 1 str))
52+ | replaceTwo = compressWhitespace (' ' : (drop 2 str))
53+ | otherwise = head str : compressWhitespace (drop 1 str)
54+ where
55+ isConstant = or $ map (isOfPrefix str) ["\"", "'"]
56+ replaceOne = or $ map (isOfPrefix str) ["\t", "\n", "\r"]
57+ replaceTwo = or $ map (isOfPrefix str) [" \t", " \n", " \r", " "]
4758
4859--------------------------------------------------------------------------------
4960-- | Function that strips CSS comments away.
5061stripComments :: String -> String
5162stripComments [] = []
5263stripComments str
64+ | isConstant = head str : retainConstants stripComments (head str) (drop 1 str)
5365 | isPrefixOf "/*" str = stripComments $ eatComments $ drop 2 str
5466 | otherwise = head str : stripComments (drop 1 str)
5567 where
68+ isConstant = or $ map (isOfPrefix str) ["\"", "'"]
5669 eatComments str'
5770 | null str' = []
5871 | isPrefixOf "*/" str' = drop 2 str'
5972 | otherwise = eatComments $ drop 1 str'
73+
74+--------------------------------------------------------------------------------
75+-- | Helper function to handle string constants correctly.
76+retainConstants :: (String -> String) -> Char -> String -> String
77+retainConstants f delim str
78+ | null str = []
79+ | isPrefixOf [delim] str = head str : f (drop 1 str)
80+ | otherwise = head str : retainConstants f delim (drop 1 str)
81+
82+--------------------------------------------------------------------------------
83+-- | Helper function to determine whether a string is a substring.
84+isOfPrefix :: String -> String -> Bool
85+isOfPrefix = flip isPrefixOf