use crate::error::MdmgError;
use crate::Result;
use handlebars::{Context, Handlebars, Helper, JsonRender, Output, RenderContext, RenderError};
use inflector::Inflector;
use serde::Serialize;
use std::env::var;
#[derive(Debug, Serialize, Default)]
pub struct MdmgCtx {
pub identify: String,
}
#[derive(Debug, Serialize, Default, PartialEq)]
pub struct Template {
body: String,
}
impl Template {
pub fn new<T: Into<String>>(body: T) -> Self {
Template { body: body.into() }
}
}
impl MdmgCtx {
pub fn new<T: Into<String>>(identify: T) -> Self {
Self {
identify: identify.into(),
}
}
}
fn pascal_case_helper(
h: &Helper,
_: &Handlebars,
_: &Context,
_: &mut RenderContext,
out: &mut dyn Output,
) -> std::result::Result<(), RenderError> {
let target = h
.param(0)
.ok_or_else(|| RenderError::new("Param 0 is required for pascal_case_decorator."))
.map(|s| s.value().render())?;
let rendered = target.to_pascal_case();
out.write(&rendered)?;
Ok(())
}
fn camel_case_helper(
h: &Helper,
_: &Handlebars,
_: &Context,
_: &mut RenderContext,
out: &mut dyn Output,
) -> std::result::Result<(), RenderError> {
let target = h
.param(0)
.ok_or_else(|| RenderError::new("Param 0 is required for camel_case_decorator."))
.map(|s| s.value().render())?;
let rendered = target.to_camel_case();
out.write(&rendered)?;
Ok(())
}
fn snake_case_helper(
h: &Helper,
_: &Handlebars,
_: &Context,
_: &mut RenderContext,
out: &mut dyn Output,
) -> std::result::Result<(), RenderError> {
let target = h
.param(0)
.ok_or_else(|| RenderError::new("Param 0 is required for snake_case_decorator."))
.map(|s| s.value().render())?;
let rendered = target.to_snake_case();
out.write(&rendered)?;
Ok(())
}
fn kebab_case_helper(
h: &Helper,
_: &Handlebars,
_: &Context,
_: &mut RenderContext,
out: &mut dyn Output,
) -> std::result::Result<(), RenderError> {
let target = h
.param(0)
.ok_or_else(|| RenderError::new("Param 0 is required for kebab_case_decorator."))
.map(|s| s.value().render())?;
let rendered = target.to_kebab_case();
out.write(&rendered)?;
Ok(())
}
fn env_helper(
h: &Helper,
_: &Handlebars,
_: &Context,
_: &mut RenderContext,
out: &mut dyn Output,
) -> std::result::Result<(), RenderError> {
let target = h
.param(0)
.ok_or_else(|| RenderError::new("Param 0 is required for kebab_case_decorator."))
.map(|s| s.value().render())?;
let rendered = var(&target).unwrap_or_else(|_| panic!("env({}) is not defined.", &target));
out.write(&rendered)?;
Ok(())
}
pub fn render(template: Template, ctx: &MdmgCtx) -> Result<String> {
let mut handlebars = Handlebars::new();
handlebars.register_helper("pascal_case", Box::new(pascal_case_helper));
handlebars.register_helper("camel_case", Box::new(camel_case_helper));
handlebars.register_helper("kebab_case", Box::new(kebab_case_helper));
handlebars.register_helper("snake_case", Box::new(snake_case_helper));
handlebars.register_helper("env", Box::new(env_helper));
handlebars
.render_template(template.body.as_str(), ctx)
.map(expand_escaped_curly_braces)
.map_err(|e| MdmgError::TempalteRenderError { reason: e.desc })
}
fn expand_escaped_curly_braces(input: String) -> String {
input.replace("\\{", "{").replace("\\}", "}")
}
#[cfg(not(tarpaulin_include))]
#[cfg(test)]
mod tests {
use crate::template::expand_escaped_curly_braces;
use super::*;
use std::default::Default;
use std::env::{remove_var, set_var};
#[test]
fn render_returning_the_piyopoyo() {
assert_eq!(
render(Template::new("PIYOPIYP"), &Default::default()).unwrap(),
"PIYOPIYP"
)
}
#[test]
fn render_returning_the_himanoa() {
assert_eq!(
render(Template::new("{{identify}}"), &MdmgCtx::new("himanoa")).unwrap(),
"himanoa"
)
}
#[test]
fn render_returning_the_variable() {
assert_eq!(
render(Template::new("{{identify}}"), &MdmgCtx::new("himanoa")).unwrap(),
"himanoa"
)
}
#[test]
fn render_returning_the_foo() {
set_var("MDMG_TEST_VALUE1", "FOO");
let actual = render(
Template::new("{{ env \"MDMG_TEST_VALUE1\"}}"),
&MdmgCtx::new("himanoa"),
);
remove_var("MDMG_TEST_VALUE1");
assert_eq!(actual.unwrap(), "FOO")
}
#[test]
fn render_returning_the_foo_adapter() {
set_var("MDMG_TEST_VALUE2", "FooAdapter");
let actual = render(
Template::new("{{ snake_case (env \"MDMG_TEST_VALUE2\")}}"),
&MdmgCtx::new("himanoa"),
);
remove_var("MDMG_TEST_VALUE2");
assert_eq!(actual.unwrap(), "foo_adapter")
}
#[test]
fn render_returning_helper() {
assert_eq!(
render(
Template::new("{{pascal_case identify}} {{camel_case identify}} {{kebab_case identify}} {{ snake_case identify }}"), &MdmgCtx::new("exampleAccountRegister")
)
.unwrap(),
"ExampleAccountRegister exampleAccountRegister example-account-register example_account_register"
)
}
#[test]
fn render_returning_foo() {
assert_eq!(
render(
Template::new("\\{\\{foo\\}\\}"),
&MdmgCtx::new("exampleAccountRegister")
)
.unwrap(),
"{{foo}}"
)
}
#[test]
fn expand_escaped_curly_braces_do_nothing() {
assert_eq!(
expand_escaped_curly_braces("fooo".to_string()),
"fooo".to_string()
)
}
#[test]
fn expand_escaped_curly_braces_remove_escape_char() {
assert_eq!(
expand_escaped_curly_braces("\\{\\{foo\\}\\}".to_string()),
"{{foo}}".to_string()
)
}
}