Generate Index

This commit is contained in:
Nathan McCarty 2025-02-05 03:26:39 -05:00
parent d861c7ef87
commit c59c266ee1
4 changed files with 115 additions and 12 deletions

View file

@ -6,12 +6,16 @@ use DB::Post;
unit class Config; unit class Config;
method generate-head(Str:D $title, BlogMeta:D $meta, $description?) { method generate-head($title, BlogMeta:D $meta, $description?) {
head [ head [
meta :charset<utf-8>; meta :charset<utf-8>;
meta :name<viewport>, :content<width=device-width, initial-scale=1>; meta :name<viewport>, :content<width=device-width, initial-scale=1>;
meta :author :content<Nathan McCarty>; meta :author :content<Nathan McCarty>;
do if $title ~~ Str:D {
title "$title {$meta.title}"; title "$title {$meta.title}";
} else {
title $meta.title;
}
# Add description, if one exists # Add description, if one exists
do if $description ~~ Str:D { do if $description ~~ Str:D {
meta :description :content($description) meta :description :content($description)
@ -123,15 +127,19 @@ method post-read-time(Post:D $post) {
] ]
} }
method post-info(Post:D $post) {
div :class<post-info>, [
self.post-date: $post;
self.post-read-time: $post;
];
}
method post-header(Post:D $post) { method post-header(Post:D $post) {
header :class<post-header>, [ header :class<post-header>, [
div :class<post-title>, [ div :class<post-title>, [
h1 $post.title; h1 $post.title;
]; ];
div :class<post-info>, [ self.post-info: $post;
self.post-date: $post;
self.post-read-time: $post;
];
# TODO: Add tags once we have support for that # TODO: Add tags once we have support for that
] ]
} }
@ -161,6 +169,59 @@ method generate-post(Post:D $post, BlogMeta:D $meta) {
"<!doctype html>$html" "<!doctype html>$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<post-blurb>, [
div :class<post-blurb-title>, [
a :href($link), span [
h2 $post.title;
];
];
self.post-info: $post;
if $desc ~~ Str:D {
div :class<post-blurb-description>, [
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<post-blurbs>, [
h1 "Recent Posts"
], @most-recent;
];
my $html =
html :lang<en>, [
$head,
$body
];
"<!doctype html>$html"
}
sub icon($icon) { sub icon($icon) {
i(:class("bx bx-$icon")) i(:class("bx bx-$icon"))
} }

View file

@ -83,17 +83,23 @@ class PostDB {
$id-path.spurt: $html; $id-path.spurt: $html;
for $post.all-slugs -> $slug { for $post.all-slugs -> $slug {
# remove the symlink if it already exists # 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; $slug-path.unlink if $slug-path.l;
$id-path.symlink: $slug-path; $id-path.symlink: $slug-path;
} }
} }
# Render the archive
# Render the rss/atom feed
# Render the index # 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" 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 #| Read the database out of a directory

View file

@ -13,3 +13,6 @@ has Str:D $.tagline is required is rw;
#| The id of the placeholder post #| The id of the placeholder post
has Int:D $.placeholder-id is rw = 0; has Int:D $.placeholder-id is rw = 0;
#| The id of the about post
has Int:D $.about-id is rw = 0;

View file

@ -46,7 +46,7 @@ body, .post {
font-style: italic; font-style: italic;
} }
.post-body, .post-header { .post-body, .post-header, .post-blurbs {
width: 66%; width: 66%;
display: block; display: block;
padding-left: 1.5rem; padding-left: 1.5rem;
@ -58,6 +58,28 @@ body, .post {
/* text-align: justify; */ /* 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 { .post-header {
padding: 1.5rem; padding: 1.5rem;
display: flex; display: flex;
@ -71,7 +93,18 @@ body, .post {
color: light-dark(#dd0f9d, #eb6eb7); 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-top: 0px;
margin-bottom: 0px; margin-bottom: 0px;
} }