diff --git a/minijinja-contrib/src/filters/mod.rs b/minijinja-contrib/src/filters/mod.rs index a303ff28..6b966853 100644 --- a/minijinja-contrib/src/filters/mod.rs +++ b/minijinja-contrib/src/filters/mod.rs @@ -214,3 +214,27 @@ pub fn truncate(state: &State, value: Value, kwargs: Kwargs) -> Result Result { + let s = value.as_str().unwrap_or_default(); + let mut count: u32 = 0; + let mut in_word = false; + + // Iterate through characters, counting transitions from non-word to word chars + for c in s.chars() { + let is_word_char = c.is_alphanumeric() || c == '_'; + if is_word_char && !in_word { + count += 1; + in_word = true; + } else if !is_word_char { + in_word = false; + } + } + + Ok(Value::from(count)) +} diff --git a/minijinja-contrib/tests/filters.rs b/minijinja-contrib/tests/filters.rs index 0e2df55f..41844726 100644 --- a/minijinja-contrib/tests/filters.rs +++ b/minijinja-contrib/tests/filters.rs @@ -1,5 +1,5 @@ use minijinja::{context, Environment}; -use minijinja_contrib::filters::pluralize; +use minijinja_contrib::filters::{pluralize, wordcount}; use similar_asserts::assert_eq; #[test] @@ -202,3 +202,68 @@ fn test_truncate() { "invalid operation: expected length >= 3, got 1 (in :1)" ); } + +#[test] +fn test_wordcount() { + let mut env = Environment::new(); + env.add_filter("wordcount", wordcount); + + assert_eq!( + env.render_str( + "{{ text|wordcount }}", + context! { + text => "Hello world! How are you?" + } + ) + .unwrap(), + "5" + ); + + // Test empty string + assert_eq!( + env.render_str( + "{{ text|wordcount }}", + context! { + text => "" + } + ) + .unwrap(), + "0" + ); + + // Test multiple whitespace + assert_eq!( + env.render_str( + "{{ text|wordcount }}", + context! { + text => "Hello world! Test" + } + ) + .unwrap(), + "3" + ); + + // Test other word separators + assert_eq!( + env.render_str( + "{{ text|wordcount }}", + context! { + text => "hello-again@world! It's_me!" + } + ) + .unwrap(), + "5" + ); + + // Test multiple other word separators + assert_eq!( + env.render_str( + "{{ text|wordcount }}", + context! { + text => "hello--again@-!world" + } + ) + .unwrap(), + "3" + ); +}