liquid_lib/stdlib/filters/
mod.rs

1use liquid_core::Expression;
2use liquid_core::Result;
3use liquid_core::Runtime;
4use liquid_core::{
5    Display_filter, Filter, FilterParameters, FilterReflection, FromFilterParameters, ParseFilter,
6};
7use liquid_core::{Value, ValueView};
8
9mod array;
10mod date;
11mod html;
12mod math;
13mod slice;
14mod string;
15mod url;
16
17pub use self::array::{
18    Compact, Concat, First, Join, Last, Map, Reverse, Sort, SortNatural, Uniq, Where,
19};
20pub use self::date::Date;
21pub use self::html::{Escape, EscapeOnce, NewlineToBr, StripHtml};
22pub use self::math::{
23    Abs, AtLeast, AtMost, Ceil, DividedBy, Floor, Minus, Modulo, Plus, Round, Times,
24};
25pub use self::slice::Slice;
26pub use self::string::case::{Capitalize, Downcase, Upcase};
27pub use self::string::operate::{Append, Prepend, Remove, RemoveFirst, Replace, ReplaceFirst};
28pub use self::string::strip::{Lstrip, Rstrip, Strip, StripNewlines};
29pub use self::string::truncate::{Truncate, TruncateWords};
30pub use self::string::Split;
31pub use self::url::{UrlDecode, UrlEncode};
32
33#[derive(Clone, ParseFilter, FilterReflection)]
34#[filter(
35    name = "size",
36    description = "Returns the size of the input. For an array or object this is the number of elements. For other values it's the length of its string representation.",
37    parsed(SizeFilter)
38)]
39pub struct Size;
40
41#[derive(Debug, Default, Display_filter)]
42#[name = "size"]
43struct SizeFilter;
44
45impl Filter for SizeFilter {
46    fn evaluate(&self, input: &dyn ValueView, _runtime: &dyn Runtime) -> Result<Value> {
47        if let Some(x) = input.as_scalar() {
48            Ok(Value::scalar(x.to_kstr().len() as i64))
49        } else if let Some(x) = input.as_array() {
50            Ok(Value::scalar(x.size()))
51        } else if let Some(x) = input.as_object() {
52            Ok(Value::scalar(x.size()))
53        } else {
54            Ok(Value::scalar(0i64))
55        }
56    }
57}
58
59#[derive(Debug, FilterParameters)]
60struct DefaultArgs {
61    #[parameter(description = "The default value.")]
62    default: Expression,
63}
64
65#[derive(Clone, ParseFilter, FilterReflection)]
66#[filter(
67    name = "default",
68    description = "Sets a default value for the given input.",
69    parameters(DefaultArgs),
70    parsed(DefaultFilter)
71)]
72pub struct Default;
73
74#[derive(Debug, FromFilterParameters, Display_filter)]
75#[name = "default"]
76struct DefaultFilter {
77    #[parameters]
78    args: DefaultArgs,
79}
80
81impl Filter for DefaultFilter {
82    fn evaluate(&self, input: &dyn ValueView, runtime: &dyn Runtime) -> Result<Value> {
83        let args = self.args.evaluate(runtime)?;
84
85        if input.query_state(liquid_core::model::State::DefaultValue) {
86            Ok(args.default.to_value())
87        } else {
88            Ok(input.to_value())
89        }
90    }
91}
92
93#[cfg(test)]
94mod tests {
95    use super::*;
96    use liquid_core::Object;
97
98    #[test]
99    fn unit_size() {
100        assert_eq!(
101            liquid_core::call_filter!(Size, "abc").unwrap(),
102            Value::scalar(3f64)
103        );
104        assert_eq!(
105            liquid_core::call_filter!(Size, "this has 22 characters").unwrap(),
106            Value::scalar(22f64)
107        );
108        assert_eq!(
109            liquid_core::call_filter!(
110                Size,
111                Value::Array(vec![
112                    Value::scalar(0f64),
113                    Value::scalar(1f64),
114                    Value::scalar(2f64),
115                    Value::scalar(3f64),
116                    Value::scalar(4f64),
117                ])
118            )
119            .unwrap(),
120            Value::scalar(5f64)
121        );
122    }
123
124    #[test]
125    fn unit_default() {
126        assert_eq!(
127            liquid_core::call_filter!(Default, "", "bar").unwrap(),
128            liquid_core::value!("bar")
129        );
130        assert_eq!(
131            liquid_core::call_filter!(Default, "foo", "bar").unwrap(),
132            liquid_core::value!("foo")
133        );
134        assert_eq!(
135            liquid_core::call_filter!(Default, 0_f64, "bar").unwrap(),
136            Value::scalar(0_f64)
137        );
138        assert_eq!(
139            liquid_core::call_filter!(Default, liquid_core::value!([]), 1_f64).unwrap(),
140            Value::scalar(1_f64)
141        );
142        assert_eq!(
143            liquid_core::call_filter!(Default, liquid_core::value!([""]), 1_f64).unwrap(),
144            liquid_core::value!([""])
145        );
146        assert_eq!(
147            liquid_core::call_filter!(Default, Object::new(), 1_f64).unwrap(),
148            Value::scalar(1_f64)
149        );
150        assert_eq!(
151            liquid_core::call_filter!(Default, false, Value::scalar(1_f64)).unwrap(),
152            Value::scalar(1_f64)
153        );
154        assert_eq!(
155            liquid_core::call_filter!(Default, true, Value::scalar(1_f64)).unwrap(),
156            Value::scalar(true)
157        );
158    }
159}