Merge branch 'homepage'
This commit is contained in:
		
						commit
						050b426f6f
					
				| @ -1,6 +1,6 @@ | ||||
| <div class="blog_post"> | ||||
|   <div class="blog_post_intro"> | ||||
|     {?.title}{?.self_link}<a class="blog_post_title" href="{.link}">{.title}</a>{:else}<div class="blog_post_title">{.title}</div>{/.self_link}{/.title} | ||||
|     {?.title}{?.self_link}<a class="blog_post_title" href="{.self_link}">{.title}</a>{:else}<div class="blog_post_title">{.title}</div>{/.self_link}{/.title} | ||||
|     {! TODO: date? !} | ||||
|   </div> | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										31
									
								
								default_environment/templates/html/blog_stream.dust
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								default_environment/templates/html/blog_stream.dust
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| <div class="blog_stream"> | ||||
|   {#.children} | ||||
|     <div class="blog_stream_post"> | ||||
|       <div class="blog_post_intro"> | ||||
|         {?.title}{?.self_link}<a class="blog_post_title" href="{.self_link}">{.title}</a>{:else}<div class="blog_post_title">{.title}</div>{/.self_link}{/.title} | ||||
|         {! TODO: date? !} | ||||
|       </div> | ||||
| 
 | ||||
|       {! TODO: Table of contents? !} | ||||
| 
 | ||||
|       <div class="blog_post_body"> | ||||
|         {#.children} | ||||
|           {>document_element/} | ||||
|         {/.children} | ||||
| 
 | ||||
|         {?.footnotes} | ||||
|           <h2>Footnotes:</h2> | ||||
|           {#.footnotes} | ||||
|             {>real_footnote_definition/} | ||||
|           {/.footnotes} | ||||
|         {/.footnotes} | ||||
|       </div> | ||||
|     </div> | ||||
|   {/.children} | ||||
|   {#.stream_pagination} | ||||
|     <div class="stream_nav"> | ||||
|       {?.older_link}<a href="{.older_link}">Older</a>{/.older_link} | ||||
|       {?.newer_link}<a href="{.newer_link}">Newer</a>{/.newer_link} | ||||
|     </div> | ||||
|   {/.stream_pagination} | ||||
| </div> | ||||
| @ -11,6 +11,7 @@ | ||||
|     <div class="main_content"> | ||||
|       {@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} | ||||
|     </div> | ||||
|  | ||||
| @ -5,8 +5,13 @@ 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; | ||||
| use crate::render::RendererIntegration; | ||||
| @ -34,7 +39,7 @@ impl SiteRenderer { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub(crate) async fn render_blog_posts(&self, config: &Config) -> Result<(), CustomError> { | ||||
|     fn init_renderer_integration(&self) -> Result<DusterRenderer<'_>, CustomError> { | ||||
|         let mut renderer_integration = DusterRenderer::new(); | ||||
| 
 | ||||
|         let sources: Vec<_> = MAIN_TEMPLATES | ||||
| @ -62,21 +67,27 @@ 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 | ||||
|                     .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 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(), | ||||
|                     None, | ||||
|                 )?; | ||||
|                 let render_context = RenderBlogPostPage::new(render_context, &convert_input)?; | ||||
|                 let rendered_output = renderer_integration.render(render_context)?; | ||||
|                 let parent_directory = output_path | ||||
|                     .parent() | ||||
| @ -89,6 +100,87 @@ impl SiteRenderer { | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     pub(crate) async fn render_blog_stream(&self, config: &Config) -> Result<(), CustomError> { | ||||
|         let renderer_integration = self.init_renderer_integration()?; | ||||
| 
 | ||||
|         // 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 (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), | ||||
|                 )?) | ||||
|             }; | ||||
| 
 | ||||
|             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(), | ||||
|                 None, | ||||
|             )?; | ||||
|             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)?; | ||||
|             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(()) | ||||
|     } | ||||
| 
 | ||||
|     pub(crate) async fn render_stylesheets(&self) -> Result<(), CustomError> { | ||||
|         let stylesheet_output_directory = self.output_directory.join("stylesheet"); | ||||
|         if !stylesheet_output_directory.exists() { | ||||
|  | ||||
| @ -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(()) | ||||
|  | ||||
| @ -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, | ||||
| @ -56,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<P: AsRef<Path>>(&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") | ||||
|     } | ||||
| @ -71,4 +81,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) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -2,13 +2,14 @@ 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<String>, | ||||
|     author: Option<String>, | ||||
|     email: Option<String>, | ||||
|     pub(super) use_relative_paths: Option<bool>, | ||||
|     pub(super) web_root: Option<String>, | ||||
|     pub(super) stream: Option<RawConfigStream>, | ||||
| } | ||||
| 
 | ||||
| impl Default for RawConfig { | ||||
| @ -19,6 +20,20 @@ impl Default for RawConfig { | ||||
|             email: None, | ||||
|             use_relative_paths: None, | ||||
|             web_root: None, | ||||
|             stream: None, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Deserialize, Serialize)] | ||||
| pub(crate) struct RawConfigStream { | ||||
|     pub(super) entries_per_page: Option<usize>, | ||||
| } | ||||
| 
 | ||||
| impl Default for RawConfigStream { | ||||
|     fn default() -> Self { | ||||
|         RawConfigStream { | ||||
|             entries_per_page: None, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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<RenderAstNode, CustomError>; | ||||
| } | ||||
| 
 | ||||
| impl IntoRenderAstNode for IAstNode { | ||||
|     fn into_render_ast_node( | ||||
|         &self, | ||||
|         config: &Config, | ||||
|         output_directory: &Path, | ||||
|         output_file: &Path, | ||||
|         render_context: RenderContext<'_>, | ||||
|     ) -> Result<RenderAstNode, CustomError> { | ||||
|         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, | ||||
|             )?)), | ||||
|         } | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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<RenderRealFootnoteDefinition>, | ||||
| } | ||||
| 
 | ||||
| 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<PageHeader>, | ||||
|         title: Option<String>, | ||||
|         self_link: Option<String>, | ||||
|         children: Vec<RenderDocumentElement>, | ||||
|         footnotes: Vec<RenderRealFootnoteDefinition>, | ||||
|     ) -> RenderBlogPostPage { | ||||
|         RenderBlogPostPage { | ||||
| render!( | ||||
|     RenderBlogPostPage, | ||||
|     RenderBlogPostPageInput, | ||||
|     original, | ||||
|     render_context, | ||||
|     { | ||||
|         let css_files = vec![ | ||||
|             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, | ||||
|                 render_context.output_file, | ||||
|                 "stylesheet/main.css", | ||||
|             )?, | ||||
|         ]; | ||||
|         let js_files = vec![get_web_path( | ||||
|             render_context.config, | ||||
|             render_context.output_root_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_root_directory, | ||||
|                 render_context.output_file, | ||||
|                 "", | ||||
|             )?), | ||||
|         ); | ||||
|         let link_to_blog_post = get_web_path( | ||||
|             render_context.config, | ||||
|             render_context.output_root_directory, | ||||
|             render_context.output_file, | ||||
|             render_context | ||||
|                 .output_file | ||||
|                 .strip_prefix(render_context.output_root_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) | ||||
|     } | ||||
| } | ||||
| ); | ||||
|  | ||||
							
								
								
									
										213
									
								
								src/context/blog_stream.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										213
									
								
								src/context/blog_stream.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,213 @@ | ||||
| use serde::Serialize; | ||||
| 
 | ||||
| use super::macros::render; | ||||
| use super::render_context::RenderContext; | ||||
| 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; | ||||
| use super::PageHeader; | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub(crate) struct RenderBlogStreamInput<'a, 'b> { | ||||
|     original: &'a [&'b BlogPost], | ||||
|     older_link: Option<String>, | ||||
|     newer_link: Option<String>, | ||||
| } | ||||
| 
 | ||||
| impl<'a, 'b> RenderBlogStreamInput<'a, 'b> { | ||||
|     pub(crate) fn new( | ||||
|         original: &'a [&'b BlogPost], | ||||
|         older_link: Option<String>, | ||||
|         newer_link: Option<String>, | ||||
|     ) -> RenderBlogStreamInput<'a, 'b> { | ||||
|         RenderBlogStreamInput { | ||||
|             original, | ||||
|             older_link, | ||||
|             newer_link, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Serialize)] | ||||
| #[serde(tag = "type")] | ||||
| #[serde(rename = "blog_stream")] | ||||
| pub(crate) struct RenderBlogStream { | ||||
|     global_settings: GlobalSettings, | ||||
|     page_header: Option<PageHeader>, | ||||
|     children: Vec<RenderBlogStreamEntry>, | ||||
|     stream_pagination: Option<RenderBlogStreamPagination>, | ||||
| } | ||||
| 
 | ||||
| render!( | ||||
|     RenderBlogStream, | ||||
|     RenderBlogStreamInput, | ||||
|     original, | ||||
|     render_context, | ||||
|     { | ||||
|         let css_files = vec![ | ||||
|             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, | ||||
|                 render_context.output_file, | ||||
|                 "stylesheet/main.css", | ||||
|             )?, | ||||
|         ]; | ||||
|         let js_files = vec![get_web_path( | ||||
|             render_context.config, | ||||
|             render_context.output_root_directory, | ||||
|             render_context.output_file, | ||||
|             "blog_post.js", | ||||
|         )?]; | ||||
|         let global_settings = GlobalSettings::new( | ||||
|             render_context.config.get_site_title().map(str::to_string), | ||||
|             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_root_directory, | ||||
|                 render_context.output_file, | ||||
|                 "", | ||||
|             )?), | ||||
|         ); | ||||
| 
 | ||||
|         let children = original | ||||
|             .original | ||||
|             .into_iter() | ||||
|             .enumerate() | ||||
|             .map(|(i, blog_post)| { | ||||
|                 RenderBlogStreamEntry::new( | ||||
|                     render_context.clone(), | ||||
|                     &RenderBlogStreamEntryInput::new(blog_post, i), | ||||
|                 ) | ||||
|             }) | ||||
|             .collect::<Result<Vec<_>, _>>()?; | ||||
| 
 | ||||
|         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 | ||||
|         }; | ||||
| 
 | ||||
|         Ok(RenderBlogStream { | ||||
|             global_settings, | ||||
|             page_header: Some(page_header), | ||||
|             children, | ||||
|             stream_pagination, | ||||
|         }) | ||||
|     } | ||||
| ); | ||||
| 
 | ||||
| #[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.
 | ||||
|     title: Option<String>, | ||||
| 
 | ||||
|     self_link: Option<String>, | ||||
| 
 | ||||
|     children: Vec<RenderDocumentElement>, | ||||
| 
 | ||||
|     footnotes: Vec<RenderRealFootnoteDefinition>, | ||||
| } | ||||
| 
 | ||||
| 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_root_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 | ||||
|             .original | ||||
|             .get_index_page() | ||||
|             .ok_or_else(|| format!("Blog post {} needs an index page.", original.original.id))?; | ||||
| 
 | ||||
|         let title = index_page.title.clone(); | ||||
| 
 | ||||
|         let children = index_page | ||||
|             .children | ||||
|             .iter() | ||||
|             .map(|child| RenderDocumentElement::new(render_context.clone(), child)) | ||||
|             .collect::<Result<Vec<_>, _>>()?; | ||||
| 
 | ||||
|         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 { | ||||
|     older_link: Option<String>, | ||||
|     newer_link: Option<String>, | ||||
| } | ||||
| 
 | ||||
| impl RenderBlogStreamPagination { | ||||
|     fn new( | ||||
|         older_link: Option<String>, | ||||
|         newer_link: Option<String>, | ||||
|     ) -> Result<RenderBlogStreamPagination, CustomError> { | ||||
|         Ok(RenderBlogStreamPagination { | ||||
|             older_link, | ||||
|             newer_link, | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| @ -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<RenderObject>, | ||||
| } | ||||
| 
 | ||||
| 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 }) | ||||
| }); | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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(), | ||||
|     }) | ||||
| }); | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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)?, | ||||
|             )), | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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)?, | ||||
|         )), | ||||
|     } | ||||
| ); | ||||
| }); | ||||
|  | ||||
| @ -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(), | ||||
|     }) | ||||
| }); | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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,21 +31,19 @@ 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 | ||||
|         }; | ||||
| 
 | ||||
|         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, | ||||
|         }) | ||||
|  | ||||
| @ -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,13 +19,14 @@ render!( | ||||
|     RenderFootnoteReference, | ||||
|     IFootnoteReference, | ||||
|     original, | ||||
|     _config, | ||||
|     _output_directory, | ||||
|     _output_file, | ||||
|     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(), | ||||
|         }) | ||||
|     } | ||||
|  | ||||
| @ -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<RenderDocumentElement>, | ||||
| } | ||||
| 
 | ||||
| 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, | ||||
|     }) | ||||
| }); | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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(), | ||||
|  | ||||
| @ -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<RenderObject>, | ||||
| } | ||||
| 
 | ||||
| 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 }) | ||||
| }); | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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(), | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -2,18 +2,12 @@ | ||||
| ///
 | ||||
| /// 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, | ||||
|                 original: &$istruct, | ||||
|                 $render_context: RenderContext<'_>, | ||||
|                 $original: &$istruct, | ||||
|             ) -> Result<$rstruct, CustomError> { | ||||
|                 let $original = original; | ||||
|                 let $config = config; | ||||
|                 let $output_directory = output_directory; | ||||
|                 let $output_file = output_file; | ||||
|                 $fnbody | ||||
|             } | ||||
|         } | ||||
| @ -29,9 +23,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 {}) | ||||
|  | ||||
| @ -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; | ||||
| @ -47,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; | ||||
| @ -64,6 +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; | ||||
| @ -71,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; | ||||
|  | ||||
| @ -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, | ||||
|         )?)), | ||||
|     } | ||||
| ); | ||||
| }); | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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<RenderObject>, | ||||
| } | ||||
| 
 | ||||
| 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 }) | ||||
| }); | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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<RenderPlainListItem>, | ||||
| } | ||||
| 
 | ||||
| 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, | ||||
|     }) | ||||
| }); | ||||
|  | ||||
| @ -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 | ||||
|         }; | ||||
|  | ||||
| @ -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(), | ||||
|     }) | ||||
| }); | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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<RenderElement>, | ||||
| } | ||||
| 
 | ||||
| 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 }) | ||||
| }); | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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<RenderObject>, | ||||
| } | ||||
| 
 | ||||
| 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, | ||||
|     }) | ||||
| }); | ||||
|  | ||||
							
								
								
									
										36
									
								
								src/context/render_context.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/context/render_context.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| 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_root_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> { | ||||
|     pub(crate) fn new( | ||||
|         config: &'intermediate Config, | ||||
|         output_directory: &'intermediate Path, | ||||
|         output_file: &'intermediate Path, | ||||
|         id_addition: Option<&'intermediate str>, | ||||
|     ) -> Result<RenderContext<'intermediate>, CustomError> { | ||||
|         Ok(RenderContext { | ||||
|             config, | ||||
|             output_root_directory: output_directory, | ||||
|             output_file, | ||||
|             id_addition, | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| @ -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<RenderElement>, | ||||
| } | ||||
| 
 | ||||
| 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 }) | ||||
| }); | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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<String>, | ||||
| } | ||||
| 
 | ||||
| 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(), | ||||
|     }) | ||||
| }); | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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 | ||||
|         }; | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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<RenderTableRow>, | ||||
| } | ||||
| 
 | ||||
| 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 }) | ||||
| }); | ||||
|  | ||||
| @ -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<RenderObject>, | ||||
| } | ||||
| 
 | ||||
| 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 }) | ||||
| }); | ||||
|  | ||||
| @ -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<RenderTableCell>, | ||||
| } | ||||
| 
 | ||||
| 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 }) | ||||
| }); | ||||
|  | ||||
| @ -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(), | ||||
|     }) | ||||
| }); | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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<RenderObject>, | ||||
| } | ||||
| 
 | ||||
| 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 }) | ||||
| }); | ||||
|  | ||||
| @ -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(), | ||||
|     }) | ||||
| }); | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
| @ -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<String> for CustomError { | ||||
|     fn from(value: String) -> Self { | ||||
|         CustomError::String(value) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<toml::ser::Error> for CustomError { | ||||
|     fn from(value: toml::ser::Error) -> Self { | ||||
|         CustomError::TomlSerialize(value) | ||||
|  | ||||
| @ -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 | ||||
| @ -77,6 +81,37 @@ 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) -> 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; | ||||
|         } | ||||
| 
 | ||||
|         self.pages | ||||
|             .iter() | ||||
|             .filter_map(|page| page.date.as_ref().map(String::as_str)) | ||||
|             .next() | ||||
|     } | ||||
| 
 | ||||
|     /// Get the blog post page for index.org
 | ||||
|     pub(crate) fn get_index_page(&self) -> Option<&BlogPostPage> { | ||||
|         self.pages | ||||
|             .iter() | ||||
|             .find(|page| page.path == Path::new("index.org")) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| async fn read_file(path: PathBuf) -> std::io::Result<(PathBuf, String)> { | ||||
| @ -8,14 +8,20 @@ pub(crate) struct IBold { | ||||
|     pub(crate) children: Vec<IObject>, | ||||
| } | ||||
| 
 | ||||
| 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 }) | ||||
|     } | ||||
| ); | ||||
|  | ||||
| @ -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(), | ||||
|         }) | ||||
|     } | ||||
| ); | ||||
|  | ||||
| @ -3,94 +3,9 @@ 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<D: AsRef<Path>, F: AsRef<Path>>( | ||||
|     config: &Config, | ||||
|     output_directory: D, | ||||
|     output_file: F, | ||||
|     _post: &BlogPost, | ||||
|     page: &BlogPostPage, | ||||
| ) -> Result<RenderBlogPostPage, CustomError> { | ||||
|     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) | ||||
| } | ||||
| 
 | ||||
| fn get_web_path<D: AsRef<Path>, F: AsRef<Path>, P: AsRef<Path>>( | ||||
| pub(crate) fn get_web_path<D: AsRef<Path>, F: AsRef<Path>, P: AsRef<Path>>( | ||||
|     config: &Config, | ||||
|     output_directory: D, | ||||
|     containing_file: F, | ||||
|  | ||||
| @ -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(), | ||||
|         }) | ||||
|     } | ||||
| ); | ||||
|  | ||||
| @ -10,7 +10,7 @@ pub(crate) struct IFootnoteDefinition {} | ||||
| 
 | ||||
| intermediate!( | ||||
|     IFootnoteDefinition, | ||||
|     FootnoteDefinition, | ||||
|     &'orig organic::types::FootnoteDefinition<'parse>, | ||||
|     original, | ||||
|     registry, | ||||
|     { | ||||
| @ -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()) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -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 { | ||||
| @ -26,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()) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -11,24 +11,30 @@ pub(crate) struct IHeading { | ||||
|     pub(crate) children: Vec<IDocumentElement>, | ||||
| } | ||||
| 
 | ||||
| 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, | ||||
|         }) | ||||
|     } | ||||
| ); | ||||
|  | ||||
| @ -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(), | ||||
|         }) | ||||
|     } | ||||
| ); | ||||
|  | ||||
| @ -8,14 +8,20 @@ pub(crate) struct IItalic { | ||||
|     pub(crate) children: Vec<IObject>, | ||||
| } | ||||
| 
 | ||||
| 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 }) | ||||
|     } | ||||
| ); | ||||
|  | ||||
| @ -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 }) | ||||
|     } | ||||
| ); | ||||
|  | ||||
| @ -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 | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @ -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; | ||||
| @ -75,8 +76,7 @@ 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 definition::BlogPost; | ||||
| pub(crate) use convert::get_web_path; | ||||
| pub(crate) use diary_sexp::IDiarySexp; | ||||
| pub(crate) use document_element::IDocumentElement; | ||||
| pub(crate) use drawer::IDrawer; | ||||
|  | ||||
| @ -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<P: Into<PathBuf>>( | ||||
|         path: P, | ||||
|         document: &'b organic::types::Document<'parse>, | ||||
|     ) -> BlogPostPageInput<'b, 'parse> { | ||||
|         BlogPostPageInput { | ||||
|             path: path.into(), | ||||
|             document, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub(crate) struct BlogPostPage { | ||||
| @ -16,26 +34,26 @@ pub(crate) struct BlogPostPage { | ||||
| 
 | ||||
|     pub(crate) title: Option<String>, | ||||
| 
 | ||||
|     pub(crate) date: Option<String>, | ||||
| 
 | ||||
|     pub(crate) children: Vec<IDocumentElement>, | ||||
| 
 | ||||
|     pub(crate) footnotes: Vec<IRealFootnoteDefinition>, | ||||
| } | ||||
| 
 | ||||
| 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<PathBuf>>( | ||||
|         path: P, | ||||
|         registry: RefRegistry<'b, 'parse>, | ||||
|         document: &'b organic::types::Document<'parse>, | ||||
|     ) -> Result<BlogPostPage, CustomError> { | ||||
|         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?, | ||||
|             )); | ||||
| @ -58,13 +76,16 @@ impl BlogPostPage { | ||||
|         }; | ||||
| 
 | ||||
|         Ok(BlogPostPage { | ||||
|             path, | ||||
|             title: get_title(&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(); | ||||
| @ -85,3 +106,14 @@ fn get_title(document: &organic::types::Document<'_>) -> Option<String> { | ||||
|         .last() | ||||
|         .map(|kw| kw.value.to_owned()) | ||||
| } | ||||
| 
 | ||||
| fn get_date(document: &organic::types::Document<'_>) -> Option<String> { | ||||
|     organic::types::AstNode::from(document) | ||||
|         .iter_all_ast_nodes() | ||||
|         .filter_map(|node| match node { | ||||
|             organic::types::AstNode::Keyword(kw) if kw.key.eq_ignore_ascii_case("date") => Some(kw), | ||||
|             _ => None, | ||||
|         }) | ||||
|         .last() | ||||
|         .map(|kw| kw.value.to_owned()) | ||||
| } | ||||
|  | ||||
| @ -8,14 +8,20 @@ pub(crate) struct IParagraph { | ||||
|     pub(crate) children: Vec<IObject>, | ||||
| } | ||||
| 
 | ||||
| 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 }) | ||||
|     } | ||||
| ); | ||||
|  | ||||
| @ -9,17 +9,23 @@ pub(crate) struct IPlainList { | ||||
|     pub(crate) children: Vec<IPlainListItem>, | ||||
| } | ||||
| 
 | ||||
| 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, | ||||
|         }) | ||||
|     } | ||||
| ); | ||||
|  | ||||
| @ -10,22 +10,28 @@ pub(crate) struct IPlainListItem { | ||||
|     pub(crate) children: Vec<IElement>, | ||||
| } | ||||
| 
 | ||||
| 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 }) | ||||
|     } | ||||
| ); | ||||
|  | ||||
| @ -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(), | ||||
|         }) | ||||
|     } | ||||
| ); | ||||
|  | ||||
| @ -8,14 +8,20 @@ pub(crate) struct IQuoteBlock { | ||||
|     pub(crate) children: Vec<IElement>, | ||||
| } | ||||
| 
 | ||||
| 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 }) | ||||
|     } | ||||
| ); | ||||
|  | ||||
| @ -9,16 +9,22 @@ pub(crate) struct IRegularLink { | ||||
|     pub(crate) children: Vec<IObject>, | ||||
| } | ||||
| 
 | ||||
| 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, | ||||
|         }) | ||||
|     } | ||||
| ); | ||||
|  | ||||
| @ -8,14 +8,20 @@ pub(crate) struct ISection { | ||||
|     pub(crate) children: Vec<IElement>, | ||||
| } | ||||
| 
 | ||||
| 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 }) | ||||
|     } | ||||
| ); | ||||
|  | ||||
| @ -7,11 +7,17 @@ pub(crate) struct ISrcBlock { | ||||
|     pub(crate) lines: Vec<String>, | ||||
| } | ||||
| 
 | ||||
| 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 }) | ||||
|     } | ||||
| ); | ||||
|  | ||||
| @ -8,14 +8,20 @@ pub(crate) struct IStrikeThrough { | ||||
|     pub(crate) children: Vec<IObject>, | ||||
| } | ||||
| 
 | ||||
| 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 }) | ||||
|     } | ||||
| ); | ||||
|  | ||||
| @ -8,14 +8,20 @@ pub(crate) struct ITable { | ||||
|     pub(crate) children: Vec<ITableRow>, | ||||
| } | ||||
| 
 | ||||
| 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 }) | ||||
|     } | ||||
| ); | ||||
|  | ||||
| @ -8,14 +8,20 @@ pub(crate) struct ITableCell { | ||||
|     pub(crate) children: Vec<IObject>, | ||||
| } | ||||
| 
 | ||||
| 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 }) | ||||
|     } | ||||
| ); | ||||
|  | ||||
| @ -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<ITableCell>, | ||||
| } | ||||
| 
 | ||||
| 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 }) | ||||
|     } | ||||
| ); | ||||
|  | ||||
| @ -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(), | ||||
|         }) | ||||
|     } | ||||
| ); | ||||
|  | ||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Tom Alexander
						Tom Alexander