From 20ecef3b3f7e606dfb4abdddc76f2a0305122146 Mon Sep 17 00:00:00 2001 From: Nathan McCarty Date: Fri, 7 Feb 2025 01:43:52 -0500 Subject: [PATCH] Generate tags page --- lib/Config.rakumod | 73 +++++++++++++++++++++++++++++++++++++++++++- lib/DB.rakumod | 3 ++ resources/colors.css | 4 +-- resources/main.css | 61 ++++++++++++++++++++++++++++++++++++ 4 files changed, 138 insertions(+), 3 deletions(-) diff --git a/lib/Config.rakumod b/lib/Config.rakumod index 85cab41..58d7b7d 100644 --- a/lib/Config.rakumod +++ b/lib/Config.rakumod @@ -69,6 +69,13 @@ method site-header(BlogMeta:D $meta) { 'Archive'; ]; ]; + a :href, [ + icon 'purchase-tag-alt'; + ' '; + span [ + 'Tags'; + ]; + ]; a :href, [ icon 'info-circle'; ' '; @@ -169,7 +176,7 @@ method post-tags(Post:D $post){ if @tags { @tags.=map(-> $tag {self.post-tag($tag)}); div :class, [ - icon 'purchase-tag'; + icon 'purchase-tag-alt'; ' '; intersperse(', ', @tags); ] @@ -299,6 +306,70 @@ method generate-archive($db) { "$html" } +method generate-tag-blurb($db, $tag, $limit?) { + sub post-to-link($id, $post) { + 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 { + "/posts/by-slug/{@slugs[*-1]}.html" + } else { + "/posts/by-id/$id.html" + } + div :class, [ + div :class, [ + a :href($link), span [ + h3 $post.title; + ]; + self.post-info: $post; + if $desc ~~ Str:D { + div :class, [ + 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, [ + span :class, [ + a :href("/tags/$tag.html"), [ + icon 'hash'; + $tag; + ]; + ]; + div :class, + @posts.map(-> $a {post-to-link $a.key, $a.value}); + ] + } else { + [] + } +} + +method generate-tags-page($db, @tags) { + my $head = self.generate-head(Nil, $db.meta); + my $body = body [ + self.site-header: $db.meta; + div :class, [ + h1 "Tags"; + ], @tags.map(-> $tag {self.generate-tag-blurb($db, $tag, 4)}); + ]; + + 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 e56ec67..87614e4 100644 --- a/lib/DB.rakumod +++ b/lib/DB.rakumod @@ -105,6 +105,9 @@ class PostDB { my $about-path = $out-dir.add('about.html'); $about-path.unlink if $about-path.l; $by-id.add("{$!meta.about-id}.html").symlink: $about-path; + # Generate the tags pages + my @tags = %!posts.values.map(*.tags).flat.unique; + $out-dir.add('tags.html').spurt: $config.generate-tags-page(self, @tags); # Render the rss/atom feed my $atom-path = $out-dir.add('atom.xml'); my $atom = posts-to-atom self; diff --git a/resources/colors.css b/resources/colors.css index 54e6cc5..fb8f588 100644 --- a/resources/colors.css +++ b/resources/colors.css @@ -53,10 +53,10 @@ a:visited { .site-tagline { color: var(--dim-0); } -.post-body, .post-header, .post-blurbs { +.post-body, .post-header, .post-blurbs, .tags, .tag-blurb-post { background-color: var(--bg-0); } -.post-blurb { +.post-blurb, .tag-blurb { background-color: var(--bg-1); } .post-title, .post-blurbs > h1 { diff --git a/resources/main.css b/resources/main.css index fad0412..5958cec 100644 --- a/resources/main.css +++ b/resources/main.css @@ -2,6 +2,7 @@ font-family: "Open Sans", sans-serif, serif; /* Variables */ --content-width: 60rem; + --blurb-width: 45%; --header-width: 35rem; --box-padding-vert: 1rem; --box-padding-horz: 1rem; @@ -18,6 +19,13 @@ } } +/* slightly larger than blurb-width to account for padding/margins */ +@media screen and (max-width: 40rem) { + :root { + --blurb-width: 100%; + } +} + /* Main Body and Post Flexboxs */ body, .post { display: flex; @@ -124,3 +132,56 @@ blockquote { border-radius: var(--box-radius); padding: var(--box-padding-vert) var(--box-padding-horz); } + +/* Style the tags blurbs and page */ +.tags { + display: flex; + flex-direction: column; + align-items: center; + gap: var(--box-gap); + max-width: var(--content-width); + /* min-width: var(--blurb-width); */ + padding: var(--box-padding-vert) var(--box-padding-horz); + border-radius: var(--box-radius); + box-sizing: border-box; +} +.tag-blurb { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + gap: var(--box-gap); + border-radius: var(--box-radius); + box-sizing: border-box; +} +.tag-blurb-links { + display: block; + border-radius: var(--box-radius); + border-radius: var(--box-radius); + display: flex; + flex-flow: row wrap; + gap: var(--box-gap); + align-items: stretch; + box-sizing: border-box; + gap: var(--box-gap); + padding: var(--box-padding-vert) var(--box-padding-horz); +} +.tag-blurb-post { + font-size: 0.8rem; + width: var(--blurb-width); + display: flex; + flex-direction: column; + align-items: center; + gap: var(--box-gap); + box-sizing: border-box; + flex-shrink: 1; + flex-grow: 1; + border-radius: var(--box-radius); + padding: var(--box-padding-vert) var(--box-padding-horz); +} +.tag-blurb-title { + margin-top: var(--box-margin-vert); + margin-bottom: 0; + font-size: 1.5em; + font-weight: bold; +}