@@ -1,47 +1,29 @@
1-- | A module for dealing with @Page@s. This module is mostly internally used.
1-- | A module for dealing with @Page@s. This module is mostly internally used.
2module Text.Hakyll.Internal.Page
2module Text.Hakyll.Internal.Page
3− ( readPage
4+ , readPage
6−import qualified Data.Map as M
7import Data.List (isPrefixOf)
8import Data.List (isPrefixOf)
8import Data.Char (isSpace)
9import Data.Char (isSpace)
9import Control.Monad.Reader (liftIO)
10import Control.Monad.Reader (liftIO)
10import System.FilePath
11import System.FilePath
11import Control.Monad.State (State, evalState, get, put)
12import Control.Monad.State (State, evalState, get, put)
15−import Text.Hakyll.Context (Context (..))
16import Text.Hakyll.File
14import Text.Hakyll.File
17import Text.Hakyll.HakyllMonad
15import Text.Hakyll.HakyllMonad
16+import Text.Hakyll.HakyllAction
18import Text.Hakyll.Regex (substituteRegex, matchesRegex)
17import Text.Hakyll.Regex (substituteRegex, matchesRegex)
19import Text.Hakyll.Util (trim)
18import Text.Hakyll.Util (trim)
20−import Text.Hakyll.Internal.Cache
21−import Text.Hakyll.Internal.FileType
23−-- | Get a render function for a given extension.
24−getRenderFunction :: FileType -> Hakyll (String -> String)
25−getRenderFunction Html = return id
26−getRenderFunction Text = return id
27−getRenderFunction UnknownFileType = return id
28−getRenderFunction fileType = do
29− parserState <- askHakyll pandocParserState
30− writerOptions <- askHakyll pandocWriterOptions
31− return $ writeHtmlString writerOptions
32− . readFunction fileType (readOptions parserState fileType)
34− readFunction ReStructuredText = readRST
35− readFunction LaTeX = readLaTeX
36− readFunction Markdown = readMarkdown
37− readFunction LiterateHaskellMarkdown = readMarkdown
38− readFunction t = error $ "Cannot render " ++ show t
40− readOptions options LiterateHaskellMarkdown = options
20+-- | Page info handle: (key, value, needs rendering)
41− { stateLiterateHaskell = True }
21+--
42− readOptions options _ = options
22+data PageSection = PageSection {unPageSection :: [(String, String, Bool)]}
44-- | Split a page into sections.
25-- | Split a page into sections.
45splitAtDelimiters :: [String] -> State (Maybe String) [[String]]
27splitAtDelimiters :: [String] -> State (Maybe String) [[String]]
46splitAtDelimiters [] = return []
28splitAtDelimiters [] = return []
47splitAtDelimiters ls@(x:xs) = do
29splitAtDelimiters ls@(x:xs) = do
@@ -63,59 +45,54 @@ isPossibleDelimiter :: String -> Bool
63isPossibleDelimiter = isPrefixOf "---"
45isPossibleDelimiter = isPrefixOf "---"
65-- | Read one section of a page.
47-- | Read one section of a page.
66−readSection :: (String -> String) -- ^ Render function.
48+--
67− -> Bool -- ^ If this section is the first section in the page.
49+readSection :: Bool -- ^ If this section is the first section in the page.
68 -> [String] -- ^ Lines in the section.
50 -> [String] -- ^ Lines in the section.
69− -> [(String, String)] -- ^ Key-values extracted.
51+ -> PageSection -- ^ Key-values extracted.
70−readSection _ _ [] = []
52+readSection _ [] = PageSection []
71−readSection renderFunction isFirst ls
53+readSection isFirst ls
72 | not isDelimiter' = body ls
54 | not isDelimiter' = body ls
73− | isNamedDelimiter = readSectionMetaData ls
55+ | isNamedDelimiter = PageSection $ readSectionMetaData ls
74− | isFirst = readSimpleMetaData (drop 1 ls)
56+ | isFirst = PageSection $ readSimpleMetaData (drop 1 ls)
75 | otherwise = body (drop 1 ls)
57 | otherwise = body (drop 1 ls)
77 isDelimiter' = isPossibleDelimiter (head ls)
59 isDelimiter' = isPossibleDelimiter (head ls)
78 isNamedDelimiter = head ls `matchesRegex` "^----* *[a-zA-Z0-9][a-zA-Z0-9]*"
60 isNamedDelimiter = head ls `matchesRegex` "^----* *[a-zA-Z0-9][a-zA-Z0-9]*"
79− body ls' = [("body", renderFunction $ unlines ls')]
61+ body ls' = PageSection [("body", unlines ls', True)]
81 readSimpleMetaData = map readPair . filter (not . all isSpace)
63 readSimpleMetaData = map readPair . filter (not . all isSpace)
82 readPair = trimPair . break (== ':')
64 readPair = trimPair . break (== ':')
83− trimPair (key, value) = (trim key, trim $ drop 1 value)
65+ trimPair (key, value) = (trim key, trim (drop 1 value), False)
85 readSectionMetaData [] = []
67 readSectionMetaData [] = []
86 readSectionMetaData (header:value) =
68 readSectionMetaData (header:value) =
87 let key = substituteRegex "[^a-zA-Z0-9]" "" header
69 let key = substituteRegex "[^a-zA-Z0-9]" "" header
88− in [(key, renderFunction $ unlines value)]
70+ in [(key, unlines value, True)]
90−-- | Read a page from a file. Metadata is supported, and if the filename
72+-- | Read a page from a file. Metadata is supported.
91−-- has a @.markdown@ extension, it will be rendered using pandoc.
73+--
92−readPageFromFile :: FilePath -> Hakyll Context
74+readPage :: FilePath -> Hakyll [PageSection]
93−readPageFromFile path = do
75+readPage path = do
94− renderFunction <- getRenderFunction $ getFileType path
95− let sectionFunctions = map (readSection renderFunction)
76+ let sectionFunctions = map readSection $ True : repeat False
96− (True : repeat False)
98 -- Read file.
78 -- Read file.
99 contents <- liftIO $ readFile path
79 contents <- liftIO $ readFile path
100 url <- toUrl path
80 url <- toUrl path
101 let sections = evalState (splitAtDelimiters $ lines contents) Nothing
81 let sections = evalState (splitAtDelimiters $ lines contents) Nothing
102− sectionsData = concat $ zipWith ($) sectionFunctions sections
82+ sectionsData = zipWith ($) sectionFunctions sections
103− context = M.fromList $
104− ("url", url) : ("path", path) : category ++ sectionsData
106− return $ Context context
84+ return $ PageSection [ ("url", url, False)
85+ , ("path", path, False)
86+ ] : category : sectionsData
108 category = let dirs = splitDirectories $ takeDirectory path
88 category = let dirs = splitDirectories $ takeDirectory path
109− in [("category", last dirs) | not (null dirs)]
89+ in PageSection [("category", last dirs, False) | not (null dirs)]
111−-- | Read a page. Might fetch it from the cache if available. Otherwise, it will
91+-- | Read a page from a file. Metadata is supported.
112−-- read it from the file given and store it in the cache.
92+--
113−readPage :: FilePath -> Hakyll Context
93+readPageAction :: FilePath -> HakyllAction () [PageSection]
114−readPage path = do
94+readPageAction path = HakyllAction
115− isCacheMoreRecent' <- isCacheMoreRecent fileName [path]
95+ { actionDependencies = [path]
116− if isCacheMoreRecent' then getFromCache fileName
96+ , actionUrl = Left $ toUrl path
117− else do page <- readPageFromFile path
97+ , actionFunction = const $ readPage path
118− storeInCache page fileName
98+ }
121− fileName = "pages" </> path