Access parent properties and partials with `parent.xyz`

feat/template
Shad Amethyst 2 years ago
parent c19ec3c6fd
commit acedfdad29
Signed by: amethyst
GPG Key ID: D970C8DD1D6DEE36

@ -1,3 +1,3 @@
<g id="hand-boop" transform="translate(1.5 -1)">
{{#boop_owo}}#hand-boop{{/boop_owo}}
{{>parent.hand-boop}}
</g>

@ -1,16 +1,3 @@
{{! TODO: use parent }}
<g id="hands">
{{#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}}
</g>
{{#set-fill}}
#fcc21b | {{>parent.hands}}
{{/set-fill}}

@ -1,9 +1,7 @@
{{#tags.boop}}
<g id="mouth" transform="translate(-0.2 0.5)">
{{/tags.boop}}
{{#tags.mouth-w}}
{{#base}}#mouth{{/base}}
{{/tags.mouth-w}}
{{>parent.mouth}}
{{#tags.boop}}
</g>
{{/tags.boop}}

@ -1,13 +1,13 @@
{{#tags.body-snug}}
<g id="nose-snug" transform="translate(1.5 0)">
{{#snug}}#nose{{/snug}}
<g transform="translate(1.5 0)">
{{>parent.nose}}
</g>
{{/tags.body-snug}}
{{^tags.body-snug}}
{{#tags.boop}}
<g id="nose-snug" transform="translate(1.5 -0.5)">
{{#snug}}#nose{{/snug}}
<g transform="translate(1.5 -0.5)">
{{>parent.nose}}
</g>
{{/tags.boop}}
{{/tags.body-snug}}

@ -1 +1 @@
{{#set-fill}}#fcc21b|{{#snug}}#tail{{/snug}}{{/set-fill}}
{{#set-fill}}#fcc21b|{{>parent.tail}}{{/set-fill}}

@ -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/"));

@ -42,6 +42,9 @@ pub struct SpeciesDecl {
#[serde(skip)]
pub asset_paths: HashMap<String, PathBuf>,
#[serde(skip)]
pub parent: Option<Box<SpeciesDecl>>,
}
/// Loads the given file as an XML tree
@ -66,10 +69,11 @@ pub fn load_species(path: impl AsRef<Path>) -> Result<SpeciesDecl, ParseError> {
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;

@ -12,14 +12,21 @@ pub struct RenderingContext {
rendered_variants: Arc<Mutex<HashMap<String, Element>>>,
loaded_assets: Arc<Mutex<HashMap<String, Element>>>,
parent: Option<Box<RenderingContext>>,
}
impl RenderingContext {
pub fn new(species: Arc<SpeciesDecl>) -> 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<Element> {
@ -185,6 +197,12 @@ impl PartialLoader for RenderingContext {
fn load(&self, name: impl AsRef<Path>) -> Result<String, mustache::Error> {
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<Element> {
if pattern == "" {
return Some(svg);

Loading…
Cancel
Save