Skip to content

Commit

Permalink
add indent filter (#798)
Browse files Browse the repository at this point in the history
* add indent filter

* update indent filter
  • Loading branch information
Lionel Untereiner authored Mar 8, 2023
1 parent 3761996 commit 10861c7
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 0 deletions.
3 changes: 3 additions & 0 deletions docs/content/docs/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -867,6 +867,9 @@ Note that only whitespace between successive opening tags and successive closing
Also note that if the template you are using it in is automatically escaped, you will
need to call the `safe` filter after `spaceless`.

#### indent
Indents a string by injecting a prefix at the start of each line. The `prefix` argument (default 4 spaces) specifies the prefix to insert per line. If the `first` argument (default false) is set true spaces are inserted for the first line. If the `blank` argument (default false) is set true spaces are inserted for blank/whitespace lines.

#### striptags
Tries to remove HTML tags from input. Does not guarantee well formed output if input is not valid HTML.

Expand Down
70 changes: 70 additions & 0 deletions src/builtins/filters/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,57 @@ pub fn linebreaksbr(value: &Value, _: &HashMap<String, Value>) -> Result<Value>
Ok(to_value(s.replace("\r\n", "<br>").replace('\n', "<br>")).unwrap())
}

/// Indents a string by the specified width.
///
/// # Arguments
///
/// * `value` - The string to indent.
/// * `args` - A set of key/value arguments that can take the following
/// keys.
/// * `prefix` - The prefix used for indentation. The default value is 4 spaces.
/// * `first` - True indents the first line. The default is false.
/// * `blank` - True indents blank lines. The default is false.
///
pub fn indent(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
let s = try_get_value!("indent", "value", String, value);

let prefix = match args.get("prefix") {
Some(p) => try_get_value!("indent", "prefix", String, p),
None => " ".to_string(),
};
let first = match args.get("first") {
Some(f) => try_get_value!("indent", "first", bool, f),
None => false,
};
let blank = match args.get("blank") {
Some(b) => try_get_value!("indent", "blank", bool, b),
None => false,
};

// Attempt to pre-allocate enough space to prevent additional allocations/copies
let mut out = String::with_capacity(
s.len() + (prefix.len() * (s.chars().filter(|&c| c == '\n').count() + 1)),
);
let mut first_pass = true;

for line in s.lines() {
if first_pass {
if first {
out.push_str(&prefix);
}
first_pass = false;
} else {
out.push('\n');
if blank || !line.trim_start().is_empty() {
out.push_str(&prefix);
}
}
out.push_str(line);
}

Ok(to_value(&out).unwrap())
}

/// Removes html tags from string
pub fn striptags(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
let s = try_get_value!("striptags", "value", String, value);
Expand Down Expand Up @@ -671,6 +722,25 @@ mod tests {
}
}

#[test]
fn test_indent_defaults() {
let args = HashMap::new();
let result = indent(&to_value("one\n\ntwo\nthree").unwrap(), &args);
assert!(result.is_ok());
assert_eq!(result.unwrap(), to_value("one\n\n two\n three").unwrap());
}

#[test]
fn test_indent_args() {
let mut args = HashMap::new();
args.insert("first".to_string(), to_value(true).unwrap());
args.insert("prefix".to_string(), to_value(" ").unwrap());
args.insert("blank".to_string(), to_value(true).unwrap());
let result = indent(&to_value("one\n\ntwo\nthree").unwrap(), &args);
assert!(result.is_ok());
assert_eq!(result.unwrap(), to_value(" one\n \n two\n three").unwrap());
}

#[test]
fn test_striptags() {
let tests = vec![
Expand Down
1 change: 1 addition & 0 deletions src/tera.rs
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,7 @@ impl Tera {
self.register_filter("capitalize", string::capitalize);
self.register_filter("title", string::title);
self.register_filter("linebreaksbr", string::linebreaksbr);
self.register_filter("indent", string::indent);
self.register_filter("striptags", string::striptags);
self.register_filter("spaceless", string::spaceless);
#[cfg(feature = "urlencode")]
Expand Down

0 comments on commit 10861c7

Please sign in to comment.