First attempt at a section render function.

Running into an issue with generics vs dynamic references.
This commit is contained in:
Tom Alexander 2020-04-28 20:46:29 -04:00
parent e5c4ba8c82
commit f0a69d12b9
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
4 changed files with 40 additions and 6 deletions

View File

@ -1,5 +1,5 @@
{#things} {#things}
Thing: {.} Thing: {.}
{:else} {:else}
No things No things {.}
{/things} {/things}

View File

@ -90,9 +90,9 @@ pub struct Span<'a> {
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub struct Container<'a> { pub struct Container<'a> {
path: Path<'a>, pub path: Path<'a>,
contents: Option<Body<'a>>, pub contents: Option<Body<'a>>,
else_contents: Option<Body<'a>>, pub else_contents: Option<Body<'a>>,
} }
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]

View File

@ -22,7 +22,5 @@ pub trait Loopable {
/// once with the context being the element at that path. Finally, /// once with the context being the element at that path. Finally,
/// if its an array-like value then it will render n-times, once /// if its an array-like value then it will render n-times, once
/// for each element of the array. /// for each element of the array.
///
/// TODO: Should this return an iterator instead of a vec?
fn get_loop_elements(&self) -> Result<Vec<&dyn ContextElement>, RenderError>; fn get_loop_elements(&self) -> Result<Vec<&dyn ContextElement>, RenderError>;
} }

View File

@ -91,6 +91,42 @@ impl<'a> DustRenderer<'a> {
return val?.render(&reference.filters); return val?.render(&reference.filters);
} }
} }
DustTag::DTSection(container) => {
let val = walk_path(context, &container.path.keys);
if let Err(RenderError::WontWalk { .. }) = val {
// If reference does not exist in the context, it becomes an empty string
return Ok("".to_owned());
} else {
let loop_elements: Vec<&dyn ContextElement> = val?.get_loop_elements()?;
if loop_elements.is_empty() {
// Oddly enough if the value is falsey (like
// an empty array or null), Dust uses the
// original context before walking the path as
// the context for rendering the else block
//
// TODO: do filters apply? I don't think so
// but I should test
return match &container.else_contents {
Some(body) => self.render_body(&body, context),
None => Ok("".to_owned()),
};
} else {
match container.contents {
None => Ok("".to_owned()),
Some(body) => {
let rendered_results: Result<Vec<String>, RenderError> =
loop_elements
.into_iter()
.map(|array_elem| self.render_body(&body, array_elem))
.collect();
let rendered_slice: &[String] = &rendered_results?;
return Ok(rendered_slice.join(""));
}
};
return Ok("".to_owned());
}
}
}
_ => (), // TODO: Implement the rest _ => (), // TODO: Implement the rest
} }
Ok("".to_owned()) Ok("".to_owned())