From 32f25ce86390cbc0f309d14c39ea10dd3c3c5d19 Mon Sep 17 00:00:00 2001 From: liquidev Date: Fri, 22 Nov 2024 23:12:57 +0100 Subject: [PATCH] implement generation of simple templates (/sandbox) --- crates/treehouse/src/dirs.rs | 2 +- crates/treehouse/src/generate.rs | 83 ++++++++++++++-------- crates/treehouse/src/html/djot.rs | 4 +- crates/treehouse/src/main.rs | 2 +- crates/treehouse/src/tree/mini_template.rs | 2 +- crates/treehouse/src/vfs/path.rs | 3 + template/sandbox.hbs | 2 + 7 files changed, 63 insertions(+), 35 deletions(-) diff --git a/crates/treehouse/src/dirs.rs b/crates/treehouse/src/dirs.rs index 48f432d..384d7d7 100644 --- a/crates/treehouse/src/dirs.rs +++ b/crates/treehouse/src/dirs.rs @@ -9,7 +9,7 @@ pub struct Dirs { pub template: DynDir, // `static` directories - pub pics: DynDir, + pub pic: DynDir, pub emoji: DynDir, pub syntax: DynDir, } diff --git a/crates/treehouse/src/generate.rs b/crates/treehouse/src/generate.rs index d7fd4bf..9d63750 100644 --- a/crates/treehouse/src/generate.rs +++ b/crates/treehouse/src/generate.rs @@ -180,31 +180,32 @@ fn parse_trees( Ok((treehouse, parsed_trees)) } -// TODO: Generation of pages in static/html -// -// for (name, &file_id) in &template_file_ids { -// let filename = name.rsplit_once('/').unwrap_or(("", name)).1; -// if !filename.starts_with('_') { -// let templated_html = match handlebars.render(name, &base_template_data) { -// Ok(html) => html, -// Err(error) => { -// Self::wrangle_handlebars_error_into_diagnostic( -// treehouse, -// &mut global_diagnostics, -// file_id, -// error.line_no, -// error.column_no, -// error.desc, -// )?; -// continue; -// } -// }; -// std::fs::write( -// paths.template_target_dir.join(name).with_extension("html"), -// templated_html, -// )?; -// } -// } +fn generate_simple_template( + sources: &Sources, + handlebars: &Handlebars, + template_name: &str, +) -> anyhow::Result { + let base_template_data = BaseTemplateData { + config: &sources.config, + import_map: serde_json::to_string_pretty(&sources.import_map) + .expect("import map should be serializable to JSON"), + season: Season::current(), + }; + handlebars + .render(template_name, &base_template_data) + .context("failed to render template") +} + +fn generate_simple_template_or_error( + sources: &Sources, + handlebars: &Handlebars, + template_name: &str, +) -> String { + match generate_simple_template(sources, handlebars, template_name) { + Ok(html) => html, + Err(error) => format!("error: {error:?}"), + } +} fn generate_tree( sources: &Sources, @@ -249,7 +250,7 @@ fn generate_tree( .thumbnail .as_ref() .map(|thumbnail| Thumbnail { - url: sources.config.pic_url(&*dirs.pics, &thumbnail.id), + url: sources.config.pic_url(&*dirs.pic, &thumbnail.id), alt: thumbnail.alt.clone(), }), scripts: roots.attributes.scripts.clone(), @@ -311,7 +312,7 @@ impl Sources { .context("failed to deserialize config")?; config.site = std::env::var("TREEHOUSE_SITE").unwrap_or(config.site); config.autopopulate_emoji(&*dirs.emoji)?; - config.autopopulate_pics(&*dirs.pics)?; + config.autopopulate_pics(&*dirs.pic)?; config.load_syntaxes(&*dirs.syntax)?; info!("parsing tree files"); @@ -391,6 +392,8 @@ impl TreehouseDir { impl Dir for TreehouseDir { fn dir(&self, path: &VPath) -> Vec { + // NOTE: This does not include simple templates, because that's not really needed right now. + let mut index = &self.dir_index; for component in path.segments() { if let Some(child) = index.children.get(component) { @@ -424,9 +427,29 @@ impl Dir for TreehouseDir { path.set_extension(""); } - self.sources.parsed_trees.get(&path).map(|parsed_tree| { - generate_tree_or_error(&self.sources, &self.dirs, &self.handlebars, parsed_tree).into() - }) + self.sources + .parsed_trees + .get(&path) + .map(|parsed_tree| { + generate_tree_or_error(&self.sources, &self.dirs, &self.handlebars, parsed_tree) + .into() + }) + .or_else(|| { + if path.file_name().is_some_and(|s| !s.starts_with('_')) { + let template_name = path.with_extension("hbs"); + if self.handlebars.has_template(template_name.as_str()) { + return Some( + generate_simple_template_or_error( + &self.sources, + &self.handlebars, + template_name.as_str(), + ) + .into(), + ); + } + } + None + }) } fn content_version(&self, _path: &VPath) -> Option { diff --git a/crates/treehouse/src/html/djot.rs b/crates/treehouse/src/html/djot.rs index 93a2d6c..4da9273 100644 --- a/crates/treehouse/src/html/djot.rs +++ b/crates/treehouse/src/html/djot.rs @@ -375,7 +375,7 @@ impl<'a> Writer<'a> { let pic_url = self .renderer .config - .pic_url(&*self.renderer.dirs.pics, placeholder_pic_id); + .pic_url(&*self.renderer.dirs.pic, placeholder_pic_id); write_attr(&pic_url, out); out.push('"'); @@ -648,7 +648,7 @@ impl<'a> Writer<'a> { ) }), "page" => Some(config.page_url(linked)), - "pic" => Some(config.pic_url(&*self.renderer.dirs.pics, linked)), + "pic" => Some(config.pic_url(&*self.renderer.dirs.pic, linked)), _ => None, }) } diff --git a/crates/treehouse/src/main.rs b/crates/treehouse/src/main.rs index 4140414..0242371 100644 --- a/crates/treehouse/src/main.rs +++ b/crates/treehouse/src/main.rs @@ -54,7 +54,7 @@ async fn fallible_main() -> anyhow::Result<()> { content: Cd::new(src.clone(), VPathBuf::new("content")).to_dyn(), static_: Cd::new(src.clone(), VPathBuf::new("static")).to_dyn(), template: Cd::new(src.clone(), VPathBuf::new("template")).to_dyn(), - pics: Cd::new(src.clone(), VPathBuf::new("static/pics")).to_dyn(), + pic: Cd::new(src.clone(), VPathBuf::new("static/pic")).to_dyn(), emoji: Cd::new(src.clone(), VPathBuf::new("static/emoji")).to_dyn(), syntax: Cd::new(src.clone(), VPathBuf::new("static/syntax")).to_dyn(), }); diff --git a/crates/treehouse/src/tree/mini_template.rs b/crates/treehouse/src/tree/mini_template.rs index 3bcb2a6..accea1b 100644 --- a/crates/treehouse/src/tree/mini_template.rs +++ b/crates/treehouse/src/tree/mini_template.rs @@ -203,7 +203,7 @@ impl Renderer<'_> { ) -> Result { let (function, arguments) = template.split_once(' ').unwrap_or((template, "")); match function { - "pic" => Ok(config.pic_url(&*dirs.pics, arguments)), + "pic" => Ok(config.pic_url(&*dirs.pic, arguments)), "include_static" => VPath::try_new(arguments) .ok() .and_then(|vpath| dirs.static_.content(vpath)) diff --git a/crates/treehouse/src/vfs/path.rs b/crates/treehouse/src/vfs/path.rs index 00e83e1..6d9707f 100644 --- a/crates/treehouse/src/vfs/path.rs +++ b/crates/treehouse/src/vfs/path.rs @@ -217,6 +217,9 @@ impl VPathBuf { let range = self.path.len() - chop_len..; self.path.replace_range(range, new_extension); + } else { + self.path.push('.'); + self.path.push_str(new_extension); } } } diff --git a/template/sandbox.hbs b/template/sandbox.hbs index fa932d2..b635ad9 100644 --- a/template/sandbox.hbs +++ b/template/sandbox.hbs @@ -3,6 +3,8 @@ + + treehouse iframe sandbox