diff --git a/src/command/build/render.rs b/src/command/build/render.rs index 05e130a..55a56f4 100644 --- a/src/command/build/render.rs +++ b/src/command/build/render.rs @@ -100,8 +100,30 @@ impl SiteRenderer { // // Steps: pass each RenderBlogStream to dust as the context to render index.html and any additional stream pages. - for blog_post in &self.blog_posts { - println!("{:?}", blog_post.get_date()?); + // Sort blog posts by date, newest first. + let sorted_blog_posts = { + let mut sorted_blog_posts: Vec<_> = self.blog_posts.iter().collect(); + sorted_blog_posts + .sort_by_key(|blog_post| (blog_post.get_date(), blog_post.id.as_str())); + sorted_blog_posts.reverse(); + sorted_blog_posts + }; + + for blog_post in &sorted_blog_posts { + if blog_post.get_date().is_none() { + return Err(format!("Blog post {} does not have a date.", blog_post.id).into()); + } + } + + // Group blog posts based on # of posts per page. + let stream_chunks: Vec<_> = sorted_blog_posts + .chunks(config.get_stream_entries_per_page()) + .collect(); + + // For each group, create a RenderBlogStream. + let num_stream_pages = stream_chunks.len(); + for chunk in stream_chunks { + // foo } Ok(()) } diff --git a/src/config/full.rs b/src/config/full.rs index 4978e8d..fbfa5f8 100644 --- a/src/config/full.rs +++ b/src/config/full.rs @@ -71,4 +71,13 @@ impl Config { pub(crate) fn get_site_title(&self) -> Option<&str> { self.raw.site_title.as_deref() } + + pub(crate) fn get_stream_entries_per_page(&self) -> usize { + self.raw + .stream + .as_ref() + .map(|stream| stream.entries_per_page) + .flatten() + .unwrap_or(5) + } } diff --git a/src/config/raw.rs b/src/config/raw.rs index ce34997..2e69d63 100644 --- a/src/config/raw.rs +++ b/src/config/raw.rs @@ -9,6 +9,7 @@ pub(crate) struct RawConfig { email: Option, pub(super) use_relative_paths: Option, pub(super) web_root: Option, + pub(super) stream: Option, } impl Default for RawConfig { @@ -19,6 +20,20 @@ impl Default for RawConfig { email: None, use_relative_paths: None, web_root: None, + stream: None, + } + } +} + +#[derive(Deserialize, Serialize)] +pub(crate) struct RawConfigStream { + pub(super) entries_per_page: Option, +} + +impl Default for RawConfigStream { + fn default() -> Self { + RawConfigStream { + entries_per_page: None, } } } diff --git a/src/error/error.rs b/src/error/error.rs index 9707bdb..a6816ee 100644 --- a/src/error/error.rs +++ b/src/error/error.rs @@ -4,6 +4,7 @@ use std::string::FromUtf8Error; #[derive(Debug)] pub(crate) enum CustomError { Static(&'static str), + String(String), IO(std::io::Error), TomlSerialize(toml::ser::Error), TomlDeserialize(toml::de::Error), @@ -29,6 +30,12 @@ impl From<&'static str> for CustomError { } } +impl From for CustomError { + fn from(value: String) -> Self { + CustomError::String(value) + } +} + impl From for CustomError { fn from(value: toml::ser::Error) -> Self { CustomError::TomlSerialize(value) diff --git a/src/intermediate/blog_post.rs b/src/intermediate/blog_post.rs index 245c0aa..865528b 100644 --- a/src/intermediate/blog_post.rs +++ b/src/intermediate/blog_post.rs @@ -87,19 +87,26 @@ impl BlogPost { /// all the pages under the blog post looking for any page that /// contains a date export setting. It will return the first date /// found. - pub(crate) fn get_date(&self) -> Result<(), CustomError> { - if let Some(index_page) = self.get_index_page()? { - println!("{:?}", index_page); + pub(crate) fn get_date(&self) -> Option<&str> { + let index_page_date = self + .get_index_page() + .map(|index_page| index_page.date.as_ref().map(String::as_str)) + .flatten(); + if index_page_date.is_some() { + return index_page_date; } - Ok(()) + + self.pages + .iter() + .filter_map(|page| page.date.as_ref().map(String::as_str)) + .next() } /// Get the blog post page for index.org - fn get_index_page(&self) -> Result, CustomError> { - Ok(self - .pages + fn get_index_page(&self) -> Option<&BlogPostPage> { + self.pages .iter() - .find(|page| page.path == Path::new("index.org"))) + .find(|page| page.path == Path::new("index.org")) } } diff --git a/src/intermediate/page.rs b/src/intermediate/page.rs index 74952fa..367422d 100644 --- a/src/intermediate/page.rs +++ b/src/intermediate/page.rs @@ -16,6 +16,8 @@ pub(crate) struct BlogPostPage { pub(crate) title: Option, + pub(crate) date: Option, + pub(crate) children: Vec, pub(crate) footnotes: Vec, @@ -60,6 +62,7 @@ impl BlogPostPage { Ok(BlogPostPage { path, title: get_title(&document), + date: get_date(&document), children, footnotes, }) @@ -85,3 +88,14 @@ fn get_title(document: &organic::types::Document<'_>) -> Option { .last() .map(|kw| kw.value.to_owned()) } + +fn get_date(document: &organic::types::Document<'_>) -> Option { + organic::types::AstNode::from(document) + .iter_all_ast_nodes() + .filter_map(|node| match node { + organic::types::AstNode::Keyword(kw) if kw.key.eq_ignore_ascii_case("date") => Some(kw), + _ => None, + }) + .last() + .map(|kw| kw.value.to_owned()) +}