use std::sync::Arc;
use minijinja::{AutoEscape, Environment, Error, ErrorKind, UndefinedBehavior, Value};
use crate::clock::Clock;
use crate::error::RAISE_SENTINEL;
use crate::json::tojson_filter;
#[derive(Clone)]
pub(crate) struct EngineConfig {
pub trim_blocks: bool,
pub lstrip_blocks: bool,
pub keep_trailing_newline: bool,
pub undefined: UndefinedBehavior,
pub pycompat: bool,
pub clock: Arc<dyn Clock>,
}
pub(crate) fn build(source: String, cfg: &EngineConfig) -> Result<Environment<'static>, Error> {
let mut env = Environment::new();
env.set_trim_blocks(cfg.trim_blocks);
env.set_lstrip_blocks(cfg.lstrip_blocks);
env.set_keep_trailing_newline(cfg.keep_trailing_newline);
env.set_undefined_behavior(cfg.undefined);
env.set_auto_escape_callback(|_name| AutoEscape::None);
let _pycompat = cfg.pycompat;
#[cfg(feature = "pycompat")]
if _pycompat {
env.set_unknown_method_callback(minijinja_contrib::pycompat::unknown_method_callback);
}
env.add_function("raise_exception", |msg: String| -> Result<Value, Error> {
Err(Error::new(
ErrorKind::InvalidOperation,
format!("{RAISE_SENTINEL}{msg}{RAISE_SENTINEL}"),
))
});
let clock = cfg.clock.clone();
env.add_function("strftime_now", move |fmt: String| -> Result<Value, Error> {
Ok(Value::from(clock.strftime(&fmt)))
});
env.add_filter("tojson", tojson_filter);
env.add_template_owned("chat", source)?;
Ok(env)
}