loose_liquid_lib/stdlib/filters/string/
case.rs

1#![allow(clippy::invisible_characters)]
2
3use liquid_core::Result;
4use liquid_core::Runtime;
5use liquid_core::{Display_filter, Filter, FilterReflection, ParseFilter};
6use liquid_core::{Value, ValueView};
7
8#[derive(Clone, ParseFilter, FilterReflection)]
9#[filter(
10    name = "downcase",
11    description = "Makes each character in a string downcase.",
12    parsed(DowncaseFilter)
13)]
14pub struct Downcase;
15
16#[derive(Debug, Default, Display_filter)]
17#[name = "downcase"]
18struct DowncaseFilter;
19
20impl Filter for DowncaseFilter {
21    fn evaluate(&self, input: &dyn ValueView, _runtime: &dyn Runtime) -> Result<Value> {
22        let s = input.to_kstr();
23        Ok(Value::scalar(s.to_lowercase()))
24    }
25}
26
27#[derive(Clone, ParseFilter, FilterReflection)]
28#[filter(
29    name = "upcase",
30    description = "Makes each character in a string uppercase.",
31    parsed(UpcaseFilter)
32)]
33pub struct Upcase;
34
35#[derive(Debug, Default, Display_filter)]
36#[name = "upcase"]
37struct UpcaseFilter;
38
39impl Filter for UpcaseFilter {
40    fn evaluate(&self, input: &dyn ValueView, _runtime: &dyn Runtime) -> Result<Value> {
41        let s = input.to_kstr();
42        Ok(Value::scalar(s.to_uppercase()))
43    }
44}
45
46#[derive(Clone, ParseFilter, FilterReflection)]
47#[filter(
48    name = "capitalize",
49    description = "Makes the first character of a string capitalized.",
50    parsed(CapitalizeFilter)
51)]
52pub struct Capitalize;
53
54#[derive(Debug, Default, Display_filter)]
55#[name = "capitalize"]
56struct CapitalizeFilter;
57
58impl Filter for CapitalizeFilter {
59    fn evaluate(&self, input: &dyn ValueView, _runtime: &dyn Runtime) -> Result<Value> {
60        let s = input.to_kstr().to_owned();
61        let mut chars = s.chars();
62        let capitalized = match chars.next() {
63            Some(first_char) => first_char.to_uppercase().chain(chars).collect(),
64            None => String::new(),
65        };
66
67        Ok(Value::scalar(capitalized))
68    }
69}
70
71#[cfg(test)]
72mod tests {
73    use super::*;
74
75    #[test]
76    fn unit_capitalize() {
77        assert_eq!(
78            liquid_core::call_filter!(Capitalize, "abc").unwrap(),
79            liquid_core::value!("Abc")
80        );
81        assert_eq!(
82            liquid_core::call_filter!(Capitalize, "hello world 21").unwrap(),
83            liquid_core::value!("Hello world 21")
84        );
85
86        // sure that Umlauts work
87        assert_eq!(
88            liquid_core::call_filter!(Capitalize, "über ètat, y̆es?").unwrap(),
89            liquid_core::value!("Über ètat, y̆es?")
90        );
91
92        // Weird UTF-8 White space is kept – this is a no-break whitespace!
93        assert_eq!(
94            liquid_core::call_filter!(Capitalize, "hello world​").unwrap(),
95            liquid_core::value!("Hello world​")
96        );
97
98        // The uppercase version of some character are more than one character long
99        assert_eq!(
100            liquid_core::call_filter!(Capitalize, "ßß").unwrap(),
101            liquid_core::value!("SSß")
102        );
103    }
104
105    #[test]
106    fn unit_downcase() {
107        assert_eq!(
108            liquid_core::call_filter!(Downcase, "Abc").unwrap(),
109            liquid_core::value!("abc")
110        );
111        assert_eq!(
112            liquid_core::call_filter!(Downcase, "Hello World 21").unwrap(),
113            liquid_core::value!("hello world 21")
114        );
115    }
116
117    #[test]
118    fn unit_upcase() {
119        assert_eq!(
120            liquid_core::call_filter!(Upcase, "abc").unwrap(),
121            liquid_core::value!("ABC")
122        );
123        assert_eq!(
124            liquid_core::call_filter!(Upcase, "Hello World 21").unwrap(),
125            liquid_core::value!("HELLO WORLD 21")
126        );
127    }
128}