From 749f6d7a55db083b22e1d874d8d5fd9c1ccd10a8 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sat, 22 Feb 2025 17:20:08 -0500 Subject: [PATCH] Dynamically register which CSS files are needed. --- src/context/blog_post_page.rs | 70 ++++++++++++++++------------ src/context/blog_stream.rs | 76 ++++++++++++++++++------------- src/context/dependency.rs | 6 +++ src/context/dependency_manager.rs | 16 +++++++ src/context/page.rs | 68 ++++++++++++++++----------- src/context/src_block.rs | 12 ++++- 6 files changed, 161 insertions(+), 87 deletions(-) diff --git a/src/context/blog_post_page.rs b/src/context/blog_post_page.rs index f1d566b..eb81bd9 100644 --- a/src/context/blog_post_page.rs +++ b/src/context/blog_post_page.rs @@ -1,3 +1,5 @@ +use std::collections::HashSet; + use serde::Serialize; use super::render_context::RenderContext; @@ -51,34 +53,6 @@ render!( render_context, { push_file!(render_context, &original.page.src, { - 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", - )?, - get_web_path( - render_context.config, - render_context.output_root_directory, - render_context.output_file, - "stylesheet/language_nix.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( @@ -120,6 +94,46 @@ render!( ret }; + let mut 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 additional_css_files = render_context + .dependency_manager + .lock() + .unwrap() + .list_css()? + .map(|css_name| { + get_web_path( + render_context.config, + render_context.output_root_directory, + render_context.output_file, + format!("stylesheet/{}", css_name), + ) + }) + .collect::, _>>()?; + css_files.extend(additional_css_files.into_iter()); + + 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 ret = RenderBlogPostPage { global_settings, page_header: Some(page_header), diff --git a/src/context/blog_stream.rs b/src/context/blog_stream.rs index 9182226..635575e 100644 --- a/src/context/blog_stream.rs +++ b/src/context/blog_stream.rs @@ -1,3 +1,5 @@ +use std::collections::HashSet; + use serde::Serialize; use super::macros::render; @@ -49,37 +51,6 @@ render!( 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", - )?, - get_web_path( - render_context.config, - render_context.output_root_directory, - render_context.output_file, - "stylesheet/language_nix.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( @@ -111,6 +82,49 @@ render!( None }; + let mut 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 additional_css_files = render_context + .dependency_manager + .lock() + .unwrap() + .list_css()? + .map(|css_name| { + get_web_path( + render_context.config, + render_context.output_root_directory, + render_context.output_file, + format!("stylesheet/{}", css_name), + ) + }) + .collect::, _>>()?; + css_files.extend(additional_css_files.into_iter()); + + 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, + ); + Ok(RenderBlogStream { global_settings, page_header: Some(page_header), diff --git a/src/context/dependency.rs b/src/context/dependency.rs index e79063f..6e537f5 100644 --- a/src/context/dependency.rs +++ b/src/context/dependency.rs @@ -7,6 +7,7 @@ use super::RenderContext; #[derive(Debug)] pub(crate) enum Dependency { StaticFile { absolute_path: PathBuf }, + CssFile { name: String }, } impl Dependency { @@ -40,6 +41,11 @@ impl Dependency { } Ok(()) } + Dependency::CssFile { name } => { + // We don't do anything because the CSS files are already copied into the output from natter's default environment. + // TODO: When we add support for CSS outside the default environment, we should add support for dynamically picking which ones to copy here. + Ok(()) + } } } } diff --git a/src/context/dependency_manager.rs b/src/context/dependency_manager.rs index a5355b6..7667c47 100644 --- a/src/context/dependency_manager.rs +++ b/src/context/dependency_manager.rs @@ -65,4 +65,20 @@ impl DependencyManager { std::mem::swap(&mut self.dependencies, &mut dependencies); dependencies } + + pub(crate) fn include_css(&mut self, name: N) -> Result<(), CustomError> + where + std::string::String: From, + { + self.dependencies + .push(Dependency::CssFile { name: name.into() }); + Ok(()) + } + + pub(crate) fn list_css(&self) -> Result, CustomError> { + Ok(self.dependencies.iter().filter_map(|dep| match dep { + Dependency::CssFile { name } => Some(name), + _ => None, + })) + } } diff --git a/src/context/page.rs b/src/context/page.rs index 5515189..be4108d 100644 --- a/src/context/page.rs +++ b/src/context/page.rs @@ -1,3 +1,5 @@ +use std::collections::HashSet; + use super::footnote_definition::RenderRealFootnoteDefinition; use super::macros::render; use super::render_context::RenderContext; @@ -30,33 +32,6 @@ pub(crate) struct RenderPage { render!(RenderPage, IPage, original, render_context, { push_file!(render_context, &original.src, { - 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", - )?, - get_web_path( - render_context.config, - render_context.output_root_directory, - render_context.output_file, - "stylesheet/language_nix.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.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( @@ -98,6 +73,45 @@ render!(RenderPage, IPage, original, render_context, { ret }; + let mut 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 additional_css_files = render_context + .dependency_manager + .lock() + .unwrap() + .list_css()? + .map(|css_name| { + get_web_path( + render_context.config, + render_context.output_root_directory, + render_context.output_file, + format!("stylesheet/{}", css_name), + ) + }) + .collect::, _>>()?; + css_files.extend(additional_css_files.into_iter()); + + 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.title.clone(), css_files, js_files); + let ret = RenderPage { global_settings, page_header: Some(page_header), diff --git a/src/context/src_block.rs b/src/context/src_block.rs index 34c32e3..e8af3ac 100644 --- a/src/context/src_block.rs +++ b/src/context/src_block.rs @@ -34,7 +34,7 @@ pub(crate) enum RenderSrcSegment { HighlightEnd, } -render!(RenderSrcBlock, ISrcBlock, original, _render_context, { +render!(RenderSrcBlock, ISrcBlock, original, render_context, { let lines = original .lines .iter() @@ -55,6 +55,16 @@ render!(RenderSrcBlock, ISrcBlock, original, _render_context, { RenderSrcLine { children } }) .collect(); + match original.language.as_ref().map(String::as_str) { + Some("nix") => { + render_context + .dependency_manager + .lock() + .unwrap() + .include_css("language_nix.css")?; + } + _ => {} + }; Ok(RenderSrcBlock { lines, language: original.language.clone(),