Generate series pages
This commit is contained in:
parent
7cf4827d0c
commit
baf8d6556b
8 changed files with 168 additions and 41 deletions
|
@ -10,14 +10,6 @@ use DB::Post;
|
|||
|
||||
unit class Config;
|
||||
|
||||
sub show-html($html) {
|
||||
my $out = "<!doctype html>$html";
|
||||
# Work around HTML::Functional automatically putting newlines between tags
|
||||
$out ~~ s:g/'</i>' \v+ '<span>'/<\/i><span>/;
|
||||
$out ~~ s:g/\v+ '</a>'/<\/a>/;
|
||||
$out
|
||||
}
|
||||
|
||||
# TODO: Support GFM admonitions
|
||||
method generate-post(Int:D $id, Post:D $post, $db) {
|
||||
my $meta = $db.meta;
|
||||
|
@ -45,34 +37,13 @@ method generate-post(Int:D $id, Post:D $post, $db) {
|
|||
show-html $html
|
||||
}
|
||||
|
||||
method generate-blurb(Int:D $id, $db) {
|
||||
my $post = $db.posts{$id};
|
||||
my $desc = $post.description;
|
||||
my $link = post-link $id, $post;
|
||||
div :class<post-blurb>, [
|
||||
div :class<post-blurb-title>, [
|
||||
a :href($link), span [
|
||||
h2 $post.title;
|
||||
];
|
||||
];
|
||||
post-info $id, $post, $db;
|
||||
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
|
||||
generate-blurb $pair.key, $db
|
||||
});
|
||||
|
||||
my $head = generate-head($db.meta);
|
||||
|
@ -97,7 +68,7 @@ method generate-archive($db) {
|
|||
$db.sorted-posts
|
||||
.grep(!*.value.hidden)
|
||||
.map(-> $pair {
|
||||
self.generate-blurb: $pair.key, $db
|
||||
generate-blurb $pair.key, $db
|
||||
});
|
||||
|
||||
my $head = generate-head($db.meta);
|
||||
|
|
|
@ -14,6 +14,7 @@ use DB::BlogMeta;
|
|||
use DB::MarkdownPost;
|
||||
use DB::IdrisPost;
|
||||
use DB::PlaceholderPost;
|
||||
use Render::Series;
|
||||
use Atom;
|
||||
use Config;
|
||||
|
||||
|
@ -140,6 +141,13 @@ class PostDB {
|
|||
$config.generate-tag-page(self, $tag);
|
||||
}
|
||||
# TODO: Generate the series pages
|
||||
my $series-dir = $out-dir.add('series/');
|
||||
mkdir $series-dir unless $series-dir.e;
|
||||
for %!series.kv -> $key, $value {
|
||||
$series-dir.add("$key.html").spurt:
|
||||
series-page($key, self);
|
||||
}
|
||||
# TODO: Generate the main series page
|
||||
# Render the rss/atom feed
|
||||
my $atom-path = $out-dir.add('atom.xml');
|
||||
my $atom = posts-to-atom self;
|
||||
|
|
|
@ -22,3 +22,14 @@ method contains-post(Int:D $post-id --> Bool:D) {
|
|||
False
|
||||
}
|
||||
}
|
||||
|
||||
#| Returns the date of the lastest post
|
||||
method latest-post($db) {
|
||||
my @posts = @!post-ids.map(-> $i {$db.posts{$i}});
|
||||
if @posts {
|
||||
my $most-recent-post = @posts.max(*.posted-at);
|
||||
$most-recent-post.posted-at
|
||||
} else {
|
||||
Nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -131,3 +131,24 @@ sub post-header(Int:D $id, Post:D $post, $db) is export {
|
|||
post-info $id, $post, $db;
|
||||
]
|
||||
}
|
||||
|
||||
sub generate-blurb(Int:D $id, $db) is export {
|
||||
my $post = $db.posts{$id};
|
||||
my $desc = $post.description;
|
||||
my $link = post-link $id, $post;
|
||||
div :class<post-blurb>, [
|
||||
div :class<post-blurb-title>, [
|
||||
a :href($link), span [
|
||||
h2 $post.title;
|
||||
];
|
||||
];
|
||||
post-info $id, $post, $db;
|
||||
if $desc ~~ Str:D {
|
||||
div :class<post-blurb-description>, [
|
||||
p $post.description;
|
||||
];
|
||||
} else {
|
||||
[]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
105
lib/Render/Series.rakumod
Normal file
105
lib/Render/Series.rakumod
Normal file
|
@ -0,0 +1,105 @@
|
|||
use v6.e.PREVIEW;
|
||||
unit module Render::Series;
|
||||
|
||||
use Render::Util;
|
||||
use Render::Head;
|
||||
use Render::Post;
|
||||
use DB::Post;
|
||||
use DB::Series;
|
||||
|
||||
use HTML::Functional;
|
||||
|
||||
sub series-date(Series:D $series, $db) is export {
|
||||
my $datetime = $series.latest-post: $db;
|
||||
if $datetime {
|
||||
my $timestamp = sprintf(
|
||||
"%s %02d:%02d%s",
|
||||
$datetime.yyyy-mm-dd,
|
||||
($datetime.hour % 12) || 12,
|
||||
$datetime.minute,
|
||||
$datetime.hour < 12 ?? 'am' !! 'pm'
|
||||
);
|
||||
|
||||
div :class<series-time>, :title("Latest post made at $timestamp"), [
|
||||
icon 'calendar';
|
||||
' ';
|
||||
$datetime.Date.Str
|
||||
]
|
||||
} else {
|
||||
[]
|
||||
}
|
||||
}
|
||||
|
||||
sub series-read-time(Series:D $series, $db) is export {
|
||||
my @readtimes = $series.post-ids.map(-> $i {$db.posts{$i}.readtimes});
|
||||
my ($slow, $average, $fast) = 0, 0, 0;
|
||||
for @readtimes -> ($s, $a, $f) {
|
||||
$slow += $s;
|
||||
$average += $a;
|
||||
$fast += $f;
|
||||
}
|
||||
div :class<series-read-time>, :title<Estimated read time at 140/180/220 WPM>, [
|
||||
icon 'timer';
|
||||
' ';
|
||||
mins-to-string $slow;
|
||||
' ';
|
||||
'/';
|
||||
' ';
|
||||
mins-to-string $average;
|
||||
' ';
|
||||
'/';
|
||||
' ';
|
||||
mins-to-string $fast;
|
||||
]
|
||||
}
|
||||
|
||||
sub series-count(Series:D $series, $db) is export {
|
||||
my $count = $series.post-ids.elems;
|
||||
div :class<series-article-count>, :title("Series has $count articles"), [
|
||||
icon 'add-to-queue';
|
||||
' ';
|
||||
"$count articles";
|
||||
]
|
||||
}
|
||||
|
||||
sub series-info(Series:D $series, $db) is export {
|
||||
div :class<series-info>, [
|
||||
series-date $series, $db;
|
||||
series-read-time $series, $db;
|
||||
series-count $series, $db;
|
||||
]
|
||||
}
|
||||
|
||||
sub series-header(Series:D $series, $db) is export {
|
||||
header :class<series-header>, [
|
||||
div :class<series-title>, [
|
||||
h1 $series.title;
|
||||
];
|
||||
div :class<series-desc>, [
|
||||
p $series.desc;
|
||||
];
|
||||
series-info $series, $db;
|
||||
]
|
||||
}
|
||||
|
||||
sub series-page(Int:D $series-id, $db) is export {
|
||||
my $meta = $db.meta;
|
||||
my $series = $db.series{$series-id};
|
||||
my $head = generate-head($meta, $series.title, $series.desc);
|
||||
my $body =
|
||||
body [
|
||||
site-header $meta;
|
||||
article :class<series>, [
|
||||
series-header $series, $db;
|
||||
div :class<series-blurbs>,
|
||||
$series.post-ids.map(*.&generate-blurb($db));
|
||||
]
|
||||
];
|
||||
|
||||
my $html = html :lang<en>, [
|
||||
$head;
|
||||
$body
|
||||
];
|
||||
|
||||
show-html $html;
|
||||
}
|
|
@ -5,6 +5,15 @@ use DB::Post;
|
|||
|
||||
use HTML::Functional;
|
||||
|
||||
sub show-html($html) is export {
|
||||
my $out = "<!doctype html>$html";
|
||||
# Work around HTML::Functional automatically putting newlines between tags
|
||||
$out ~~ s:g/'</i>' \v+ '<span>'/<\/i><span>/;
|
||||
$out ~~ s:g/\v+ '</a>'/<\/a>/;
|
||||
$out ~~ s:g/',' \v+ '<span'/,<span/;
|
||||
$out
|
||||
}
|
||||
|
||||
sub opt($test, $item) is export {
|
||||
if $test {
|
||||
$item
|
||||
|
|
|
@ -53,7 +53,8 @@ a:visited {
|
|||
.site-tagline {
|
||||
color: var(--dim-0);
|
||||
}
|
||||
.post-body, .post-header, .post-blurbs, .tags, .tags .tag-blurb-post {
|
||||
.post-body, .post-header, .post-blurbs, .tags, .tags .tag-blurb-post,
|
||||
.series-header, .series-blurbs {
|
||||
background-color: var(--bg-0);
|
||||
}
|
||||
.post-blurb, .tags .tag-blurb {
|
||||
|
@ -65,13 +66,13 @@ a:visited {
|
|||
:not(.tags) .tag-blurb-post {
|
||||
background-color: var(--bg-1);
|
||||
}
|
||||
.post-title, .post-blurbs h1 {
|
||||
.post-title, .post-blurbs h1, .series-header h1 {
|
||||
color: var(--green);
|
||||
}
|
||||
.post-body h2, .post-body h3, .post-body h4 {
|
||||
color: var(--fg-1);
|
||||
}
|
||||
.post-info > * {
|
||||
.post-info > *, .series-info > * {
|
||||
background-color: var(--bg-2);
|
||||
}
|
||||
blockquote {
|
||||
|
|
|
@ -27,13 +27,13 @@
|
|||
}
|
||||
|
||||
/* Main Body and Post Flexboxs */
|
||||
body, .post {
|
||||
body, .post, .series {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: var(--box-gap);
|
||||
}
|
||||
.post {
|
||||
.post, .series {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ body, .post {
|
|||
|
||||
/* Style the post header, body, and blurbs */
|
||||
/* TODO: Style footnotes and get footnote hover working */
|
||||
.post-header, .post-body {
|
||||
.post-header, .post-body, .series-header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
@ -90,11 +90,11 @@ body, .post {
|
|||
margin: auto var(--box-margin-horz);
|
||||
align-self: stretch;
|
||||
}
|
||||
.post-title h1 {
|
||||
.post-title h1, .series-title h1 {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.post-info {
|
||||
.post-info, .series-info {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
@ -108,7 +108,7 @@ body, .post {
|
|||
.post-body h2, .post-body h3, .post-body h4 {
|
||||
text-align: center;
|
||||
}
|
||||
.post-blurbs {
|
||||
.post-blurbs, .series-blurbs {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
@ -116,6 +116,7 @@ body, .post {
|
|||
max-width: var(--content-width);
|
||||
padding: var(--box-padding-vert) var(--box-padding-horz);
|
||||
border-radius: var(--box-radius);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.post-blurb {
|
||||
width: 100%;
|
||||
|
@ -128,7 +129,7 @@ body, .post {
|
|||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.post-info > * {
|
||||
.post-info > *, .series-info > * {
|
||||
padding: 0.25em;
|
||||
border-radius: 0.25em;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue