165 lines
5.8 KiB
Haskell
165 lines
5.8 KiB
Haskell
module SiteGenerator (generateSite) where
|
|
|
|
import Byg.Types (Token(..), Date(..), formatDate, formatDateShort)
|
|
import Byg.DependencyGenerator
|
|
import Byg.Functions
|
|
|
|
import Data.List (sort, elemIndex)
|
|
import Data.Function ((&))
|
|
import Data.Text (Text)
|
|
import qualified Data.Text as T
|
|
import Control.Monad (forM_, (<=<))
|
|
|
|
elemIndex' :: (Show a, Eq a) => a -> [a] -> Int
|
|
elemIndex' x xs = case elemIndex x xs of
|
|
Just i -> i
|
|
Nothing -> error ("unexpected unknown directory index for " ++ show x ++ " in " ++ show xs)
|
|
|
|
head' :: [a] -> a
|
|
head' [] = error "error"
|
|
head' (x : _) = x
|
|
|
|
handleRecipeDir :: Token FilePath -> Token FilePath
|
|
-> Token Template -> Token FilePath
|
|
-> Token [FilePath] -> Token FilePath
|
|
-> DepGenM (Token ((Text, Date), FilePath))
|
|
handleRecipeDir recipesDir outputDir htmlTemplate indexName recipeSubDirs name = do
|
|
dir <- joinPaths recipesDir name
|
|
recipeDirOut <- joinPaths outputDir dir
|
|
makeDir recipeDirOut
|
|
imageFilenames <-
|
|
listDirectory dir
|
|
& filterDepGenM (hasExtension (inject ["jpg"]))
|
|
& onToken sort
|
|
htmlBodyImages <- forDepGenM imageFilenames $ \filename -> do
|
|
path <- joinPaths dir filename
|
|
path `copyTo` outputDir
|
|
(base, ext) <- untupleDepGenM $ fileComponents filename
|
|
thumbnailName <- onToken concat [ pure base, inject "-thumbnail.", pure ext ]
|
|
imageResized <- convertImage (openImage path) (inject (ResizeToWidth 800))
|
|
saveImage imageResized (joinPaths recipeDirOut thumbnailName)
|
|
onToken T.concat [ inject "<p class=\"image\"><a href=\""
|
|
, onToken T.pack filename
|
|
, inject "\"><img src=\""
|
|
, onToken T.pack thumbnailName
|
|
, inject "\"></a></p>\n"
|
|
]
|
|
ingredienserHeadline <- inject "## Ingredienser"
|
|
mdTemplate <- makeTemplate
|
|
(readTextFile (joinPaths dir (inject "ret.md")))
|
|
ingredienserHeadline
|
|
pandoc <-
|
|
[ inject "<p class=\"imagetext\">Opskrift fortsætter efter billedet.</p>\n"
|
|
, onToken T.concat htmlBodyImages
|
|
, inject "\n"
|
|
, pure ingredienserHeadline
|
|
]
|
|
& onToken T.concat
|
|
& applyTemplate mdTemplate
|
|
& readMarkdown
|
|
title <- extractTitle pandoc
|
|
date <- extractDate name
|
|
pandoc' <- injectAfterTitle (
|
|
(onToken T.concat [ inject "<p class=\"date\">Lagt op "
|
|
, onToken formatDate date
|
|
, inject "</p>"
|
|
]))
|
|
pandoc
|
|
dirIndex <- onTupleToken elemIndex' name recipeSubDirs
|
|
prev <- onTupleToken (
|
|
\ds i -> if i < length ds - 1
|
|
then T.concat [ "<a class=\"prev\" href=\"/retter/"
|
|
, T.pack (ds !! (i + 1))
|
|
, "\">Forrige</a>"
|
|
]
|
|
else "")
|
|
recipeSubDirs dirIndex
|
|
next <- onTupleToken (
|
|
\ds i -> if i > 0
|
|
then T.concat [ "<a class=\"next\" href=\"/retter/"
|
|
, T.pack (ds !! (i - 1))
|
|
, "\">Næste</a>"
|
|
]
|
|
else "")
|
|
recipeSubDirs dirIndex
|
|
prevnext <- onToken T.concat [ inject "<p class=\"prevnext\">", pure prev, pure next, inject "</p>" ]
|
|
html <-
|
|
pandoc'
|
|
& writeHtml
|
|
& onTupleToken T.append prevnext
|
|
& onTupleToken (flip T.append) prevnext
|
|
& applyTemplate htmlTemplate
|
|
saveTextFile html (joinPaths recipeDirOut indexName)
|
|
pure $ TupleToken (TupleToken title date) dir
|
|
|
|
handleFontDir :: Token FilePath -> Token FilePath -> DepGenM ()
|
|
handleFontDir outputDir dir = do
|
|
makeDir $ joinPaths outputDir dir
|
|
paths <-
|
|
listDirectory dir
|
|
& mapDepGenM (joinPaths dir)
|
|
& filterDepGenM (hasExtension (inject ["woff2", "css"]))
|
|
mapDepGenM_ (`copyTo` outputDir) paths
|
|
|
|
generateSite :: DepGenM ()
|
|
generateSite = do
|
|
outputDir <- inject "site"
|
|
makeDir outputDir
|
|
htmlTemplate <- makeTemplate (readTextFile (inject "template.html")) (inject "CONTENT")
|
|
indexName <- inject "index.html"
|
|
|
|
-- Handle recipes
|
|
recipesDir <- inject "retter"
|
|
outputRecipesDir <- joinPaths outputDir recipesDir
|
|
makeDir $ outputRecipesDir
|
|
recipeSubDirs <-
|
|
listDirectory recipesDir
|
|
& onToken (reverse . sort)
|
|
& filterDepGenM (isDirectory <=< joinPaths recipesDir)
|
|
infos <- mapDepGenM (handleRecipeDir recipesDir outputDir htmlTemplate indexName recipeSubDirs) recipeSubDirs
|
|
allRecipesHtml <-
|
|
infos
|
|
& onToken (T.append "# Alle retter\n\n"
|
|
. T.intercalate "\n"
|
|
. map (\((t, d), u) -> T.concat ["- ", "[", t, " *(", formatDateShort d, ")*](/", T.pack u, ")"]))
|
|
& markdownToHtml
|
|
& applyTemplate htmlTemplate
|
|
saveTextFile allRecipesHtml (joinPaths outputRecipesDir indexName)
|
|
|
|
newest <- onToken (snd . fst . head') infos
|
|
atomText <- generateAtom newest infos
|
|
saveTextFile atomText (joinPaths outputDir (inject "atom.xml"))
|
|
|
|
redirectTemplate <- makeTemplate (readTextFile (inject "redirect.html")) (inject "URL")
|
|
newestSlug <- onToken (T.pack . snd . head') infos
|
|
saveTextFile (applyTemplate redirectTemplate newestSlug) (joinPaths outputDir indexName)
|
|
|
|
-- Handle about page
|
|
outputAboutDir <- joinPaths outputDir (inject "om")
|
|
makeDir outputAboutDir
|
|
aboutHtml <-
|
|
inject "om.md"
|
|
& readTextFile
|
|
& markdownToHtml
|
|
& applyTemplate htmlTemplate
|
|
saveTextFile aboutHtml (joinPaths outputAboutDir indexName)
|
|
|
|
-- Handle style
|
|
inject "style.css" `copyTo` outputDir
|
|
|
|
-- Handle images
|
|
imgDir <- inject "img"
|
|
makeDir $ joinPaths outputDir imgDir
|
|
forM_ ["mad-icon.png", "mad-logo.png", "julekalender.png", "platte.jpg", "køkken.jpg"] $ \name ->
|
|
joinPaths imgDir (inject name) `copyTo` outputDir
|
|
|
|
-- Handle fonts
|
|
fontsDir <- inject "fonts"
|
|
makeDir $ joinPaths outputDir fontsDir
|
|
fontSubDirs <-
|
|
fontsDir
|
|
& listDirectory
|
|
& mapDepGenM (joinPaths fontsDir)
|
|
& filterDepGenM isDirectory
|
|
mapDepGenM_ (handleFontDir outputDir) fontSubDirs
|