Skip to main content

tera_sprig/
string.rs

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
74/// Truncate a string with ellipses. `abbrev 5 "hello world"` yields `"he..."`.
75pub 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
101/// Remove all space characters from a string. nospace "h e l l o" becomes "hello".
102pub 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
119/// Register all filters.
120pub 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}