90 lines
3.3 KiB
Rust
90 lines
3.3 KiB
Rust
use crate::parser::template;
|
|
use crate::parser::Path;
|
|
use crate::parser::Template;
|
|
use crate::renderer::breadcrumb_tree::BreadcrumbTree;
|
|
use crate::renderer::breadcrumb_tree::BreadcrumbTreeElement;
|
|
use crate::renderer::context_element::ContextElement;
|
|
use crate::renderer::context_element::IntoContextElement;
|
|
use crate::renderer::errors::CompileError;
|
|
use crate::renderer::tree_walking::walk_path;
|
|
use std::collections::HashMap;
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct DustRenderer<'a> {
|
|
templates: HashMap<String, &'a Template<'a>>,
|
|
}
|
|
|
|
pub fn compile_template<'a>(source: &'a str) -> Result<Template<'a>, CompileError> {
|
|
let (_remaining, parsed_template) = template(source).map_err(|err| CompileError {
|
|
message: "Failed to compile template".to_owned(),
|
|
})?;
|
|
Ok(parsed_template)
|
|
}
|
|
|
|
impl<'a> DustRenderer<'a> {
|
|
pub fn new() -> DustRenderer<'a> {
|
|
DustRenderer {
|
|
templates: HashMap::new(),
|
|
}
|
|
}
|
|
|
|
pub fn load_source(&mut self, template: &'a Template, name: String) {
|
|
self.templates.insert(name, template);
|
|
}
|
|
|
|
/// Returns a option of a tuple of (parent, new_node_elements)
|
|
/// which can then be formed into new BreadcrumbTreeNodes
|
|
///
|
|
/// If None is returned, then it is a signal to simply re-use the
|
|
/// existing breadcrumbs.
|
|
///
|
|
/// Otherwise, the parent (which may be None, especially for
|
|
/// explicit contexts) and the additional node elements (which may
|
|
/// be empty) should be combined into a final BreadcrumbTreeNode
|
|
fn new_breadcrumbs_section<'b>(
|
|
&self,
|
|
maybe_breadcrumbs: Option<&'a BreadcrumbTree>,
|
|
index_context: Option<&'b dyn IntoContextElement>,
|
|
injected_context: Option<&'b dyn IntoContextElement>,
|
|
explicit_context: &Option<Path<'b>>,
|
|
new_context_element: Option<&'b dyn ContextElement>,
|
|
) -> Option<(Option<&'b BreadcrumbTree>, Vec<BreadcrumbTreeElement<'b>>)> {
|
|
// If none of the additional contexts are present, return None
|
|
// to signal that the original breadcrumbs should be used
|
|
// rather than incurring a copy here.
|
|
match (
|
|
index_context,
|
|
injected_context,
|
|
explicit_context,
|
|
new_context_element,
|
|
) {
|
|
(None, None, None, None) => return None,
|
|
_ => (),
|
|
}
|
|
|
|
// If there is an explicit context, then drop all the current
|
|
// context
|
|
let mut parent = match explicit_context {
|
|
Some(_) => None,
|
|
None => maybe_breadcrumbs,
|
|
};
|
|
let mut new_nodes: Vec<BreadcrumbTreeElement> = Vec::new();
|
|
|
|
explicit_context.as_ref().map(|path| {
|
|
let x = walk_path(maybe_breadcrumbs, &path.keys);
|
|
x.map(|ice| ice.into_context_element(self, maybe_breadcrumbs))
|
|
.map(|val| {
|
|
if val.is_truthy() {
|
|
new_nodes.push(BreadcrumbTreeElement::Borrowed(val.from_context_element()))
|
|
}
|
|
});
|
|
});
|
|
injected_context.map(|ctx| new_nodes.push(BreadcrumbTreeElement::Borrowed(ctx)));
|
|
new_context_element
|
|
.map(|ctx| new_nodes.push(BreadcrumbTreeElement::Borrowed(ctx.from_context_element())));
|
|
index_context.map(|ctx| new_nodes.push(BreadcrumbTreeElement::Borrowed(ctx)));
|
|
|
|
Some((parent, new_nodes))
|
|
}
|
|
}
|