From f0a69d12b94672be18d23e27cd7f2d4527147dd1 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Tue, 28 Apr 2020 20:46:29 -0400 Subject: [PATCH] First attempt at a section render function. Running into an issue with generics vs dynamic references. --- js/test_cases/sections/main.dust | 2 +- src/parser/parser.rs | 6 +++--- src/renderer/context_element.rs | 2 -- src/renderer/renderer.rs | 36 ++++++++++++++++++++++++++++++++ 4 files changed, 40 insertions(+), 6 deletions(-) diff --git a/js/test_cases/sections/main.dust b/js/test_cases/sections/main.dust index 7394d2b..8f5d538 100644 --- a/js/test_cases/sections/main.dust +++ b/js/test_cases/sections/main.dust @@ -1,5 +1,5 @@ {#things} Thing: {.} {:else} -No things +No things {.} {/things} diff --git a/src/parser/parser.rs b/src/parser/parser.rs index 25fc802..480cd68 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -90,9 +90,9 @@ pub struct Span<'a> { #[derive(Clone, Debug, PartialEq)] pub struct Container<'a> { - path: Path<'a>, - contents: Option>, - else_contents: Option>, + pub path: Path<'a>, + pub contents: Option>, + pub else_contents: Option>, } #[derive(Clone, Debug, PartialEq)] diff --git a/src/renderer/context_element.rs b/src/renderer/context_element.rs index 6b8f7e2..14f1aae 100644 --- a/src/renderer/context_element.rs +++ b/src/renderer/context_element.rs @@ -22,7 +22,5 @@ pub trait Loopable { /// once with the context being the element at that path. Finally, /// if its an array-like value then it will render n-times, once /// for each element of the array. - /// - /// TODO: Should this return an iterator instead of a vec? fn get_loop_elements(&self) -> Result, RenderError>; } diff --git a/src/renderer/renderer.rs b/src/renderer/renderer.rs index 4af3d3c..b98e77c 100644 --- a/src/renderer/renderer.rs +++ b/src/renderer/renderer.rs @@ -91,6 +91,42 @@ impl<'a> DustRenderer<'a> { 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, 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 } Ok("".to_owned())