| //! A Set of string utilities often required during code generation. |
| //! |
| //! See also: [`heck`](https://docs.rs/heck/latest/heck) |
| //! |
| //! `lowerCamelCase`: Convert a string to lowerCamelCase |
| //! `upperCamelCase`: Convert a string to UpperCamelCase |
| //! `snakeCase`: Convert a string to snake_case |
| //! `kebabCase`: Conver a string to kebab-case |
| //! `shoutySnakeCase`: Convert a string to SHOUTY_SNAKE_CASE |
| //! `shoutyKebabCase`: Convert a string to SHOUTY-KEBAB-CASE |
| //! `titleCase`: Convert a string to Title Case |
| //! `trainCase`: Convert a string to Train-Case |
| |
| use heck::{ |
| ToKebabCase, ToLowerCamelCase, ToShoutyKebabCase, ToShoutySnakeCase, ToSnakeCase, ToTitleCase, |
| ToTrainCase, ToUpperCamelCase, |
| }; |
| |
| macro_rules! define_case_helper { |
| ($helper_fn_name: ident, $heck_fn_name:ident) => { |
| pub(crate) fn $helper_fn_name( |
| h: &crate::render::Helper<'_>, |
| _: &crate::Handlebars<'_>, |
| _: &crate::context::Context, |
| _rc: &mut crate::render::RenderContext<'_, '_>, |
| out: &mut dyn crate::output::Output, |
| ) -> crate::helpers::HelperResult { |
| let param = h.param(0).and_then(|v| v.value().as_str()).ok_or_else(|| { |
| crate::error::RenderErrorReason::ParamTypeMismatchForName( |
| stringify!($helper_fn_name), |
| "0".to_owned(), |
| "string".to_owned(), |
| ) |
| })?; |
| out.write(param.$heck_fn_name().as_ref())?; |
| Ok(()) |
| } |
| }; |
| } |
| |
| define_case_helper!(lower_camel_case, to_lower_camel_case); |
| define_case_helper!(upper_camel_case, to_upper_camel_case); |
| define_case_helper!(snake_case, to_snake_case); |
| define_case_helper!(shouty_snake_case, to_shouty_snake_case); |
| define_case_helper!(kebab_case, to_kebab_case); |
| define_case_helper!(shouty_kebab_case, to_shouty_kebab_case); |
| define_case_helper!(title_case, to_title_case); |
| define_case_helper!(train_case, to_train_case); |
| |
| #[cfg(test)] |
| mod tests { |
| macro_rules! define_case_helpers_test_cases { |
| ($template_fn_name:literal, $helper_tc_fn_name:ident, $(($tc_input:literal, $tc_expected:literal),)+) => { |
| |
| #[test] |
| fn $helper_tc_fn_name() { |
| let hbs = crate::registry::Registry::new(); |
| let test_cases = vec![$(($tc_input, $tc_expected)),+]; |
| for tc in test_cases { |
| let result = |
| hbs.render_template( |
| concat!("{{", $template_fn_name, " data}}"), |
| &json!({"data": tc.0})); |
| assert!(result.is_ok(), "{}", result.err().unwrap()); |
| assert_eq!(result.unwrap(), tc.1.to_string()); |
| } |
| } |
| } |
| } |
| |
| define_case_helpers_test_cases!( |
| "lowerCamelCase", |
| test_lower_camel_case, |
| ("lower camel case", "lowerCamelCase"), |
| ("lower-camel-case", "lowerCamelCase"), |
| ("lower_camel_case", "lowerCamelCase"), |
| ); |
| |
| define_case_helpers_test_cases!( |
| "upperCamelCase", |
| test_upper_camel_case, |
| ("upper camel case", "UpperCamelCase"), |
| ("upper-camel-case", "UpperCamelCase"), |
| ("upper_camel_case", "UpperCamelCase"), |
| ); |
| |
| define_case_helpers_test_cases!( |
| "snakeCase", |
| test_snake_case, |
| ("snake case", "snake_case"), |
| ("snake-case", "snake_case"), |
| ); |
| |
| define_case_helpers_test_cases!( |
| "kebabCase", |
| test_kebab_case, |
| ("kebab case", "kebab-case"), |
| ("kebab_case", "kebab-case"), |
| ); |
| |
| define_case_helpers_test_cases!( |
| "shoutySnakeCase", |
| test_shouty_snake_case, |
| ("shouty snake case", "SHOUTY_SNAKE_CASE"), |
| ("shouty snake-case", "SHOUTY_SNAKE_CASE"), |
| ); |
| |
| define_case_helpers_test_cases!( |
| "shoutyKebabCase", |
| test_shouty_kebab_case, |
| ("shouty kebab case", "SHOUTY-KEBAB-CASE"), |
| ("shouty_kebab_case", "SHOUTY-KEBAB-CASE"), |
| ); |
| |
| define_case_helpers_test_cases!("titleCase", test_title_case, ("title case", "Title Case"),); |
| |
| define_case_helpers_test_cases!("trainCase", test_train_case, ("train case", "Train-Case"),); |
| |
| #[test] |
| fn test_invalid_input() { |
| use crate::error::RenderErrorReason; |
| |
| let hbs = crate::registry::Registry::new(); |
| let err = hbs |
| .render_template("{{snakeCase 1}}", &json!({})) |
| .unwrap_err(); |
| assert!(matches!( |
| err.reason(), |
| RenderErrorReason::ParamTypeMismatchForName(_, _, _) |
| )); |
| } |
| } |