@@ -1,47 +1,29 @@
11-- | A module for dealing with @Page@s. This module is mostly internally used.
22module Text.Hakyll.Internal.Page
3− ( readPage
3+ ( PageSection (..)
4+ , readPage
5+ , readPageAction
46 ) where
57
6−import qualified Data.Map as M
78import Data.List (isPrefixOf)
89import Data.Char (isSpace)
910import Control.Monad.Reader (liftIO)
1011import System.FilePath
1112import Control.Monad.State (State, evalState, get, put)
1213
13−import Text.Pandoc
14−
15−import Text.Hakyll.Context (Context (..))
1614import Text.Hakyll.File
1715import Text.Hakyll.HakyllMonad
16+import Text.Hakyll.HakyllAction
1817import Text.Hakyll.Regex (substituteRegex, matchesRegex)
1918import Text.Hakyll.Util (trim)
20−import Text.Hakyll.Internal.Cache
21−import Text.Hakyll.Internal.FileType
22−
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)
33− where
34− readFunction ReStructuredText = readRST
35− readFunction LaTeX = readLaTeX
36− readFunction Markdown = readMarkdown
37− readFunction LiterateHaskellMarkdown = readMarkdown
38− readFunction t = error $ "Cannot render " ++ show t
3919
40− readOptions options LiterateHaskellMarkdown = options
41− { stateLiterateHaskell = True }
42− readOptions options _ = options
20+-- | Page info handle: (key, value, needs rendering)
21+--
22+data PageSection = PageSection {unPageSection :: [(String, String, Bool)]}
23+ deriving (Show)
4324
4425-- | Split a page into sections.
26+--
4527splitAtDelimiters :: [String] -> State (Maybe String) [[String]]
4628splitAtDelimiters [] = return []
4729splitAtDelimiters ls@(x:xs) = do
@@ -63,59 +45,54 @@ isPossibleDelimiter :: String -> Bool
6345isPossibleDelimiter = isPrefixOf "---"
6446
6547-- | Read one section of a page.
66−readSection :: (String -> String) -- ^ Render function.
67− -> Bool -- ^ If this section is the first section in the page.
48+--
49+readSection :: Bool -- ^ If this section is the first section in the page.
6850 -> [String] -- ^ Lines in the section.
69− -> [(String, String)] -- ^ Key-values extracted.
70−readSection _ _ [] = []
71−readSection renderFunction isFirst ls
51+ -> PageSection -- ^ Key-values extracted.
52+readSection _ [] = PageSection []
53+readSection isFirst ls
7254 | not isDelimiter' = body ls
73− | isNamedDelimiter = readSectionMetaData ls
74− | isFirst = readSimpleMetaData (drop 1 ls)
55+ | isNamedDelimiter = PageSection $ readSectionMetaData ls
56+ | isFirst = PageSection $ readSimpleMetaData (drop 1 ls)
7557 | otherwise = body (drop 1 ls)
7658 where
7759 isDelimiter' = isPossibleDelimiter (head ls)
7860 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)]
8062
8163 readSimpleMetaData = map readPair . filter (not . all isSpace)
8264 readPair = trimPair . break (== ':')
83− trimPair (key, value) = (trim key, trim $ drop 1 value)
65+ trimPair (key, value) = (trim key, trim (drop 1 value), False)
8466
8567 readSectionMetaData [] = []
8668 readSectionMetaData (header:value) =
8769 let key = substituteRegex "[^a-zA-Z0-9]" "" header
88− in [(key, renderFunction $ unlines value)]
70+ in [(key, unlines value, True)]
8971
90−-- | Read a page from a file. Metadata is supported, and if the filename
91−-- has a @.markdown@ extension, it will be rendered using pandoc.
92−readPageFromFile :: FilePath -> Hakyll Context
93−readPageFromFile path = do
94− renderFunction <- getRenderFunction $ getFileType path
95− let sectionFunctions = map (readSection renderFunction)
96− (True : repeat False)
72+-- | Read a page from a file. Metadata is supported.
73+--
74+readPage :: FilePath -> Hakyll [PageSection]
75+readPage path = do
76+ let sectionFunctions = map readSection $ True : repeat False
9777
9878 -- Read file.
9979 contents <- liftIO $ readFile path
10080 url <- toUrl path
10181 let sections = evalState (splitAtDelimiters $ lines contents) Nothing
102− sectionsData = concat $ zipWith ($) sectionFunctions sections
103− context = M.fromList $
104− ("url", url) : ("path", path) : category ++ sectionsData
82+ sectionsData = zipWith ($) sectionFunctions sections
10583
106− return $ Context context
84+ return $ PageSection [ ("url", url, False)
85+ , ("path", path, False)
86+ ] : category : sectionsData
10787 where
10888 category = let dirs = splitDirectories $ takeDirectory path
109− in [("category", last dirs) | not (null dirs)]
89+ in PageSection [("category", last dirs, False) | not (null dirs)]
11090
111−-- | Read a page. Might fetch it from the cache if available. Otherwise, it will
112−-- read it from the file given and store it in the cache.
113−readPage :: FilePath -> Hakyll Context
114−readPage path = do
115− isCacheMoreRecent' <- isCacheMoreRecent fileName [path]
116− if isCacheMoreRecent' then getFromCache fileName
117− else do page <- readPageFromFile path
118− storeInCache page fileName
119− return page
120− where
121− fileName = "pages" </> path
91+-- | Read a page from a file. Metadata is supported.
92+--
93+readPageAction :: FilePath -> HakyllAction () [PageSection]
94+readPageAction path = HakyllAction
95+ { actionDependencies = [path]
96+ , actionUrl = Left $ toUrl path
97+ , actionFunction = const $ readPage path
98+ }