From c59c266ee1b65ef2e8dae30ad51e508cfea866eb Mon Sep 17 00:00:00 2001 From: Nathan McCarty Date: Wed, 5 Feb 2025 03:26:39 -0500 Subject: [PATCH] Generate Index --- lib/Config.rakumod | 73 +++++++++++++++++++++++++++++++++++++---- lib/DB.rakumod | 14 +++++--- lib/DB/BlogMeta.rakumod | 3 ++ resources/main.css | 37 +++++++++++++++++++-- 4 files changed, 115 insertions(+), 12 deletions(-) diff --git a/lib/Config.rakumod b/lib/Config.rakumod index 8348145..c8f31d9 100644 --- a/lib/Config.rakumod +++ b/lib/Config.rakumod @@ -6,12 +6,16 @@ use DB::Post; unit class Config; -method generate-head(Str:D $title, BlogMeta:D $meta, $description?) { +method generate-head($title, BlogMeta:D $meta, $description?) { head [ meta :charset; meta :name, :content; meta :author :content; - title "$title — {$meta.title}"; + do if $title ~~ Str:D { + title "$title — {$meta.title}"; + } else { + title $meta.title; + } # Add description, if one exists do if $description ~~ Str:D { meta :description :content($description) @@ -123,15 +127,19 @@ method post-read-time(Post:D $post) { ] } +method post-info(Post:D $post) { + div :class, [ + self.post-date: $post; + self.post-read-time: $post; + ]; +} + method post-header(Post:D $post) { header :class, [ div :class, [ h1 $post.title; ]; - div :class, [ - self.post-date: $post; - self.post-read-time: $post; - ]; + self.post-info: $post; # TODO: Add tags once we have support for that ] } @@ -161,6 +169,59 @@ method generate-post(Post:D $post, BlogMeta:D $meta) { "$html" } +method generate-blurb(Int:D $id, $db) { + my $post = $db.posts{$id}; + my $desc = $post.description; + my @slugs = $post.all-slugs; + # Use the primary slug if there is one, the id if there isn't + my $link = do if @slugs.elems > 0 { + "/posts/by-slug/{@slugs[0]}.html" + } else { + "/posts/by-id/$id.html" + } + div :class, [ + div :class, [ + a :href($link), span [ + h2 $post.title; + ]; + ]; + self.post-info: $post; + if $desc ~~ Str:D { + div :class, [ + p $post.description; + ]; + } else { + [] + } + ] +} + +method generate-index($db) { + my @most-recent = + $db.sorted-posts + .head(10) + .grep(!*.value.hidden) + .map(-> $pair { + self.generate-blurb: $pair.key, $db + }); + + my $head = self.generate-head(Nil, $db.meta); + my $body = body [ + self.site-header: $db.meta; + div :class, [ + h1 "Recent Posts" + ], @most-recent; + ]; + + my $html = + html :lang, [ + $head, + $body + ]; + + "$html" +} + sub icon($icon) { i(:class("bx bx-$icon")) } diff --git a/lib/DB.rakumod b/lib/DB.rakumod index 576c309..653e4c7 100644 --- a/lib/DB.rakumod +++ b/lib/DB.rakumod @@ -83,17 +83,23 @@ class PostDB { $id-path.spurt: $html; for $post.all-slugs -> $slug { # remove the symlink if it already exists - my $slug-path = $by-slug.add: $slug; + my $slug-path = $by-slug.add: "$slug.html"; $slug-path.unlink if $slug-path.l; $id-path.symlink: $slug-path; } } - # Render the archive - # Render the rss/atom feed # Render the index - # Symlink the about article + $out-dir.add('index.html').spurt: $config.generate-index(self); + # TODO: Render the archive + # TODO: Render the rss/atom feed + # TODO: Symlink the about article die "Not Implemented" } + + #| Get a list of posts sorted by date + method sorted-posts() { + %!posts.sort(*.value.posted-at).reverse + } } #| Read the database out of a directory diff --git a/lib/DB/BlogMeta.rakumod b/lib/DB/BlogMeta.rakumod index f2a0382..b8477ae 100644 --- a/lib/DB/BlogMeta.rakumod +++ b/lib/DB/BlogMeta.rakumod @@ -13,3 +13,6 @@ has Str:D $.tagline is required is rw; #| The id of the placeholder post has Int:D $.placeholder-id is rw = 0; + +#| The id of the about post +has Int:D $.about-id is rw = 0; diff --git a/resources/main.css b/resources/main.css index 4a530e1..6f12ebf 100644 --- a/resources/main.css +++ b/resources/main.css @@ -46,7 +46,7 @@ body, .post { font-style: italic; } -.post-body, .post-header { +.post-body, .post-header, .post-blurbs { width: 66%; display: block; padding-left: 1.5rem; @@ -58,6 +58,28 @@ body, .post { /* text-align: justify; */ } +.post-blurbs { + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + gap: 1rem; +} + +.post-blurb { + width: 100%; + display: block; + border-radius: 1rem; + padding: 0.5rem; + background-color: light-dark(#ebebeb, #252525); + /* background-color: light-dark(#cdcdcd, #3b3b3b); */ + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + /* gap: 0.25rem; */ +} + .post-header { padding: 1.5rem; display: flex; @@ -71,7 +93,18 @@ body, .post { color: light-dark(#dd0f9d, #eb6eb7); } -.post-title > h1 { +.post-blurbs > h1 { + color: light-dark(#1d9700, #70b433); +} + +a:link { + color: light-dark(#009c8f, #41c7b9); +} + +a:visited { + color: light-dark(#dd0f9d, #eb6eb7); +} +.post-title > h1, .post-blurb-title > h2 { margin-top: 0px; margin-bottom: 0px; }