diff --git a/TODO.org b/TODO.org index 02aabbd..aeab71b 100644 --- a/TODO.org +++ b/TODO.org @@ -1,4 +1,4 @@ -* Things to do [5/14] +* Things to do [6/17] ** DONE If the paragraph only contains an image, text-align center ** DONE Syntax highlighting for code blocks ** TODO Render gnuplot @@ -16,3 +16,6 @@ *** TODO gnuplot https://github.com/dpezto/tree-sitter-gnuplot is not on crates.io so I'd have to add a git dependency to use it. This would prevent publishing this crate to crates.io. ** DONE Bug: carry over highlight starts when breaking lines +** TODO Add dates to posts +** DONE Add support for unlisted posts (posts that do not show up on the homepage). +** TODO Add support for showing file name where we currently show language diff --git a/src/command/build/render.rs b/src/command/build/render.rs index a5420cb..b32f63f 100644 --- a/src/command/build/render.rs +++ b/src/command/build/render.rs @@ -18,6 +18,7 @@ use crate::error::CustomError; use crate::intermediate::get_web_path; use crate::intermediate::BlogPost; use crate::intermediate::IPage; +use crate::intermediate::PublishStatus; use crate::render::DusterRenderer; use crate::render::RendererIntegration; use crate::walk_fs::walk_fs; @@ -84,7 +85,11 @@ impl SiteRenderer { pub(crate) async fn render_pages(&self, config: &Config) -> Result<(), CustomError> { let renderer_integration = self.init_renderer_integration()?; - for page in &self.pages { + for page in self.pages.iter().filter(|page| match page.natter_publish { + PublishStatus::Full => true, + PublishStatus::Unlisted => true, + PublishStatus::Unpublished => false, + }) { let output_path = self.output_directory.join(page.get_output_path()); let dependency_manager = std::sync::Arc::new(std::sync::Mutex::new(DependencyManager::new())); @@ -115,7 +120,17 @@ impl SiteRenderer { pub(crate) async fn render_blog_posts(&self, config: &Config) -> Result<(), CustomError> { let renderer_integration = self.init_renderer_integration()?; - for blog_post in &self.blog_posts { + for blog_post in self.blog_posts.iter().filter(|blog_post| { + match blog_post + .get_index_page() + .expect("Blog posts should have an index page.") + .natter_publish + { + PublishStatus::Full => true, + PublishStatus::Unlisted => true, + PublishStatus::Unpublished => false, + } + }) { for blog_post_page in &blog_post.pages { let output_path = self .output_directory @@ -155,7 +170,21 @@ impl SiteRenderer { // Sort blog posts by date, newest first. let sorted_blog_posts = { - let mut sorted_blog_posts: Vec<_> = self.blog_posts.iter().collect(); + let mut sorted_blog_posts: Vec<_> = self + .blog_posts + .iter() + .filter(|blog_post| { + match blog_post + .get_index_page() + .expect("Blog posts should have an index page.") + .natter_publish + { + PublishStatus::Full => true, + PublishStatus::Unlisted => false, + PublishStatus::Unpublished => false, + } + }) + .collect(); sorted_blog_posts .sort_by_key(|blog_post| (blog_post.get_date(), blog_post.id.as_str())); sorted_blog_posts.reverse(); diff --git a/src/intermediate/blog_post_page.rs b/src/intermediate/blog_post_page.rs index 55a81fe..27069f6 100644 --- a/src/intermediate/blog_post_page.rs +++ b/src/intermediate/blog_post_page.rs @@ -48,6 +48,16 @@ pub(crate) struct BlogPostPage { pub(crate) children: Vec, pub(crate) footnotes: Vec, + + pub(crate) natter_publish: PublishStatus, +} + +#[derive(Debug, Default)] +pub(crate) enum PublishStatus { + #[default] + Full, + Unlisted, + Unpublished, } intermediate!( @@ -93,6 +103,7 @@ intermediate!( date: get_date(original.document), children, footnotes, + natter_publish: get_publish_status(original.document).unwrap_or_default(), }) } ); @@ -129,3 +140,25 @@ pub(crate) fn get_date(document: &organic::types::Document<'_>) -> Option) -> Option { + let publish_string = 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("natter_publish") => + { + Some(kw) + } + _ => None, + }) + .last() + .map(|kw| kw.value); + match publish_string { + Some("full") => Some(PublishStatus::Full), + Some("unlisted") => Some(PublishStatus::Unlisted), + Some("unpublished") => Some(PublishStatus::Unpublished), + Some(status) => panic!("Unrecognized publish status: {}", status), + None => None, + } +} diff --git a/src/intermediate/mod.rs b/src/intermediate/mod.rs index 41950f1..1fc4c0b 100644 --- a/src/intermediate/mod.rs +++ b/src/intermediate/mod.rs @@ -74,6 +74,7 @@ pub(crate) use babel_call::IBabelCall; pub(crate) use blog_post::get_org_files; pub(crate) use blog_post::BlogPost; pub(crate) use blog_post_page::BlogPostPage; +pub(crate) use blog_post_page::PublishStatus; pub(crate) use bold::IBold; pub(crate) use center_block::ICenterBlock; pub(crate) use citation::ICitation; diff --git a/src/intermediate/page.rs b/src/intermediate/page.rs index 6c673c5..a819f1b 100644 --- a/src/intermediate/page.rs +++ b/src/intermediate/page.rs @@ -1,10 +1,12 @@ use super::blog_post_page::get_date; +use super::blog_post_page::get_publish_status; use super::blog_post_page::get_title; use super::footnote_definition::IRealFootnoteDefinition; use super::macros::intermediate; use super::IDocumentElement; use super::IHeading; use super::ISection; +use super::PublishStatus; use crate::error::CustomError; use std::path::PathBuf; @@ -24,6 +26,8 @@ pub(crate) struct IPage { pub(crate) children: Vec, pub(crate) footnotes: Vec, + + pub(crate) natter_publish: PublishStatus, } intermediate!( @@ -69,6 +73,7 @@ intermediate!( date: get_date(original.document), children, footnotes, + natter_publish: get_publish_status(original.document).unwrap_or_default(), }) } );