Add prev and next navigation

This commit is contained in:
Niels G. W. Serup 2024-10-16 22:09:51 +02:00
parent ae7126bc19
commit 1b222217a1
No known key found for this signature in database
GPG Key ID: 38EEEBCE67324F19
4 changed files with 125 additions and 12 deletions

62
byg/src/Functions/Date.hs Normal file
View File

@ -0,0 +1,62 @@
module Functions.Date
( Date
, extractDate
, formatDate
, formatDateShort
) where
import Types (Token)
import DependencyGenerator (DepGenM, TokenableTo(..), onToken)
import Text.Printf (printf)
import qualified Data.Text as T
import Data.List.NonEmpty (NonEmpty(..))
import qualified Data.List.NonEmpty as NE
import Data.Text (Text)
data Date = Date Int Int Int
deriving (Eq, Ord, Show)
split :: Eq a => a -> [a] -> NonEmpty [a]
split sep = \case
[] ->
NE.singleton []
(c : cs) ->
(if sep == c
then NE.cons []
else \(h :| t) -> (c : h) :| t)
$ split sep cs
extractDate :: TokenableTo String a => a -> DepGenM (Token Date)
extractDate = onToken $ \dirName -> case split '-' dirName of
year :| (month : day : _) ->
Date (read year) (read month) (read day)
_ ->
error "unexpected"
formatDate :: Date -> Text
formatDate (Date year month day) =
T.concat [ "den "
, T.pack (show day)
, ". "
, months !! (month - 1)
, " "
, T.pack (show year)
]
where months = [ "januar"
, "februar"
, "marts"
, "april"
, "maj"
, "juni"
, "juli"
, "august"
, "september"
, "oktober"
, "november"
, "december"
]
formatDateShort :: Date -> Text
formatDateShort (Date year month day) =
T.concat [ T.pack (show year), "-", T.pack (printf "%02d" month), "-", T.pack (printf "%02d" day) ]

View File

@ -38,5 +38,5 @@ extractTitle = onToken $ \(PD.Pandoc _ blocks) -> case blocks of
injectAfterTitle :: (TokenableTo Text a, TokenableTo Pandoc b) => a -> b -> DepGenM (Token Pandoc) injectAfterTitle :: (TokenableTo Text a, TokenableTo Pandoc b) => a -> b -> DepGenM (Token Pandoc)
injectAfterTitle = onTupleToken $ \extra (PD.Pandoc meta blocks) -> case blocks of injectAfterTitle = onTupleToken $ \extra (PD.Pandoc meta blocks) -> case blocks of
(header@(PD.Header _ _ _) : rest) -> PD.Pandoc meta (header : PD.Para [PD.Emph [PD.Str extra]] : rest) (header@(PD.Header _ _ _) : rest) -> PD.Pandoc meta (header : PD.RawBlock "html" extra : rest)
_ -> error "unexpected" _ -> error "unexpected"

View File

@ -4,17 +4,22 @@ import Types (Token(..))
import DependencyGenerator import DependencyGenerator
import Functions import Functions
import Data.Ord (comparing) import Data.List (sort, elemIndex)
import Data.List (sortBy)
import Data.Function ((&)) import Data.Function ((&))
import Data.Text (Text) import Data.Text (Text)
import qualified Data.Text as T import qualified Data.Text as T
import Control.Monad (forM_, (<=<)) 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)
handleRecipeDir :: Token FilePath -> Token FilePath handleRecipeDir :: Token FilePath -> Token FilePath
-> Token Template -> Token FilePath -> Token Template -> Token FilePath
-> Token FilePath -> DepGenM (Token ((Text, Date), FilePath)) -> Token [FilePath] -> Token FilePath
handleRecipeDir recipesDir outputDir htmlTemplate indexName name = do -> DepGenM (Token ((Text, Date), FilePath))
handleRecipeDir recipesDir outputDir htmlTemplate indexName recipeSubDirs name = do
dir <- joinPaths recipesDir name dir <- joinPaths recipesDir name
recipeDirOut <- joinPaths outputDir dir recipeDirOut <- joinPaths outputDir dir
makeDir recipeDirOut makeDir recipeDirOut
@ -49,13 +54,35 @@ handleRecipeDir recipesDir outputDir htmlTemplate indexName name = do
& readMarkdown & readMarkdown
title <- extractTitle pandoc title <- extractTitle pandoc
date <- extractDate name date <- extractDate name
pandoc' <- injectAfterTitle (onTupleToken T.append pandoc' <- injectAfterTitle (
(inject "Offentliggjort ") (onToken T.concat [ inject "<p class=\"date\">Offentliggjort "
(onToken formatDate date)) , onToken formatDate date
, inject "</p>"
]))
pandoc 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 <- html <-
pandoc' pandoc'
& writeHtml & writeHtml
& onTupleToken T.append prevnext
& onTupleToken (flip T.append) prevnext
& applyTemplate htmlTemplate & applyTemplate htmlTemplate
saveTextFile html (joinPaths recipeDirOut indexName) saveTextFile html (joinPaths recipeDirOut indexName)
pure $ TupleToken (TupleToken title date) dir pure $ TupleToken (TupleToken title date) dir
@ -82,14 +109,14 @@ generateSite = do
makeDir $ outputRecipesDir makeDir $ outputRecipesDir
recipeSubDirs <- recipeSubDirs <-
listDirectory recipesDir listDirectory recipesDir
& onToken (reverse . sort)
& filterDepGenM (isDirectory <=< joinPaths recipesDir) & filterDepGenM (isDirectory <=< joinPaths recipesDir)
infos <- mapDepGenM (handleRecipeDir recipesDir outputDir htmlTemplate indexName) recipeSubDirs infos <- mapDepGenM (handleRecipeDir recipesDir outputDir htmlTemplate indexName recipeSubDirs) recipeSubDirs
allRecipesHtml <- allRecipesHtml <-
infos infos
& onToken (T.append "# Alle retter\n\n" & onToken (T.append "# Alle retter\n\n"
. T.intercalate "\n" . T.intercalate "\n"
. map (\((t, d), u) -> T.concat ["- ", "[", t, " *(", formatDateShort d, ")*](/", T.pack u, ")"]) . map (\((t, d), u) -> T.concat ["- ", "[", t, " *(", formatDateShort d, ")*](/", T.pack u, ")"]))
. sortBy (flip (comparing (\((_, d), _) -> d))))
& markdownToHtml & markdownToHtml
& applyTemplate htmlTemplate & applyTemplate htmlTemplate
saveTextFile allRecipesHtml (joinPaths outputRecipesDir indexName) saveTextFile allRecipesHtml (joinPaths outputRecipesDir indexName)

View File

@ -66,7 +66,7 @@ section {
} }
article { article {
padding: 0 10px; padding: 0 10px 50px 10px;
} }
h1, h2, h3 { h1, h2, h3 {
@ -76,6 +76,7 @@ h1, h2, h3 {
h1 { h1 {
font-size: 2em; font-size: 2em;
clear: both;
} }
h2 { h2 {
@ -98,6 +99,29 @@ p.imagetext {
margin-bottom: 0.1em; margin-bottom: 0.1em;
} }
p.prevnext {
margin: 0;
a {
display: inline-block;
}
a.prev {
float: left;
}
a.prev:before {
content: '↫ ';
}
a.next {
float: right;
}
a.next:after {
content: ' ↬';
}
}
p.date {
margin: 0;
}
p.image { p.image {
margin: 0; margin: 0;
img { img {