website/lib/Config.rakumod

344 lines
7.5 KiB
Raku
Raw Normal View History

2025-02-03 21:36:07 -05:00
use v6.e.PREVIEW;
use HTML::Functional;
2025-02-07 02:26:17 -05:00
use Render::Head;
2025-02-07 02:33:40 -05:00
use Render::Util;
2025-02-03 21:36:07 -05:00
use DB::BlogMeta;
2025-02-04 16:51:37 -05:00
use DB::Post;
2025-02-03 21:36:07 -05:00
unit class Config;
2025-02-04 21:39:47 -05:00
method site-header(BlogMeta:D $meta) {
header :class<site-header>, [
div :class<site-logo>, [
# TODO: Use a real image here
$meta.title
];
div :class<site-tagline>, [
$meta.tagline
];
div :class<header-links>, [
2025-02-05 00:26:12 -05:00
a :href</index.html>, [
icon 'home';
' ';
span [
'Home';
];
];
a :href</archive.html>, [
icon 'archive';
' ';
span [
'Archive';
];
];
2025-02-07 01:43:52 -05:00
a :href</tags.html>, [
icon 'purchase-tag-alt';
' ';
span [
'Tags';
];
];
2025-02-05 00:26:12 -05:00
a :href</about.html>, [
icon 'info-circle';
' ';
span [
'About';
];
];
2025-02-05 04:37:28 -05:00
a :href</atom.xml>, [
2025-02-05 00:26:12 -05:00
icon 'rss';
' ';
span [
'Feed';
];
];
];
2025-02-04 21:39:47 -05:00
]
}
2025-02-04 23:43:42 -05:00
method post-date(Post:D $post) {
my $datetime = $post.posted-at;
my $timestamp = sprintf(
2025-02-05 03:45:01 -05:00
"%s %02d:%02d%s",
2025-02-04 23:43:42 -05:00
$datetime.yyyy-mm-dd,
($datetime.hour % 12) || 12,
$datetime.minute,
$datetime.hour < 12 ?? 'am' !! 'pm'
);
div :class<post-time>, :title("Posted At $timestamp"), [
icon 'time';
'&nbsp;';
$timestamp
]
}
2025-02-05 03:45:01 -05:00
method post-edit(Post:D $post) {
return [] unless $post.edited-at.elems;
my $datetime = $post.edited-at.max;
my $timestamp = sprintf(
"%s %02d:%02d%s",
$datetime.yyyy-mm-dd,
($datetime.hour % 12) || 12,
$datetime.minute,
$datetime.hour < 12 ?? 'am' !! 'pm'
);
div :class<post-edit>, :title("Laste Edited At $timestamp"), [
icon 'edit';
'&nbsp;';
$timestamp
]
}
2025-02-04 23:43:42 -05:00
sub mins-to-string($mins) {
if $mins < 60 {
$mins.Str ~ "m"
} else {
my $h = $mins div 60;
my $m = $mins mod 60;
$h.Str ~ "h" ~ $m.Str ~ "m"
}
}
method post-read-time(Post:D $post) {
my ($slow, $average, $fast) = $post.readtimes;
div :class<post-read-time>, :title<Estimated read time at 140/180/220 WPM>, [
icon 'timer';
'&nbsp;';
mins-to-string $slow;
'&nbsp;';
'/';
'&nbsp;';
mins-to-string $average;
'&nbsp;';
'/';
'&nbsp;';
mins-to-string $fast;
]
}
2025-02-06 23:45:26 -05:00
method post-tag(Str:D $tag) {
span :class<post-tag>, [
a :href("/tags/$tag.html"), [
icon 'hash';
$tag;
]
]
}
method post-tags(Post:D $post){
sub intersperse (\element, +list) {
gather for list {
FIRST .take, next;
take slip element, $_;
}
}
my @tags = $post.tags;
if @tags {
@tags.=map(-> $tag {self.post-tag($tag)});
div :class<post-tags>, [
2025-02-07 01:43:52 -05:00
icon 'purchase-tag-alt';
2025-02-06 23:45:26 -05:00
'&nbsp;';
intersperse(', ', @tags);
]
} else {
[]
}
}
2025-02-05 03:26:39 -05:00
method post-info(Post:D $post) {
div :class<post-info>, [
self.post-date: $post;
2025-02-05 03:45:01 -05:00
self.post-edit: $post;
2025-02-05 03:26:39 -05:00
self.post-read-time: $post;
2025-02-06 23:45:26 -05:00
self.post-tags: $post;
2025-02-05 03:26:39 -05:00
];
}
method post-header(Post:D $post) {
header :class<post-header>, [
div :class<post-title>, [
h1 $post.title;
2025-02-04 23:43:42 -05:00
];
2025-02-05 03:26:39 -05:00
self.post-info: $post;
]
}
2025-02-04 16:51:37 -05:00
# TODO: Support GFM admonitions
method generate-post(Post:D $post, BlogMeta:D $meta) {
my $content = $post.render-html;
2025-02-07 02:26:17 -05:00
my $head = generate-head($meta, $post.title, $post.description);
2025-02-03 21:51:09 -05:00
my $body =
body [
2025-02-04 21:39:47 -05:00
self.site-header: $meta;
article :class<post>, [
self.post-header: $post;
div :class<post-body>, [
$content;
]
2025-02-03 21:51:09 -05:00
]
];
# TODO: Setup footer
2025-02-03 21:36:07 -05:00
# my $footer;
my $html = html :lang<en>, [
$head,
$body
];
"<!doctype html>$html"
}
2025-02-04 23:43:42 -05:00
2025-02-05 03:26:39 -05:00
method generate-blurb(Int:D $id, $db) {
my $post = $db.posts{$id};
my $desc = $post.description;
2025-02-07 02:33:40 -05:00
my $link = post-link $id, $post;
2025-02-05 03:26:39 -05:00
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
});
2025-02-07 02:26:17 -05:00
my $head = generate-head($db.meta);
2025-02-05 03:26:39 -05:00
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"
}
2025-02-05 03:28:49 -05:00
method generate-archive($db) {
my @most-recent =
$db.sorted-posts
.grep(!*.value.hidden)
.map(-> $pair {
self.generate-blurb: $pair.key, $db
});
2025-02-07 02:26:17 -05:00
my $head = generate-head($db.meta);
2025-02-05 03:28:49 -05:00
my $body = body [
self.site-header: $db.meta;
div :class<post-blurbs>, [
h1 "All Posts"
], @most-recent;
];
my $html =
html :lang<en>, [
$head,
$body
];
"<!doctype html>$html"
}
2025-02-07 01:43:52 -05:00
method generate-tag-blurb($db, $tag, $limit?) {
sub post-to-link($id, $post) {
my $desc = $post.description;
2025-02-07 02:33:40 -05:00
my $link = post-link $id, $post;
2025-02-07 01:43:52 -05:00
div :class<tag-blurb-post>, [
div :class<tag-blurb-post-title>, [
a :href($link), span [
h3 $post.title;
];
self.post-info: $post;
if $desc ~~ Str:D {
div :class<tag-blurb-post-description>, [
p $post.description;
];
} else {
[]
}
];
]
}
my @posts = $db.sorted-posts.grep(-> $a { $tag (elem) $a.value.tags });
if $limit {
@posts.=head($limit);
}
if @posts {
div :class<tag-blurb>, [
span :class<tag-blurb-title>, [
a :href("/tags/$tag.html"), [
icon 'hash';
$tag;
];
];
div :class<tag-blurb-links>,
@posts.map(-> $a {post-to-link $a.key, $a.value});
]
} else {
[]
}
}
method generate-tags-page($db, @tags) {
2025-02-07 02:26:17 -05:00
my $head = generate-head($db.meta);
2025-02-07 01:43:52 -05:00
my $body = body [
self.site-header: $db.meta;
div :class<tags>, [
h1 "Tags";
], @tags.map(-> $tag {self.generate-tag-blurb($db, $tag, 4)});
];
my $html =
html :lang<en>, [
$head,
$body
];
"<!doctype html>$html"
}
2025-02-07 01:58:44 -05:00
method generate-tag-page($db, $tag) {
2025-02-07 02:26:17 -05:00
my $head = generate-head($db.meta);
2025-02-07 01:58:44 -05:00
my $body = body [
self.site-header: $db.meta;
self.generate-tag-blurb($db, $tag, 4);
];
my $html =
html :lang<en>, [
$head,
$body
];
"<!doctype html>$html"
}
2025-02-04 23:43:42 -05:00
sub icon($icon) {
i(:class("bx bx-$icon"))
}