diff --git a/minijinja-contrib/src/pycompat.rs b/minijinja-contrib/src/pycompat.rs index bb39f59d..3b485765 100644 --- a/minijinja-contrib/src/pycompat.rs +++ b/minijinja-contrib/src/pycompat.rs @@ -31,6 +31,7 @@ use minijinja::{Error, ErrorKind, State, Value}; /// * `str.replace` /// * `str.rstrip` /// * `str.split` +/// * `str.splitlines` /// * `str.strip` /// * `str.title` /// * `str.upper` @@ -123,6 +124,23 @@ fn string_methods(value: &Value, method: &str, args: &[Value]) -> Result()) } + "splitlines" => { + let (keepends,): (Option,) = from_args(args)?; + if !keepends.unwrap_or(false) { + Ok(s.lines().map(Value::from).collect()) + } else { + let mut rv = Vec::new(); + let mut rest = s; + while let Some(offset) = rest.find('\n') { + rv.push(Value::from(&rest[..offset + 1])); + rest = &rest[offset + 1..]; + } + if !rest.is_empty() { + rv.push(Value::from(rest)); + } + Ok(Value::from(rv)) + } + } "capitalize" => { from_args(args)?; // one shall not call into these filters. However we consider ourselves diff --git a/minijinja-contrib/tests/pycompat.rs b/minijinja-contrib/tests/pycompat.rs index 42890392..e4403b49 100644 --- a/minijinja-contrib/tests/pycompat.rs +++ b/minijinja-contrib/tests/pycompat.rs @@ -45,6 +45,8 @@ fn test_string_methods() { assert!(eval_expr("'a b c'.split() == ['a', 'b', 'c']").is_true()); assert!(eval_expr("'a b c'.split(none, 1) == ['a', 'b c']").is_true()); assert!(eval_expr("'abcbd'.split('b', 1) == ['a', 'cbd']").is_true()); + assert!(eval_expr("'a\\nb\\r\\nc'.splitlines() == ['a', 'b', 'c']").is_true()); + assert!(eval_expr("'a\\nb\\r\\nc'.splitlines(true) == ['a\\n', 'b\\r\\n', 'c']").is_true()); } #[test]