From 00c444373e8901e9a53e8a72fdc74b3ba84d9dcf Mon Sep 17 00:00:00 2001 From: Fuwn Date: Sat, 14 Feb 2026 21:42:19 -0800 Subject: fix(blog): Remove extra whitespace on category pages without descriptions --- src/modules/blog/module.rs | 132 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 100 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/modules/blog/module.rs b/src/modules/blog/module.rs index e16861a..bcb61da 100644 --- a/src/modules/blog/module.rs +++ b/src/modules/blog/module.rs @@ -73,38 +73,9 @@ pub fn module(router: &mut windmark::router::Router) { ); }; let category_posts = visible_posts_for_blog(&posts, &category.notion_id); - let post_listing = category_posts - .iter() - .map(|post| { - let post_slug = slugify(&post.title); - - format!( - "=> /blog/{}/{} {}{}", - blog_slug, - post_slug, - post.title, - post - .description - .as_ref() - .filter(|description_text| !description_text.is_empty()) - .map_or_else(String::new, |description_text| format!( - " ― {description_text}" - )) - ) - }) - .collect::>() - .join("\n"); success( - &format!( - "# {} ({})\n\n{}\n\n{}\n\n## Really Simple Syndication\n\nAccess \ - {0}'s RSS feed\n\n=> /blog/{}.xml here!", - category.title, - category_posts.len(), - category.description.as_deref().unwrap_or(""), - post_listing, - blog_slug, - ), + &render_blog_page(category, blog_slug.as_str(), &category_posts), &context, ) }, @@ -180,6 +151,51 @@ fn construct_header(post: &BlogPost) -> String { fn slugify(text: &str) -> String { text.replace(' ', "_").to_lowercase() } +fn render_blog_page( + category: &BlogCategory, + blog_slug: &str, + category_posts: &[&BlogPost], +) -> String { + let post_listing = category_posts + .iter() + .map(|post| { + let post_slug = slugify(&post.title); + + format!( + "=> /blog/{}/{} {}{}", + blog_slug, + post_slug, + post.title, + post + .description + .as_ref() + .filter(|description_text| !description_text.is_empty()) + .map_or_else(String::new, |description_text| format!( + " ― {description_text}" + )) + ) + }) + .collect::>() + .join("\n"); + let description_block = category + .description + .as_deref() + .filter(|description_text| !description_text.is_empty()) + .map_or_else(String::new, |description_text| { + format!("{description_text}\n\n") + }); + + format!( + "# {} ({})\n\n{}{post_listing}\n\n## Really Simple Syndication\n\nAccess \ + {}'s RSS feed\n\n=> /blog/{}.xml here!", + category.title, + category_posts.len(), + description_block, + category.title, + blog_slug, + ) +} + fn parse_chronological_sort_key(raw_date: Option<&str>) -> i64 { raw_date .and_then(|date_text| { @@ -427,8 +443,9 @@ pub fn refresh_loop() { #[cfg(test)] mod tests { use super::{ - build_global_posts, build_rss_feed, find_visible_post_by_slug, slugify, - visible_posts_for_blog, BLOG_CATEGORIES, BLOG_POSTS, + build_global_posts, build_rss_feed, find_visible_post_by_slug, + render_blog_page, slugify, visible_posts_for_blog, BLOG_CATEGORIES, + BLOG_POSTS, }; use crate::modules::blog::config::{BlogCategory, BlogPost}; @@ -653,4 +670,55 @@ mod tests { ] ); } + + #[test] + fn render_blog_page_without_description_has_single_spacing_before_listing() { + let category = BlogCategory { + title: "The Daily".to_string(), + description: None, + priority: 1, + notion_id: "blog-id".to_string(), + }; + let post = BlogPost { + title: "Entry One".to_string(), + description: None, + author: None, + created_raw: None, + created: None, + last_modified: None, + content: "content".to_string(), + blog_id: "blog-id".to_string(), + hidden: false, + }; + let rendered = render_blog_page(&category, "the_daily", &[&post]); + + assert!(rendered.contains("# The Daily (1)\n\n=> /blog/the_daily/entry_one Entry One")); + assert!(!rendered.contains("# The Daily (1)\n\n\n")); + } + + #[test] + fn render_blog_page_with_description_keeps_expected_spacing() { + let category = BlogCategory { + title: "The Daily".to_string(), + description: Some("desc".to_string()), + priority: 1, + notion_id: "blog-id".to_string(), + }; + let post = BlogPost { + title: "Entry One".to_string(), + description: None, + author: None, + created_raw: None, + created: None, + last_modified: None, + content: "content".to_string(), + blog_id: "blog-id".to_string(), + hidden: false, + }; + let rendered = render_blog_page(&category, "the_daily", &[&post]); + + assert!(rendered.contains( + "# The Daily (1)\n\ndesc\n\n=> /blog/the_daily/entry_one Entry One" + )); + } } -- cgit v1.2.3