1use std::collections::HashMap;
2
3use convert_case::Case;
4use convert_case::Casing;
5use tera::Tera;
6use tera::Value;
7
8use crate::common::argument_get_string;
9use crate::common::Result;
10
11#[cfg(test)]
12use crate::common::render_template_string_filter;
13
14#[cfg(test)]
15use crate::common::render_template_string;
16
17#[test]
18fn test_kebabcase() -> Result<()> {
19 assert_eq!(
20 render_template_string_filter("FirstName", "sprig_kebabcase")?,
21 "first-name"
22 );
23
24 Ok(())
25}
26
27pub fn sprig_kebabcase(text: &Value, _: &HashMap<String, Value>) -> Result<Value> {
28 let text = argument_get_string(text, "kebabcase")?;
29 let text = text.to_case(Case::Kebab);
30 Ok(text.into())
31}
32
33#[test]
34fn test_camelcase() -> Result<()> {
35 assert_eq!(
36 render_template_string_filter("http_server", "sprig_camelcase")?,
37 "HttpServer"
38 );
39
40 Ok(())
41}
42
43pub fn sprig_camelcase(text: &Value, _: &HashMap<String, Value>) -> Result<Value> {
44 let text = argument_get_string(text, "camelcase")?;
45 let text = text.to_case(Case::Pascal);
46 Ok(text.into())
47}
48
49#[test]
50fn test_snakecase() -> Result<()> {
51 assert_eq!(
52 render_template_string(r#"{{ "FirstName" | sprig_snakecase }}"#)?,
53 "first_name"
54 );
55
56 Ok(())
57}
58
59pub fn sprig_snakecase(text: &Value, _: &HashMap<String, Value>) -> Result<Value> {
60 let text = argument_get_string(text, "snakecase")?;
61 let text = text.to_case(Case::Snake);
62 Ok(text.into())
63}
64
65#[test]
66fn test_abbrev() -> Result<()> {
67 assert_eq!(
68 render_template_string_filter("hello world", "sprig_abbrev(len=5)")?,
69 "he...",
70 );
71 Ok(())
72}
73
74pub fn sprig_abbrev(text: &Value, args: &HashMap<String, Value>) -> Result<Value> {
76 let text = text
77 .as_str()
78 .ok_or_else(|| tera::Error::msg("abbrev need string value"))?;
79 let width =
80 args.get("len")
81 .ok_or_else(|| tera::Error::msg("abbrev need argument 'len'"))?
82 .as_u64()
83 .ok_or_else(|| tera::Error::msg("abbrev argument 'len' must be u64"))? as usize;
84
85 if width < 4 || text.len() < width {
86 Ok(text.into())
87 } else {
88 Ok(format!("{}...", &text[..width - 3]).into())
89 }
90}
91
92#[test]
93fn test_nospace() -> Result<()> {
94 assert_eq!(
95 render_template_string(r#"{{ "h e l l o" | sprig_nospace }}"#)?,
96 "hello",
97 );
98 Ok(())
99}
100
101pub fn sprig_nospace(text: &Value, _: &HashMap<String, Value>) -> Result<Value> {
103 let text = text
104 .as_str()
105 .ok_or_else(|| tera::Error::msg("nospace need string value"))?;
106
107 let bytes: Vec<_> = text
108 .as_bytes()
109 .iter()
110 .copied()
111 .filter(|x| *x != b' ')
112 .collect();
113
114 Ok(Value::String(String::from_utf8(bytes).map_err(|e| {
115 tera::Error::utf8_conversion_error(e, "nospace output not utf-8".into())
116 })?))
117}
118
119pub fn register(tera: &mut Tera) {
121 tera.register_filter("sprig_nospace", sprig_nospace);
122 tera.register_filter("sprig_abbrev", sprig_abbrev);
123 tera.register_filter("sprig_snakecase", sprig_snakecase);
124 tera.register_filter("sprig_camelcase", sprig_camelcase);
125 tera.register_filter("sprig_kebabcase", sprig_kebabcase);
126}