guidon 0.4.1

Library to initialize project from templates
Documentation
use crate::crypto::{gdecrypt, gencrypt};
use handlebars::{Context, Handlebars, Helper, HelperResult, Output, RenderContext, RenderError};

/// Handlebars helper to replace a string by another in the vars.
///
/// The helper takes two parameters:
/// * from: the string to replace
/// * to: the replacement string
///
/// ```properties
/// {{replace input "Roger" "Brian"}}
/// ```
/// Every occurence of "Roger" in *input* will be replaced by "Brian"
pub fn replace(
    h: &Helper<'_, '_>,
    _: &Handlebars<'_>,
    _: &Context,
    _rc: &mut RenderContext<'_, '_>,
    out: &mut dyn Output,
) -> HelperResult {
    // get parameter from helper or throw an error
    let param = h.param(0).and_then(|v| v.value().as_str()).unwrap_or("");
    let from = h.param(1).and_then(|v| v.value().as_str()).unwrap_or("");
    let to = h.param(2).and_then(|v| v.value().as_str()).unwrap_or("");
    out.write(param.replace(from, to).as_ref())?;
    Ok(())
}

/// Handlebars helpers for to uppercase the input
///
/// The helper doesn't take any argument :
/// ```properties
/// {{up param}}
/// ```

pub fn up(
    h: &Helper<'_, '_>,
    _: &Handlebars<'_>,
    _: &Context,
    _rc: &mut RenderContext<'_, '_>,
    out: &mut dyn Output,
) -> HelperResult {
    // get parameter from helper or throw an error
    let param = h.param(0).and_then(|v| v.value().as_str()).unwrap_or("");
    out.write(param.to_uppercase().as_ref())?;
    Ok(())
}

/// Handlebars helpers for to lowercase the input
///
/// The helper doesn't take any argument :
/// ```properties
/// {{up input}}
/// ```
pub fn low(
    h: &Helper<'_, '_>,
    _: &Handlebars<'_>,
    _: &Context,
    _rc: &mut RenderContext<'_, '_>,
    out: &mut dyn Output,
) -> HelperResult {
    // get parameter from helper or throw an error
    let param = h.param(0).and_then(|v| v.value().as_str()).unwrap_or("");
    out.write(param.to_lowercase().as_ref())?;
    Ok(())
}

/// Handlebars helper to apppend a string by another in the vars.
///
/// The helper takes one parameter:
/// * to_append: the string to append to *input*
///
/// ```properties
/// {{append input "-suffix" }}
/// ```
pub fn append(
    h: &Helper<'_, '_>,
    _: &Handlebars<'_>,
    _: &Context,
    _rc: &mut RenderContext<'_, '_>,
    out: &mut dyn Output,
) -> HelperResult {
    // get parameter from helper or throw an error
    let param = h.param(0).and_then(|v| v.value().as_str()).unwrap_or("");
    let to_append = h.param(1).and_then(|v| v.value().as_str()).unwrap_or("");
    out.write(format!("{}{}", param, to_append).as_ref())?;
    Ok(())
}

/// Handlebars helper to prepend a string to the input.
///
/// The helper takes one parameters:
/// * to_prepend: the string to prepend
///
/// ```properties
/// {{prepend input "prefix-"}}
/// ```
pub fn prepend(
    h: &Helper<'_, '_>,
    _: &Handlebars<'_>,
    _: &Context,
    _rc: &mut RenderContext<'_, '_>,
    out: &mut dyn Output,
) -> HelperResult {
    // get parameter from helper or throw an error
    let param = h.param(0).and_then(|v| v.value().as_str()).unwrap_or("");
    let to_prepend = h.param(1).and_then(|v| v.value().as_str()).unwrap_or("");
    out.write(format!("{}{}", to_prepend, param).as_ref())?;
    Ok(())
}

/// Handlebars helper to default to a given value if input is empty
///
/// The helper takes one parameters:
/// * to_prepend: the string to prepend
///
/// ```properties
/// {{default input "default-value"}}
/// ```
pub fn default(
    h: &Helper<'_, '_>,
    _: &Handlebars<'_>,
    _: &Context,
    _rc: &mut RenderContext<'_, '_>,
    out: &mut dyn Output,
) -> HelperResult {
    // get parameter from helper or throw an error
    let mut param = h.param(0).and_then(|v| v.value().as_str()).unwrap_or("");
    let default_value = h.param(1).and_then(|v| v.value().as_str()).unwrap_or("");
    if param.is_empty() {
        param = default_value;
    }

    out.write(format!("{}", param).as_ref())?;
    Ok(())
}

/// Handlebars helper to encrypt a string.
///
/// The key must be a env var (cf module crypto doc).
///
/// ```properties
/// {{encrypt input}}
/// ```
#[cfg(feature = "crypto")]
pub fn encrypt(
    h: &Helper<'_, '_>,
    _: &Handlebars<'_>,
    _: &Context,
    _rc: &mut RenderContext<'_, '_>,
    out: &mut dyn Output,
) -> HelperResult {
    // get parameter from helper or throw an error
    let param = h.param(0).and_then(|v| v.value().as_str()).unwrap_or("");
    let msg = gencrypt(param, None).map_err(RenderError::with)?;
    out.write(msg.as_ref())?;
    Ok(())
}

/// Handlebars helper to decrypt a string.
///
/// The key must be a env var (cf module crypto doc).
///
/// ```properties
/// {{encrypt input}}
/// ```
#[cfg(feature = "crypto")]
pub fn decrypt(
    h: &Helper<'_, '_>,
    _: &Handlebars<'_>,
    _: &Context,
    _rc: &mut RenderContext<'_, '_>,
    out: &mut dyn Output,
) -> HelperResult {
    // get parameter from helper or throw an error
    let param = h.param(0).and_then(|v| v.value().as_str()).unwrap_or("");
    let msg = gdecrypt(param, None).map_err(RenderError::with)?;
    out.write(msg.as_ref())?;
    Ok(())
}

#[cfg(test)]
mod tests {
    use crate::helpers::default;
    use crate::{append, decrypt, low, prepend, replace, up};
    use handlebars::Handlebars;
    use log::LevelFilter;
    use pretty_assertions::assert_eq;
    use std::collections::BTreeMap;
    use std::env;
    use std::sync::Once;

    static INIT: Once = Once::new();

    fn setup() {
        INIT.call_once(|| {
            let _ = env_logger::builder()
                .is_test(true)
                .filter_level(LevelFilter::Trace)
                .try_init();
        });
    }

    #[test]
    fn should_replace() {
        setup();
        let mut vars = BTreeMap::new();
        vars.insert("teacher", "Repeat after me");
        vars.insert("sentence", "Roger is in the kitchen");

        let mut handlebars = Handlebars::new();
        handlebars.register_helper("replace", Box::new(replace));
        let res = handlebars
            .render_template(
                "{{teacher}}: {{replace sentence \"Roger\" \"Brian\"}}.",
                &vars,
            )
            .unwrap();
        println!("{}", res);
        assert_eq!(res, "Repeat after me: Brian is in the kitchen.");
    }

    #[test]
    fn should_uppercase() {
        setup();
        let mut vars = BTreeMap::new();
        vars.insert("teacher", "Repeat after me");
        vars.insert("sentence", "Brian is in the kitchen");

        let mut handlebars = Handlebars::new();
        handlebars.register_helper("up", Box::new(up));
        let res = handlebars
            .render_template("{{teacher}}: {{up sentence}}.", &vars)
            .unwrap();
        println!("{}", res);
        assert_eq!(res, "Repeat after me: BRIAN IS IN THE KITCHEN.");
    }

    #[test]
    fn should_lowercase() {
        setup();
        let mut vars = BTreeMap::new();
        vars.insert("teacher", "Repeat after me");
        vars.insert("sentence", "Brian IS IN THE KITCHEN");

        let mut handlebars = Handlebars::new();
        handlebars.register_helper("low", Box::new(low));
        let res = handlebars
            .render_template("{{teacher}}: {{low sentence}}.", &vars)
            .unwrap();
        println!("{}", res);
        assert_eq!(res, "Repeat after me: brian is in the kitchen.");
    }

    #[test]
    fn should_append() {
        setup();
        let mut vars = BTreeMap::new();
        vars.insert("teacher", "Repeat after me");
        vars.insert("sentence", "Brian");

        let mut handlebars = Handlebars::new();
        handlebars.register_helper("append", Box::new(append));
        let res = handlebars
            .render_template(
                r#"{{teacher}}: {{append sentence " is in the kitchen"}}."#,
                &vars,
            )
            .unwrap();
        println!("{}", res);
        assert_eq!(res, "Repeat after me: Brian is in the kitchen.");
    }

    #[test]
    fn should_prepend() {
        setup();
        let mut vars = BTreeMap::new();
        vars.insert("teacher", "Repeat after me");
        vars.insert("sentence", "is in the kitchen");

        let mut handlebars = Handlebars::new();
        handlebars.register_helper("prepend", Box::new(prepend));
        let res = handlebars
            .render_template(r#"{{teacher}}: {{prepend sentence "Brian "}}."#, &vars)
            .unwrap();
        println!("{}", res);
        assert_eq!(res, "Repeat after me: Brian is in the kitchen.");
    }

    #[test]
    fn should_default() {
        setup();
        let mut vars = BTreeMap::new();
        vars.insert("teacher", "Repeat after me");
        vars.insert("sentence", "is in the kitchen");

        let mut handlebars = Handlebars::new();
        handlebars.register_helper("default", Box::new(default));
        let res = handlebars
            .render_template(
                r#"{{teacher}}: Brian {{default where "is in the saloon"}}."#,
                &vars,
            )
            .unwrap();
        println!("{}", res);
        assert_eq!(res, "Repeat after me: Brian is in the saloon.");

        let res = handlebars
            .render_template(
                r#"{{teacher}}: Brian {{default sentence "is in the saloon"}}."#,
                &vars,
            )
            .unwrap();
        println!("{}", res);
        assert_eq!(res, "Repeat after me: Brian is in the kitchen.");
    }

    #[test]
    fn should_decrypt() {
        setup();
        let key = "Yr5(M\\@Nf4\"@PA5XLNR.F_hf{Bg`JA4=[%/3CG`(w'gA~~GRfv8v%q{JUhW\"7%L1Kt++7Uc_2hlBR-=2^KM>a5D#aIWaofoGvmO{w!lpbD,R6'ziO6eym!{%Wm9)Q#f{K\"-2[Vw'/\\BI%HlL?rU^/b]vmH?z]]j'7,jGj[7m~Oa!oN_PbupuQ*|M{C&^E`I]`huX,7{|2(2-h),V[P[xWA0z/UG.bbBO'u<|*7E$~BcUke^m;U7Ydk4L$.SF])/U";
        env::set_var("GUIDON_KEY", key);

        let mut vars = BTreeMap::new();
        vars.insert("hello", "336636376137663234393439323037353638326639316266613463656261356261303138633732343863383038346663636239353963366635386332383061380a393032636562323461343033343434393731663961656130363836323337333637366630333261666364333938326561373038626531653434643664313362320a3531653262383631653134343936646265346262396430383062353834323236");

        let mut handlebars = Handlebars::new();
        handlebars.register_helper("decrypt", Box::new(decrypt));
        let res = handlebars
            .render_template(r#"{{decrypt hello}}"#, &vars)
            .unwrap();
        println!("{}", res);
        assert_eq!(res, "Hello World!");
    }
}