From acedfdad2943f18d204918edb721f4ebc26a052c Mon Sep 17 00:00:00 2001 From: Adrien Burgun Date: Fri, 29 Jul 2022 19:50:11 +0200 Subject: [PATCH] :sparkles: Access parent properties and partials with `parent.xyz` --- species/blobcat/templates/hand-boop.mustache | 2 +- species/blobcat/templates/hands.mustache | 19 +----- species/blobcat/templates/mouth.mustache | 4 +- species/blobcat/templates/nose.mustache | 8 +-- species/blobcat/templates/tail.mustache | 2 +- src/main.rs | 3 +- src/parse.rs | 12 ++-- src/template.rs | 63 ++++++++++++++++---- 8 files changed, 69 insertions(+), 44 deletions(-) diff --git a/species/blobcat/templates/hand-boop.mustache b/species/blobcat/templates/hand-boop.mustache index 7ac88f4..4b256b0 100644 --- a/species/blobcat/templates/hand-boop.mustache +++ b/species/blobcat/templates/hand-boop.mustache @@ -1,3 +1,3 @@ - {{#boop_owo}}#hand-boop{{/boop_owo}} + {{>parent.hand-boop}} diff --git a/species/blobcat/templates/hands.mustache b/species/blobcat/templates/hands.mustache index 62c1b4e..48cf6f3 100644 --- a/species/blobcat/templates/hands.mustache +++ b/species/blobcat/templates/hands.mustache @@ -1,16 +1,3 @@ -{{! TODO: use parent }} - - {{#tags.hands-reach}} - {{#set-fill}}#fcc21b|{{#reach_aww}}#left-hand{{/reach_aww}}{{/set-fill}} - {{#set-fill}}#fcc21b|{{#reach_aww}}#right-hand{{/reach_aww}}{{/set-fill}} - {{/tags.hands-reach}} - {{#tags.hand-3c}} - {{#tags.holding}} - {{#set-fill}}#fcc21b|{{#knife}}#left-hand{{/knife}}{{/set-fill}} - {{/tags.holding}} - {{^tags.holding}} - {{! :3c hand }} - {{#set-fill}}#fcc21b|{{#3c_evil}}#left-hand{{/3c_evil}}{{/set-fill}} - {{/tags.holding}} - {{/tags.hand-3c}} - +{{#set-fill}} + #fcc21b | {{>parent.hands}} +{{/set-fill}} diff --git a/species/blobcat/templates/mouth.mustache b/species/blobcat/templates/mouth.mustache index b7fc2fa..660cb04 100644 --- a/species/blobcat/templates/mouth.mustache +++ b/species/blobcat/templates/mouth.mustache @@ -1,9 +1,7 @@ {{#tags.boop}} {{/tags.boop}} - {{#tags.mouth-w}} - {{#base}}#mouth{{/base}} - {{/tags.mouth-w}} + {{>parent.mouth}} {{#tags.boop}} {{/tags.boop}} diff --git a/species/blobcat/templates/nose.mustache b/species/blobcat/templates/nose.mustache index 0e08567..cbe2790 100644 --- a/species/blobcat/templates/nose.mustache +++ b/species/blobcat/templates/nose.mustache @@ -1,13 +1,13 @@ {{#tags.body-snug}} - - {{#snug}}#nose{{/snug}} + + {{>parent.nose}} {{/tags.body-snug}} {{^tags.body-snug}} {{#tags.boop}} - - {{#snug}}#nose{{/snug}} + + {{>parent.nose}} {{/tags.boop}} {{/tags.body-snug}} diff --git a/species/blobcat/templates/tail.mustache b/species/blobcat/templates/tail.mustache index 28c29d7..52e0027 100644 --- a/species/blobcat/templates/tail.mustache +++ b/species/blobcat/templates/tail.mustache @@ -1 +1 @@ -{{#set-fill}}#fcc21b|{{#snug}}#tail{{/snug}}{{/set-fill}} +{{#set-fill}}#fcc21b|{{>parent.tail}}{{/set-fill}} diff --git a/src/main.rs b/src/main.rs index 06f9c67..b25f515 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,3 @@ -use std::sync::Arc; use clap::Parser; use std::path::PathBuf; @@ -14,7 +13,7 @@ use export::*; fn main() { let args = Args::parse(); - let species = Arc::new(load_species(args.decl.clone()).unwrap()); + let species = load_species(args.decl.clone()).unwrap(); let context = RenderingContext::new(species); let output_dir = args.output_dir.clone().unwrap_or(PathBuf::from("output/")); diff --git a/src/parse.rs b/src/parse.rs index 1cfe013..3567cbd 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -42,6 +42,9 @@ pub struct SpeciesDecl { #[serde(skip)] pub asset_paths: HashMap, + + #[serde(skip)] + pub parent: Option>, } /// Loads the given file as an XML tree @@ -66,10 +69,11 @@ pub fn load_species(path: impl AsRef) -> Result { let path = path.as_ref().to_path_buf().join(base); let base = load_species(path)?; - res.template_paths = base.template_paths; - res.variant_paths = base.variant_paths; - res.asset_paths = base.asset_paths; - res.variants = base.variants; + res.template_paths = base.template_paths.clone(); + res.variant_paths = base.variant_paths.clone(); + res.asset_paths = base.asset_paths.clone(); + res.variants = base.variants.clone(); + res.parent = Some(Box::new(base)); } // Read the `templates` directory and populate the `template_paths` field; diff --git a/src/template.rs b/src/template.rs index 59d20fa..d775f56 100644 --- a/src/template.rs +++ b/src/template.rs @@ -12,14 +12,21 @@ pub struct RenderingContext { rendered_variants: Arc>>, loaded_assets: Arc>>, + + parent: Option>, } impl RenderingContext { - pub fn new(species: Arc) -> Self { + pub fn new(mut species: SpeciesDecl) -> Self { + let parent = std::mem::take(&mut species.parent).map(|parent| { + Box::new(Self::new(*parent)) + }); + Self { - species, + species: Arc::new(species), rendered_variants: Arc::new(Mutex::new(HashMap::new())), loaded_assets: Arc::new(Mutex::new(HashMap::new())), + parent } } @@ -39,6 +46,10 @@ impl RenderingContext { } pub fn get_data(&self, variant_name: &str) -> Data { + self.get_builder(variant_name).build() + } + + fn get_builder(&self, variant_name: &str) -> MapBuilder { let mut builder = MapBuilder::new(); builder = builder.insert_map("variant", |mut builder| { @@ -92,16 +103,7 @@ impl RenderingContext { // Convert `xml` to XML match Element::parse(xml.as_bytes()) { Ok(mut xml) => { - // Substitute the fill color - if let Some(style) = xml.attributes.get("style") { - xml.attributes.insert( - "style".to_string(), - format!("{};fill: {};", style, color), - ); - } - if let Some(_fill) = xml.attributes.get("fill") { - xml.attributes.insert("fill".to_string(), color); - } + set_fill(&color.trim(), &mut xml); // Render XML to string if let Some(res) = xml_to_string(xml) { @@ -122,6 +124,16 @@ impl RenderingContext { } }); + if let Some(ref parent) = self.parent { + let parent = parent.clone(); + let variant_name = variant_name.to_string(); + builder = builder.insert_map("parent", move |_| { + parent.get_builder(&variant_name) + }); + } + + // TODO: memoize the builder to this stage + // Variant tags if let Some(tags) = self.species.variants.get(variant_name) { builder = builder.insert_map("tags", move |mut builder| { @@ -133,7 +145,7 @@ impl RenderingContext { }); } - builder.build() + builder } pub fn get_variant(&self, name: &String) -> Option { @@ -185,6 +197,12 @@ impl PartialLoader for RenderingContext { fn load(&self, name: impl AsRef) -> Result { let name = name.as_ref().to_str().ok_or(mustache::Error::InvalidStr)?; + if let Some(ref parent) = self.parent { + if name.starts_with("parent.") { + return parent.load(&name[7..]); + } + } + if let Some(path) = self.species.template_paths.get(name) { Ok(std::fs::read_to_string(path)?) } else { @@ -194,6 +212,25 @@ impl PartialLoader for RenderingContext { } } +fn set_fill(color: &str, xml: &mut Element) { + // Substitute the fill color + if let Some(style) = xml.attributes.get("style") { + xml.attributes.insert( + "style".to_string(), + format!("{};fill: {};", style, color), + ); + } + if let Some(_fill) = xml.attributes.get("fill") { + xml.attributes.insert("fill".to_string(), color.to_string()); + } + + for child in xml.children.iter_mut() { + if let XMLNode::Element(ref mut child) = child { + set_fill(color, child); + } + } +} + pub fn query_selector(svg: Element, pattern: &str) -> Option { if pattern == "" { return Some(svg);