on master help sign in
Readability++.
commitdae0258a62a714fb7fd9b47473bf259eb858f9f1 authorJasper Van der Jeugt <jaspervdj@gmail.com> dateMon 11 Jan 2010, 13:56 (17 years ago) parent7a765f2
9 files changed+187−148
src/Network/Hakyll/SimpleServer.hs+63−51 src/Text/Hakyll.hs+5−4 src/Text/Hakyll/CompressCSS.hs+7−5 src/Text/Hakyll/Context.hs+9−8 src/Text/Hakyll/File.hs+14−9 src/Text/Hakyll/Page.hs+29−22 src/Text/Hakyll/Render.hs+27−22 src/Text/Hakyll/Tags.hs+28−24 src/Text/Hakyll/Util.hs+5−3
src/Network/Hakyll/SimpleServer.hs+63−51
@@ -78,8 +78,9 @@ defaultResponse = Response { responseVersion = B.pack "HTTP/1.1"
7878
7979-- | Create a response for a given HTTP request.
8080createResponse :: Request -> Server Response
81−createResponse request | requestMethod request == B.pack "GET" = createGetResponse request
82− | otherwise = return $ createErrorResponse 501 (B.pack "Not Implemented")
81+createResponse request
82+ | requestMethod request == B.pack "GET" = createGetResponse request
83+ | otherwise = return $ createErrorResponse 501 (B.pack "Not Implemented")
8384
8485-- | Create a simple error response.
8586createErrorResponse :: Int -- ^ Error code.
@@ -89,9 +90,10 @@ createErrorResponse statusCode phrase = defaultResponse
8990 { responseStatusCode = statusCode
9091 , responsePhrase = phrase
9192 , responseHeaders = M.singleton (B.pack "Content-Type") (B.pack "text/html")
92− , responseBody = B.pack $ "<html> <head> <title>" ++ show statusCode ++ "</title> </head>"
93− ++ "<body> <h1>" ++ show statusCode ++ "</h1>\n"
94− ++ "<p>" ++ (B.unpack phrase) ++ "</p> </body> </html>"
93+ , responseBody = B.pack $
94+ "<html> <head> <title>" ++ show statusCode ++ "</title> </head>"
95+ ++ "<body> <h1>" ++ show statusCode ++ "</h1>\n"
96+ ++ "<p>" ++ (B.unpack phrase) ++ "</p> </body> </html>"
9597 }
9698
9799-- | Create a simple get response.
@@ -100,48 +102,56 @@ createGetResponse request = do
100102 -- Construct the complete fileName of the requested resource.
101103 config <- ask
102104 let uri = B.unpack (requestURI request)
105+ log' = writeChan (logChannel config)
103106 isDirectory <- liftIO $ doesDirectoryExist $ documentRoot config ++ uri
104− let fileName = (documentRoot config) ++ if isDirectory then uri ++ "/index.html"
105− else uri
107+ let fileName =
108+ (documentRoot config) ++ if isDirectory then uri ++ "/index.html"
109+ else uri
106110
107111 create200 = do
108112 body <- B.readFile fileName
109− let headers = [ (B.pack "Content-Length", B.pack $ show $ B.length body)
110− ] ++ getMIMEHeader fileName
111− return $ defaultResponse { responseStatusCode = 200
112− , responsePhrase = B.pack "OK"
113− , responseHeaders = (responseHeaders defaultResponse)
114− `M.union` M.fromList headers
115− , responseBody = body
116− }
113+ let headers =
114+ [ (B.pack "Content-Length", B.pack $ show $ B.length body)
115+ ] ++ getMIMEHeader fileName
116+ return $ defaultResponse
117+ { responseStatusCode = 200
118+ , responsePhrase = B.pack "OK"
119+ , responseHeaders = (responseHeaders defaultResponse)
120+ `M.union` M.fromList headers
121+ , responseBody = body
122+ }
117123
118124 -- Called when an error occurs during the creation of a 200 response.
119− create500 e = do writeChan (logChannel config) $ "Internal Error: " ++ show e
120− return $ createErrorResponse 500 (B.pack "Internal Server Error")
125+ create500 e = do
126+ log' $ "Internal Error: " ++ show e
127+ return $ createErrorResponse 500 (B.pack "Internal Server Error")
121128
122129 -- Send back the page if found.
123130 exists <- liftIO $ doesFileExist fileName
124− if exists then do response <- liftIO $ catch create200 create500
125− return response
126− else do liftIO $ writeChan (logChannel config) $ "Not Found: " ++ fileName
127− return $ createErrorResponse 404 (B.pack "Not Found")
131+ if exists
132+ then do response <- liftIO $ catch create200 create500
133+ return response
134+ else do liftIO $ log' $ "Not Found: " ++ fileName
135+ return $ createErrorResponse 404 (B.pack "Not Found")
128136
129137-- | Get the mime header for a certain filename. This is based on the extension
130138-- of the given 'FilePath'.
131139getMIMEHeader :: FilePath -> [(B.ByteString, B.ByteString)]
132−getMIMEHeader fileName = case result of (Just x) -> [(B.pack "Content-Type", B.pack x)]
133− Nothing -> []
134− where result = lookup (takeExtension fileName) [ (".css", "text/css")
135− , (".gif", "image/gif")
136− , (".htm", "text/html")
137− , (".html", "text/html")
138− , (".jpeg", "image/jpeg")
139− , (".jpg", "image/jpeg")
140− , (".js", "text/javascript")
141− , (".png", "image/png")
142− , (".txt", "text/plain")
143− , (".xml", "text/xml")
144− ]
140+getMIMEHeader fileName =
141+ case result of (Just x) -> [(B.pack "Content-Type", B.pack x)]
142+ Nothing -> []
143+ where
144+ result = lookup (takeExtension fileName) [ (".css", "text/css")
145+ , (".gif", "image/gif")
146+ , (".htm", "text/html")
147+ , (".html", "text/html")
148+ , (".jpeg", "image/jpeg")
149+ , (".jpg", "image/jpeg")
150+ , (".js", "text/javascript")
151+ , (".png", "image/png")
152+ , (".txt", "text/plain")
153+ , (".xml", "text/xml")
154+ ]
145155
146156-- | Respond to an incoming request.
147157respond :: Handle -> Server ()
@@ -152,24 +162,28 @@ respond handle = do
152162
153163 -- Generate some output.
154164 config <- ask
155− liftIO $ writeChan (logChannel config) $ show request ++ " => " ++ show response
165+ liftIO $ writeChan (logChannel config)
166+ $ show request ++ " => " ++ show response
156167
157168 -- Send the response back to the handle.
158169 liftIO $ putResponse response
159− where putResponse response = do B.hPutStr handle $ B.intercalate (B.pack " ")
160− [ responseVersion response
161− , B.pack $ show $ responseStatusCode response
162− , responsePhrase response
163− ]
164− hPutStr handle "\r\n"
165− mapM_ putHeader (M.toList $ responseHeaders response)
166− hPutStr handle "\r\n"
167− B.hPutStr handle $ responseBody response
168− hPutStr handle "\r\n"
169− hClose handle
170−
171− putHeader (key, value) = B.hPutStr handle $ key `B.append` B.pack ": "
172− `B.append` value `B.append` B.pack "\r\n"
170+ where
171+ putResponse response = do B.hPutStr handle $ B.intercalate (B.pack " ")
172+ [ responseVersion response
173+ , B.pack $ show $ responseStatusCode response
174+ , responsePhrase response
175+ ]
176+ hPutStr handle "\r\n"
177+ mapM_ putHeader
178+ (M.toList $ responseHeaders response)
179+ hPutStr handle "\r\n"
180+ B.hPutStr handle $ responseBody response
181+ hPutStr handle "\r\n"
182+ hClose handle
183+
184+ putHeader (key, value) =
185+ B.hPutStr handle $ key `B.append` B.pack ": "
186+ `B.append` value `B.append` B.pack "\r\n"
173187
174188-- | Start a simple http server on the given 'PortNumber', serving the given
175189-- directory.
@@ -194,5 +208,3 @@ simpleServer port root = do
194208 writeChan logChan $ "Starting hakyll server on port " ++ show port ++ "..."
195209 socket <- listenOn (PortNumber port)
196210 forever (listen socket)
197− where
198−
src/Text/Hakyll.hs+5−4
@@ -28,10 +28,11 @@ build buildFunction = do putStrLn "Generating..."
2828clean :: IO ()
2929clean = do remove' "_cache"
3030 remove' "_site"
31− where remove' dir = do putStrLn $ "Removing " ++ dir ++ "..."
32− exists <- doesDirectoryExist dir
33− if exists then removeDirectoryRecursive dir
34− else return ()
31+ where
32+ remove' dir = do putStrLn $ "Removing " ++ dir ++ "..."
33+ exists <- doesDirectoryExist dir
34+ if exists then removeDirectoryRecursive dir
35+ else return ()
3536
3637-- | Show usage information.
3738help :: IO ()
src/Text/Hakyll/CompressCSS.hs+7−5
@@ -24,8 +24,10 @@ compressWhitespace = substituteRegex "[ \t\n][ \t\n]*" " "
2424-- | Function that strips CSS comments away.
2525stripComments :: String -> String
2626stripComments [] = []
27−stripComments str | isPrefixOf "/*" str = stripComments $ eatComments $ drop 2 str
28− | otherwise = (head str) : (stripComments $ tail str)
29− where eatComments str' | null str' = []
30− | isPrefixOf "*/" str' = drop 2 str'
31− | otherwise = eatComments $ tail str'
27+stripComments str
28+ | isPrefixOf "/*" str = stripComments $ eatComments $ drop 2 str
29+ | otherwise = (head str) : (stripComments $ tail str)
30+ where
31+ eatComments str' | null str' = []
32+ | isPrefixOf "*/" str' = drop 2 str'
33+ | otherwise = eatComments $ tail str'
src/Text/Hakyll/Context.hs+9−8
@@ -38,11 +38,12 @@ renderDate :: String -- ^ Key in which the rendered date should be placed.
3838 -> String -- ^ Default value when the date cannot be parsed.
3939 -> ContextManipulation
4040renderDate key format defaultValue context = M.insert key value context
41− where value = fromMaybe defaultValue pretty
42− pretty = do filePath <- M.lookup "path" context
43− let dateString = substituteRegex "^([0-9]*-[0-9]*-[0-9]*).*" "\\1"
44− (takeFileName filePath)
45− time <- parseTime defaultTimeLocale
46− "%Y-%m-%d"
47− dateString :: Maybe UTCTime
48− return $ formatTime defaultTimeLocale format time
41+ where
42+ value = fromMaybe defaultValue pretty
43+ pretty = do filePath <- M.lookup "path" context
44+ let dateString = substituteRegex "^([0-9]*-[0-9]*-[0-9]*).*" "\\1"
45+ (takeFileName filePath)
46+ time <- parseTime defaultTimeLocale
47+ "%Y-%m-%d"
48+ dateString :: Maybe UTCTime
49+ return $ formatTime defaultTimeLocale format time
src/Text/Hakyll/File.hs+14−9
@@ -25,8 +25,9 @@ removeLeadingSeparator [] = []
2525removeLeadingSeparator path
2626 | (head path') `elem` pathSeparators = (tail path')
2727 | otherwise = path'
28− where path' = if "$root" `isPrefixOf` path then drop 5 path
29− else path
28+ where
29+ path' = if "$root" `isPrefixOf` path then drop 5 path
30+ else path
3031
3132-- | Convert a relative filepath to a filepath in the destination (_site).
3233toDestination :: FilePath -> FilePath
@@ -46,21 +47,24 @@ toURL path = if takeExtension path `elem` [".markdown", ".md", ".tex"]
4647toRoot :: FilePath -> FilePath
4748toRoot = emptyException . joinPath . map parent . splitPath
4849 . takeDirectory . removeLeadingSeparator
49− where parent = const ".."
50− emptyException [] = "."
51− emptyException x = x
50+ where
51+ parent = const ".."
52+ emptyException [] = "."
53+ emptyException x = x
5254
5355-- | Swaps spaces for '-'.
5456removeSpaces :: FilePath -> FilePath
5557removeSpaces = map swap
56− where swap ' ' = '-'
57− swap x = x
58+ where
59+ swap ' ' = '-'
60+ swap x = x
5861
5962-- | Given a path to a file, try to make the path writable by making
6063-- all directories on the path.
6164makeDirectories :: FilePath -> IO ()
6265makeDirectories path = createDirectoryIfMissing True dir
63− where dir = takeDirectory path
66+ where
67+ dir = takeDirectory path
6468
6569-- | Get all contents of a directory. Note that files starting with a dot (.)
6670-- will be ignored.
@@ -75,7 +79,8 @@ getRecursiveContents topdir = do
7579 then getRecursiveContents path
7680 else return [path]
7781 return (concat paths)
78− where isProper = not . (== '.') . head
82+ where
83+ isProper = not . (== '.') . head
7984
8085-- | A filter that takes all file names with a given extension. Prefix the
8186-- extension with a dot:
src/Text/Hakyll/Page.hs+29−22
@@ -42,7 +42,8 @@ getPageURL (Page page) = fromMaybe (error "No page url") $ M.lookup "url" page
4242
4343-- | Get the original page path.
4444getPagePath :: Page -> String
45−getPagePath (Page page) = fromMaybe (error "No page path") $ M.lookup "path" page
45+getPagePath (Page page) =
46+ fromMaybe (error "No page path") $ M.lookup "path" page
4647
4748-- | Get the body for a certain page. When not defined, the body will be
4849-- empty.
@@ -56,21 +57,24 @@ writerOptions = defaultWriterOptions
5657-- | Get a render function for a given extension.
5758renderFunction :: String -> (String -> String)
5859renderFunction ".html" = id
59−renderFunction ext = writeHtmlString writerOptions .
60− readFunction ext defaultParserState
61− where readFunction ".markdown" = readMarkdown
62− readFunction ".md" = readMarkdown
63− readFunction ".tex" = readLaTeX
64− readFunction _ = readMarkdown
60+renderFunction ext = writeHtmlString writerOptions
61+ . readFunction ext defaultParserState
62+ where
63+ readFunction ".markdown" = readMarkdown
64+ readFunction ".md" = readMarkdown
65+ readFunction ".tex" = readLaTeX
66+ readFunction _ = readMarkdown
6567
6668-- | Read metadata header from a file handle.
6769readMetaData :: Handle -> IO [(String, String)]
6870readMetaData handle = do
6971 line <- hGetLine handle
70− if isDelimiter line then return []
71− else do others <- readMetaData handle
72− return $ (trimPair . break (== ':')) line : others
73− where trimPair (key, value) = (trim key, trim $ tail value)
72+ if isDelimiter line
73+ then return []
74+ else do others <- readMetaData handle
75+ return $ (trimPair . break (== ':')) line : others
76+ where
77+ trimPair (key, value) = (trim key, trim $ tail value)
7478
7579-- | Check if the given string is a metadata delimiter.
7680isDelimiter :: String -> Bool
@@ -87,10 +91,11 @@ cachePage page@(Page mapping) = do
8791 hPutStrLn handle "---"
8892 hPutStr handle $ getBody page
8993 hClose handle
90− where writePair h (k, v) = hPutStr h k >>
91− hPutStr h ": " >>
92− hPutStr h v >>
93− hPutStrLn h ""
94+ where
95+ writePair h (k, v) = do hPutStr h k
96+ hPutStr h ": "
97+ hPutStr h v
98+ hPutStrLn h ""
9499
95100-- | Read a page from a file. Metadata is supported, and if the filename
96101-- has a .markdown extension, it will be rendered using pandoc. Note that
@@ -104,11 +109,12 @@ readPage pagePath = do
104109 -- Read file.
105110 handle <- openFile path ReadMode
106111 line <- hGetLine handle
107− (context, body) <- if isDelimiter line
108− then do md <- readMetaData handle
109− c <- hGetContents handle
110− return (md, c)
111− else hGetContents handle >>= \b -> return ([], line ++ b)
112+ (context, body) <-
113+ if isDelimiter line
114+ then do md <- readMetaData handle
115+ c <- hGetContents handle
116+ return (md, c)
117+ else hGetContents handle >>= \b -> return ([], line ++ b)
112118
113119 -- Render file
114120 let rendered = (renderFunction $ takeExtension path) body
@@ -123,8 +129,9 @@ readPage pagePath = do
123129 -- Cache if needed
124130 if getFromCache then return () else cachePage page
125131 return page
126− where url = toURL pagePath
127− cacheFile = toCache url
132+ where
133+ url = toURL pagePath
134+ cacheFile = toCache url
128135
129136-- Make pages renderable.
130137instance Renderable Page where
src/Text/Hakyll/Render.hs+27−22
@@ -43,11 +43,12 @@ substitute escaper string context
4343 | "$$" `isPrefixOf` string = escaper ++ substitute' (tail tail')
4444 | "$" `isPrefixOf` string = substituteKey
4545 | otherwise = (head string) : (substitute' tail')
46− where tail' = tail string
47− (key, rest) = break (not . isAlpha) tail'
48− replacement = fromMaybe ('$' : key) $ M.lookup key context
49− substituteKey = replacement ++ substitute' rest
50− substitute' str = substitute escaper str context
46+ where
47+ tail' = tail string
48+ (key, rest) = break (not . isAlpha) tail'
49+ replacement = fromMaybe ('$' : key) $ M.lookup key context
50+ substituteKey = replacement ++ substitute' rest
51+ substitute' str = substitute escaper str context
5152
5253-- | "substitute" for use during a chain.
5354regularSubstitute :: String -> Context -> String
@@ -97,11 +98,12 @@ renderAndConcatWith :: Renderable a
9798 -> IO String
9899renderAndConcatWith manipulation templatePath renderables =
99100 foldM concatRender' [] renderables
100− where concatRender' :: Renderable a => String -> a -> IO String
101− concatRender' chunk renderable = do
102− rendered <- renderWith manipulation templatePath renderable
103− let body = getBody rendered
104− return $ chunk ++ body
101+ where
102+ concatRender' :: Renderable a => String -> a -> IO String
103+ concatRender' chunk renderable = do
104+ rendered <- renderWith manipulation templatePath renderable
105+ let body = getBody rendered
106+ return $ chunk ++ body
105107
106108-- | Chain a render action for a page with a number of templates. This will
107109-- also write the result to the site destination. This is the preferred way
@@ -125,23 +127,26 @@ writePage page = do
125127 let destination = toDestination url
126128 makeDirectories destination
127129 writeFile destination body
128− where url = getURL page
129−          -- Substitute $root here, just before writing.
130−          body = finalSubstitute (getBody page)
131−                             (M.singleton "root" $ toRoot url)
130+ where
131+ url = getURL page
132+    -- Substitute $root here, just before writing.
133+    body = finalSubstitute (getBody page)
134+                           (M.singleton "root" $ toRoot url)
132135
133136-- | Mark a certain file as static, so it will just be copied when the site is
134137-- generated.
135138static :: FilePath -> IO ()
136−static source = depends destination [source]
137− (makeDirectories destination >> copyFile source destination)
138− where destination = toDestination source
139+static source = depends destination [source] action
140+ where
141+ destination = toDestination source
142+ action = do makeDirectories destination
143+ copyFile source destination
139144
140145-- | Render a css file, compressing it.
141146css :: FilePath -> IO ()
142147css source = depends destination [source] css'
143− where destination = toDestination source
144− css' = do h <- openFile source ReadMode
145− contents <- hGetContents h
146− makeDirectories destination
147− writeFile destination (compressCSS contents)
148+ where
149+ destination = toDestination source
150+ css' = do contents <- readFile source
151+ makeDirectories destination
152+ writeFile destination (compressCSS contents)
src/Text/Hakyll/Tags.hs+28−24
@@ -21,10 +21,11 @@ import Control.Arrow (second)
2121-- commas.
2222readTagMap :: [FilePath] -> IO (M.Map String [FilePath])
2323readTagMap paths = foldM addPaths M.empty paths
24− where addPaths current path = do
25− page <- readPage path
26− let tags = map trim $ splitRegex "," $ getValue ("tags") page
27− return $ foldr (\t -> M.insertWith (++) t [path]) current tags
24+ where
25+ addPaths current path = do
26+ page <- readPage path
27+ let tags = map trim $ splitRegex "," $ getValue ("tags") page
28+ return $ foldr (\t -> M.insertWith (++) t [path]) current tags
2829
2930-- | Render a tag cloud.
3031renderTagCloud :: M.Map String [FilePath] -- ^ A tag map as produced by 'readTagMap'.
@@ -34,28 +35,31 @@ renderTagCloud :: M.Map String [FilePath] -- ^ A tag map as produced by 'readTag
3435 -> String -- ^ Result of the render.
3536renderTagCloud tagMap urlFunction minSize maxSize =
3637 intercalate " " $ map renderTag tagCount
37− where renderTag :: (String, Float) -> String
38− renderTag (tag, count) = "<a style=\"font-size: "
39− ++ sizeTag count ++ "\" href=\""
40− ++ urlFunction tag ++ "\">"
41− ++ tag ++ "</a>"
42−
43− sizeTag :: Float -> String
44− sizeTag count = show size' ++ "%"
45− where size' :: Int
46− size' = floor (minSize + (relative count) * (maxSize - minSize))
47−
48− minCount = minimum $ map snd $ tagCount
49− maxCount = maximum $ map snd $ tagCount
50− relative count = (count - minCount) / (maxCount - minCount)
51−
52− tagCount :: [(String, Float)]
53− tagCount = map (second $ fromIntegral . length) $ M.toList tagMap
38+ where
39+ renderTag :: (String, Float) -> String
40+ renderTag (tag, count) = "<a style=\"font-size: "
41+ ++ sizeTag count ++ "\" href=\""
42+ ++ urlFunction tag ++ "\">"
43+ ++ tag ++ "</a>"
44+
45+ sizeTag :: Float -> String
46+ sizeTag count = show size' ++ "%"
47+ where
48+ size' :: Int
49+ size' = floor (minSize + (relative count) * (maxSize - minSize))
50+
51+ minCount = minimum $ map snd $ tagCount
52+ maxCount = maximum $ map snd $ tagCount
53+ relative count = (count - minCount) / (maxCount - minCount)
54+
55+ tagCount :: [(String, Float)]
56+ tagCount = map (second $ fromIntegral . length) $ M.toList tagMap
5457
5558-- Render all tags to links.
5659renderTagLinks :: (String -> String) -- ^ Function that produces an url for a tag.
5760 -> ContextManipulation
5861renderTagLinks urlFunction = renderValue "tags" "tags" renderTagLinks'
59− where renderTagLinks' = intercalate ", "
60− . map (\t -> link t $ urlFunction t)
61− . map trim . splitRegex ","
62+ where
63+ renderTagLinks' = intercalate ", "
64+ . map (\t -> link t $ urlFunction t)
65+ . map trim . splitRegex ","
src/Text/Hakyll/Util.hs+5−3
@@ -9,7 +9,8 @@ import Data.Char (isSpace)
99-- | Trim a string (drop spaces and tabs at both sides).
1010trim :: String -> String
1111trim = reverse . trim' . reverse . trim'
12− where trim' = dropWhile isSpace
12+ where
13+ trim' = dropWhile isSpace
1314
1415-- | Strip html tags.
1516stripHTML :: String -> String
@@ -18,8 +19,9 @@ stripHTML str = let (beforeTag, rest) = break (== '<') str
1819 (_, afterTag) = break (== '>') rest
1920 in beforeTag ++ (stripHTML $ tail' afterTag)
2021 -- We need a failsafe tail function.
21− where tail' [] = []
22− tail' xs = tail xs
22+ where
23+ tail' [] = []
24+ tail' xs = tail xs
2325
2426-- | Make a HTML link.
2527--