render tags, run head-first into template problems

This commit is contained in:
Mirek Kratochvil 2023-05-27 20:19:11 +02:00
parent 919e953d20
commit 35837f5607
5 changed files with 74 additions and 35 deletions

View file

@ -43,6 +43,7 @@ data SiteState =
, _assetDir :: FilePath -- ^ Directory for output , _assetDir :: FilePath -- ^ Directory for output
, _defaultTemplate :: FilePath -- ^ Name of the default template , _defaultTemplate :: FilePath -- ^ Name of the default template
, _redirectTemplate :: FilePath -- ^ Name of the template for redirect pages , _redirectTemplate :: FilePath -- ^ Name of the template for redirect pages
, _tagTemplate :: FilePath -- ^ Name of the template for tag listing pages
} }
deriving (Show) deriving (Show)
@ -61,6 +62,7 @@ emptySiteState =
, _assetDir = "assets" , _assetDir = "assets"
, _defaultTemplate = "default.html" , _defaultTemplate = "default.html"
, _redirectTemplate = "redirect.html" , _redirectTemplate = "redirect.html"
, _tagTemplate = "tag.html"
} }
-- | Monad for running the site generator. -- | Monad for running the site generator.

View file

@ -26,7 +26,7 @@ hasSuffix s = isJust . stripSuffix s
second :: (a -> b) -> (c, a) -> (c, b) second :: (a -> b) -> (c, a) -> (c, b)
second f (a, b) = (a, f b) second f (a, b) = (a, f b)
-- | A pandoc walker for printing the URLs. -- | A pandoc walker for modifying the URLs.
walkURLs :: (FilePath -> Site FilePath) -> Text.Pandoc.Definition.Pandoc -> Site Text.Pandoc.Definition.Pandoc walkURLs :: (FilePath -> Site FilePath) -> Text.Pandoc.Definition.Pandoc -> Site Text.Pandoc.Definition.Pandoc
walkURLs f = Text.Pandoc.Walk.walkM go walkURLs f = Text.Pandoc.Walk.walkM go
where where

75
site.hs
View file

@ -22,7 +22,13 @@ import Hakyll.Core.Util.File (getRecursiveContents, makeDirectories)
import Lens.Micro import Lens.Micro
import Lens.Micro.Aeson import Lens.Micro.Aeson
import Lens.Micro.Mtl import Lens.Micro.Mtl
import System.FilePath ((</>), splitDirectories, splitPath, takeFileName, isAbsolute) import System.FilePath
( (</>)
, isAbsolute
, splitDirectories
, splitPath
, takeFileName
)
import qualified Text.Mustache as Mu import qualified Text.Mustache as Mu
import Text.Pandoc.Class (runIOorExplode) import Text.Pandoc.Class (runIOorExplode)
import Text.Pandoc.Readers.Markdown (readMarkdown) import Text.Pandoc.Readers.Markdown (readMarkdown)
@ -72,7 +78,9 @@ pageTemplate pi = do
pageTemplates :: Site [FilePath] pageTemplates :: Site [FilePath]
pageTemplates = do pageTemplates = do
rt <- use redirectTemplate rt <- use redirectTemplate
nub . (rt :) <$> (gets (^.. pages . traverse) >>= traverse pageTemplate) tt <- use tagTemplate
nub . ([rt, tt] ++) <$>
(gets (^.. pages . traverse) >>= traverse pageTemplate)
compileTemplate :: compileTemplate ::
FilePath FilePath
@ -109,21 +117,28 @@ checkTarget fp = do
-- | Process a single link pointing out from a page. -- | Process a single link pointing out from a page.
processLink :: FilePath -> String -> Site String processLink :: FilePath -> String -> Site String
processLink base l = do processLink base l = do
io $ putStrLn l
if isAbsolute l if isAbsolute l
then then pure l
pure l else (do io . putStrLn $ "rel:" ++ l
else (do pure $ '/' : (base </> l) -- TODO
io $ putStrLn "rel" )
pure $ '/':(base</>l)) -- TODO
-- | Get a mount point of the page into the correct location.
pageFilename :: FilePath -> Site FilePath
pageFilename p = indexFilename $ "page" </> p
checkedSubstitute t v = do
let (es, txt) = Mu.checkedSubstitute t v
io $ traverse_ (putStrLn . ("Error: " ++) . show) es
--null es `unless` error "template substitution problems"
pure txt
-- | Render a page using the current template. -- | Render a page using the current template.
installPage :: FilePath -> PageInfo -> Site () installPage :: FilePath -> PageInfo -> Site ()
installPage mount pi installPage mount pi = do
= do
tname <- pageTemplate pi tname <- pageTemplate pi
templ <- use $ templates . to (M.! fromString tname) templ <- use $ templates . to (M.! fromString tname)
file <- indexFilename mount file <- pageFilename mount
fixedUrlDoc <- walkURLs (processLink mount) $ pi ^. pageDoc fixedUrlDoc <- walkURLs (processLink mount) $ pi ^. pageDoc
checkTarget file checkTarget file
io $ do io $ do
@ -132,7 +147,7 @@ installPage mount pi
body <- runIOorExplode $ writeHtml5String htmlWriteOpts fixedUrlDoc body <- runIOorExplode $ writeHtml5String htmlWriteOpts fixedUrlDoc
let Y.Object meta' = pi ^. pageMeta let Y.Object meta' = pi ^. pageMeta
meta = Y.Object $ KM.insert "body" (Y.String body) meta' meta = Y.Object $ KM.insert "body" (Y.String body) meta'
TIO.writeFile file $ Mu.substitute templ meta checkedSubstitute templ meta >>= TIO.writeFile file
installPageRedirects mount pi installPageRedirects mount pi
{- | Install a simple redirect handler page. -} {- | Install a simple redirect handler page. -}
@ -145,8 +160,8 @@ installRedirect target from = do
io $ do io $ do
putStrLn $ "@ -> " ++ file ++ " -> " ++ target putStrLn $ "@ -> " ++ file ++ " -> " ++ target
makeDirectories file makeDirectories file
TIO.writeFile file . Mu.substitute templ $ txt <- checkedSubstitute templ $ Y.object [("target", Y.String $ T.pack target)]
Y.object [("target", Y.String $ T.pack target)] TIO.writeFile file txt
-- | Install all redirects required by one page. -- | Install all redirects required by one page.
installPageRedirects :: FilePath -> PageInfo -> Site () installPageRedirects :: FilePath -> PageInfo -> Site ()
@ -203,6 +218,7 @@ installAssets =
use assetDir >>= use assetDir >>=
(io . getRecursiveContents (pure . const False) >=> traverse_ installAsset) (io . getRecursiveContents (pure . const False) >=> traverse_ installAsset)
-- | Get all tags from the pages of the site.
sourceTags :: Site () sourceTags :: Site ()
sourceTags = do sourceTags = do
sgat <- sgat <-
@ -217,13 +233,35 @@ invTags :: [(FilePath, [[String]])] -> [([String], [FilePath])]
invTags x = invTags x =
map (fmap nub) $ groupSort [(t, p) | (p, htl) <- x, ht <- htl, t <- inits ht] map (fmap nub) $ groupSort [(t, p) | (p, htl) <- x, ht <- htl, t <- inits ht]
-- | Get the destination for the tag page.
tagFilename :: FilePath -> Site FilePath
tagFilename tag = indexFilename $ "tag" </> tag
-- | Render a site for a given tag string. -- | Render a site for a given tag string.
renderTag :: [String] -> Site () renderTag :: [String] -> [FilePath] -> Site ()
renderTag = undefined renderTag tag pages = do
tname <- use tagTemplate
templ <- use $ templates . to (M.! fromString tname)
let tagpath = foldr (</>) mempty tag
file <- tagFilename tagpath
checkTarget file
io $ do
putStrLn $ "# -> " ++ file
makeDirectories file
let str = fromString
arr = Y.array
meta =
Y.Object $
KM.fromList
[ ("tagpath", str tagpath)
, ("tag", arr $ map str tag)
, ("pages", arr $ map str pages)
]
checkedSubstitute templ meta >>= TIO.writeFile file
-- | Render all tag sites. -- | Render all tag sites.
renderTags :: Site () renderTags :: Site ()
renderTags = undefined renderTags = use (htags . to M.assocs) >>= traverse_ (uncurry renderTag)
-- | Build the whole site. -- | Build the whole site.
main = main =
@ -233,6 +271,9 @@ main =
sourceTags sourceTags
sourceTemplates "templates" sourceTemplates "templates"
use pages >>= traverse (uncurry installPage) . M.assocs use pages >>= traverse (uncurry installPage) . M.assocs
renderTags
-- testing part begin
installFile "external/mypage/img/awesome.png" installFile "external/mypage/img/awesome.png"
-- testing part end
io $ putStrLn "OK" io $ putStrLn "OK"
get >>= io . print get >>= io . print

View file

@ -1,3 +0,0 @@
<section>
$body$
</section>

View file

@ -1,14 +1,13 @@
<section> <!doctype html5>
<h2>Tag</h2> <html>
<ul> {{> head.html}}
$for(htags)$ <body>
<li>$htag$</li> <h2>{{?tag}}Tag: {{tagpath}}{{/tag}}{{^tag}}All pages{{/tag}}</h2>
$endfor$ Path: (root){{#tag}} / #{{.}}{{/tag}}
</ul> <ul>
<h2>Pages</h2> {{#pages}}
<ul> <li>{{#anchor}}{{name}}{{/anchor}}</li>
$for(pages)$ {{/pages}}
<li><a href="$page$">$page$</a></li> </ul>
$endfor$ </body>
</ul> </html>
</section>