Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement replace_re filter #2163

Merged
merged 6 commits into from
Apr 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 69 additions & 1 deletion components/templates/src/filters.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use std::borrow::Cow;
use std::collections::HashMap;
use std::hash::BuildHasher;
use std::sync::{Arc, Mutex};

use config::Config;

use libs::base64::engine::{general_purpose::STANDARD as standard_b64, Engine};
use libs::regex::Regex;
use libs::tera::{
to_value, try_get_value, Error as TeraError, Filter as TeraFilter, Result as TeraResult, Tera,
Value,
Expand Down Expand Up @@ -78,6 +81,53 @@ pub fn base64_decode<S: BuildHasher>(
Ok(to_value(as_str).unwrap())
}

#[derive(Debug)]
pub struct RegexReplaceFilter {
re_cache: Arc<Mutex<HashMap<String, Regex>>>,
}

impl RegexReplaceFilter {
pub fn new() -> Self {
return Self { re_cache: Arc::new(Mutex::new(HashMap::new())) };
}
}

impl TeraFilter for RegexReplaceFilter {
fn filter(&self, value: &Value, args: &HashMap<String, Value>) -> TeraResult<Value> {
let text = try_get_value!("regex_replace", "value", String, value);
let pattern = match args.get("pattern") {
Some(val) => try_get_value!("regex_replace", "pattern", String, val),
None => {
return Err(TeraError::msg(
"Filter `regex_replace` expected an arg called `pattern`",
))
}
};
let rep = match args.get("rep") {
Some(val) => try_get_value!("regex_replace", "rep", String, val),
None => {
return Err(TeraError::msg("Filter `regex_replace` expected an arg called `rep`"))
}
};

let mut cache = self.re_cache.lock().expect("re_cache lock");
let replaced = {
match cache.get(&pattern) {
Some(pat) => pat.replace_all(&text, &rep),
None => {
let pat = Regex::new(&pattern)
.map_err(|e| format!("`regex_replace`: failed to compile regex: {}", e))?;
let replaced = pat.replace_all(&text, &rep);
cache.insert(pattern, pat);
replaced
}
}
};

Ok(to_value(replaced).unwrap())
}
}

#[derive(Debug)]
pub struct NumFormatFilter {
default_language: String,
Expand Down Expand Up @@ -114,7 +164,9 @@ mod tests {

use libs::tera::{to_value, Filter, Tera};

use super::{base64_decode, base64_encode, MarkdownFilter, NumFormatFilter};
use super::{
base64_decode, base64_encode, MarkdownFilter, NumFormatFilter, RegexReplaceFilter,
};
use config::Config;

#[test]
Expand Down Expand Up @@ -251,6 +303,22 @@ mod tests {
}
}

#[test]
fn regex_replace_filter() {
let value = "Springsteen, Bruce";
let expected = "Bruce Springsteen";
let pattern = r"(?P<last>[^,\s]+),\s+(?P<first>\S+)";
let rep = "$first $last";
let mut args = HashMap::new();
args.insert("pattern".to_string(), to_value(pattern).unwrap());
args.insert("rep".to_string(), to_value(rep).unwrap());
let regex_replace = RegexReplaceFilter::new();
let result = regex_replace.filter(&to_value(value).unwrap(), &args);
assert!(result.is_ok());
assert_eq!(result.unwrap(), to_value(expected).unwrap());
assert!(regex_replace.re_cache.lock().unwrap().contains_key(pattern));
}

#[test]
fn num_format_filter() {
let tests = vec![
Expand Down
1 change: 1 addition & 0 deletions components/templates/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub static ZOLA_TERA: Lazy<Tera> = Lazy::new(|| {
.unwrap();
tera.register_filter("base64_encode", filters::base64_encode);
tera.register_filter("base64_decode", filters::base64_decode);
tera.register_filter("regex_replace", filters::RegexReplaceFilter::new());
tera
});

Expand Down
8 changes: 8 additions & 0 deletions docs/content/documentation/templates/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,14 @@ Encode the variable to base64.
### base64_decode
Decode the variable from base64.

### regex_replace
Replace text via regular expressions.

```jinja2
{{ "World Hello" | regex_replace(pattern=`(?P<subject>\w+), (?P<greeting>\w+)`, rep=`$greeting $subject`) }}
<!-- Hello World -->
```

### num_format
Format a number into its string representation.

Expand Down