Implement the new render functions.
This commit is contained in:
		
							parent
							
								
									a3bb8e47c1
								
							
						
					
					
						commit
						26fe996b0d
					
				@ -44,10 +44,11 @@ fn main() {
 | 
			
		||||
        .first()
 | 
			
		||||
        .expect("There should be more than 1 template")
 | 
			
		||||
        .name;
 | 
			
		||||
    let breadcrumbs = vec![&context as &dyn ContextElement];
 | 
			
		||||
    println!(
 | 
			
		||||
        "{}",
 | 
			
		||||
        dust_renderer
 | 
			
		||||
            .render(main_template_name, &context)
 | 
			
		||||
            .new_render(main_template_name, &breadcrumbs)
 | 
			
		||||
            .expect("Failed to render")
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -63,6 +63,23 @@ impl<'a> DustRenderer<'a> {
 | 
			
		||||
            .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>>
 | 
			
		||||
    where
 | 
			
		||||
        C: ContextElement,
 | 
			
		||||
@ -79,6 +96,24 @@ impl<'a> DustRenderer<'a> {
 | 
			
		||||
        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>>
 | 
			
		||||
    where
 | 
			
		||||
        C: ContextElement,
 | 
			
		||||
@ -96,6 +131,70 @@ impl<'a> DustRenderer<'a> {
 | 
			
		||||
        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>>
 | 
			
		||||
    where
 | 
			
		||||
        C: ContextElement,
 | 
			
		||||
@ -209,7 +308,7 @@ fn walk_path_from_single_level<'a>(
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn new_walk_path<'a>(
 | 
			
		||||
    breadcrumbs: Vec<&'a dyn ContextElement>,
 | 
			
		||||
    breadcrumbs: &Vec<&'a dyn ContextElement>,
 | 
			
		||||
    path: &'a Vec<&str>,
 | 
			
		||||
) -> Result<&'a dyn ContextElement, RenderError<'a>> {
 | 
			
		||||
    for context in breadcrumbs.iter().rev() {
 | 
			
		||||
@ -221,7 +320,7 @@ fn new_walk_path<'a>(
 | 
			
		||||
            WalkResult::PartialWalk => {
 | 
			
		||||
                return Err(RenderError::NotFound {
 | 
			
		||||
                    path: path,
 | 
			
		||||
                    breadcrumbs: breadcrumbs,
 | 
			
		||||
                    breadcrumbs: breadcrumbs.clone(),
 | 
			
		||||
                })
 | 
			
		||||
            }
 | 
			
		||||
            WalkResult::FullyWalked(new_context) => return Ok(new_context),
 | 
			
		||||
@ -229,7 +328,7 @@ fn new_walk_path<'a>(
 | 
			
		||||
    }
 | 
			
		||||
    Err(RenderError::NotFound {
 | 
			
		||||
        path: path,
 | 
			
		||||
        breadcrumbs: breadcrumbs,
 | 
			
		||||
        breadcrumbs: breadcrumbs.clone(),
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user