use serde::Serialize;
use crate::{
escape::{self, EscapeFn},
helper::HelperRegistry,
output::{Output, StringOutput},
parser::{Parser, ParserOptions},
template::{Template, Templates},
Error, Result,
};
pub struct Registry<'reg, 'source> {
helpers: HelperRegistry<'reg>,
templates: Templates<'source>,
escape: EscapeFn,
strict: bool,
}
impl<'reg, 'source> Registry<'reg, 'source> {
pub fn new() -> Self {
Self {
helpers: HelperRegistry::new(),
templates: Default::default(),
escape: Box::new(escape::html),
strict: false,
}
}
pub fn set_strict(&mut self, strict: bool) {
self.strict = strict
}
pub fn strict(&self) -> bool {
self.strict
}
pub fn set_escape(&mut self, escape: EscapeFn) {
self.escape = escape;
}
pub fn escape(&self) -> &EscapeFn {
&self.escape
}
pub fn helpers(&self) -> &HelperRegistry<'reg> {
&self.helpers
}
pub fn helpers_mut(&mut self) -> &mut HelperRegistry<'reg> {
&mut self.helpers
}
pub fn templates(&self) -> &Templates<'source> {
&self.templates
}
pub fn templates_mut(&mut self) -> &mut Templates<'source> {
&mut self.templates
}
pub fn compile(
&self,
template: &'source str,
options: ParserOptions,
) -> Result<Template<'source>> {
Templates::compile(template, options)
}
pub fn parse(
&self,
name: &str,
template: &'source str,
) -> Result<Template<'source>> {
self.compile(template, ParserOptions::new(name.to_string(), 0, 0))
}
pub fn lint(
&self,
name: &str,
template: &'source str,
) -> Result<Vec<Error>> {
let mut errors: Vec<Error> = Vec::new();
let mut parser =
Parser::new(template, ParserOptions::new(name.to_string(), 0, 0));
parser.set_errors(&mut errors);
for _ in parser {}
Ok(errors)
}
pub fn once<T>(&self, name: &str, source: &str, data: &T) -> Result<String>
where
T: Serialize,
{
let mut writer = StringOutput::new();
let template =
self.compile(source, ParserOptions::new(name.to_string(), 0, 0))?;
template.render(
self.strict(),
self.escape(),
self.helpers(),
self.templates(),
name,
data,
&mut writer,
)?;
Ok(writer.into())
}
pub fn render<T>(&self, name: &str, data: &T) -> Result<String>
where
T: Serialize,
{
let mut writer = StringOutput::new();
self.render_to_write(name, data, &mut writer)?;
Ok(writer.into())
}
pub fn render_template<T>(
&self,
name: &str,
template: &Template<'source>,
data: &T,
) -> Result<String>
where
T: Serialize,
{
let mut writer = StringOutput::new();
template.render(
self.strict(),
self.escape(),
self.helpers(),
self.templates(),
name,
data,
&mut writer,
)?;
Ok(writer.into())
}
pub fn render_to_write<T>(
&self,
name: &str,
data: &T,
writer: &mut impl Output,
) -> Result<()>
where
T: Serialize,
{
let tpl = self
.templates
.get(name)
.ok_or_else(|| Error::TemplateNotFound(name.to_string()))?;
tpl.render(
self.strict(),
self.escape(),
self.helpers(),
self.templates(),
name,
data,
writer,
)?;
Ok(())
}
}
impl<'reg, 'source> From<Templates<'source>> for Registry<'reg, 'source> {
fn from(templates: Templates<'source>) -> Self {
let mut reg = Registry::new();
reg.templates = templates;
reg
}
}