From 60555999dbc7dc6a132918df28d35dfefd162d32 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sun, 17 Dec 2023 14:04:19 -0500 Subject: [PATCH 01/18] TEMP: Disable the css reset. This is so I can develop the header without having any CSS written yet since the page is a mess without CSS. --- src/intermediate/convert.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/intermediate/convert.rs b/src/intermediate/convert.rs index 596a55c..f830fcf 100644 --- a/src/intermediate/convert.rs +++ b/src/intermediate/convert.rs @@ -23,12 +23,12 @@ pub(crate) fn convert_blog_post_page_to_render_context, F: AsRef< let output_directory = output_directory.as_ref(); let output_file = output_file.as_ref(); let css_files = vec![ - get_web_path( - config, - output_directory, - output_file, - "stylesheet/reset.css", - )?, + // get_web_path( + // config, + // output_directory, + // output_file, + // "stylesheet/reset.css", + // )?, get_web_path(config, output_directory, output_file, "stylesheet/main.css")?, ]; let js_files = vec![get_web_path( From e8ed4a4f4aeb8e8e2a3055127a0f3e29db5a1cfc Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sun, 17 Dec 2023 15:23:40 -0500 Subject: [PATCH 02/18] Initial structure for rendering a blog post stream. --- src/command/build/render.rs | 13 +++++++++++ src/command/build/runner.rs | 1 + src/context/blog_stream.rs | 46 +++++++++++++++++++++++++++++++++++++ src/context/mod.rs | 1 + 4 files changed, 61 insertions(+) create mode 100644 src/context/blog_stream.rs diff --git a/src/command/build/render.rs b/src/command/build/render.rs index 4420ddc..c57a132 100644 --- a/src/command/build/render.rs +++ b/src/command/build/render.rs @@ -89,6 +89,19 @@ impl SiteRenderer { Ok(()) } + pub(crate) async fn render_blog_stream(&self, config: &Config) -> Result<(), CustomError> { + // TODO: Actually render a blog stream to index.html + + // Steps: sort blog posts by date, newest first + // + // Steps: group blog posts based on # of posts per page + // + // Steps: for each group, create a RenderBlogStream + // + // Steps: pass each RenderBlogStream to dust as the context to render index.html and any additional stream pages. + Ok(()) + } + pub(crate) async fn render_stylesheets(&self) -> Result<(), CustomError> { let stylesheet_output_directory = self.output_directory.join("stylesheet"); if !stylesheet_output_directory.exists() { diff --git a/src/command/build/runner.rs b/src/command/build/runner.rs index f41cf74..984dd9b 100644 --- a/src/command/build/runner.rs +++ b/src/command/build/runner.rs @@ -23,6 +23,7 @@ pub(crate) async fn build_site(args: BuildArgs) -> Result<(), CustomError> { stylesheets, ); renderer.render_blog_posts(&config).await?; + renderer.render_blog_stream(&config).await?; renderer.render_stylesheets().await?; Ok(()) diff --git a/src/context/blog_stream.rs b/src/context/blog_stream.rs new file mode 100644 index 0000000..25f21b6 --- /dev/null +++ b/src/context/blog_stream.rs @@ -0,0 +1,46 @@ +use std::path::Path; + +use serde::Serialize; + +use crate::config::Config; +use crate::context::RenderDocumentElement; +use crate::context::RenderRealFootnoteDefinition; +use crate::error::CustomError; +use crate::intermediate::BlogPost; + +use super::GlobalSettings; +use super::PageHeader; + +#[derive(Debug, Serialize)] +#[serde(tag = "type")] +#[serde(rename = "blog_stream")] +pub(crate) struct RenderBlogStream { + global_settings: GlobalSettings, + page_header: Option, + children: Vec, + older_link: Option, + newer_link: Option, +} + +impl RenderBlogStream { + pub(crate) fn new( + config: &Config, + output_directory: &Path, + output_file: &Path, + original: &Vec, + ) -> Result { + todo!() + } +} + +#[derive(Debug, Serialize)] +pub(crate) struct RenderBlogStreamEntry { + /// The title that will be shown visibly on the page. + title: Option, + + self_link: Option, + + children: Vec, + + footnotes: Vec, +} diff --git a/src/context/mod.rs b/src/context/mod.rs index f3a8311..f39cf34 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -2,6 +2,7 @@ mod angle_link; mod ast_node; mod babel_call; mod blog_post_page; +mod blog_stream; mod bold; mod center_block; mod citation; From 0a4376dfb80bd5617bfe831d65347e0ad8d9efed Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sun, 17 Dec 2023 15:31:26 -0500 Subject: [PATCH 03/18] Rename intermediate blog post source file. --- src/intermediate/{definition.rs => blog_post.rs} | 0 src/intermediate/mod.rs | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/intermediate/{definition.rs => blog_post.rs} (100%) diff --git a/src/intermediate/definition.rs b/src/intermediate/blog_post.rs similarity index 100% rename from src/intermediate/definition.rs rename to src/intermediate/blog_post.rs diff --git a/src/intermediate/mod.rs b/src/intermediate/mod.rs index fd969ef..df8f1b2 100644 --- a/src/intermediate/mod.rs +++ b/src/intermediate/mod.rs @@ -1,6 +1,7 @@ mod angle_link; mod ast_node; mod babel_call; +mod blog_post; mod bold; mod center_block; mod citation; @@ -10,7 +11,6 @@ mod code; mod comment; mod comment_block; mod convert; -mod definition; mod diary_sexp; mod document_element; mod drawer; @@ -67,6 +67,7 @@ mod verse_block; pub(crate) use angle_link::IAngleLink; pub(crate) use ast_node::IAstNode; pub(crate) use babel_call::IBabelCall; +pub(crate) use blog_post::BlogPost; pub(crate) use bold::IBold; pub(crate) use center_block::ICenterBlock; pub(crate) use citation::ICitation; @@ -76,7 +77,6 @@ pub(crate) use code::ICode; pub(crate) use comment::IComment; pub(crate) use comment_block::ICommentBlock; pub(crate) use convert::convert_blog_post_page_to_render_context; -pub(crate) use definition::BlogPost; pub(crate) use diary_sexp::IDiarySexp; pub(crate) use document_element::IDocumentElement; pub(crate) use drawer::IDrawer; From fdf84e3d0b4db2c2c10eae0e37de3ff5e8c34e3e Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sun, 17 Dec 2023 15:45:50 -0500 Subject: [PATCH 04/18] Finding the index page. --- src/command/build/render.rs | 4 ++++ src/intermediate/blog_post.rs | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/command/build/render.rs b/src/command/build/render.rs index c57a132..05e130a 100644 --- a/src/command/build/render.rs +++ b/src/command/build/render.rs @@ -99,6 +99,10 @@ impl SiteRenderer { // Steps: for each group, create a RenderBlogStream // // 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()?); + } Ok(()) } diff --git a/src/intermediate/blog_post.rs b/src/intermediate/blog_post.rs index 4b58d8e..245c0aa 100644 --- a/src/intermediate/blog_post.rs +++ b/src/intermediate/blog_post.rs @@ -77,6 +77,30 @@ impl BlogPost { } inner(root_dir.as_ref(), post_dir.as_ref()).await } + + /// Get the date for a blog post. + /// + /// The date is set by the "#+date" export setting. This will + /// first attempt to read the date from an index.org if such a + /// file exists. If that file does not exist or that file does not + /// contain a date export setting, then this will iterate through + /// 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); + } + Ok(()) + } + + /// Get the blog post page for index.org + fn get_index_page(&self) -> Result, CustomError> { + Ok(self + .pages + .iter() + .find(|page| page.path == Path::new("index.org"))) + } } async fn read_file(path: PathBuf) -> std::io::Result<(PathBuf, String)> { From c3482cf1e4a3ebcdc1dabb56f3950c33ad2868a9 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sun, 17 Dec 2023 16:57:37 -0500 Subject: [PATCH 05/18] Chunking the blog posts for the stream. --- src/command/build/render.rs | 26 ++++++++++++++++++++++++-- src/config/full.rs | 9 +++++++++ src/config/raw.rs | 15 +++++++++++++++ src/error/error.rs | 7 +++++++ src/intermediate/blog_post.rs | 23 +++++++++++++++-------- src/intermediate/page.rs | 14 ++++++++++++++ 6 files changed, 84 insertions(+), 10 deletions(-) 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()) +} From 2ba4a5e3d7decf67e1c86fd0bd7933389d9a7f67 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sun, 17 Dec 2023 17:16:26 -0500 Subject: [PATCH 06/18] Generate newer and older links. --- src/command/build/render.rs | 38 +++++++++++++++++++++++++++++++++++-- src/context/blog_stream.rs | 2 +- src/intermediate/convert.rs | 2 +- src/intermediate/mod.rs | 1 + 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/command/build/render.rs b/src/command/build/render.rs index 55a56f4..a40f158 100644 --- a/src/command/build/render.rs +++ b/src/command/build/render.rs @@ -7,6 +7,7 @@ use include_dir::Dir; use crate::config::Config; use crate::error::CustomError; use crate::intermediate::convert_blog_post_page_to_render_context; +use crate::intermediate::get_web_path; use crate::intermediate::BlogPost; use crate::render::DusterRenderer; use crate::render::RendererIntegration; @@ -122,8 +123,41 @@ impl SiteRenderer { // For each group, create a RenderBlogStream. let num_stream_pages = stream_chunks.len(); - for chunk in stream_chunks { - // foo + for (page_num, chunk) in stream_chunks.into_iter().enumerate() { + let output_file = if page_num == 0 { + self.output_directory.join("index.html") + } else { + self.output_directory + .join("stream") + .join(format!("{}.html", page_num)) + }; + let newer_link = if page_num == 0 { + None + } else if page_num == 1 { + Some(get_web_path( + config, + &self.output_directory, + &output_file, + "index.html", + )?) + } else { + Some(get_web_path( + config, + &self.output_directory, + &output_file, + format!("stream/{}.html", page_num - 1), + )?) + }; + let older_link = if page_num == (num_stream_pages - 1) { + None + } else { + Some(get_web_path( + config, + &self.output_directory, + &output_file, + format!("stream/{}.html", page_num + 1), + )?) + }; } Ok(()) } diff --git a/src/context/blog_stream.rs b/src/context/blog_stream.rs index 25f21b6..f0b2846 100644 --- a/src/context/blog_stream.rs +++ b/src/context/blog_stream.rs @@ -27,7 +27,7 @@ impl RenderBlogStream { config: &Config, output_directory: &Path, output_file: &Path, - original: &Vec, + original: &[&BlogPost], ) -> Result { todo!() } diff --git a/src/intermediate/convert.rs b/src/intermediate/convert.rs index f830fcf..49bc45d 100644 --- a/src/intermediate/convert.rs +++ b/src/intermediate/convert.rs @@ -90,7 +90,7 @@ pub(crate) fn convert_blog_post_page_to_render_context, F: AsRef< Ok(ret) } -fn get_web_path, F: AsRef, P: AsRef>( +pub(crate) fn get_web_path, F: AsRef, P: AsRef>( config: &Config, output_directory: D, containing_file: F, diff --git a/src/intermediate/mod.rs b/src/intermediate/mod.rs index df8f1b2..2f165a2 100644 --- a/src/intermediate/mod.rs +++ b/src/intermediate/mod.rs @@ -77,6 +77,7 @@ pub(crate) use code::ICode; pub(crate) use comment::IComment; pub(crate) use comment_block::ICommentBlock; pub(crate) use convert::convert_blog_post_page_to_render_context; +pub(crate) use convert::get_web_path; pub(crate) use diary_sexp::IDiarySexp; pub(crate) use document_element::IDocumentElement; pub(crate) use drawer::IDrawer; From cbe2010407becc0615e28ac9ae32424a2c3d537f Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sun, 17 Dec 2023 17:26:15 -0500 Subject: [PATCH 07/18] Invoke dust to render the stream pages. At this point the render_blog_stream function is done, but RenderBlogStream::new needs to be implemented to actually generate the render context. The body of this function should be similar to convert_blog_post_page_to_render_context. --- src/command/build/render.rs | 36 ++++++++++++++++++++++++++---------- src/context/blog_stream.rs | 2 ++ src/context/mod.rs | 1 + 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/command/build/render.rs b/src/command/build/render.rs index a40f158..06eddb3 100644 --- a/src/command/build/render.rs +++ b/src/command/build/render.rs @@ -5,6 +5,7 @@ use include_dir::include_dir; use include_dir::Dir; use crate::config::Config; +use crate::context::RenderBlogStream; use crate::error::CustomError; use crate::intermediate::convert_blog_post_page_to_render_context; use crate::intermediate::get_web_path; @@ -35,7 +36,7 @@ impl SiteRenderer { } } - pub(crate) async fn render_blog_posts(&self, config: &Config) -> Result<(), CustomError> { + fn init_renderer_integration(&self) -> Result, CustomError> { let mut renderer_integration = DusterRenderer::new(); let sources: Vec<_> = MAIN_TEMPLATES @@ -63,6 +64,12 @@ impl SiteRenderer { renderer_integration.load_template(name, contents)?; } + Ok(renderer_integration) + } + + 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_page in &blog_post.pages { let output_path = self @@ -91,15 +98,7 @@ impl SiteRenderer { } pub(crate) async fn render_blog_stream(&self, config: &Config) -> Result<(), CustomError> { - // TODO: Actually render a blog stream to index.html - - // Steps: sort blog posts by date, newest first - // - // Steps: group blog posts based on # of posts per page - // - // Steps: for each group, create a RenderBlogStream - // - // Steps: pass each RenderBlogStream to dust as the context to render index.html and any additional stream pages. + let renderer_integration = self.init_renderer_integration()?; // Sort blog posts by date, newest first. let sorted_blog_posts = { @@ -158,6 +157,23 @@ impl SiteRenderer { format!("stream/{}.html", page_num + 1), )?) }; + + let blog_stream = RenderBlogStream::new( + config, + self.output_directory.as_path(), + output_file.as_path(), + chunk, + older_link, + newer_link, + )?; + + // Pass each RenderBlogStream to dust as the context to render index.html and any additional stream pages. + let rendered_output = renderer_integration.render(blog_stream)?; + let parent_directory = output_file + .parent() + .ok_or("Output file should have a containing directory.")?; + tokio::fs::create_dir_all(parent_directory).await?; + tokio::fs::write(output_file, rendered_output).await?; } Ok(()) } diff --git a/src/context/blog_stream.rs b/src/context/blog_stream.rs index f0b2846..f476f43 100644 --- a/src/context/blog_stream.rs +++ b/src/context/blog_stream.rs @@ -28,6 +28,8 @@ impl RenderBlogStream { output_directory: &Path, output_file: &Path, original: &[&BlogPost], + older_link: Option, + newer_link: Option, ) -> Result { todo!() } diff --git a/src/context/mod.rs b/src/context/mod.rs index f39cf34..76a0921 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -65,6 +65,7 @@ mod verbatim; mod verse_block; pub(crate) use blog_post_page::RenderBlogPostPage; +pub(crate) use blog_stream::RenderBlogStream; pub(crate) use document_element::RenderDocumentElement; pub(crate) use element::RenderElement; pub(crate) use footnote_definition::RenderRealFootnoteDefinition; From 53cd55932b9f85a7dd0c8def98a5c2be8982100f Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Tue, 19 Dec 2023 10:47:03 -0500 Subject: [PATCH 08/18] Implement RenderBlogStream::new. I still need to implement RenderBlogStreamEntry::new. --- src/context/blog_stream.rs | 52 +++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/src/context/blog_stream.rs b/src/context/blog_stream.rs index f476f43..31c78c9 100644 --- a/src/context/blog_stream.rs +++ b/src/context/blog_stream.rs @@ -6,6 +6,7 @@ use crate::config::Config; use crate::context::RenderDocumentElement; use crate::context::RenderRealFootnoteDefinition; use crate::error::CustomError; +use crate::intermediate::get_web_path; use crate::intermediate::BlogPost; use super::GlobalSettings; @@ -31,7 +32,45 @@ impl RenderBlogStream { older_link: Option, newer_link: Option, ) -> Result { - todo!() + let css_files = vec![ + // get_web_path( + // config, + // output_directory, + // output_file, + // "stylesheet/reset.css", + // )?, + get_web_path(config, output_directory, output_file, "stylesheet/main.css")?, + ]; + let js_files = vec![get_web_path( + config, + output_directory, + output_file, + "blog_post.js", + )?]; + let global_settings = GlobalSettings::new( + config.get_site_title().map(str::to_string), + css_files, + js_files, + ); + let page_header = PageHeader::new( + config.get_site_title().map(str::to_string), + Some(get_web_path(config, output_directory, output_file, "")?), + ); + + let children = original + .into_iter() + .map(|blog_post| { + RenderBlogStreamEntry::new(config, output_directory, output_file, blog_post) + }) + .collect::, _>>()?; + + Ok(RenderBlogStream { + global_settings, + page_header: Some(page_header), + children, + older_link, + newer_link, + }) } } @@ -46,3 +85,14 @@ pub(crate) struct RenderBlogStreamEntry { footnotes: Vec, } + +impl RenderBlogStreamEntry { + pub(crate) fn new( + config: &Config, + output_directory: &Path, + output_file: &Path, + original: &BlogPost, + ) -> Result { + todo!() + } +} From 6511115b95dfa165fb5d76a9a0c8d12be2dcbb0a Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Tue, 19 Dec 2023 10:59:34 -0500 Subject: [PATCH 09/18] Implement a flawed version of RenderBlogStreamEntry::new. There are some shortcomings in this implementation listed in the comments, but this is the general structure. --- src/context/blog_stream.rs | 29 ++++++++++++++++++++++++++++- src/intermediate/blog_post.rs | 2 +- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/context/blog_stream.rs b/src/context/blog_stream.rs index 31c78c9..5c2c7a9 100644 --- a/src/context/blog_stream.rs +++ b/src/context/blog_stream.rs @@ -93,6 +93,33 @@ impl RenderBlogStreamEntry { output_file: &Path, original: &BlogPost, ) -> Result { - todo!() + // TODO: This link is probably wrong. + let link_to_blog_post = get_web_path( + config, + output_directory, + output_file, + output_file.strip_prefix(output_directory)?, + )?; + + // TODO: Should I guess an index page instead of erroring out? + let index_page = original + .get_index_page() + .ok_or_else(|| format!("Blog post {} needs an index page.", original.id))?; + + let title = index_page.title.clone(); + + // TODO: Handle footnotes. + let children = index_page + .children + .iter() + .map(|child| RenderDocumentElement::new(config, output_directory, output_file, child)) + .collect::, _>>()?; + + Ok(RenderBlogStreamEntry { + title, + self_link: Some(link_to_blog_post), + children, + footnotes: Vec::new(), + }) } } diff --git a/src/intermediate/blog_post.rs b/src/intermediate/blog_post.rs index 865528b..52c38ef 100644 --- a/src/intermediate/blog_post.rs +++ b/src/intermediate/blog_post.rs @@ -103,7 +103,7 @@ impl BlogPost { } /// Get the blog post page for index.org - fn get_index_page(&self) -> Option<&BlogPostPage> { + pub(crate) fn get_index_page(&self) -> Option<&BlogPostPage> { self.pages .iter() .find(|page| page.path == Path::new("index.org")) From 94d9a95967a27167c0d7b343df240b0bf0d49487 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Tue, 19 Dec 2023 14:13:29 -0500 Subject: [PATCH 10/18] Add a basic template for the blog stream page. --- .../templates/html/blog_stream.dust | 31 ++++++++++++++++++ default_environment/templates/html/main.dust | 1 + src/context/blog_stream.rs | 32 ++++++++++++++++--- 3 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 default_environment/templates/html/blog_stream.dust diff --git a/default_environment/templates/html/blog_stream.dust b/default_environment/templates/html/blog_stream.dust new file mode 100644 index 0000000..d0b5caf --- /dev/null +++ b/default_environment/templates/html/blog_stream.dust @@ -0,0 +1,31 @@ +
+ {#.children} +
+
+ {?.title}{?.self_link}{.title}{:else}
{.title}
{/.self_link}{/.title} + {! TODO: date? !} +
+ + {! TODO: Table of contents? !} + +
+ {#.children} + {>document_element/} + {/.children} + + {?.footnotes} +

Footnotes:

+ {#.footnotes} + {>real_footnote_definition/} + {/.footnotes} + {/.footnotes} +
+
+ {/.children} + {#.stream_pagination} +
+ {?.older_link}Older{/.older_link} + {?.newer_link}Newer{/.newer_link} +
+ {/.stream_pagination} +
diff --git a/default_environment/templates/html/main.dust b/default_environment/templates/html/main.dust index 375d21b..9f0f5ed 100644 --- a/default_environment/templates/html/main.dust +++ b/default_environment/templates/html/main.dust @@ -11,6 +11,7 @@
{@select key=.type} {@eq value="blog_post_page"}{>blog_post_page/}{/eq} + {@eq value="blog_stream"}{>blog_stream/}{/eq} {@none}{!TODO: make this panic!}ERROR: Unrecognized page content type{/none} {/select}
diff --git a/src/context/blog_stream.rs b/src/context/blog_stream.rs index 5c2c7a9..3cab6dc 100644 --- a/src/context/blog_stream.rs +++ b/src/context/blog_stream.rs @@ -19,8 +19,7 @@ pub(crate) struct RenderBlogStream { global_settings: GlobalSettings, page_header: Option, children: Vec, - older_link: Option, - newer_link: Option, + stream_pagination: Option, } impl RenderBlogStream { @@ -64,12 +63,17 @@ impl RenderBlogStream { }) .collect::, _>>()?; + let stream_pagination = if older_link.is_some() || newer_link.is_some() { + Some(RenderBlogStreamPagination::new(older_link, newer_link)?) + } else { + None + }; + Ok(RenderBlogStream { global_settings, page_header: Some(page_header), children, - older_link, - newer_link, + stream_pagination, }) } } @@ -87,7 +91,7 @@ pub(crate) struct RenderBlogStreamEntry { } impl RenderBlogStreamEntry { - pub(crate) fn new( + fn new( config: &Config, output_directory: &Path, output_file: &Path, @@ -123,3 +127,21 @@ impl RenderBlogStreamEntry { }) } } + +#[derive(Debug, Serialize)] +pub(crate) struct RenderBlogStreamPagination { + older_link: Option, + newer_link: Option, +} + +impl RenderBlogStreamPagination { + fn new( + older_link: Option, + newer_link: Option, + ) -> Result { + Ok(RenderBlogStreamPagination { + older_link, + newer_link, + }) + } +} From cb3278aba5feaf2e2e0e6728ccc96b852fbd115a Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Tue, 19 Dec 2023 14:54:12 -0500 Subject: [PATCH 11/18] Create a struct that will combine all the context for converting intermediate objects into the dust render context. --- src/config/full.rs | 1 + src/config/raw.rs | 4 ++-- src/context/mod.rs | 1 + src/context/render_context.rs | 27 +++++++++++++++++++++++++++ 4 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 src/context/render_context.rs diff --git a/src/config/full.rs b/src/config/full.rs index fbfa5f8..ce5ce3c 100644 --- a/src/config/full.rs +++ b/src/config/full.rs @@ -8,6 +8,7 @@ use crate::error::CustomError; use super::raw::RawConfig; /// This is the config struct used by most of the code, which is an interpreted version of the RawConfig struct which is the raw disk-representation of the config. +#[derive(Debug)] pub(crate) struct Config { raw: RawConfig, config_path: PathBuf, diff --git a/src/config/raw.rs b/src/config/raw.rs index 2e69d63..29cb4b9 100644 --- a/src/config/raw.rs +++ b/src/config/raw.rs @@ -2,7 +2,7 @@ use serde::Deserialize; use serde::Serialize; /// This is the struct for the writer.toml config file that ends up in each site's root directory. -#[derive(Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize)] pub(crate) struct RawConfig { pub(super) site_title: Option, author: Option, @@ -25,7 +25,7 @@ impl Default for RawConfig { } } -#[derive(Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize)] pub(crate) struct RawConfigStream { pub(super) entries_per_page: Option, } diff --git a/src/context/mod.rs b/src/context/mod.rs index 76a0921..abaec4d 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -48,6 +48,7 @@ mod quote_block; mod radio_link; mod radio_target; mod regular_link; +mod render_context; mod section; mod special_block; mod src_block; diff --git a/src/context/render_context.rs b/src/context/render_context.rs new file mode 100644 index 0000000..4c8fcb7 --- /dev/null +++ b/src/context/render_context.rs @@ -0,0 +1,27 @@ +use std::path::Path; + +use crate::config::Config; +use crate::error::CustomError; + +/// The supporting information used for converting the intermediate representation into the dust context for rendering. +#[derive(Debug, Clone)] +pub(crate) struct RenderContext<'intermediate> { + pub(crate) config: &'intermediate Config, + // TODO: Perhaps rename to output_root_directory. + pub(crate) output_directory: &'intermediate Path, + pub(crate) output_file: &'intermediate Path, +} + +impl<'intermediate> RenderContext<'intermediate> { + pub(crate) fn new( + config: &'intermediate Config, + output_directory: &'intermediate Path, + output_file: &'intermediate Path, + ) -> Result, CustomError> { + Ok(RenderContext { + config, + output_directory, + output_file, + }) + } +} From add267d61675c7d185a606e02882105279cb9946 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Tue, 19 Dec 2023 15:42:37 -0500 Subject: [PATCH 12/18] Switch over to using the render context in render calls. --- src/command/build/render.rs | 22 +-- src/context/angle_link.rs | 4 +- src/context/ast_node.rs | 200 +++++++--------------- src/context/babel_call.rs | 4 +- src/context/blog_post_page.rs | 110 ++++++++++-- src/context/blog_stream.rs | 140 +++++++++------- src/context/bold.rs | 37 ++--- src/context/center_block.rs | 4 +- src/context/citation.rs | 4 +- src/context/citation_reference.rs | 4 +- src/context/clock.rs | 4 +- src/context/code.rs | 22 +-- src/context/comment.rs | 4 +- src/context/comment_block.rs | 4 +- src/context/diary_sexp.rs | 4 +- src/context/document_element.rs | 12 +- src/context/drawer.rs | 4 +- src/context/dynamic_block.rs | 4 +- src/context/element.rs | 226 +++++++++++-------------- src/context/entity.rs | 22 +-- src/context/example_block.rs | 4 +- src/context/export_block.rs | 4 +- src/context/export_snippet.rs | 4 +- src/context/fixed_width_area.rs | 4 +- src/context/footnote_definition.rs | 10 +- src/context/footnote_reference.rs | 8 +- src/context/heading.rs | 64 +++---- src/context/horizontal_rule.rs | 4 +- src/context/inline_babel_call.rs | 4 +- src/context/inline_source_block.rs | 8 +- src/context/italic.rs | 37 ++--- src/context/keyword.rs | 4 +- src/context/latex_environment.rs | 4 +- src/context/latex_fragment.rs | 8 +- src/context/line_break.rs | 4 +- src/context/macros.rs | 14 +- src/context/mod.rs | 3 + src/context/object.rs | 259 ++++++++++++----------------- src/context/org_macro.rs | 4 +- src/context/paragraph.rs | 37 ++--- src/context/plain_link.rs | 4 +- src/context/plain_list.rs | 53 +++--- src/context/plain_list_item.rs | 22 +-- src/context/plain_text.rs | 22 +-- src/context/planning.rs | 4 +- src/context/property_drawer.rs | 4 +- src/context/quote_block.rs | 37 ++--- src/context/radio_link.rs | 4 +- src/context/radio_target.rs | 4 +- src/context/regular_link.rs | 43 ++--- src/context/section.rs | 37 ++--- src/context/special_block.rs | 4 +- src/context/src_block.rs | 22 +-- src/context/statistics_cookie.rs | 4 +- src/context/strike_through.rs | 15 +- src/context/subscript.rs | 4 +- src/context/superscript.rs | 4 +- src/context/table.rs | 37 ++--- src/context/table_cell.rs | 37 ++--- src/context/table_row.rs | 37 ++--- src/context/target.rs | 22 +-- src/context/timestamp.rs | 4 +- src/context/underline.rs | 37 ++--- src/context/verbatim.rs | 22 +-- src/context/verse_block.rs | 4 +- src/intermediate/convert.rs | 85 ---------- src/intermediate/mod.rs | 1 - 67 files changed, 699 insertions(+), 1197 deletions(-) diff --git a/src/command/build/render.rs b/src/command/build/render.rs index 06eddb3..de44026 100644 --- a/src/command/build/render.rs +++ b/src/command/build/render.rs @@ -5,9 +5,12 @@ use include_dir::include_dir; use include_dir::Dir; use crate::config::Config; +use crate::context::RenderBlogPostPage; +use crate::context::RenderBlogPostPageInput; use crate::context::RenderBlogStream; +use crate::context::RenderBlogStreamInput; +use crate::context::RenderContext; use crate::error::CustomError; -use crate::intermediate::convert_blog_post_page_to_render_context; use crate::intermediate::get_web_path; use crate::intermediate::BlogPost; use crate::render::DusterRenderer; @@ -78,13 +81,13 @@ impl SiteRenderer { .join(&blog_post.id) .join(blog_post_page.get_output_path()); - let render_context = convert_blog_post_page_to_render_context( + let convert_input = RenderBlogPostPageInput::new(blog_post, blog_post_page); + let render_context = RenderContext::new( config, - &self.output_directory, - &output_path, - blog_post, - blog_post_page, + self.output_directory.as_path(), + output_path.as_path(), )?; + let render_context = RenderBlogPostPage::new(render_context, &convert_input)?; let rendered_output = renderer_integration.render(render_context)?; let parent_directory = output_path .parent() @@ -158,14 +161,13 @@ impl SiteRenderer { )?) }; - let blog_stream = RenderBlogStream::new( + let convert_input = RenderBlogStreamInput::new(chunk, older_link, newer_link); + let render_context = RenderContext::new( config, self.output_directory.as_path(), output_file.as_path(), - chunk, - older_link, - newer_link, )?; + let blog_stream = RenderBlogStream::new(render_context, &convert_input)?; // Pass each RenderBlogStream to dust as the context to render index.html and any additional stream pages. let rendered_output = renderer_integration.render(blog_stream)?; diff --git a/src/context/angle_link.rs b/src/context/angle_link.rs index bb7fcb2..f456e60 100644 --- a/src/context/angle_link.rs +++ b/src/context/angle_link.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IAngleLink; diff --git a/src/context/ast_node.rs b/src/context/ast_node.rs index 7a2ffcd..c466297 100644 --- a/src/context/ast_node.rs +++ b/src/context/ast_node.rs @@ -1,8 +1,5 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; use crate::error::CustomError; use crate::intermediate::IAstNode; @@ -45,6 +42,7 @@ use super::quote_block::RenderQuoteBlock; use super::radio_link::RenderRadioLink; use super::radio_target::RenderRadioTarget; use super::regular_link::RenderRegularLink; +use super::render_context::RenderContext; use super::special_block::RenderSpecialBlock; use super::src_block::RenderSrcBlock; use super::statistics_cookie::RenderStatisticsCookie; @@ -121,285 +119,207 @@ pub(crate) enum RenderAstNode { pub(crate) trait IntoRenderAstNode { fn into_render_ast_node( &self, - config: &Config, - output_directory: &Path, - output_file: &Path, + render_context: RenderContext<'_>, ) -> Result; } impl IntoRenderAstNode for IAstNode { fn into_render_ast_node( &self, - config: &Config, - output_directory: &Path, - output_file: &Path, + render_context: RenderContext<'_>, ) -> Result { match self { IAstNode::Heading(inner) => Ok(RenderAstNode::Heading(RenderHeading::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::Section(inner) => Ok(RenderAstNode::Section(RenderSection::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::Paragraph(inner) => Ok(RenderAstNode::Paragraph(RenderParagraph::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::PlainList(inner) => Ok(RenderAstNode::PlainList(RenderPlainList::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::CenterBlock(inner) => Ok(RenderAstNode::CenterBlock(RenderCenterBlock::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::QuoteBlock(inner) => Ok(RenderAstNode::QuoteBlock(RenderQuoteBlock::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::SpecialBlock(inner) => Ok(RenderAstNode::SpecialBlock( - RenderSpecialBlock::new(config, output_directory, output_file, inner)?, + RenderSpecialBlock::new(render_context, inner)?, )), IAstNode::DynamicBlock(inner) => Ok(RenderAstNode::DynamicBlock( - RenderDynamicBlock::new(config, output_directory, output_file, inner)?, + RenderDynamicBlock::new(render_context, inner)?, )), IAstNode::FootnoteDefinition(inner) => Ok(RenderAstNode::FootnoteDefinition( - RenderFootnoteDefinition::new(config, output_directory, output_file, inner)?, + RenderFootnoteDefinition::new(render_context, inner)?, )), IAstNode::Comment(inner) => Ok(RenderAstNode::Comment(RenderComment::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::Drawer(inner) => Ok(RenderAstNode::Drawer(RenderDrawer::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::PropertyDrawer(inner) => Ok(RenderAstNode::PropertyDrawer( - RenderPropertyDrawer::new(config, output_directory, output_file, inner)?, + RenderPropertyDrawer::new(render_context, inner)?, )), IAstNode::Table(inner) => Ok(RenderAstNode::Table(RenderTable::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::VerseBlock(inner) => Ok(RenderAstNode::VerseBlock(RenderVerseBlock::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::CommentBlock(inner) => Ok(RenderAstNode::CommentBlock( - RenderCommentBlock::new(config, output_directory, output_file, inner)?, + RenderCommentBlock::new(render_context, inner)?, )), IAstNode::ExampleBlock(inner) => Ok(RenderAstNode::ExampleBlock( - RenderExampleBlock::new(config, output_directory, output_file, inner)?, + RenderExampleBlock::new(render_context, inner)?, )), IAstNode::ExportBlock(inner) => Ok(RenderAstNode::ExportBlock(RenderExportBlock::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::SrcBlock(inner) => Ok(RenderAstNode::SrcBlock(RenderSrcBlock::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::Clock(inner) => Ok(RenderAstNode::Clock(RenderClock::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::DiarySexp(inner) => Ok(RenderAstNode::DiarySexp(RenderDiarySexp::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::Planning(inner) => Ok(RenderAstNode::Planning(RenderPlanning::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::FixedWidthArea(inner) => Ok(RenderAstNode::FixedWidthArea( - RenderFixedWidthArea::new(config, output_directory, output_file, inner)?, + RenderFixedWidthArea::new(render_context, inner)?, )), IAstNode::HorizontalRule(inner) => Ok(RenderAstNode::HorizontalRule( - RenderHorizontalRule::new(config, output_directory, output_file, inner)?, + RenderHorizontalRule::new(render_context, inner)?, )), IAstNode::Keyword(inner) => Ok(RenderAstNode::Keyword(RenderKeyword::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::BabelCall(inner) => Ok(RenderAstNode::BabelCall(RenderBabelCall::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::LatexEnvironment(inner) => Ok(RenderAstNode::LatexEnvironment( - RenderLatexEnvironment::new(config, output_directory, output_file, inner)?, + RenderLatexEnvironment::new(render_context, inner)?, )), - IAstNode::Bold(inner) => Ok(RenderAstNode::Bold(RenderBold::new( - config, - output_directory, - output_file, - inner, - )?)), + IAstNode::Bold(inner) => { + Ok(RenderAstNode::Bold(RenderBold::new(render_context, inner)?)) + } IAstNode::Italic(inner) => Ok(RenderAstNode::Italic(RenderItalic::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::Underline(inner) => Ok(RenderAstNode::Underline(RenderUnderline::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::StrikeThrough(inner) => Ok(RenderAstNode::StrikeThrough( - RenderStrikeThrough::new(config, output_directory, output_file, inner)?, + RenderStrikeThrough::new(render_context, inner)?, )), - IAstNode::Code(inner) => Ok(RenderAstNode::Code(RenderCode::new( - config, - output_directory, - output_file, - inner, - )?)), + IAstNode::Code(inner) => { + Ok(RenderAstNode::Code(RenderCode::new(render_context, inner)?)) + } IAstNode::Verbatim(inner) => Ok(RenderAstNode::Verbatim(RenderVerbatim::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::PlainText(inner) => Ok(RenderAstNode::PlainText(RenderPlainText::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::RegularLink(inner) => Ok(RenderAstNode::RegularLink(RenderRegularLink::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::RadioLink(inner) => Ok(RenderAstNode::RadioLink(RenderRadioLink::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::RadioTarget(inner) => Ok(RenderAstNode::RadioTarget(RenderRadioTarget::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::PlainLink(inner) => Ok(RenderAstNode::PlainLink(RenderPlainLink::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::AngleLink(inner) => Ok(RenderAstNode::AngleLink(RenderAngleLink::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::OrgMacro(inner) => Ok(RenderAstNode::OrgMacro(RenderOrgMacro::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::Entity(inner) => Ok(RenderAstNode::Entity(RenderEntity::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::LatexFragment(inner) => Ok(RenderAstNode::LatexFragment( - RenderLatexFragment::new(config, output_directory, output_file, inner)?, + RenderLatexFragment::new(render_context, inner)?, )), IAstNode::ExportSnippet(inner) => Ok(RenderAstNode::ExportSnippet( - RenderExportSnippet::new(config, output_directory, output_file, inner)?, + RenderExportSnippet::new(render_context, inner)?, )), IAstNode::FootnoteReference(inner) => Ok(RenderAstNode::FootnoteReference( - RenderFootnoteReference::new(config, output_directory, output_file, inner)?, + RenderFootnoteReference::new(render_context, inner)?, )), IAstNode::Citation(inner) => Ok(RenderAstNode::Citation(RenderCitation::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::CitationReference(inner) => Ok(RenderAstNode::CitationReference( - RenderCitationReference::new(config, output_directory, output_file, inner)?, + RenderCitationReference::new(render_context, inner)?, )), IAstNode::InlineBabelCall(inner) => Ok(RenderAstNode::InlineBabelCall( - RenderInlineBabelCall::new(config, output_directory, output_file, inner)?, + RenderInlineBabelCall::new(render_context, inner)?, )), IAstNode::InlineSourceBlock(inner) => Ok(RenderAstNode::InlineSourceBlock( - RenderInlineSourceBlock::new(config, output_directory, output_file, inner)?, + RenderInlineSourceBlock::new(render_context, inner)?, )), IAstNode::LineBreak(inner) => Ok(RenderAstNode::LineBreak(RenderLineBreak::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::Target(inner) => Ok(RenderAstNode::Target(RenderTarget::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::StatisticsCookie(inner) => Ok(RenderAstNode::StatisticsCookie( - RenderStatisticsCookie::new(config, output_directory, output_file, inner)?, + RenderStatisticsCookie::new(render_context, inner)?, )), IAstNode::Subscript(inner) => Ok(RenderAstNode::Subscript(RenderSubscript::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::Superscript(inner) => Ok(RenderAstNode::Superscript(RenderSuperscript::new( - config, - output_directory, - output_file, + render_context, inner, )?)), IAstNode::Timestamp(inner) => Ok(RenderAstNode::Timestamp(RenderTimestamp::new( - config, - output_directory, - output_file, + render_context, inner, )?)), } diff --git a/src/context/babel_call.rs b/src/context/babel_call.rs index f376b36..9c1fa0d 100644 --- a/src/context/babel_call.rs +++ b/src/context/babel_call.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IBabelCall; diff --git a/src/context/blog_post_page.rs b/src/context/blog_post_page.rs index b42df31..20ae9d5 100644 --- a/src/context/blog_post_page.rs +++ b/src/context/blog_post_page.rs @@ -1,10 +1,29 @@ use serde::Serialize; +use super::render_context::RenderContext; +use crate::error::CustomError; +use crate::intermediate::get_web_path; +use crate::intermediate::BlogPost; +use crate::intermediate::BlogPostPage; + use super::footnote_definition::RenderRealFootnoteDefinition; +use super::macros::render; use super::GlobalSettings; use super::PageHeader; use super::RenderDocumentElement; +#[derive(Debug)] +pub(crate) struct RenderBlogPostPageInput<'a> { + post: &'a BlogPost, + page: &'a BlogPostPage, +} + +impl<'a> RenderBlogPostPageInput<'a> { + pub(crate) fn new(post: &'a BlogPost, page: &'a BlogPostPage) -> RenderBlogPostPageInput<'a> { + RenderBlogPostPageInput { post, page } + } +} + #[derive(Debug, Serialize)] #[serde(tag = "type")] #[serde(rename = "blog_post_page")] @@ -23,23 +42,82 @@ pub(crate) struct RenderBlogPostPage { footnotes: Vec, } -impl RenderBlogPostPage { - // TODO: Maybe these settings should be moved into a common struct so this can have the same type signature as the others. - pub(crate) fn new( - global_settings: GlobalSettings, - page_header: Option, - title: Option, - self_link: Option, - children: Vec, - footnotes: Vec, - ) -> RenderBlogPostPage { - RenderBlogPostPage { +render!( + RenderBlogPostPage, + RenderBlogPostPageInput, + original, + render_context, + { + let css_files = vec![ + // get_web_path( + // config, + // output_directory, + // output_file, + // "stylesheet/reset.css", + // )?, + get_web_path( + render_context.config, + render_context.output_directory, + render_context.output_file, + "stylesheet/main.css", + )?, + ]; + let js_files = vec![get_web_path( + render_context.config, + render_context.output_directory, + render_context.output_file, + "blog_post.js", + )?]; + let global_settings = GlobalSettings::new(original.page.title.clone(), css_files, js_files); + let page_header = PageHeader::new( + render_context.config.get_site_title().map(str::to_string), + Some(get_web_path( + render_context.config, + render_context.output_directory, + render_context.output_file, + "", + )?), + ); + let link_to_blog_post = get_web_path( + render_context.config, + render_context.output_directory, + render_context.output_file, + render_context + .output_file + .strip_prefix(render_context.output_directory)?, + )?; + + let children = { + let mut children = Vec::new(); + + for child in original.page.children.iter() { + children.push(RenderDocumentElement::new(render_context.clone(), child)?); + } + + children + }; + + let footnotes = { + let mut ret = Vec::new(); + + for footnote in original.page.footnotes.iter() { + ret.push(RenderRealFootnoteDefinition::new( + render_context.clone(), + footnote, + )?); + } + + ret + }; + + let ret = RenderBlogPostPage { global_settings, - page_header, - title, - self_link, + page_header: Some(page_header), + title: original.page.title.clone(), + self_link: Some(link_to_blog_post), children, footnotes, - } + }; + Ok(ret) } -} +); diff --git a/src/context/blog_stream.rs b/src/context/blog_stream.rs index 3cab6dc..aefe096 100644 --- a/src/context/blog_stream.rs +++ b/src/context/blog_stream.rs @@ -1,8 +1,7 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::macros::render; +use super::render_context::RenderContext; use crate::context::RenderDocumentElement; use crate::context::RenderRealFootnoteDefinition; use crate::error::CustomError; @@ -12,6 +11,27 @@ use crate::intermediate::BlogPost; use super::GlobalSettings; use super::PageHeader; +#[derive(Debug)] +pub(crate) struct RenderBlogStreamInput<'a, 'b> { + original: &'a [&'b BlogPost], + older_link: Option, + newer_link: Option, +} + +impl<'a, 'b> RenderBlogStreamInput<'a, 'b> { + pub(crate) fn new( + original: &'a [&'b BlogPost], + older_link: Option, + newer_link: Option, + ) -> RenderBlogStreamInput<'a, 'b> { + RenderBlogStreamInput { + original, + older_link, + newer_link, + } + } +} + #[derive(Debug, Serialize)] #[serde(tag = "type")] #[serde(rename = "blog_stream")] @@ -22,15 +42,12 @@ pub(crate) struct RenderBlogStream { stream_pagination: Option, } -impl RenderBlogStream { - pub(crate) fn new( - config: &Config, - output_directory: &Path, - output_file: &Path, - original: &[&BlogPost], - older_link: Option, - newer_link: Option, - ) -> Result { +render!( + RenderBlogStream, + RenderBlogStreamInput, + original, + render_context, + { let css_files = vec![ // get_web_path( // config, @@ -38,33 +55,45 @@ impl RenderBlogStream { // output_file, // "stylesheet/reset.css", // )?, - get_web_path(config, output_directory, output_file, "stylesheet/main.css")?, + get_web_path( + render_context.config, + render_context.output_directory, + render_context.output_file, + "stylesheet/main.css", + )?, ]; let js_files = vec![get_web_path( - config, - output_directory, - output_file, + render_context.config, + render_context.output_directory, + render_context.output_file, "blog_post.js", )?]; let global_settings = GlobalSettings::new( - config.get_site_title().map(str::to_string), + render_context.config.get_site_title().map(str::to_string), css_files, js_files, ); let page_header = PageHeader::new( - config.get_site_title().map(str::to_string), - Some(get_web_path(config, output_directory, output_file, "")?), + render_context.config.get_site_title().map(str::to_string), + Some(get_web_path( + render_context.config, + render_context.output_directory, + render_context.output_file, + "", + )?), ); let children = original + .original .into_iter() - .map(|blog_post| { - RenderBlogStreamEntry::new(config, output_directory, output_file, blog_post) - }) + .map(|blog_post| RenderBlogStreamEntry::new(render_context.clone(), blog_post)) .collect::, _>>()?; - let stream_pagination = if older_link.is_some() || newer_link.is_some() { - Some(RenderBlogStreamPagination::new(older_link, newer_link)?) + let stream_pagination = if original.older_link.is_some() || original.newer_link.is_some() { + Some(RenderBlogStreamPagination::new( + original.older_link.clone(), + original.newer_link.clone(), + )?) } else { None }; @@ -76,7 +105,7 @@ impl RenderBlogStream { stream_pagination, }) } -} +); #[derive(Debug, Serialize)] pub(crate) struct RenderBlogStreamEntry { @@ -90,43 +119,38 @@ pub(crate) struct RenderBlogStreamEntry { footnotes: Vec, } -impl RenderBlogStreamEntry { - fn new( - config: &Config, - output_directory: &Path, - output_file: &Path, - original: &BlogPost, - ) -> Result { - // TODO: This link is probably wrong. - let link_to_blog_post = get_web_path( - config, - output_directory, - output_file, - output_file.strip_prefix(output_directory)?, - )?; +render!(RenderBlogStreamEntry, BlogPost, original, render_context, { + // TODO: This link is probably wrong. + let link_to_blog_post = get_web_path( + render_context.config, + render_context.output_directory, + render_context.output_file, + render_context + .output_file + .strip_prefix(render_context.output_directory)?, + )?; - // TODO: Should I guess an index page instead of erroring out? - let index_page = original - .get_index_page() - .ok_or_else(|| format!("Blog post {} needs an index page.", original.id))?; + // TODO: Should I guess an index page instead of erroring out? + let index_page = original + .get_index_page() + .ok_or_else(|| format!("Blog post {} needs an index page.", original.id))?; - let title = index_page.title.clone(); + let title = index_page.title.clone(); - // TODO: Handle footnotes. - let children = index_page - .children - .iter() - .map(|child| RenderDocumentElement::new(config, output_directory, output_file, child)) - .collect::, _>>()?; + // TODO: Handle footnotes. + let children = index_page + .children + .iter() + .map(|child| RenderDocumentElement::new(render_context.clone(), child)) + .collect::, _>>()?; - Ok(RenderBlogStreamEntry { - title, - self_link: Some(link_to_blog_post), - children, - footnotes: Vec::new(), - }) - } -} + Ok(RenderBlogStreamEntry { + title, + self_link: Some(link_to_blog_post), + children, + footnotes: Vec::new(), + }) +}); #[derive(Debug, Serialize)] pub(crate) struct RenderBlogStreamPagination { diff --git a/src/context/bold.rs b/src/context/bold.rs index 87c6fb0..7049a23 100644 --- a/src/context/bold.rs +++ b/src/context/bold.rs @@ -1,12 +1,10 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; use crate::error::CustomError; use crate::intermediate::IBold; use super::macros::render; +use super::render_context::RenderContext; use super::RenderObject; #[derive(Debug, Serialize)] @@ -16,27 +14,14 @@ pub(crate) struct RenderBold { children: Vec, } -render!( - RenderBold, - IBold, - original, - config, - output_directory, - output_file, - { - let children = { - let mut ret = Vec::new(); - for obj in original.children.iter() { - ret.push(RenderObject::new( - config, - output_directory, - output_file, - obj, - )?); - } - ret - }; +render!(RenderBold, IBold, original, render_context, { + let children = { + let mut ret = Vec::new(); + for obj in original.children.iter() { + ret.push(RenderObject::new(render_context.clone(), obj)?); + } + ret + }; - Ok(RenderBold { children }) - } -); + Ok(RenderBold { children }) +}); diff --git a/src/context/center_block.rs b/src/context/center_block.rs index e0da129..04db135 100644 --- a/src/context/center_block.rs +++ b/src/context/center_block.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::ICenterBlock; diff --git a/src/context/citation.rs b/src/context/citation.rs index 0ca5fbb..c9d44fa 100644 --- a/src/context/citation.rs +++ b/src/context/citation.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::ICitation; diff --git a/src/context/citation_reference.rs b/src/context/citation_reference.rs index 7d1143f..8c188d4 100644 --- a/src/context/citation_reference.rs +++ b/src/context/citation_reference.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::ICitationReference; diff --git a/src/context/clock.rs b/src/context/clock.rs index 8165502..a8fe617 100644 --- a/src/context/clock.rs +++ b/src/context/clock.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IClock; diff --git a/src/context/code.rs b/src/context/code.rs index b7ff530..bdce2ac 100644 --- a/src/context/code.rs +++ b/src/context/code.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::ICode; @@ -15,16 +13,8 @@ pub(crate) struct RenderCode { contents: String, } -render!( - RenderCode, - ICode, - original, - _config, - _output_directory, - _output_file, - { - Ok(RenderCode { - contents: original.contents.clone(), - }) - } -); +render!(RenderCode, ICode, original, _render_context, { + Ok(RenderCode { + contents: original.contents.clone(), + }) +}); diff --git a/src/context/comment.rs b/src/context/comment.rs index 37c81ef..fbab8e1 100644 --- a/src/context/comment.rs +++ b/src/context/comment.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IComment; diff --git a/src/context/comment_block.rs b/src/context/comment_block.rs index c2801f6..34702e2 100644 --- a/src/context/comment_block.rs +++ b/src/context/comment_block.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::ICommentBlock; diff --git a/src/context/diary_sexp.rs b/src/context/diary_sexp.rs index 889fc9f..e6235e5 100644 --- a/src/context/diary_sexp.rs +++ b/src/context/diary_sexp.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IDiarySexp; diff --git a/src/context/document_element.rs b/src/context/document_element.rs index aa10d75..b11239c 100644 --- a/src/context/document_element.rs +++ b/src/context/document_element.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IDocumentElement; @@ -21,16 +19,14 @@ render!( RenderDocumentElement, IDocumentElement, original, - config, - output_directory, - output_file, + render_context, { match original { IDocumentElement::Heading(inner) => Ok(RenderDocumentElement::Heading( - RenderHeading::new(config, output_directory, output_file, inner)?, + RenderHeading::new(render_context.clone(), inner)?, )), IDocumentElement::Section(inner) => Ok(RenderDocumentElement::Section( - RenderSection::new(config, output_directory, output_file, inner)?, + RenderSection::new(render_context.clone(), inner)?, )), } } diff --git a/src/context/drawer.rs b/src/context/drawer.rs index f6989b7..a6b7f5e 100644 --- a/src/context/drawer.rs +++ b/src/context/drawer.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IDrawer; diff --git a/src/context/dynamic_block.rs b/src/context/dynamic_block.rs index bd562e1..bf7840f 100644 --- a/src/context/dynamic_block.rs +++ b/src/context/dynamic_block.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IDynamicBlock; diff --git a/src/context/element.rs b/src/context/element.rs index 781ca28..f493919 100644 --- a/src/context/element.rs +++ b/src/context/element.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IElement; @@ -61,132 +59,98 @@ pub(crate) enum RenderElement { LatexEnvironment(RenderLatexEnvironment), } -render!( - RenderElement, - IElement, - original, - config, - output_directory, - output_file, - { - match original { - IElement::Paragraph(inner) => Ok(RenderElement::Paragraph(RenderParagraph::new( - config, - output_directory, - output_file, - inner, - )?)), - IElement::PlainList(inner) => Ok(RenderElement::PlainList(RenderPlainList::new( - config, - output_directory, - output_file, - inner, - )?)), - IElement::CenterBlock(inner) => Ok(RenderElement::CenterBlock(RenderCenterBlock::new( - config, - output_directory, - output_file, - inner, - )?)), - IElement::QuoteBlock(inner) => Ok(RenderElement::QuoteBlock(RenderQuoteBlock::new( - config, - output_directory, - output_file, - inner, - )?)), - IElement::SpecialBlock(inner) => Ok(RenderElement::SpecialBlock( - RenderSpecialBlock::new(config, output_directory, output_file, inner)?, - )), - IElement::DynamicBlock(inner) => Ok(RenderElement::DynamicBlock( - RenderDynamicBlock::new(config, output_directory, output_file, inner)?, - )), - IElement::FootnoteDefinition(inner) => Ok(RenderElement::FootnoteDefinition( - RenderFootnoteDefinition::new(config, output_directory, output_file, inner)?, - )), - IElement::Comment(inner) => Ok(RenderElement::Comment(RenderComment::new( - config, - output_directory, - output_file, - inner, - )?)), - IElement::Drawer(inner) => Ok(RenderElement::Drawer(RenderDrawer::new( - config, - output_directory, - output_file, - inner, - )?)), - IElement::PropertyDrawer(inner) => Ok(RenderElement::PropertyDrawer( - RenderPropertyDrawer::new(config, output_directory, output_file, inner)?, - )), - IElement::Table(inner) => Ok(RenderElement::Table(RenderTable::new( - config, - output_directory, - output_file, - inner, - )?)), - IElement::VerseBlock(inner) => Ok(RenderElement::VerseBlock(RenderVerseBlock::new( - config, - output_directory, - output_file, - inner, - )?)), - IElement::CommentBlock(inner) => Ok(RenderElement::CommentBlock( - RenderCommentBlock::new(config, output_directory, output_file, inner)?, - )), - IElement::ExampleBlock(inner) => Ok(RenderElement::ExampleBlock( - RenderExampleBlock::new(config, output_directory, output_file, inner)?, - )), - IElement::ExportBlock(inner) => Ok(RenderElement::ExportBlock(RenderExportBlock::new( - config, - output_directory, - output_file, - inner, - )?)), - IElement::SrcBlock(inner) => Ok(RenderElement::SrcBlock(RenderSrcBlock::new( - config, - output_directory, - output_file, - inner, - )?)), - IElement::Clock(inner) => Ok(RenderElement::Clock(RenderClock::new( - config, - output_directory, - output_file, - inner, - )?)), - IElement::DiarySexp(inner) => Ok(RenderElement::DiarySexp(RenderDiarySexp::new( - config, - output_directory, - output_file, - inner, - )?)), - IElement::Planning(inner) => Ok(RenderElement::Planning(RenderPlanning::new( - config, - output_directory, - output_file, - inner, - )?)), - IElement::FixedWidthArea(inner) => Ok(RenderElement::FixedWidthArea( - RenderFixedWidthArea::new(config, output_directory, output_file, inner)?, - )), - IElement::HorizontalRule(inner) => Ok(RenderElement::HorizontalRule( - RenderHorizontalRule::new(config, output_directory, output_file, inner)?, - )), - IElement::Keyword(inner) => Ok(RenderElement::Keyword(RenderKeyword::new( - config, - output_directory, - output_file, - inner, - )?)), - IElement::BabelCall(inner) => Ok(RenderElement::BabelCall(RenderBabelCall::new( - config, - output_directory, - output_file, - inner, - )?)), - IElement::LatexEnvironment(inner) => Ok(RenderElement::LatexEnvironment( - RenderLatexEnvironment::new(config, output_directory, output_file, inner)?, - )), - } +render!(RenderElement, IElement, original, render_context, { + match original { + IElement::Paragraph(inner) => Ok(RenderElement::Paragraph(RenderParagraph::new( + render_context.clone(), + inner, + )?)), + IElement::PlainList(inner) => Ok(RenderElement::PlainList(RenderPlainList::new( + render_context.clone(), + inner, + )?)), + IElement::CenterBlock(inner) => Ok(RenderElement::CenterBlock(RenderCenterBlock::new( + render_context.clone(), + inner, + )?)), + IElement::QuoteBlock(inner) => Ok(RenderElement::QuoteBlock(RenderQuoteBlock::new( + render_context.clone(), + inner, + )?)), + IElement::SpecialBlock(inner) => Ok(RenderElement::SpecialBlock(RenderSpecialBlock::new( + render_context.clone(), + inner, + )?)), + IElement::DynamicBlock(inner) => Ok(RenderElement::DynamicBlock(RenderDynamicBlock::new( + render_context.clone(), + inner, + )?)), + IElement::FootnoteDefinition(inner) => Ok(RenderElement::FootnoteDefinition( + RenderFootnoteDefinition::new(render_context.clone(), inner)?, + )), + IElement::Comment(inner) => Ok(RenderElement::Comment(RenderComment::new( + render_context.clone(), + inner, + )?)), + IElement::Drawer(inner) => Ok(RenderElement::Drawer(RenderDrawer::new( + render_context.clone(), + inner, + )?)), + IElement::PropertyDrawer(inner) => Ok(RenderElement::PropertyDrawer( + RenderPropertyDrawer::new(render_context.clone(), inner)?, + )), + IElement::Table(inner) => Ok(RenderElement::Table(RenderTable::new( + render_context.clone(), + inner, + )?)), + IElement::VerseBlock(inner) => Ok(RenderElement::VerseBlock(RenderVerseBlock::new( + render_context.clone(), + inner, + )?)), + IElement::CommentBlock(inner) => Ok(RenderElement::CommentBlock(RenderCommentBlock::new( + render_context.clone(), + inner, + )?)), + IElement::ExampleBlock(inner) => Ok(RenderElement::ExampleBlock(RenderExampleBlock::new( + render_context.clone(), + inner, + )?)), + IElement::ExportBlock(inner) => Ok(RenderElement::ExportBlock(RenderExportBlock::new( + render_context.clone(), + inner, + )?)), + IElement::SrcBlock(inner) => Ok(RenderElement::SrcBlock(RenderSrcBlock::new( + render_context.clone(), + inner, + )?)), + IElement::Clock(inner) => Ok(RenderElement::Clock(RenderClock::new( + render_context.clone(), + inner, + )?)), + IElement::DiarySexp(inner) => Ok(RenderElement::DiarySexp(RenderDiarySexp::new( + render_context.clone(), + inner, + )?)), + IElement::Planning(inner) => Ok(RenderElement::Planning(RenderPlanning::new( + render_context.clone(), + inner, + )?)), + IElement::FixedWidthArea(inner) => Ok(RenderElement::FixedWidthArea( + RenderFixedWidthArea::new(render_context.clone(), inner)?, + )), + IElement::HorizontalRule(inner) => Ok(RenderElement::HorizontalRule( + RenderHorizontalRule::new(render_context.clone(), inner)?, + )), + IElement::Keyword(inner) => Ok(RenderElement::Keyword(RenderKeyword::new( + render_context.clone(), + inner, + )?)), + IElement::BabelCall(inner) => Ok(RenderElement::BabelCall(RenderBabelCall::new( + render_context.clone(), + inner, + )?)), + IElement::LatexEnvironment(inner) => Ok(RenderElement::LatexEnvironment( + RenderLatexEnvironment::new(render_context.clone(), inner)?, + )), } -); +}); diff --git a/src/context/entity.rs b/src/context/entity.rs index f4c2ec9..a69f24f 100644 --- a/src/context/entity.rs +++ b/src/context/entity.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IEntity; @@ -15,16 +13,8 @@ pub(crate) struct RenderEntity { html: String, } -render!( - RenderEntity, - IEntity, - original, - _config, - _output_directory, - _output_file, - { - Ok(RenderEntity { - html: original.html.clone(), - }) - } -); +render!(RenderEntity, IEntity, original, _render_context, { + Ok(RenderEntity { + html: original.html.clone(), + }) +}); diff --git a/src/context/example_block.rs b/src/context/example_block.rs index a15868a..464d435 100644 --- a/src/context/example_block.rs +++ b/src/context/example_block.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IExampleBlock; diff --git a/src/context/export_block.rs b/src/context/export_block.rs index 837df0f..36e5a06 100644 --- a/src/context/export_block.rs +++ b/src/context/export_block.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IExportBlock; diff --git a/src/context/export_snippet.rs b/src/context/export_snippet.rs index 4a422c0..246f25a 100644 --- a/src/context/export_snippet.rs +++ b/src/context/export_snippet.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IExportSnippet; diff --git a/src/context/fixed_width_area.rs b/src/context/fixed_width_area.rs index c31fbc8..ca9bb7f 100644 --- a/src/context/fixed_width_area.rs +++ b/src/context/fixed_width_area.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IFixedWidthArea; diff --git a/src/context/footnote_definition.rs b/src/context/footnote_definition.rs index e443fc1..de62fd4 100644 --- a/src/context/footnote_definition.rs +++ b/src/context/footnote_definition.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IFootnoteDefinition; use crate::intermediate::IRealFootnoteDefinition; @@ -33,14 +31,12 @@ render!( RenderRealFootnoteDefinition, IRealFootnoteDefinition, original, - config, - output_directory, - output_file, + render_context, { let contents = { let mut ret = Vec::new(); for obj in original.contents.iter() { - ret.push(obj.into_render_ast_node(config, output_directory, output_file)?); + ret.push(obj.into_render_ast_node(render_context.clone())?); } ret }; diff --git a/src/context/footnote_reference.rs b/src/context/footnote_reference.rs index 0b188cc..3d4f00c 100644 --- a/src/context/footnote_reference.rs +++ b/src/context/footnote_reference.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IFootnoteReference; @@ -21,9 +19,7 @@ render!( RenderFootnoteReference, IFootnoteReference, original, - _config, - _output_directory, - _output_file, + _render_context, { Ok(RenderFootnoteReference { reference_id: original.get_reference_id(), diff --git a/src/context/heading.rs b/src/context/heading.rs index f9f9fa8..9b0064f 100644 --- a/src/context/heading.rs +++ b/src/context/heading.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IHeading; @@ -19,44 +17,26 @@ pub(crate) struct RenderHeading { children: Vec, } -render!( - RenderHeading, - IHeading, - original, - config, - output_directory, - output_file, - { - let title = { - let mut ret = Vec::new(); - for obj in original.title.iter() { - ret.push(RenderObject::new( - config, - output_directory, - output_file, - obj, - )?); - } - ret - }; +render!(RenderHeading, IHeading, original, render_context, { + let title = { + let mut ret = Vec::new(); + for obj in original.title.iter() { + ret.push(RenderObject::new(render_context.clone(), obj)?); + } + ret + }; - let children = { - let mut ret = Vec::new(); - for obj in original.children.iter() { - ret.push(RenderDocumentElement::new( - config, - output_directory, - output_file, - obj, - )?); - } - ret - }; + let children = { + let mut ret = Vec::new(); + for obj in original.children.iter() { + ret.push(RenderDocumentElement::new(render_context.clone(), obj)?); + } + ret + }; - Ok(RenderHeading { - level: original.level + 1, // Adding 1 because the page title is going to be h1. - title, - children, - }) - } -); + Ok(RenderHeading { + level: original.level + 1, // Adding 1 because the page title is going to be h1. + title, + children, + }) +}); diff --git a/src/context/horizontal_rule.rs b/src/context/horizontal_rule.rs index 92ecb34..e941eb7 100644 --- a/src/context/horizontal_rule.rs +++ b/src/context/horizontal_rule.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IHorizontalRule; diff --git a/src/context/inline_babel_call.rs b/src/context/inline_babel_call.rs index 6ff79db..cdbb1ac 100644 --- a/src/context/inline_babel_call.rs +++ b/src/context/inline_babel_call.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IInlineBabelCall; diff --git a/src/context/inline_source_block.rs b/src/context/inline_source_block.rs index 637678c..79c9710 100644 --- a/src/context/inline_source_block.rs +++ b/src/context/inline_source_block.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IInlineSourceBlock; @@ -19,9 +17,7 @@ render!( RenderInlineSourceBlock, IInlineSourceBlock, original, - _config, - _output_directory, - _output_file, + _render_context, { Ok(RenderInlineSourceBlock { value: original.value.clone(), diff --git a/src/context/italic.rs b/src/context/italic.rs index d5240b4..9c4e995 100644 --- a/src/context/italic.rs +++ b/src/context/italic.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IItalic; @@ -16,27 +14,14 @@ pub(crate) struct RenderItalic { children: Vec, } -render!( - RenderItalic, - IItalic, - original, - config, - output_directory, - output_file, - { - let children = { - let mut ret = Vec::new(); - for obj in original.children.iter() { - ret.push(RenderObject::new( - config, - output_directory, - output_file, - obj, - )?); - } - ret - }; +render!(RenderItalic, IItalic, original, render_context, { + let children = { + let mut ret = Vec::new(); + for obj in original.children.iter() { + ret.push(RenderObject::new(render_context.clone(), obj)?); + } + ret + }; - Ok(RenderItalic { children }) - } -); + Ok(RenderItalic { children }) +}); diff --git a/src/context/keyword.rs b/src/context/keyword.rs index c1f7268..17e08e7 100644 --- a/src/context/keyword.rs +++ b/src/context/keyword.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IKeyword; diff --git a/src/context/latex_environment.rs b/src/context/latex_environment.rs index a43f5ce..72a59e4 100644 --- a/src/context/latex_environment.rs +++ b/src/context/latex_environment.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::ILatexEnvironment; diff --git a/src/context/latex_fragment.rs b/src/context/latex_fragment.rs index 6226ad5..fa695a0 100644 --- a/src/context/latex_fragment.rs +++ b/src/context/latex_fragment.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::ILatexFragment; @@ -19,9 +17,7 @@ render!( RenderLatexFragment, ILatexFragment, original, - _config, - _output_directory, - _output_file, + _render_context, { Ok(RenderLatexFragment { value: original.value.clone(), diff --git a/src/context/line_break.rs b/src/context/line_break.rs index aa6b7a9..95f8554 100644 --- a/src/context/line_break.rs +++ b/src/context/line_break.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::ILineBreak; diff --git a/src/context/macros.rs b/src/context/macros.rs index aa6bf2f..1b01231 100644 --- a/src/context/macros.rs +++ b/src/context/macros.rs @@ -2,18 +2,14 @@ /// /// This exists to make changing the type signature easier. macro_rules! render { - ($rstruct:ident, $istruct:ident, $original:ident, $config:ident, $output_directory:ident, $output_file:ident, $fnbody:tt) => { + ($rstruct:ident, $istruct:ident, $original:ident, $render_context:ident, $fnbody:tt) => { impl $rstruct { pub(crate) fn new( - config: &Config, - output_directory: &Path, - output_file: &Path, + render_context: RenderContext<'_>, original: &$istruct, ) -> Result<$rstruct, CustomError> { let $original = original; - let $config = config; - let $output_directory = output_directory; - let $output_file = output_file; + let $render_context = render_context; $fnbody } } @@ -29,9 +25,7 @@ macro_rules! rnoop { ($rstruct:ident, $istruct:ident) => { impl $rstruct { pub(crate) fn new( - _config: &Config, - _output_directory: &Path, - _output_file: &Path, + _render_context: RenderContext<'_>, _original: &$istruct, ) -> Result<$rstruct, CustomError> { Ok($rstruct {}) diff --git a/src/context/mod.rs b/src/context/mod.rs index abaec4d..99ff45c 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -66,7 +66,9 @@ mod verbatim; mod verse_block; pub(crate) use blog_post_page::RenderBlogPostPage; +pub(crate) use blog_post_page::RenderBlogPostPageInput; pub(crate) use blog_stream::RenderBlogStream; +pub(crate) use blog_stream::RenderBlogStreamInput; pub(crate) use document_element::RenderDocumentElement; pub(crate) use element::RenderElement; pub(crate) use footnote_definition::RenderRealFootnoteDefinition; @@ -74,4 +76,5 @@ pub(crate) use global_settings::GlobalSettings; pub(crate) use heading::RenderHeading; pub(crate) use object::RenderObject; pub(crate) use page_header::PageHeader; +pub(crate) use render_context::RenderContext; pub(crate) use section::RenderSection; diff --git a/src/context/object.rs b/src/context/object.rs index 44fa771..c684e7e 100644 --- a/src/context/object.rs +++ b/src/context/object.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IObject; @@ -67,153 +65,110 @@ pub(crate) enum RenderObject { Timestamp(RenderTimestamp), } -render!( - RenderObject, - IObject, - original, - config, - output_directory, - output_file, - { - match original { - IObject::Bold(inner) => Ok(RenderObject::Bold(RenderBold::new( - config, - output_directory, - output_file, - inner, - )?)), - IObject::Italic(inner) => Ok(RenderObject::Italic(RenderItalic::new( - config, - output_directory, - output_file, - inner, - )?)), - IObject::Underline(inner) => Ok(RenderObject::Underline(RenderUnderline::new( - config, - output_directory, - output_file, - inner, - )?)), - IObject::StrikeThrough(inner) => Ok(RenderObject::StrikeThrough( - RenderStrikeThrough::new(config, output_directory, output_file, inner)?, - )), - IObject::Code(inner) => Ok(RenderObject::Code(RenderCode::new( - config, - output_directory, - output_file, - inner, - )?)), - IObject::Verbatim(inner) => Ok(RenderObject::Verbatim(RenderVerbatim::new( - config, - output_directory, - output_file, - inner, - )?)), - IObject::PlainText(inner) => Ok(RenderObject::PlainText(RenderPlainText::new( - config, - output_directory, - output_file, - inner, - )?)), - IObject::RegularLink(inner) => Ok(RenderObject::RegularLink(RenderRegularLink::new( - config, - output_directory, - output_file, - inner, - )?)), - IObject::RadioLink(inner) => Ok(RenderObject::RadioLink(RenderRadioLink::new( - config, - output_directory, - output_file, - inner, - )?)), - IObject::RadioTarget(inner) => Ok(RenderObject::RadioTarget(RenderRadioTarget::new( - config, - output_directory, - output_file, - inner, - )?)), - IObject::PlainLink(inner) => Ok(RenderObject::PlainLink(RenderPlainLink::new( - config, - output_directory, - output_file, - inner, - )?)), - IObject::AngleLink(inner) => Ok(RenderObject::AngleLink(RenderAngleLink::new( - config, - output_directory, - output_file, - inner, - )?)), - IObject::OrgMacro(inner) => Ok(RenderObject::OrgMacro(RenderOrgMacro::new( - config, - output_directory, - output_file, - inner, - )?)), - IObject::Entity(inner) => Ok(RenderObject::Entity(RenderEntity::new( - config, - output_directory, - output_file, - inner, - )?)), - IObject::LatexFragment(inner) => Ok(RenderObject::LatexFragment( - RenderLatexFragment::new(config, output_directory, output_file, inner)?, - )), - IObject::ExportSnippet(inner) => Ok(RenderObject::ExportSnippet( - RenderExportSnippet::new(config, output_directory, output_file, inner)?, - )), - IObject::FootnoteReference(inner) => Ok(RenderObject::FootnoteReference( - RenderFootnoteReference::new(config, output_directory, output_file, inner)?, - )), - IObject::Citation(inner) => Ok(RenderObject::Citation(RenderCitation::new( - config, - output_directory, - output_file, - inner, - )?)), - IObject::CitationReference(inner) => Ok(RenderObject::CitationReference( - RenderCitationReference::new(config, output_directory, output_file, inner)?, - )), - IObject::InlineBabelCall(inner) => Ok(RenderObject::InlineBabelCall( - RenderInlineBabelCall::new(config, output_directory, output_file, inner)?, - )), - IObject::InlineSourceBlock(inner) => Ok(RenderObject::InlineSourceBlock( - RenderInlineSourceBlock::new(config, output_directory, output_file, inner)?, - )), - IObject::LineBreak(inner) => Ok(RenderObject::LineBreak(RenderLineBreak::new( - config, - output_directory, - output_file, - inner, - )?)), - IObject::Target(inner) => Ok(RenderObject::Target(RenderTarget::new( - config, - output_directory, - output_file, - inner, - )?)), - IObject::StatisticsCookie(inner) => Ok(RenderObject::StatisticsCookie( - RenderStatisticsCookie::new(config, output_directory, output_file, inner)?, - )), - IObject::Subscript(inner) => Ok(RenderObject::Subscript(RenderSubscript::new( - config, - output_directory, - output_file, - inner, - )?)), - IObject::Superscript(inner) => Ok(RenderObject::Superscript(RenderSuperscript::new( - config, - output_directory, - output_file, - inner, - )?)), - IObject::Timestamp(inner) => Ok(RenderObject::Timestamp(RenderTimestamp::new( - config, - output_directory, - output_file, - inner, - )?)), - } +render!(RenderObject, IObject, original, render_context, { + match original { + IObject::Bold(inner) => Ok(RenderObject::Bold(RenderBold::new( + render_context.clone(), + inner, + )?)), + IObject::Italic(inner) => Ok(RenderObject::Italic(RenderItalic::new( + render_context.clone(), + inner, + )?)), + IObject::Underline(inner) => Ok(RenderObject::Underline(RenderUnderline::new( + render_context.clone(), + inner, + )?)), + IObject::StrikeThrough(inner) => Ok(RenderObject::StrikeThrough(RenderStrikeThrough::new( + render_context.clone(), + inner, + )?)), + IObject::Code(inner) => Ok(RenderObject::Code(RenderCode::new( + render_context.clone(), + inner, + )?)), + IObject::Verbatim(inner) => Ok(RenderObject::Verbatim(RenderVerbatim::new( + render_context.clone(), + inner, + )?)), + IObject::PlainText(inner) => Ok(RenderObject::PlainText(RenderPlainText::new( + render_context.clone(), + inner, + )?)), + IObject::RegularLink(inner) => Ok(RenderObject::RegularLink(RenderRegularLink::new( + render_context.clone(), + inner, + )?)), + IObject::RadioLink(inner) => Ok(RenderObject::RadioLink(RenderRadioLink::new( + render_context.clone(), + inner, + )?)), + IObject::RadioTarget(inner) => Ok(RenderObject::RadioTarget(RenderRadioTarget::new( + render_context.clone(), + inner, + )?)), + IObject::PlainLink(inner) => Ok(RenderObject::PlainLink(RenderPlainLink::new( + render_context.clone(), + inner, + )?)), + IObject::AngleLink(inner) => Ok(RenderObject::AngleLink(RenderAngleLink::new( + render_context.clone(), + inner, + )?)), + IObject::OrgMacro(inner) => Ok(RenderObject::OrgMacro(RenderOrgMacro::new( + render_context.clone(), + inner, + )?)), + IObject::Entity(inner) => Ok(RenderObject::Entity(RenderEntity::new( + render_context.clone(), + inner, + )?)), + IObject::LatexFragment(inner) => Ok(RenderObject::LatexFragment(RenderLatexFragment::new( + render_context.clone(), + inner, + )?)), + IObject::ExportSnippet(inner) => Ok(RenderObject::ExportSnippet(RenderExportSnippet::new( + render_context.clone(), + inner, + )?)), + IObject::FootnoteReference(inner) => Ok(RenderObject::FootnoteReference( + RenderFootnoteReference::new(render_context.clone(), inner)?, + )), + IObject::Citation(inner) => Ok(RenderObject::Citation(RenderCitation::new( + render_context.clone(), + inner, + )?)), + IObject::CitationReference(inner) => Ok(RenderObject::CitationReference( + RenderCitationReference::new(render_context.clone(), inner)?, + )), + IObject::InlineBabelCall(inner) => Ok(RenderObject::InlineBabelCall( + RenderInlineBabelCall::new(render_context.clone(), inner)?, + )), + IObject::InlineSourceBlock(inner) => Ok(RenderObject::InlineSourceBlock( + RenderInlineSourceBlock::new(render_context.clone(), inner)?, + )), + IObject::LineBreak(inner) => Ok(RenderObject::LineBreak(RenderLineBreak::new( + render_context.clone(), + inner, + )?)), + IObject::Target(inner) => Ok(RenderObject::Target(RenderTarget::new( + render_context.clone(), + inner, + )?)), + IObject::StatisticsCookie(inner) => Ok(RenderObject::StatisticsCookie( + RenderStatisticsCookie::new(render_context.clone(), inner)?, + )), + IObject::Subscript(inner) => Ok(RenderObject::Subscript(RenderSubscript::new( + render_context.clone(), + inner, + )?)), + IObject::Superscript(inner) => Ok(RenderObject::Superscript(RenderSuperscript::new( + render_context.clone(), + inner, + )?)), + IObject::Timestamp(inner) => Ok(RenderObject::Timestamp(RenderTimestamp::new( + render_context.clone(), + inner, + )?)), } -); +}); diff --git a/src/context/org_macro.rs b/src/context/org_macro.rs index cdf6659..8c03ff2 100644 --- a/src/context/org_macro.rs +++ b/src/context/org_macro.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IOrgMacro; diff --git a/src/context/paragraph.rs b/src/context/paragraph.rs index 4063e5e..c7bd6e3 100644 --- a/src/context/paragraph.rs +++ b/src/context/paragraph.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IParagraph; @@ -16,27 +14,14 @@ pub(crate) struct RenderParagraph { children: Vec, } -render!( - RenderParagraph, - IParagraph, - original, - config, - output_directory, - output_file, - { - let children = { - let mut ret = Vec::new(); - for obj in original.children.iter() { - ret.push(RenderObject::new( - config, - output_directory, - output_file, - obj, - )?); - } - ret - }; +render!(RenderParagraph, IParagraph, original, render_context, { + let children = { + let mut ret = Vec::new(); + for obj in original.children.iter() { + ret.push(RenderObject::new(render_context.clone(), obj)?); + } + ret + }; - Ok(RenderParagraph { children }) - } -); + Ok(RenderParagraph { children }) +}); diff --git a/src/context/plain_link.rs b/src/context/plain_link.rs index ffb5481..a30c77e 100644 --- a/src/context/plain_link.rs +++ b/src/context/plain_link.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IPlainLink; diff --git a/src/context/plain_list.rs b/src/context/plain_list.rs index d7be696..7b6fe69 100644 --- a/src/context/plain_list.rs +++ b/src/context/plain_list.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IPlainList; @@ -17,35 +15,22 @@ pub(crate) struct RenderPlainList { children: Vec, } -render!( - RenderPlainList, - IPlainList, - original, - config, - output_directory, - output_file, - { - let list_type = match original.list_type { - organic::types::PlainListType::Unordered => "unordered".to_owned(), - organic::types::PlainListType::Ordered => "ordered".to_owned(), - organic::types::PlainListType::Descriptive => "descriptive".to_owned(), - }; - let children = { - let mut ret = Vec::new(); - for obj in original.children.iter() { - ret.push(RenderPlainListItem::new( - config, - output_directory, - output_file, - obj, - )?); - } - ret - }; +render!(RenderPlainList, IPlainList, original, render_context, { + let list_type = match original.list_type { + organic::types::PlainListType::Unordered => "unordered".to_owned(), + organic::types::PlainListType::Ordered => "ordered".to_owned(), + organic::types::PlainListType::Descriptive => "descriptive".to_owned(), + }; + let children = { + let mut ret = Vec::new(); + for obj in original.children.iter() { + ret.push(RenderPlainListItem::new(render_context.clone(), obj)?); + } + ret + }; - Ok(RenderPlainList { - list_type, - children, - }) - } -); + Ok(RenderPlainList { + list_type, + children, + }) +}); diff --git a/src/context/plain_list_item.rs b/src/context/plain_list_item.rs index 4fa2edc..e40484c 100644 --- a/src/context/plain_list_item.rs +++ b/src/context/plain_list_item.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IPlainListItem; @@ -22,19 +20,12 @@ render!( RenderPlainListItem, IPlainListItem, original, - config, - output_directory, - output_file, + render_context, { let tag = { let mut ret = Vec::new(); for obj in original.tag.iter() { - ret.push(RenderObject::new( - config, - output_directory, - output_file, - obj, - )?); + ret.push(RenderObject::new(render_context.clone(), obj)?); } ret }; @@ -42,12 +33,7 @@ render!( let children = { let mut ret = Vec::new(); for obj in original.children.iter() { - ret.push(RenderElement::new( - config, - output_directory, - output_file, - obj, - )?); + ret.push(RenderElement::new(render_context.clone(), obj)?); } ret }; diff --git a/src/context/plain_text.rs b/src/context/plain_text.rs index 00dfda8..134d685 100644 --- a/src/context/plain_text.rs +++ b/src/context/plain_text.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IPlainText; @@ -15,16 +13,8 @@ pub(crate) struct RenderPlainText { source: String, } -render!( - RenderPlainText, - IPlainText, - original, - _config, - _output_directory, - _output_file, - { - Ok(RenderPlainText { - source: original.source.clone(), - }) - } -); +render!(RenderPlainText, IPlainText, original, _render_context, { + Ok(RenderPlainText { + source: original.source.clone(), + }) +}); diff --git a/src/context/planning.rs b/src/context/planning.rs index 6a13895..33f8b2c 100644 --- a/src/context/planning.rs +++ b/src/context/planning.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IPlanning; diff --git a/src/context/property_drawer.rs b/src/context/property_drawer.rs index d19ba3b..69ee47e 100644 --- a/src/context/property_drawer.rs +++ b/src/context/property_drawer.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IPropertyDrawer; diff --git a/src/context/quote_block.rs b/src/context/quote_block.rs index cae413d..581cbe2 100644 --- a/src/context/quote_block.rs +++ b/src/context/quote_block.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IQuoteBlock; @@ -16,27 +14,14 @@ pub(crate) struct RenderQuoteBlock { children: Vec, } -render!( - RenderQuoteBlock, - IQuoteBlock, - original, - config, - output_directory, - output_file, - { - let children = { - let mut ret = Vec::new(); - for obj in original.children.iter() { - ret.push(RenderElement::new( - config, - output_directory, - output_file, - obj, - )?); - } - ret - }; +render!(RenderQuoteBlock, IQuoteBlock, original, render_context, { + let children = { + let mut ret = Vec::new(); + for obj in original.children.iter() { + ret.push(RenderElement::new(render_context.clone(), obj)?); + } + ret + }; - Ok(RenderQuoteBlock { children }) - } -); + Ok(RenderQuoteBlock { children }) +}); diff --git a/src/context/radio_link.rs b/src/context/radio_link.rs index 06c727f..a7eabdb 100644 --- a/src/context/radio_link.rs +++ b/src/context/radio_link.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IRadioLink; diff --git a/src/context/radio_target.rs b/src/context/radio_target.rs index 5bbfd56..5f91d13 100644 --- a/src/context/radio_target.rs +++ b/src/context/radio_target.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IRadioTarget; diff --git a/src/context/regular_link.rs b/src/context/regular_link.rs index 91efe9e..9dfceae 100644 --- a/src/context/regular_link.rs +++ b/src/context/regular_link.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IRegularLink; @@ -17,30 +15,17 @@ pub(crate) struct RenderRegularLink { children: Vec, } -render!( - RenderRegularLink, - IRegularLink, - original, - config, - output_directory, - output_file, - { - let children = { - let mut ret = Vec::new(); - for obj in original.children.iter() { - ret.push(RenderObject::new( - config, - output_directory, - output_file, - obj, - )?); - } - ret - }; +render!(RenderRegularLink, IRegularLink, original, render_context, { + let children = { + let mut ret = Vec::new(); + for obj in original.children.iter() { + ret.push(RenderObject::new(render_context.clone(), obj)?); + } + ret + }; - Ok(RenderRegularLink { - raw_link: original.raw_link.clone(), - children, - }) - } -); + Ok(RenderRegularLink { + raw_link: original.raw_link.clone(), + children, + }) +}); diff --git a/src/context/section.rs b/src/context/section.rs index 3f92fe9..aa297c3 100644 --- a/src/context/section.rs +++ b/src/context/section.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::ISection; @@ -16,27 +14,14 @@ pub(crate) struct RenderSection { children: Vec, } -render!( - RenderSection, - ISection, - original, - config, - output_directory, - output_file, - { - let children = { - let mut ret = Vec::new(); - for obj in original.children.iter() { - ret.push(RenderElement::new( - config, - output_directory, - output_file, - obj, - )?); - } - ret - }; +render!(RenderSection, ISection, original, render_context, { + let children = { + let mut ret = Vec::new(); + for obj in original.children.iter() { + ret.push(RenderElement::new(render_context.clone(), obj)?); + } + ret + }; - Ok(RenderSection { children }) - } -); + Ok(RenderSection { children }) +}); diff --git a/src/context/special_block.rs b/src/context/special_block.rs index cb42967..21f96fc 100644 --- a/src/context/special_block.rs +++ b/src/context/special_block.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::ISpecialBlock; diff --git a/src/context/src_block.rs b/src/context/src_block.rs index f6161f8..d5346d7 100644 --- a/src/context/src_block.rs +++ b/src/context/src_block.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::ISrcBlock; @@ -15,16 +13,8 @@ pub(crate) struct RenderSrcBlock { lines: Vec, } -render!( - RenderSrcBlock, - ISrcBlock, - original, - _config, - _output_directory, - _output_file, - { - Ok(RenderSrcBlock { - lines: original.lines.clone(), - }) - } -); +render!(RenderSrcBlock, ISrcBlock, original, _render_context, { + Ok(RenderSrcBlock { + lines: original.lines.clone(), + }) +}); diff --git a/src/context/statistics_cookie.rs b/src/context/statistics_cookie.rs index 35dc122..ca71b95 100644 --- a/src/context/statistics_cookie.rs +++ b/src/context/statistics_cookie.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IStatisticsCookie; diff --git a/src/context/strike_through.rs b/src/context/strike_through.rs index c84fa37..1d53f9c 100644 --- a/src/context/strike_through.rs +++ b/src/context/strike_through.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IStrikeThrough; @@ -20,19 +18,12 @@ render!( RenderStrikeThrough, IStrikeThrough, original, - config, - output_directory, - output_file, + render_context, { let children = { let mut ret = Vec::new(); for obj in original.children.iter() { - ret.push(RenderObject::new( - config, - output_directory, - output_file, - obj, - )?); + ret.push(RenderObject::new(render_context.clone(), obj)?); } ret }; diff --git a/src/context/subscript.rs b/src/context/subscript.rs index b54c5e1..359492c 100644 --- a/src/context/subscript.rs +++ b/src/context/subscript.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::ISubscript; diff --git a/src/context/superscript.rs b/src/context/superscript.rs index bb030c5..3af3340 100644 --- a/src/context/superscript.rs +++ b/src/context/superscript.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::ISuperscript; diff --git a/src/context/table.rs b/src/context/table.rs index f460650..d1af62f 100644 --- a/src/context/table.rs +++ b/src/context/table.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::ITable; @@ -16,27 +14,14 @@ pub(crate) struct RenderTable { children: Vec, } -render!( - RenderTable, - ITable, - original, - config, - output_directory, - output_file, - { - let children = { - let mut ret = Vec::new(); - for obj in original.children.iter() { - ret.push(RenderTableRow::new( - config, - output_directory, - output_file, - obj, - )?); - } - ret - }; +render!(RenderTable, ITable, original, render_context, { + let children = { + let mut ret = Vec::new(); + for obj in original.children.iter() { + ret.push(RenderTableRow::new(render_context.clone(), obj)?); + } + ret + }; - Ok(RenderTable { children }) - } -); + Ok(RenderTable { children }) +}); diff --git a/src/context/table_cell.rs b/src/context/table_cell.rs index c2cef3c..85ce972 100644 --- a/src/context/table_cell.rs +++ b/src/context/table_cell.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::ITableCell; @@ -16,27 +14,14 @@ pub(crate) struct RenderTableCell { children: Vec, } -render!( - RenderTableCell, - ITableCell, - original, - config, - output_directory, - output_file, - { - let children = { - let mut ret = Vec::new(); - for obj in original.children.iter() { - ret.push(RenderObject::new( - config, - output_directory, - output_file, - obj, - )?); - } - ret - }; +render!(RenderTableCell, ITableCell, original, render_context, { + let children = { + let mut ret = Vec::new(); + for obj in original.children.iter() { + ret.push(RenderObject::new(render_context.clone(), obj)?); + } + ret + }; - Ok(RenderTableCell { children }) - } -); + Ok(RenderTableCell { children }) +}); diff --git a/src/context/table_row.rs b/src/context/table_row.rs index c4da3a8..95cae10 100644 --- a/src/context/table_row.rs +++ b/src/context/table_row.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::ITableRow; @@ -16,27 +14,14 @@ pub(crate) struct RenderTableRow { children: Vec, } -render!( - RenderTableRow, - ITableRow, - original, - config, - output_directory, - output_file, - { - let children = { - let mut ret = Vec::new(); - for obj in original.children.iter() { - ret.push(RenderTableCell::new( - config, - output_directory, - output_file, - obj, - )?); - } - ret - }; +render!(RenderTableRow, ITableRow, original, render_context, { + let children = { + let mut ret = Vec::new(); + for obj in original.children.iter() { + ret.push(RenderTableCell::new(render_context.clone(), obj)?); + } + ret + }; - Ok(RenderTableRow { children }) - } -); + Ok(RenderTableRow { children }) +}); diff --git a/src/context/target.rs b/src/context/target.rs index 9a04061..458bc69 100644 --- a/src/context/target.rs +++ b/src/context/target.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::ITarget; @@ -15,16 +13,8 @@ pub(crate) struct RenderTarget { id: String, } -render!( - RenderTarget, - ITarget, - original, - _config, - _output_directory, - _output_file, - { - Ok(RenderTarget { - id: original.id.clone(), - }) - } -); +render!(RenderTarget, ITarget, original, _render_context, { + Ok(RenderTarget { + id: original.id.clone(), + }) +}); diff --git a/src/context/timestamp.rs b/src/context/timestamp.rs index 73b6031..cf5ce54 100644 --- a/src/context/timestamp.rs +++ b/src/context/timestamp.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::ITimestamp; diff --git a/src/context/underline.rs b/src/context/underline.rs index 41cb21c..ab5fa5a 100644 --- a/src/context/underline.rs +++ b/src/context/underline.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IUnderline; @@ -16,27 +14,14 @@ pub(crate) struct RenderUnderline { children: Vec, } -render!( - RenderUnderline, - IUnderline, - original, - config, - output_directory, - output_file, - { - let children = { - let mut ret = Vec::new(); - for obj in original.children.iter() { - ret.push(RenderObject::new( - config, - output_directory, - output_file, - obj, - )?); - } - ret - }; +render!(RenderUnderline, IUnderline, original, render_context, { + let children = { + let mut ret = Vec::new(); + for obj in original.children.iter() { + ret.push(RenderObject::new(render_context.clone(), obj)?); + } + ret + }; - Ok(RenderUnderline { children }) - } -); + Ok(RenderUnderline { children }) +}); diff --git a/src/context/verbatim.rs b/src/context/verbatim.rs index 0314b63..68d2d0d 100644 --- a/src/context/verbatim.rs +++ b/src/context/verbatim.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IVerbatim; @@ -15,16 +13,8 @@ pub(crate) struct RenderVerbatim { contents: String, } -render!( - RenderVerbatim, - IVerbatim, - original, - _config, - _output_directory, - _output_file, - { - Ok(RenderVerbatim { - contents: original.contents.clone(), - }) - } -); +render!(RenderVerbatim, IVerbatim, original, _render_context, { + Ok(RenderVerbatim { + contents: original.contents.clone(), + }) +}); diff --git a/src/context/verse_block.rs b/src/context/verse_block.rs index 9e4cef2..cea5eb5 100644 --- a/src/context/verse_block.rs +++ b/src/context/verse_block.rs @@ -1,8 +1,6 @@ -use std::path::Path; - use serde::Serialize; -use crate::config::Config; +use super::render_context::RenderContext; use crate::error::CustomError; use crate::intermediate::IVerseBlock; diff --git a/src/intermediate/convert.rs b/src/intermediate/convert.rs index 49bc45d..ca462ef 100644 --- a/src/intermediate/convert.rs +++ b/src/intermediate/convert.rs @@ -3,93 +3,8 @@ use std::path::Path; use std::path::PathBuf; use crate::config::Config; -use crate::context::GlobalSettings; -use crate::context::PageHeader; -use crate::context::RenderBlogPostPage; -use crate::context::RenderDocumentElement; -use crate::context::RenderRealFootnoteDefinition; use crate::error::CustomError; -use super::BlogPost; -use super::BlogPostPage; - -pub(crate) fn convert_blog_post_page_to_render_context, F: AsRef>( - config: &Config, - output_directory: D, - output_file: F, - _post: &BlogPost, - page: &BlogPostPage, -) -> Result { - let output_directory = output_directory.as_ref(); - let output_file = output_file.as_ref(); - let css_files = vec![ - // get_web_path( - // config, - // output_directory, - // output_file, - // "stylesheet/reset.css", - // )?, - get_web_path(config, output_directory, output_file, "stylesheet/main.css")?, - ]; - let js_files = vec![get_web_path( - config, - output_directory, - output_file, - "blog_post.js", - )?]; - let global_settings = GlobalSettings::new(page.title.clone(), css_files, js_files); - let page_header = PageHeader::new( - config.get_site_title().map(str::to_string), - Some(get_web_path(config, output_directory, output_file, "")?), - ); - let link_to_blog_post = get_web_path( - config, - output_directory, - output_file, - output_file.strip_prefix(output_directory)?, - )?; - - let children = { - let mut children = Vec::new(); - - for child in page.children.iter() { - children.push(RenderDocumentElement::new( - config, - output_directory, - output_file, - child, - )?); - } - - children - }; - - let footnotes = { - let mut ret = Vec::new(); - - for footnote in page.footnotes.iter() { - ret.push(RenderRealFootnoteDefinition::new( - config, - output_directory, - output_file, - footnote, - )?); - } - - ret - }; - - let ret = RenderBlogPostPage::new( - global_settings, - Some(page_header), - page.title.clone(), - Some(link_to_blog_post), - children, - footnotes, - ); - Ok(ret) -} - pub(crate) fn get_web_path, F: AsRef, P: AsRef>( config: &Config, output_directory: D, diff --git a/src/intermediate/mod.rs b/src/intermediate/mod.rs index 2f165a2..4a7595f 100644 --- a/src/intermediate/mod.rs +++ b/src/intermediate/mod.rs @@ -76,7 +76,6 @@ pub(crate) use clock::IClock; pub(crate) use code::ICode; pub(crate) use comment::IComment; pub(crate) use comment_block::ICommentBlock; -pub(crate) use convert::convert_blog_post_page_to_render_context; pub(crate) use convert::get_web_path; pub(crate) use diary_sexp::IDiarySexp; pub(crate) use document_element::IDocumentElement; From 261fe8a1a29ac445f523572039b9f2b071c914f9 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Tue, 19 Dec 2023 16:46:32 -0500 Subject: [PATCH 13/18] Fix the links to the blog posts. --- default_environment/templates/html/blog_post_page.dust | 2 +- default_environment/templates/html/blog_stream.dust | 2 +- src/command/build/render.rs | 3 +-- src/config/full.rs | 9 +++++++++ src/context/blog_stream.rs | 5 ++--- 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/default_environment/templates/html/blog_post_page.dust b/default_environment/templates/html/blog_post_page.dust index 067b223..d846e3e 100644 --- a/default_environment/templates/html/blog_post_page.dust +++ b/default_environment/templates/html/blog_post_page.dust @@ -1,6 +1,6 @@
- {?.title}{?.self_link}{.title}{:else}
{.title}
{/.self_link}{/.title} + {?.title}{?.self_link}{.title}{:else}
{.title}
{/.self_link}{/.title} {! TODO: date? !}
diff --git a/default_environment/templates/html/blog_stream.dust b/default_environment/templates/html/blog_stream.dust index d0b5caf..97fe63c 100644 --- a/default_environment/templates/html/blog_stream.dust +++ b/default_environment/templates/html/blog_stream.dust @@ -2,7 +2,7 @@ {#.children}
- {?.title}{?.self_link}{.title}{:else}
{.title}
{/.self_link}{/.title} + {?.title}{?.self_link}{.title}{:else}
{.title}
{/.self_link}{/.title} {! TODO: date? !}
diff --git a/src/command/build/render.rs b/src/command/build/render.rs index de44026..6373398 100644 --- a/src/command/build/render.rs +++ b/src/command/build/render.rs @@ -77,8 +77,7 @@ impl SiteRenderer { for blog_post_page in &blog_post.pages { let output_path = self .output_directory - .join("posts") - .join(&blog_post.id) + .join(config.get_relative_path_to_post(&blog_post.id)) .join(blog_post_page.get_output_path()); let convert_input = RenderBlogPostPageInput::new(blog_post, blog_post_page); diff --git a/src/config/full.rs b/src/config/full.rs index ce5ce3c..5fdfd1f 100644 --- a/src/config/full.rs +++ b/src/config/full.rs @@ -57,6 +57,15 @@ impl Config { self.get_root_directory().join("posts") } + /// Get the relative path to the folder containing a blog post. + /// + /// This could be appended to the output root directory to get the + /// blog post output folder or it could be used to generate a link + /// to the blog post. + pub(crate) fn get_relative_path_to_post>(&self, post_id: P) -> PathBuf { + Path::new("posts").join(post_id) + } + pub(crate) fn get_output_directory(&self) -> PathBuf { self.get_root_directory().join("output") } diff --git a/src/context/blog_stream.rs b/src/context/blog_stream.rs index aefe096..28f6bb0 100644 --- a/src/context/blog_stream.rs +++ b/src/context/blog_stream.rs @@ -120,14 +120,13 @@ pub(crate) struct RenderBlogStreamEntry { } render!(RenderBlogStreamEntry, BlogPost, original, render_context, { - // TODO: This link is probably wrong. let link_to_blog_post = get_web_path( render_context.config, render_context.output_directory, render_context.output_file, render_context - .output_file - .strip_prefix(render_context.output_directory)?, + .config + .get_relative_path_to_post(&original.id), )?; // TODO: Should I guess an index page instead of erroring out? From 4bb1f9983a4202d569e9d357dd682f82d6c7ebd7 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Tue, 19 Dec 2023 17:09:11 -0500 Subject: [PATCH 14/18] Standardize the construction of intermediate BlogPostPage. --- src/intermediate/blog_post.rs | 8 +++-- src/intermediate/bold.rs | 26 ++++++++------ src/intermediate/code.rs | 18 ++++++---- src/intermediate/entity.rs | 16 ++++++--- src/intermediate/footnote_definition.rs | 2 +- src/intermediate/footnote_reference.rs | 22 +++++++----- src/intermediate/heading.rs | 48 ++++++++++++++----------- src/intermediate/inline_source_block.rs | 16 ++++++--- src/intermediate/italic.rs | 26 ++++++++------ src/intermediate/latex_fragment.rs | 26 ++++++++------ src/intermediate/macros.rs | 8 ++--- src/intermediate/page.rs | 46 ++++++++++++++++-------- src/intermediate/paragraph.rs | 26 ++++++++------ src/intermediate/plain_list.rs | 32 ++++++++++------- src/intermediate/plain_list_item.rs | 40 ++++++++++++--------- src/intermediate/plain_text.rs | 16 ++++++--- src/intermediate/quote_block.rs | 26 ++++++++------ src/intermediate/regular_link.rs | 32 ++++++++++------- src/intermediate/section.rs | 26 ++++++++------ src/intermediate/src_block.rs | 22 +++++++----- src/intermediate/strike_through.rs | 26 ++++++++------ src/intermediate/table.rs | 26 ++++++++------ src/intermediate/table_cell.rs | 26 ++++++++------ src/intermediate/table_row.rs | 27 ++++++++------ src/intermediate/target.rs | 22 +++++++----- src/intermediate/underline.rs | 26 ++++++++------ src/intermediate/verbatim.rs | 18 ++++++---- 27 files changed, 405 insertions(+), 248 deletions(-) diff --git a/src/intermediate/blog_post.rs b/src/intermediate/blog_post.rs index 52c38ef..6116653 100644 --- a/src/intermediate/blog_post.rs +++ b/src/intermediate/blog_post.rs @@ -7,6 +7,7 @@ use tokio::task::JoinHandle; use walkdir::WalkDir; use crate::error::CustomError; +use crate::intermediate::page::BlogPostPageInput; use crate::intermediate::registry::Registry; use super::BlogPostPage; @@ -63,8 +64,11 @@ impl BlogPost { let registry = Arc::new(Mutex::new(registry)); let relative_to_post_dir_path = real_path.strip_prefix(post_dir)?; ret.push( - BlogPostPage::new(relative_to_post_dir_path, registry, parsed_document) - .await?, + BlogPostPage::new( + registry, + BlogPostPageInput::new(relative_to_post_dir_path, parsed_document), + ) + .await?, ); } ret diff --git a/src/intermediate/bold.rs b/src/intermediate/bold.rs index dbca21d..6774fb0 100644 --- a/src/intermediate/bold.rs +++ b/src/intermediate/bold.rs @@ -8,14 +8,20 @@ pub(crate) struct IBold { pub(crate) children: Vec, } -intermediate!(IBold, Bold, original, registry, { - let children = { - let mut ret = Vec::new(); - for obj in original.children.iter() { - ret.push(IObject::new(registry.clone(), obj).await?); - } - ret - }; +intermediate!( + IBold, + &'orig organic::types::Bold<'parse>, + original, + registry, + { + let children = { + let mut ret = Vec::new(); + for obj in original.children.iter() { + ret.push(IObject::new(registry.clone(), obj).await?); + } + ret + }; - Ok(IBold { children }) -}); + Ok(IBold { children }) + } +); diff --git a/src/intermediate/code.rs b/src/intermediate/code.rs index b121666..6f32ac6 100644 --- a/src/intermediate/code.rs +++ b/src/intermediate/code.rs @@ -7,9 +7,15 @@ pub(crate) struct ICode { pub(crate) contents: String, } -intermediate!(ICode, Code, original, _registry, { - Ok(ICode { - // TODO: Should this coalesce whitespace like PlainText? - contents: original.contents.to_owned(), - }) -}); +intermediate!( + ICode, + &'orig organic::types::Code<'parse>, + original, + _registry, + { + Ok(ICode { + // TODO: Should this coalesce whitespace like PlainText? + contents: original.contents.to_owned(), + }) + } +); diff --git a/src/intermediate/entity.rs b/src/intermediate/entity.rs index b2043ed..071daa0 100644 --- a/src/intermediate/entity.rs +++ b/src/intermediate/entity.rs @@ -7,8 +7,14 @@ pub(crate) struct IEntity { pub(crate) html: String, } -intermediate!(IEntity, Entity, original, _registry, { - Ok(IEntity { - html: original.html.to_owned(), - }) -}); +intermediate!( + IEntity, + &'orig organic::types::Entity<'parse>, + original, + _registry, + { + Ok(IEntity { + html: original.html.to_owned(), + }) + } +); diff --git a/src/intermediate/footnote_definition.rs b/src/intermediate/footnote_definition.rs index 424c56f..336b40e 100644 --- a/src/intermediate/footnote_definition.rs +++ b/src/intermediate/footnote_definition.rs @@ -10,7 +10,7 @@ pub(crate) struct IFootnoteDefinition {} intermediate!( IFootnoteDefinition, - FootnoteDefinition, + &'orig organic::types::FootnoteDefinition<'parse>, original, registry, { diff --git a/src/intermediate/footnote_reference.rs b/src/intermediate/footnote_reference.rs index f9f448c..7d3baa3 100644 --- a/src/intermediate/footnote_reference.rs +++ b/src/intermediate/footnote_reference.rs @@ -9,14 +9,20 @@ pub(crate) struct IFootnoteReference { duplicate_offset: usize, } -intermediate!(IFootnoteReference, FootnoteReference, original, registry, { - let (footnote_id, reference_count) = - get_footnote_reference_id(registry, original.label, &original.definition).await?; - Ok(IFootnoteReference { - footnote_id, - duplicate_offset: reference_count, - }) -}); +intermediate!( + IFootnoteReference, + &'orig organic::types::FootnoteReference<'parse>, + original, + registry, + { + let (footnote_id, reference_count) = + get_footnote_reference_id(registry, original.label, &original.definition).await?; + Ok(IFootnoteReference { + footnote_id, + duplicate_offset: reference_count, + }) + } +); impl IFootnoteReference { pub(crate) fn get_display_label(&self) -> String { diff --git a/src/intermediate/heading.rs b/src/intermediate/heading.rs index 9446068..74830b3 100644 --- a/src/intermediate/heading.rs +++ b/src/intermediate/heading.rs @@ -11,24 +11,30 @@ pub(crate) struct IHeading { pub(crate) children: Vec, } -intermediate!(IHeading, Heading, original, registry, { - let title = { - let mut ret = Vec::new(); - for obj in original.title.iter() { - ret.push(IObject::new(registry.clone(), obj).await?); - } - ret - }; - let children = { - let mut ret = Vec::new(); - for obj in original.children.iter() { - ret.push(IDocumentElement::new(registry.clone(), obj).await?); - } - ret - }; - Ok(IHeading { - title, - level: original.level, - children, - }) -}); +intermediate!( + IHeading, + &'orig organic::types::Heading<'parse>, + original, + registry, + { + let title = { + let mut ret = Vec::new(); + for obj in original.title.iter() { + ret.push(IObject::new(registry.clone(), obj).await?); + } + ret + }; + let children = { + let mut ret = Vec::new(); + for obj in original.children.iter() { + ret.push(IDocumentElement::new(registry.clone(), obj).await?); + } + ret + }; + Ok(IHeading { + title, + level: original.level, + children, + }) + } +); diff --git a/src/intermediate/inline_source_block.rs b/src/intermediate/inline_source_block.rs index dd23be8..68e31b2 100644 --- a/src/intermediate/inline_source_block.rs +++ b/src/intermediate/inline_source_block.rs @@ -7,8 +7,14 @@ pub(crate) struct IInlineSourceBlock { pub(crate) value: String, } -intermediate!(IInlineSourceBlock, InlineSourceBlock, original, _registry, { - Ok(IInlineSourceBlock { - value: original.value.to_owned(), - }) -}); +intermediate!( + IInlineSourceBlock, + &'orig organic::types::InlineSourceBlock<'parse>, + original, + _registry, + { + Ok(IInlineSourceBlock { + value: original.value.to_owned(), + }) + } +); diff --git a/src/intermediate/italic.rs b/src/intermediate/italic.rs index 29d3fb3..23ecdc3 100644 --- a/src/intermediate/italic.rs +++ b/src/intermediate/italic.rs @@ -8,14 +8,20 @@ pub(crate) struct IItalic { pub(crate) children: Vec, } -intermediate!(IItalic, Italic, original, registry, { - let children = { - let mut ret = Vec::new(); - for obj in original.children.iter() { - ret.push(IObject::new(registry.clone(), obj).await?); - } - ret - }; +intermediate!( + IItalic, + &'orig organic::types::Italic<'parse>, + original, + registry, + { + let children = { + let mut ret = Vec::new(); + for obj in original.children.iter() { + ret.push(IObject::new(registry.clone(), obj).await?); + } + ret + }; - Ok(IItalic { children }) -}); + Ok(IItalic { children }) + } +); diff --git a/src/intermediate/latex_fragment.rs b/src/intermediate/latex_fragment.rs index 14721fd..75cf59e 100644 --- a/src/intermediate/latex_fragment.rs +++ b/src/intermediate/latex_fragment.rs @@ -7,13 +7,19 @@ pub(crate) struct ILatexFragment { pub(crate) value: String, } -intermediate!(ILatexFragment, LatexFragment, original, _registry, { - let value: String = if original.value.starts_with("$$") && original.value.ends_with("$$") { - format!("\\[{}\\]", &original.value[2..(original.value.len() - 2)]) - } else if original.value.starts_with("$") && original.value.ends_with("$") { - format!("\\({}\\)", &original.value[1..(original.value.len() - 1)]) - } else { - original.value.to_owned() - }; - Ok(ILatexFragment { value }) -}); +intermediate!( + ILatexFragment, + &'orig organic::types::LatexFragment<'parse>, + original, + _registry, + { + let value: String = if original.value.starts_with("$$") && original.value.ends_with("$$") { + format!("\\[{}\\]", &original.value[2..(original.value.len() - 2)]) + } else if original.value.starts_with("$") && original.value.ends_with("$") { + format!("\\({}\\)", &original.value[1..(original.value.len() - 1)]) + } else { + original.value.to_owned() + }; + Ok(ILatexFragment { value }) + } +); diff --git a/src/intermediate/macros.rs b/src/intermediate/macros.rs index cdebb49..b3c5465 100644 --- a/src/intermediate/macros.rs +++ b/src/intermediate/macros.rs @@ -23,14 +23,12 @@ pub(crate) use inoop; /// /// This exists to make changing the type signature easier. macro_rules! intermediate { - ($istruct:ident, $pstruct:ident, $original:ident, $registry:ident, $fnbody:tt) => { + ($istruct:ident, $pstruct:ty, $original:ident, $registry:ident, $fnbody:tt) => { impl $istruct { pub(crate) async fn new<'orig, 'parse>( - registry: crate::intermediate::RefRegistry<'orig, 'parse>, - original: &'orig organic::types::$pstruct<'parse>, + $registry: crate::intermediate::RefRegistry<'orig, 'parse>, + $original: $pstruct, ) -> Result<$istruct, CustomError> { - let $original = original; - let $registry = registry; $fnbody } } diff --git a/src/intermediate/page.rs b/src/intermediate/page.rs index 367422d..8de8e24 100644 --- a/src/intermediate/page.rs +++ b/src/intermediate/page.rs @@ -4,10 +4,28 @@ use crate::error::CustomError; use super::footnote_definition::IRealFootnoteDefinition; +use super::macros::intermediate; use super::IDocumentElement; use super::IHeading; use super::ISection; -use super::RefRegistry; + +#[derive(Debug)] +pub(crate) struct BlogPostPageInput<'b, 'parse> { + path: PathBuf, + document: &'b organic::types::Document<'parse>, +} + +impl<'b, 'parse> BlogPostPageInput<'b, 'parse> { + pub(crate) fn new>( + path: P, + document: &'b organic::types::Document<'parse>, + ) -> BlogPostPageInput<'b, 'parse> { + BlogPostPageInput { + path: path.into(), + document, + } + } +} #[derive(Debug)] pub(crate) struct BlogPostPage { @@ -23,21 +41,19 @@ pub(crate) struct BlogPostPage { pub(crate) footnotes: Vec, } -impl BlogPostPage { - // TODO: Move path into the registry so I can give this a standard interface like the others. - pub(crate) async fn new<'a, 'b, 'parse, P: Into>( - path: P, - registry: RefRegistry<'b, 'parse>, - document: &'b organic::types::Document<'parse>, - ) -> Result { - let path = path.into(); +intermediate!( + BlogPostPage, + BlogPostPageInput<'orig, 'parse>, + original, + registry, + { let mut children = Vec::new(); - if let Some(section) = document.zeroth_section.as_ref() { + if let Some(section) = original.document.zeroth_section.as_ref() { children.push(IDocumentElement::Section( ISection::new(registry.clone(), section).await?, )); } - for heading in document.children.iter() { + for heading in original.document.children.iter() { children.push(IDocumentElement::Heading( IHeading::new(registry.clone(), heading).await?, )); @@ -60,14 +76,16 @@ impl BlogPostPage { }; Ok(BlogPostPage { - path, - title: get_title(&document), - date: get_date(&document), + path: original.path, + title: get_title(original.document), + date: get_date(original.document), children, footnotes, }) } +); +impl BlogPostPage { /// Get the output path relative to the post directory. pub(crate) fn get_output_path(&self) -> PathBuf { let mut ret = self.path.clone(); diff --git a/src/intermediate/paragraph.rs b/src/intermediate/paragraph.rs index c9cb886..2c2e112 100644 --- a/src/intermediate/paragraph.rs +++ b/src/intermediate/paragraph.rs @@ -8,14 +8,20 @@ pub(crate) struct IParagraph { pub(crate) children: Vec, } -intermediate!(IParagraph, Paragraph, original, registry, { - let children = { - let mut ret = Vec::new(); - for obj in original.children.iter() { - ret.push(IObject::new(registry.clone(), obj).await?); - } - ret - }; +intermediate!( + IParagraph, + &'orig organic::types::Paragraph<'parse>, + original, + registry, + { + let children = { + let mut ret = Vec::new(); + for obj in original.children.iter() { + ret.push(IObject::new(registry.clone(), obj).await?); + } + ret + }; - Ok(IParagraph { children }) -}); + Ok(IParagraph { children }) + } +); diff --git a/src/intermediate/plain_list.rs b/src/intermediate/plain_list.rs index a6e09c2..68dc0b8 100644 --- a/src/intermediate/plain_list.rs +++ b/src/intermediate/plain_list.rs @@ -9,17 +9,23 @@ pub(crate) struct IPlainList { pub(crate) children: Vec, } -intermediate!(IPlainList, PlainList, original, registry, { - let children = { - let mut ret = Vec::new(); - for obj in original.children.iter() { - ret.push(IPlainListItem::new(registry.clone(), obj).await?); - } - ret - }; +intermediate!( + IPlainList, + &'orig organic::types::PlainList<'parse>, + original, + registry, + { + let children = { + let mut ret = Vec::new(); + for obj in original.children.iter() { + ret.push(IPlainListItem::new(registry.clone(), obj).await?); + } + ret + }; - Ok(IPlainList { - list_type: original.list_type, - children, - }) -}); + Ok(IPlainList { + list_type: original.list_type, + children, + }) + } +); diff --git a/src/intermediate/plain_list_item.rs b/src/intermediate/plain_list_item.rs index eee5947..ca971c6 100644 --- a/src/intermediate/plain_list_item.rs +++ b/src/intermediate/plain_list_item.rs @@ -10,22 +10,28 @@ pub(crate) struct IPlainListItem { pub(crate) children: Vec, } -intermediate!(IPlainListItem, PlainListItem, original, registry, { - let tag = { - let mut ret = Vec::new(); - for obj in original.tag.iter() { - ret.push(IObject::new(registry.clone(), obj).await?); - } - ret - }; +intermediate!( + IPlainListItem, + &'orig organic::types::PlainListItem<'parse>, + original, + registry, + { + let tag = { + let mut ret = Vec::new(); + for obj in original.tag.iter() { + ret.push(IObject::new(registry.clone(), obj).await?); + } + ret + }; - let children = { - let mut ret = Vec::new(); - for elem in original.children.iter() { - ret.push(IElement::new(registry.clone(), elem).await?); - } - ret - }; + let children = { + let mut ret = Vec::new(); + for elem in original.children.iter() { + ret.push(IElement::new(registry.clone(), elem).await?); + } + ret + }; - Ok(IPlainListItem { tag, children }) -}); + Ok(IPlainListItem { tag, children }) + } +); diff --git a/src/intermediate/plain_text.rs b/src/intermediate/plain_text.rs index 085ae23..ee419ad 100644 --- a/src/intermediate/plain_text.rs +++ b/src/intermediate/plain_text.rs @@ -8,8 +8,14 @@ pub(crate) struct IPlainText { pub(crate) source: String, } -intermediate!(IPlainText, PlainText, original, _registry, { - Ok(IPlainText { - source: coalesce_whitespace(original.source).into_owned(), - }) -}); +intermediate!( + IPlainText, + &'orig organic::types::PlainText<'parse>, + original, + _registry, + { + Ok(IPlainText { + source: coalesce_whitespace(original.source).into_owned(), + }) + } +); diff --git a/src/intermediate/quote_block.rs b/src/intermediate/quote_block.rs index 17c3dd4..e7485d0 100644 --- a/src/intermediate/quote_block.rs +++ b/src/intermediate/quote_block.rs @@ -8,14 +8,20 @@ pub(crate) struct IQuoteBlock { pub(crate) children: Vec, } -intermediate!(IQuoteBlock, QuoteBlock, original, registry, { - let children = { - let mut ret = Vec::new(); - for obj in original.children.iter() { - ret.push(IElement::new(registry.clone(), obj).await?); - } - ret - }; +intermediate!( + IQuoteBlock, + &'orig organic::types::QuoteBlock<'parse>, + original, + registry, + { + let children = { + let mut ret = Vec::new(); + for obj in original.children.iter() { + ret.push(IElement::new(registry.clone(), obj).await?); + } + ret + }; - Ok(IQuoteBlock { children }) -}); + Ok(IQuoteBlock { children }) + } +); diff --git a/src/intermediate/regular_link.rs b/src/intermediate/regular_link.rs index 0fcf77c..5f10fb0 100644 --- a/src/intermediate/regular_link.rs +++ b/src/intermediate/regular_link.rs @@ -9,16 +9,22 @@ pub(crate) struct IRegularLink { pub(crate) children: Vec, } -intermediate!(IRegularLink, RegularLink, original, registry, { - let children = { - let mut ret = Vec::new(); - for obj in original.children.iter() { - ret.push(IObject::new(registry.clone(), obj).await?); - } - ret - }; - Ok(IRegularLink { - raw_link: original.get_raw_link().into_owned(), - children, - }) -}); +intermediate!( + IRegularLink, + &'orig organic::types::RegularLink<'parse>, + original, + registry, + { + let children = { + let mut ret = Vec::new(); + for obj in original.children.iter() { + ret.push(IObject::new(registry.clone(), obj).await?); + } + ret + }; + Ok(IRegularLink { + raw_link: original.get_raw_link().into_owned(), + children, + }) + } +); diff --git a/src/intermediate/section.rs b/src/intermediate/section.rs index 66d5be3..9dc1119 100644 --- a/src/intermediate/section.rs +++ b/src/intermediate/section.rs @@ -8,14 +8,20 @@ pub(crate) struct ISection { pub(crate) children: Vec, } -intermediate!(ISection, Section, original, registry, { - let children = { - let mut ret = Vec::new(); - for elem in original.children.iter() { - ret.push(IElement::new(registry.clone(), elem).await?); - } - ret - }; +intermediate!( + ISection, + &'orig organic::types::Section<'parse>, + original, + registry, + { + let children = { + let mut ret = Vec::new(); + for elem in original.children.iter() { + ret.push(IElement::new(registry.clone(), elem).await?); + } + ret + }; - Ok(ISection { children }) -}); + Ok(ISection { children }) + } +); diff --git a/src/intermediate/src_block.rs b/src/intermediate/src_block.rs index 90824ba..0e1b2d1 100644 --- a/src/intermediate/src_block.rs +++ b/src/intermediate/src_block.rs @@ -7,11 +7,17 @@ pub(crate) struct ISrcBlock { pub(crate) lines: Vec, } -intermediate!(ISrcBlock, SrcBlock, original, _registry, { - let lines = original - .get_value() - .split_inclusive('\n') - .map(|s| s.to_owned()) - .collect(); - Ok(ISrcBlock { lines }) -}); +intermediate!( + ISrcBlock, + &'orig organic::types::SrcBlock<'parse>, + original, + _registry, + { + let lines = original + .get_value() + .split_inclusive('\n') + .map(|s| s.to_owned()) + .collect(); + Ok(ISrcBlock { lines }) + } +); diff --git a/src/intermediate/strike_through.rs b/src/intermediate/strike_through.rs index 430670b..40d0fb5 100644 --- a/src/intermediate/strike_through.rs +++ b/src/intermediate/strike_through.rs @@ -8,14 +8,20 @@ pub(crate) struct IStrikeThrough { pub(crate) children: Vec, } -intermediate!(IStrikeThrough, StrikeThrough, original, registry, { - let children = { - let mut ret = Vec::new(); - for obj in original.children.iter() { - ret.push(IObject::new(registry.clone(), obj).await?); - } - ret - }; +intermediate!( + IStrikeThrough, + &'orig organic::types::StrikeThrough<'parse>, + original, + registry, + { + let children = { + let mut ret = Vec::new(); + for obj in original.children.iter() { + ret.push(IObject::new(registry.clone(), obj).await?); + } + ret + }; - Ok(IStrikeThrough { children }) -}); + Ok(IStrikeThrough { children }) + } +); diff --git a/src/intermediate/table.rs b/src/intermediate/table.rs index aeb7f2f..396d05b 100644 --- a/src/intermediate/table.rs +++ b/src/intermediate/table.rs @@ -8,14 +8,20 @@ pub(crate) struct ITable { pub(crate) children: Vec, } -intermediate!(ITable, Table, original, registry, { - let children = { - let mut ret = Vec::new(); - for obj in original.children.iter() { - ret.push(ITableRow::new(registry.clone(), obj).await?); - } - ret - }; +intermediate!( + ITable, + &'orig organic::types::Table<'parse>, + original, + registry, + { + let children = { + let mut ret = Vec::new(); + for obj in original.children.iter() { + ret.push(ITableRow::new(registry.clone(), obj).await?); + } + ret + }; - Ok(ITable { children }) -}); + Ok(ITable { children }) + } +); diff --git a/src/intermediate/table_cell.rs b/src/intermediate/table_cell.rs index 212cf02..37691c4 100644 --- a/src/intermediate/table_cell.rs +++ b/src/intermediate/table_cell.rs @@ -8,14 +8,20 @@ pub(crate) struct ITableCell { pub(crate) children: Vec, } -intermediate!(ITableCell, TableCell, original, registry, { - let children = { - let mut ret = Vec::new(); - for obj in original.children.iter() { - ret.push(IObject::new(registry.clone(), obj).await?); - } - ret - }; +intermediate!( + ITableCell, + &'orig organic::types::TableCell<'parse>, + original, + registry, + { + let children = { + let mut ret = Vec::new(); + for obj in original.children.iter() { + ret.push(IObject::new(registry.clone(), obj).await?); + } + ret + }; - Ok(ITableCell { children }) -}); + Ok(ITableCell { children }) + } +); diff --git a/src/intermediate/table_row.rs b/src/intermediate/table_row.rs index 9628d8e..666519d 100644 --- a/src/intermediate/table_row.rs +++ b/src/intermediate/table_row.rs @@ -1,5 +1,4 @@ use super::macros::intermediate; - use super::table_cell::ITableCell; use crate::error::CustomError; @@ -8,14 +7,20 @@ pub(crate) struct ITableRow { pub(crate) children: Vec, } -intermediate!(ITableRow, TableRow, original, registry, { - let children = { - let mut ret = Vec::new(); - for obj in original.children.iter() { - ret.push(ITableCell::new(registry.clone(), obj).await?); - } - ret - }; +intermediate!( + ITableRow, + &'orig organic::types::TableRow<'parse>, + original, + registry, + { + let children = { + let mut ret = Vec::new(); + for obj in original.children.iter() { + ret.push(ITableCell::new(registry.clone(), obj).await?); + } + ret + }; - Ok(ITableRow { children }) -}); + Ok(ITableRow { children }) + } +); diff --git a/src/intermediate/target.rs b/src/intermediate/target.rs index ea1f3ce..de3b32e 100644 --- a/src/intermediate/target.rs +++ b/src/intermediate/target.rs @@ -8,11 +8,17 @@ pub(crate) struct ITarget { value: String, } -intermediate!(ITarget, Target, original, registry, { - let mut registry = registry.lock().unwrap(); - let id = registry.get_target(original.value); - Ok(ITarget { - id: id.clone(), - value: original.value.to_owned(), - }) -}); +intermediate!( + ITarget, + &'orig organic::types::Target<'parse>, + original, + registry, + { + let mut registry = registry.lock().unwrap(); + let id = registry.get_target(original.value); + Ok(ITarget { + id: id.clone(), + value: original.value.to_owned(), + }) + } +); diff --git a/src/intermediate/underline.rs b/src/intermediate/underline.rs index 2f35db3..1fd1b3c 100644 --- a/src/intermediate/underline.rs +++ b/src/intermediate/underline.rs @@ -8,14 +8,20 @@ pub(crate) struct IUnderline { pub(crate) children: Vec, } -intermediate!(IUnderline, Underline, original, registry, { - let children = { - let mut ret = Vec::new(); - for obj in original.children.iter() { - ret.push(IObject::new(registry.clone(), obj).await?); - } - ret - }; +intermediate!( + IUnderline, + &'orig organic::types::Underline<'parse>, + original, + registry, + { + let children = { + let mut ret = Vec::new(); + for obj in original.children.iter() { + ret.push(IObject::new(registry.clone(), obj).await?); + } + ret + }; - Ok(IUnderline { children }) -}); + Ok(IUnderline { children }) + } +); diff --git a/src/intermediate/verbatim.rs b/src/intermediate/verbatim.rs index cceb972..6e83727 100644 --- a/src/intermediate/verbatim.rs +++ b/src/intermediate/verbatim.rs @@ -7,9 +7,15 @@ pub(crate) struct IVerbatim { pub(crate) contents: String, } -intermediate!(IVerbatim, Verbatim, original, _registry, { - Ok(IVerbatim { - // TODO: Should this coalesce whitespace like PlainText? - contents: original.contents.to_owned(), - }) -}); +intermediate!( + IVerbatim, + &'orig organic::types::Verbatim<'parse>, + original, + _registry, + { + Ok(IVerbatim { + // TODO: Should this coalesce whitespace like PlainText? + contents: original.contents.to_owned(), + }) + } +); From d4b290ebe618272437124a472ed19f3b37c5027e Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Tue, 19 Dec 2023 17:31:50 -0500 Subject: [PATCH 15/18] Remove unnecessary let statements from render macro. --- src/context/macros.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/context/macros.rs b/src/context/macros.rs index 1b01231..1ed3338 100644 --- a/src/context/macros.rs +++ b/src/context/macros.rs @@ -5,11 +5,9 @@ macro_rules! render { ($rstruct:ident, $istruct:ident, $original:ident, $render_context:ident, $fnbody:tt) => { impl $rstruct { pub(crate) fn new( - render_context: RenderContext<'_>, - original: &$istruct, + $render_context: RenderContext<'_>, + $original: &$istruct, ) -> Result<$rstruct, CustomError> { - let $original = original; - let $render_context = render_context; $fnbody } } From 2e1c979127a9619a5584228e4de2e75f2ac2be72 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Tue, 19 Dec 2023 17:51:35 -0500 Subject: [PATCH 16/18] Add a prefix to footnote IDs. This avoids a conflict with multiple blog posts rendering in the same stream. --- src/command/build/render.rs | 2 + src/context/blog_stream.rs | 99 ++++++++++++++++++------- src/context/footnote_definition.rs | 4 +- src/context/footnote_reference.rs | 9 ++- src/context/render_context.rs | 9 +++ src/intermediate/footnote_definition.rs | 16 +++- src/intermediate/footnote_reference.rs | 18 +++-- 7 files changed, 115 insertions(+), 42 deletions(-) diff --git a/src/command/build/render.rs b/src/command/build/render.rs index 6373398..642a386 100644 --- a/src/command/build/render.rs +++ b/src/command/build/render.rs @@ -85,6 +85,7 @@ impl SiteRenderer { config, self.output_directory.as_path(), output_path.as_path(), + None, )?; let render_context = RenderBlogPostPage::new(render_context, &convert_input)?; let rendered_output = renderer_integration.render(render_context)?; @@ -165,6 +166,7 @@ impl SiteRenderer { config, self.output_directory.as_path(), output_file.as_path(), + None, )?; let blog_stream = RenderBlogStream::new(render_context, &convert_input)?; diff --git a/src/context/blog_stream.rs b/src/context/blog_stream.rs index 28f6bb0..9b571cc 100644 --- a/src/context/blog_stream.rs +++ b/src/context/blog_stream.rs @@ -86,7 +86,13 @@ render!( let children = original .original .into_iter() - .map(|blog_post| RenderBlogStreamEntry::new(render_context.clone(), blog_post)) + .enumerate() + .map(|(i, blog_post)| { + RenderBlogStreamEntry::new( + render_context.clone(), + &RenderBlogStreamEntryInput::new(blog_post, i), + ) + }) .collect::, _>>()?; let stream_pagination = if original.older_link.is_some() || original.newer_link.is_some() { @@ -107,6 +113,18 @@ render!( } ); +#[derive(Debug)] +pub(crate) struct RenderBlogStreamEntryInput<'a> { + original: &'a BlogPost, + offset: usize, +} + +impl<'a> RenderBlogStreamEntryInput<'a> { + fn new(original: &'a BlogPost, offset: usize) -> RenderBlogStreamEntryInput<'a> { + RenderBlogStreamEntryInput { original, offset } + } +} + #[derive(Debug, Serialize)] pub(crate) struct RenderBlogStreamEntry { /// The title that will be shown visibly on the page. @@ -119,37 +137,62 @@ pub(crate) struct RenderBlogStreamEntry { footnotes: Vec, } -render!(RenderBlogStreamEntry, BlogPost, original, render_context, { - let link_to_blog_post = get_web_path( - render_context.config, - render_context.output_directory, - render_context.output_file, - render_context - .config - .get_relative_path_to_post(&original.id), - )?; +render!( + RenderBlogStreamEntry, + RenderBlogStreamEntryInput, + original, + render_context, + { + let offset_string = original.offset.to_string(); + let render_context = { + let mut render_context = render_context.clone(); + render_context.id_addition = Some(offset_string.as_str()); + render_context + }; + let link_to_blog_post = get_web_path( + render_context.config, + render_context.output_directory, + render_context.output_file, + render_context + .config + .get_relative_path_to_post(&original.original.id), + )?; - // TODO: Should I guess an index page instead of erroring out? - let index_page = original - .get_index_page() - .ok_or_else(|| format!("Blog post {} needs an index page.", original.id))?; + // TODO: Should I guess an index page instead of erroring out? + let index_page = original + .original + .get_index_page() + .ok_or_else(|| format!("Blog post {} needs an index page.", original.original.id))?; - let title = index_page.title.clone(); + let title = index_page.title.clone(); - // TODO: Handle footnotes. - let children = index_page - .children - .iter() - .map(|child| RenderDocumentElement::new(render_context.clone(), child)) - .collect::, _>>()?; + let children = index_page + .children + .iter() + .map(|child| RenderDocumentElement::new(render_context.clone(), child)) + .collect::, _>>()?; - Ok(RenderBlogStreamEntry { - title, - self_link: Some(link_to_blog_post), - children, - footnotes: Vec::new(), - }) -}); + let footnotes = { + let mut ret = Vec::new(); + + for footnote in index_page.footnotes.iter() { + ret.push(RenderRealFootnoteDefinition::new( + render_context.clone(), + footnote, + )?); + } + + ret + }; + + Ok(RenderBlogStreamEntry { + title, + self_link: Some(link_to_blog_post), + children, + footnotes, + }) + } +); #[derive(Debug, Serialize)] pub(crate) struct RenderBlogStreamPagination { diff --git a/src/context/footnote_definition.rs b/src/context/footnote_definition.rs index de62fd4..8077f33 100644 --- a/src/context/footnote_definition.rs +++ b/src/context/footnote_definition.rs @@ -42,8 +42,8 @@ render!( }; Ok(RenderRealFootnoteDefinition { - definition_id: original.get_definition_id(), - reference_link: format!("#{}", original.get_reference_id()), + definition_id: original.get_definition_id(render_context.id_addition), + reference_link: format!("#{}", original.get_reference_id(render_context.id_addition)), label: original.get_display_label(), contents, }) diff --git a/src/context/footnote_reference.rs b/src/context/footnote_reference.rs index 3d4f00c..28e319d 100644 --- a/src/context/footnote_reference.rs +++ b/src/context/footnote_reference.rs @@ -19,11 +19,14 @@ render!( RenderFootnoteReference, IFootnoteReference, original, - _render_context, + render_context, { Ok(RenderFootnoteReference { - reference_id: original.get_reference_id(), - definition_link: format!("#{}", original.get_definition_id()), + reference_id: original.get_reference_id(render_context.id_addition), + definition_link: format!( + "#{}", + original.get_definition_id(render_context.id_addition) + ), label: original.get_display_label(), }) } diff --git a/src/context/render_context.rs b/src/context/render_context.rs index 4c8fcb7..ce4f933 100644 --- a/src/context/render_context.rs +++ b/src/context/render_context.rs @@ -10,6 +10,13 @@ pub(crate) struct RenderContext<'intermediate> { // TODO: Perhaps rename to output_root_directory. pub(crate) output_directory: &'intermediate Path, pub(crate) output_file: &'intermediate Path, + + /// An optional string that gets added to IDs in HTML. + /// + /// This is useful for cases where you may have conflicting HTML + /// IDs, for example, multiple blog posts with footnotes in a blog + /// stream. + pub(crate) id_addition: Option<&'intermediate str>, } impl<'intermediate> RenderContext<'intermediate> { @@ -17,11 +24,13 @@ impl<'intermediate> RenderContext<'intermediate> { config: &'intermediate Config, output_directory: &'intermediate Path, output_file: &'intermediate Path, + id_addition: Option<&'intermediate str>, ) -> Result, CustomError> { Ok(RenderContext { config, output_directory, output_file, + id_addition, }) } } diff --git a/src/intermediate/footnote_definition.rs b/src/intermediate/footnote_definition.rs index 336b40e..265c215 100644 --- a/src/intermediate/footnote_definition.rs +++ b/src/intermediate/footnote_definition.rs @@ -44,14 +44,22 @@ impl IRealFootnoteDefinition { /// Get an ID to refer to the first reference to this footnote definition. /// /// This ID could, for example, be used for the id attribute in HTML for the reference anchor tag. - pub(crate) fn get_reference_id(&self) -> String { - format!("fnr.{}", self.get_display_label()) + pub(crate) fn get_reference_id(&self, id_addition: Option<&str>) -> String { + let id_addition = id_addition + .map(|id_addition| format!("sec{}.", id_addition)) + .unwrap_or(String::default()); + + format!("{}fnr.{}", id_addition, self.get_display_label()) } /// Get an ID to refer to the footnote definition. /// /// This ID could, for example, be used for the id attribute in HTML for the definition anchor tag. - pub(crate) fn get_definition_id(&self) -> String { - format!("fn.{}", self.get_display_label()) + pub(crate) fn get_definition_id(&self, id_addition: Option<&str>) -> String { + let id_addition = id_addition + .map(|id_addition| format!("sec{}.", id_addition)) + .unwrap_or(String::default()); + + format!("{}fn.{}", id_addition, self.get_display_label()) } } diff --git a/src/intermediate/footnote_reference.rs b/src/intermediate/footnote_reference.rs index 7d3baa3..175edd2 100644 --- a/src/intermediate/footnote_reference.rs +++ b/src/intermediate/footnote_reference.rs @@ -32,20 +32,28 @@ impl IFootnoteReference { /// Get an ID to refer to this footnote reference. /// /// This ID could, for example, be used for the id attribute in HTML for the reference anchor tag. - pub(crate) fn get_reference_id(&self) -> String { + pub(crate) fn get_reference_id(&self, id_addition: Option<&str>) -> String { + let id_addition = id_addition + .map(|id_addition| format!("sec{}.", id_addition)) + .unwrap_or(String::default()); + if self.duplicate_offset == 0 { - format!("fnr.{}", self.get_display_label()) + format!("{}fnr.{}", id_addition, self.get_display_label()) } else { // Org-mode makes all duplicates use "100" but I figure there is no harm in giving each a unique ID. let append = 100 + self.duplicate_offset - 1; - format!("fnr.{}.{}", self.get_display_label(), append) + format!("{}fnr.{}.{}", id_addition, self.get_display_label(), append) } } /// Get an ID to refer to the footnote definition this footnote reference references. /// /// This ID could, for example, be used for the id attribute in HTML for the definition anchor tag. - pub(crate) fn get_definition_id(&self) -> String { - format!("fn.{}", self.get_display_label()) + pub(crate) fn get_definition_id(&self, id_addition: Option<&str>) -> String { + let id_addition = id_addition + .map(|id_addition| format!("sec{}.", id_addition)) + .unwrap_or(String::default()); + + format!("{}fn.{}", id_addition, self.get_display_label()) } } From 1581e5c4011d336906a9d9d9605b3c284db6f0e2 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Tue, 19 Dec 2023 18:03:59 -0500 Subject: [PATCH 17/18] Rename the output root directory in the render context. --- src/context/blog_post_page.rs | 10 +++++----- src/context/blog_stream.rs | 8 ++++---- src/context/render_context.rs | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/context/blog_post_page.rs b/src/context/blog_post_page.rs index 20ae9d5..1bbebdc 100644 --- a/src/context/blog_post_page.rs +++ b/src/context/blog_post_page.rs @@ -57,14 +57,14 @@ render!( // )?, get_web_path( render_context.config, - render_context.output_directory, + render_context.output_root_directory, render_context.output_file, "stylesheet/main.css", )?, ]; let js_files = vec![get_web_path( render_context.config, - render_context.output_directory, + render_context.output_root_directory, render_context.output_file, "blog_post.js", )?]; @@ -73,18 +73,18 @@ render!( render_context.config.get_site_title().map(str::to_string), Some(get_web_path( render_context.config, - render_context.output_directory, + render_context.output_root_directory, render_context.output_file, "", )?), ); let link_to_blog_post = get_web_path( render_context.config, - render_context.output_directory, + render_context.output_root_directory, render_context.output_file, render_context .output_file - .strip_prefix(render_context.output_directory)?, + .strip_prefix(render_context.output_root_directory)?, )?; let children = { diff --git a/src/context/blog_stream.rs b/src/context/blog_stream.rs index 9b571cc..8fc944f 100644 --- a/src/context/blog_stream.rs +++ b/src/context/blog_stream.rs @@ -57,14 +57,14 @@ render!( // )?, get_web_path( render_context.config, - render_context.output_directory, + render_context.output_root_directory, render_context.output_file, "stylesheet/main.css", )?, ]; let js_files = vec![get_web_path( render_context.config, - render_context.output_directory, + render_context.output_root_directory, render_context.output_file, "blog_post.js", )?]; @@ -77,7 +77,7 @@ render!( render_context.config.get_site_title().map(str::to_string), Some(get_web_path( render_context.config, - render_context.output_directory, + render_context.output_root_directory, render_context.output_file, "", )?), @@ -151,7 +151,7 @@ render!( }; let link_to_blog_post = get_web_path( render_context.config, - render_context.output_directory, + render_context.output_root_directory, render_context.output_file, render_context .config diff --git a/src/context/render_context.rs b/src/context/render_context.rs index ce4f933..18ad7d0 100644 --- a/src/context/render_context.rs +++ b/src/context/render_context.rs @@ -8,7 +8,7 @@ use crate::error::CustomError; pub(crate) struct RenderContext<'intermediate> { pub(crate) config: &'intermediate Config, // TODO: Perhaps rename to output_root_directory. - pub(crate) output_directory: &'intermediate Path, + pub(crate) output_root_directory: &'intermediate Path, pub(crate) output_file: &'intermediate Path, /// An optional string that gets added to IDs in HTML. @@ -28,7 +28,7 @@ impl<'intermediate> RenderContext<'intermediate> { ) -> Result, CustomError> { Ok(RenderContext { config, - output_directory, + output_root_directory: output_directory, output_file, id_addition, }) From da81f93e4adc90a0cd80ccdd57de777b1ff56577 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Tue, 19 Dec 2023 18:06:52 -0500 Subject: [PATCH 18/18] Re-enable the CSS reset sheet. --- src/context/blog_post_page.rs | 12 ++++++------ src/context/blog_stream.rs | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/context/blog_post_page.rs b/src/context/blog_post_page.rs index 1bbebdc..ed5b8d9 100644 --- a/src/context/blog_post_page.rs +++ b/src/context/blog_post_page.rs @@ -49,12 +49,12 @@ render!( render_context, { let css_files = vec![ - // get_web_path( - // config, - // output_directory, - // output_file, - // "stylesheet/reset.css", - // )?, + get_web_path( + render_context.config, + render_context.output_root_directory, + render_context.output_file, + "stylesheet/reset.css", + )?, get_web_path( render_context.config, render_context.output_root_directory, diff --git a/src/context/blog_stream.rs b/src/context/blog_stream.rs index 8fc944f..04fac51 100644 --- a/src/context/blog_stream.rs +++ b/src/context/blog_stream.rs @@ -49,12 +49,12 @@ render!( render_context, { let css_files = vec![ - // get_web_path( - // config, - // output_directory, - // output_file, - // "stylesheet/reset.css", - // )?, + get_web_path( + render_context.config, + render_context.output_root_directory, + render_context.output_file, + "stylesheet/reset.css", + )?, get_web_path( render_context.config, render_context.output_root_directory,