use crate::context::Context;
use crate::error::RenderError;
use crate::json::value::ScopedJson;
use crate::output::Output;
use crate::registry::Registry;
use crate::render::{do_escape, Helper, RenderContext};
mod block_util;
mod coll;
mod helper_ctx;
mod helper_each;
mod helper_error;
pub(crate) mod helper_extras;
mod helper_get;
mod helper_if;
mod helper_indent;
mod helper_json;
mod helper_log;
mod helper_lookup;
mod helper_raw;
mod helper_read_dir;
mod helper_read_file;
mod helper_var;
mod helper_with;
mod names;
pub use self::names::HelperName;
pub use self::coll::{APPEND_HELPER, INSERT_HELPER, PREPEND_HELPER, REMOVE_HELPER};
pub use self::helper_ctx::CTX_HELPER;
pub use self::helper_each::EACH_HELPER;
pub use self::helper_error::ERROR_HELPER;
pub use self::helper_if::{IF_HELPER, IF_TERNARY_HELPER, UNLESS_HELPER, UNLESS_TERNARY_HELPER};
pub use self::helper_indent::INDENT_HELPER;
pub use self::helper_json::JSON_HELPER;
pub use self::helper_log::LOG_HELPER;
pub use self::helper_lookup::LOOKUP_HELPER;
pub use self::helper_raw::RAW_HELPER;
pub use self::helper_read_dir::READ_DIR_HELPER;
pub use self::helper_read_file::READ_FILE_HELPER;
pub use self::helper_var::VAR_HELPER;
pub use self::helper_with::WITH_HELPER;
pub use helper_get::GET_HELPER;
pub type HelperResult = Result<(), RenderError>;
pub trait HelperDef {
fn call_inner<'reg: 'rc, 'rc>(
&self,
_: &Helper<'rc>,
_: &'reg Registry<'reg>,
_: &'rc Context,
_: &mut RenderContext<'reg, 'rc>,
) -> Result<ScopedJson<'rc>, RenderError> {
Err(RenderError::unimplemented())
}
fn call<'reg: 'rc, 'rc>(
&self,
h: &Helper<'rc>,
r: &'reg Registry<'reg>,
ctx: &'rc Context,
rc: &mut RenderContext<'reg, 'rc>,
out: &mut dyn Output,
) -> HelperResult {
match self.call_inner(h, r, ctx, rc) {
Ok(result) => {
if r.strict_mode() && result.is_missing() {
Err(RenderError::strict_error(None))
} else {
let output = do_escape(r, rc, result.render());
out.write(output.as_ref())?;
Ok(())
}
}
Err(e) => {
if e.is_unimplemented() {
Ok(())
} else {
Err(e)
}
}
}
}
}
impl<
F: for<'reg, 'rc> Fn(
&Helper<'rc>,
&'reg Registry<'reg>,
&'rc Context,
&mut RenderContext<'reg, 'rc>,
&mut dyn Output,
) -> HelperResult,
> HelperDef for F
{
fn call<'reg: 'rc, 'rc>(
&self,
h: &Helper<'rc>,
r: &'reg Registry<'reg>,
ctx: &'rc Context,
rc: &mut RenderContext<'reg, 'rc>,
out: &mut dyn Output,
) -> HelperResult {
(*self)(h, r, ctx, rc, out)
}
}
#[cfg(feature = "script_helper")]
pub(crate) mod scripting;
#[cfg(test)]
mod test {
use std::collections::BTreeMap;
use crate::context::Context;
use crate::error::RenderError;
use crate::helpers::HelperDef;
use crate::json::value::JsonRender;
use crate::output::Output;
use crate::registry::Registry;
use crate::render::{Helper, RenderContext, Renderable};
#[derive(Clone, Copy)]
struct MetaHelper;
impl HelperDef for MetaHelper {
fn call<'reg: 'rc, 'rc>(
&self,
h: &Helper<'rc>,
r: &'reg Registry<'reg>,
ctx: &'rc Context,
rc: &mut RenderContext<'reg, 'rc>,
out: &mut dyn Output,
) -> Result<(), RenderError> {
let v = h.param(0).unwrap();
write!(out, "{}:{}", h.name(), v.value().render())?;
if h.is_block() {
out.write("->")?;
h.template().unwrap().render(r, ctx, rc, out)?;
}
Ok(())
}
}
#[test]
fn test_meta_helper() {
let mut handbar = Registry::new();
assert!(handbar
.register_template_string("t0", "{{foo this}}")
.is_ok());
assert!(handbar
.register_template_string("t1", "{{#bar this}}nice{{/bar}}")
.is_ok());
let meta_helper = MetaHelper;
handbar.register_helper("helperMissing", Box::new(meta_helper));
handbar.register_helper("blockHelperMissing", Box::new(meta_helper));
let r0 = handbar.render("t0", &true);
assert_eq!(r0.ok().unwrap(), "foo:true".to_string());
let r1 = handbar.render("t1", &true);
assert_eq!(r1.ok().unwrap(), "bar:true->nice".to_string());
}
#[test]
fn test_helper_for_subexpression() {
let mut handbar = Registry::new();
assert!(handbar
.register_template_string("t2", "{{foo value=(bar 0)}}")
.is_ok());
handbar.register_helper(
"helperMissing",
Box::new(
|h: &Helper<'_>,
_: &Registry<'_>,
_: &Context,
_: &mut RenderContext<'_, '_>,
out: &mut dyn Output|
-> Result<(), RenderError> {
write!(out, "{}{}", h.name(), h.param(0).unwrap().value())?;
Ok(())
},
),
);
handbar.register_helper(
"foo",
Box::new(
|h: &Helper<'_>,
_: &Registry<'_>,
_: &Context,
_: &mut RenderContext<'_, '_>,
out: &mut dyn Output|
-> Result<(), RenderError> {
write!(out, "{}", h.hash_get("value").unwrap().value().render())?;
Ok(())
},
),
);
let mut data = BTreeMap::new();
data.insert("bar0".to_string(), true);
let r2 = handbar.render("t2", &data);
assert_eq!(r2.ok().unwrap(), "bar0".to_string());
}
}