Implement the new render functions.
This commit is contained in:
parent
a3bb8e47c1
commit
26fe996b0d
@ -44,10 +44,11 @@ fn main() {
|
|||||||
.first()
|
.first()
|
||||||
.expect("There should be more than 1 template")
|
.expect("There should be more than 1 template")
|
||||||
.name;
|
.name;
|
||||||
|
let breadcrumbs = vec![&context as &dyn ContextElement];
|
||||||
println!(
|
println!(
|
||||||
"{}",
|
"{}",
|
||||||
dust_renderer
|
dust_renderer
|
||||||
.render(main_template_name, &context)
|
.new_render(main_template_name, &breadcrumbs)
|
||||||
.expect("Failed to render")
|
.expect("Failed to render")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,23 @@ impl<'a> DustRenderer<'a> {
|
|||||||
.insert(template.name.clone(), &template.template);
|
.insert(template.name.clone(), &template.template);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_render(
|
||||||
|
&'a self,
|
||||||
|
name: &str,
|
||||||
|
breadcrumbs: &Vec<&'a dyn ContextElement>,
|
||||||
|
) -> Result<String, RenderError<'a>> {
|
||||||
|
let main_template = match self.templates.get(name) {
|
||||||
|
Some(tmpl) => tmpl,
|
||||||
|
None => {
|
||||||
|
return Err(RenderError::Generic(format!(
|
||||||
|
"No template named {} in context",
|
||||||
|
name
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
self.new_render_body(&main_template.contents, breadcrumbs)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn render<C>(&'a self, name: &str, context: &'a C) -> Result<String, RenderError<'a>>
|
pub fn render<C>(&'a self, name: &str, context: &'a C) -> Result<String, RenderError<'a>>
|
||||||
where
|
where
|
||||||
C: ContextElement,
|
C: ContextElement,
|
||||||
@ -79,6 +96,24 @@ impl<'a> DustRenderer<'a> {
|
|||||||
self.render_body(&main_template.contents, context)
|
self.render_body(&main_template.contents, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn new_render_body(
|
||||||
|
&'a self,
|
||||||
|
body: &'a Body,
|
||||||
|
breadcrumbs: &Vec<&'a dyn ContextElement>,
|
||||||
|
) -> Result<String, RenderError<'a>> {
|
||||||
|
let mut output = String::new();
|
||||||
|
for elem in &body.elements {
|
||||||
|
match elem {
|
||||||
|
TemplateElement::TEIgnoredWhitespace(_) => {}
|
||||||
|
TemplateElement::TESpan(span) => output.push_str(span.contents),
|
||||||
|
TemplateElement::TETag(dt) => {
|
||||||
|
output.push_str(&self.new_render_tag(dt, breadcrumbs)?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(output)
|
||||||
|
}
|
||||||
|
|
||||||
fn render_body<C>(&'a self, body: &Body, context: &'a C) -> Result<String, RenderError<'a>>
|
fn render_body<C>(&'a self, body: &Body, context: &'a C) -> Result<String, RenderError<'a>>
|
||||||
where
|
where
|
||||||
C: ContextElement,
|
C: ContextElement,
|
||||||
@ -96,6 +131,70 @@ impl<'a> DustRenderer<'a> {
|
|||||||
Ok(output)
|
Ok(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn new_render_tag(
|
||||||
|
&'a self,
|
||||||
|
tag: &'a DustTag,
|
||||||
|
breadcrumbs: &Vec<&'a dyn ContextElement>,
|
||||||
|
) -> Result<String, RenderError<'a>> {
|
||||||
|
match tag {
|
||||||
|
DustTag::DTComment(_comment) => (),
|
||||||
|
DustTag::DTSpecial(special) => {
|
||||||
|
return Ok(match special {
|
||||||
|
Special::Space => " ",
|
||||||
|
Special::NewLine => "\n",
|
||||||
|
Special::CarriageReturn => "\r",
|
||||||
|
Special::LeftCurlyBrace => "{",
|
||||||
|
Special::RightCurlyBrace => "}",
|
||||||
|
}
|
||||||
|
.to_owned())
|
||||||
|
}
|
||||||
|
DustTag::DTReference(reference) => {
|
||||||
|
let val = new_walk_path(breadcrumbs, &reference.path.keys);
|
||||||
|
if let Err(RenderError::NotFound { .. }) = val {
|
||||||
|
// If reference does not exist in the context, it becomes an empty string
|
||||||
|
return Ok("".to_owned());
|
||||||
|
} else {
|
||||||
|
return val?.render(&reference.filters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DustTag::DTSection(container) => {
|
||||||
|
let val = new_walk_path(breadcrumbs, &container.path.keys);
|
||||||
|
let loop_elements: Vec<&dyn ContextElement> = self.get_loop_elements(val)?;
|
||||||
|
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.new_render_body(&body, breadcrumbs),
|
||||||
|
None => Ok("".to_owned()),
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
match &container.contents {
|
||||||
|
None => return Ok("".to_owned()),
|
||||||
|
Some(body) => {
|
||||||
|
let rendered_results: Result<Vec<String>, RenderError> = loop_elements
|
||||||
|
.into_iter()
|
||||||
|
.map(|array_elem| {
|
||||||
|
let mut new_breadcumbs = breadcrumbs.clone();
|
||||||
|
new_breadcumbs.push(array_elem);
|
||||||
|
self.new_render_body(&body, &new_breadcumbs)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let rendered_slice: &[String] = &rendered_results?;
|
||||||
|
return Ok(rendered_slice.join(""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (), // TODO: Implement the rest
|
||||||
|
}
|
||||||
|
Ok("".to_owned())
|
||||||
|
}
|
||||||
|
|
||||||
fn render_tag<C>(&'a self, tag: &DustTag, context: &'a C) -> Result<String, RenderError<'a>>
|
fn render_tag<C>(&'a self, tag: &DustTag, context: &'a C) -> Result<String, RenderError<'a>>
|
||||||
where
|
where
|
||||||
C: ContextElement,
|
C: ContextElement,
|
||||||
@ -209,7 +308,7 @@ fn walk_path_from_single_level<'a>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn new_walk_path<'a>(
|
fn new_walk_path<'a>(
|
||||||
breadcrumbs: Vec<&'a dyn ContextElement>,
|
breadcrumbs: &Vec<&'a dyn ContextElement>,
|
||||||
path: &'a Vec<&str>,
|
path: &'a Vec<&str>,
|
||||||
) -> Result<&'a dyn ContextElement, RenderError<'a>> {
|
) -> Result<&'a dyn ContextElement, RenderError<'a>> {
|
||||||
for context in breadcrumbs.iter().rev() {
|
for context in breadcrumbs.iter().rev() {
|
||||||
@ -221,7 +320,7 @@ fn new_walk_path<'a>(
|
|||||||
WalkResult::PartialWalk => {
|
WalkResult::PartialWalk => {
|
||||||
return Err(RenderError::NotFound {
|
return Err(RenderError::NotFound {
|
||||||
path: path,
|
path: path,
|
||||||
breadcrumbs: breadcrumbs,
|
breadcrumbs: breadcrumbs.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
WalkResult::FullyWalked(new_context) => return Ok(new_context),
|
WalkResult::FullyWalked(new_context) => return Ok(new_context),
|
||||||
@ -229,7 +328,7 @@ fn new_walk_path<'a>(
|
|||||||
}
|
}
|
||||||
Err(RenderError::NotFound {
|
Err(RenderError::NotFound {
|
||||||
path: path,
|
path: path,
|
||||||
breadcrumbs: breadcrumbs,
|
breadcrumbs: breadcrumbs.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user