use std::collections::BTreeMap;
use femstache_eval::{TemplateEnv, TemplateInput};
use femstache_loader::{TemplateLoader, TemplateSource};
use femstache_parser::Template;
use femstache_types::{TyContext, TyError};
use crate::{
FemstacheError, FemstacheResult,
output::{EscapeMode, Output},
renderer::TemplateRenderer,
};
#[derive(Debug)]
pub struct Femstache {
loader: TemplateLoader,
escape: EscapeMode,
}
impl Femstache {
pub fn new(source: TemplateSource, escape: EscapeMode) -> Self {
let loader = TemplateLoader::new(source);
Self { loader, escape }
}
pub fn render(&self, path: &str, inputs: &impl TemplateInput) -> FemstacheResult<String> {
let template = self.loader.load(path)?;
let mut ctx = TyContext::new(self.loader.clone());
ctx.infer_document(template.document())?;
for (name, ty_id) in ctx.globals() {
let Some(value) = inputs.get(name) else {
return Err(FemstacheError::TypeError(TyError::Conflicts(Vec::new())));
};
if !value.conforms_to(&ctx, *ty_id) {
return Err(FemstacheError::TypeError(TyError::Conflicts(Vec::new())));
}
}
let env = TemplateEnv::new(inputs);
let mut renderer = TemplateRenderer::new(env, BTreeMap::new(), Some(self.loader.clone()));
let mut output = Output::string(self.escape);
renderer.render_document(template.document(), &mut output)?;
Ok(output.into_inner())
}
}
pub fn render(template: &Template, inputs: &impl TemplateInput) -> FemstacheResult<String> {
let mut ctx = TyContext::new(TemplateLoader::new(TemplateSource::none()));
ctx.infer_document(template.document()).unwrap();
for (name, ty_id) in ctx.globals() {
let Some(value) = inputs.get(name) else {
return Err(FemstacheError::TypeError(TyError::Conflicts(Vec::new())));
};
if !value.conforms_to(&ctx, *ty_id) {
return Err(FemstacheError::TypeError(TyError::Conflicts(Vec::new())));
}
}
let env = TemplateEnv::new(inputs);
let blocks = BTreeMap::new();
let mut renderer = TemplateRenderer::new(env, blocks, None);
let mut output = Output::string(EscapeMode::None);
renderer.render_document(template.document(), &mut output)?;
Ok(output.into_inner())
}