use regex::Regex;
use serde_json::Value;
use std::collections::HashMap;
use tera::TeraResult;
use crate::template::engine_adapter::{JsonRegisterExt, try_get_value};
pub fn ruby_escape_str(s: &str) -> String {
s.replace('\\', "\\\\").replace('"', "\\\"")
}
pub(crate) fn register_ruby_escape(tera: &mut tera::Tera) {
tera.register_json_filter(
"ruby_escape",
|value: &Value, _: &HashMap<String, Value>| {
let s = try_get_value!("ruby_escape", "value", String, value);
Ok(Value::String(ruby_escape_str(&s)))
},
);
}
pub(super) fn register(tera: &mut tera::Tera) {
tera.register_json_filter("tolower", |value: &Value, _: &HashMap<String, Value>| {
let s = try_get_value!("tolower", "value", String, value);
Ok(Value::String(s.to_lowercase()))
});
tera.register_json_filter("toupper", |value: &Value, _: &HashMap<String, Value>| {
let s = try_get_value!("toupper", "value", String, value);
Ok(Value::String(s.to_uppercase()))
});
tera.register_json_filter(
"trimprefix",
|value: &Value, args: &HashMap<String, Value>| {
let s = try_get_value!("trimprefix", "value", String, value);
let prefix = args
.get("prefix")
.and_then(|v| v.as_str())
.ok_or_else(|| tera::Error::message("trimprefix requires a `prefix` argument"))?;
let result = s.strip_prefix(prefix).unwrap_or(&s);
Ok(Value::String(result.to_string()))
},
);
tera.register_json_filter(
"trimsuffix",
|value: &Value, args: &HashMap<String, Value>| {
let s = try_get_value!("trimsuffix", "value", String, value);
let suffix = args
.get("suffix")
.and_then(|v| v.as_str())
.ok_or_else(|| tera::Error::message("trimsuffix requires a `suffix` argument"))?;
let result = s.strip_suffix(suffix).unwrap_or(&s);
Ok(Value::String(result.to_string()))
},
);
tera.register_json_filter("mdv2escape", |value: &Value, _: &HashMap<String, Value>| {
let s = try_get_value!("mdv2escape", "value", String, value);
let escaped = s
.chars()
.map(|c| {
if "_*[]()~`>#+-=|{}.!".contains(c) {
format!("\\{}", c)
} else {
c.to_string()
}
})
.collect::<String>();
Ok(Value::String(escaped))
});
tera.register_json_function(
"contains",
|args: &HashMap<String, Value>| -> TeraResult<Value> {
let s = args
.get("s")
.and_then(|v| v.as_str())
.ok_or_else(|| tera::Error::message("contains requires `s` argument"))?;
let substr = args
.get("substr")
.and_then(|v| v.as_str())
.ok_or_else(|| tera::Error::message("contains requires `substr` argument"))?;
Ok(Value::Bool(s.contains(substr)))
},
);
tera.register_json_function(
"reReplaceAll",
|args: &HashMap<String, Value>| -> TeraResult<Value> {
let pattern = args
.get("pattern")
.and_then(|v| v.as_str())
.ok_or_else(|| tera::Error::message("reReplaceAll requires `pattern` argument"))?;
let input = args
.get("input")
.and_then(|v| v.as_str())
.ok_or_else(|| tera::Error::message("reReplaceAll requires `input` argument"))?;
let replacement = args
.get("replacement")
.and_then(|v| v.as_str())
.ok_or_else(|| {
tera::Error::message("reReplaceAll requires `replacement` argument")
})?;
let re = Regex::new(pattern).map_err(|e| {
tera::Error::message(format!("reReplaceAll: invalid regex '{}': {}", pattern, e))
})?;
Ok(Value::String(
re.replace_all(input, replacement).to_string(),
))
},
);
tera.register_json_filter(
"reReplaceAll",
|value: &Value, args: &HashMap<String, Value>| {
let input = try_get_value!("reReplaceAll", "value", String, value);
let pattern = args
.get("pattern")
.and_then(|v| v.as_str())
.ok_or_else(|| {
tera::Error::message("reReplaceAll filter requires `pattern` argument")
})?;
let replacement = args
.get("replacement")
.and_then(|v| v.as_str())
.ok_or_else(|| {
tera::Error::message("reReplaceAll filter requires `replacement` argument")
})?;
let re = Regex::new(pattern).map_err(|e| {
tera::Error::message(format!("reReplaceAll: invalid regex '{}': {}", pattern, e))
})?;
Ok(Value::String(
re.replace_all(&input, replacement).to_string(),
))
},
);
tera.register_json_function(
"replace",
|args: &HashMap<String, Value>| -> TeraResult<Value> {
let s = args
.get("s")
.and_then(|v| v.as_str())
.ok_or_else(|| tera::Error::message("replace requires `s` argument"))?;
let old = args
.get("old")
.and_then(|v| v.as_str())
.ok_or_else(|| tera::Error::message("replace requires `old` argument"))?;
let new = args
.get("new")
.and_then(|v| v.as_str())
.ok_or_else(|| tera::Error::message("replace requires `new` argument"))?;
Ok(Value::String(s.replace(old, new)))
},
);
tera.register_json_filter("replace", |value: &Value, args: &HashMap<String, Value>| {
let s = try_get_value!("replace", "value", String, value);
let from = args
.get("from")
.and_then(|v| v.as_str())
.ok_or_else(|| tera::Error::message("replace filter requires `from` argument"))?;
let to = args
.get("to")
.and_then(|v| v.as_str())
.ok_or_else(|| tera::Error::message("replace filter requires `to` argument"))?;
Ok(Value::String(s.replace(from, to)))
});
tera.register_json_function(
"split",
|args: &HashMap<String, Value>| -> TeraResult<Value> {
let s = args
.get("s")
.and_then(|v| v.as_str())
.ok_or_else(|| tera::Error::message("split requires `s` argument"))?;
let sep = args
.get("sep")
.and_then(|v| v.as_str())
.ok_or_else(|| tera::Error::message("split requires `sep` argument"))?;
let parts: Vec<Value> = s.split(sep).map(|p| Value::String(p.to_string())).collect();
Ok(Value::Array(parts))
},
);
tera.register_json_filter("split", |value: &Value, args: &HashMap<String, Value>| {
let s = try_get_value!("split", "value", String, value);
let sep = args
.get("sep")
.and_then(|v| v.as_str())
.ok_or_else(|| tera::Error::message("split filter requires `sep` argument"))?;
let parts: Vec<Value> = s.split(sep).map(|p| Value::String(p.to_string())).collect();
Ok(Value::Array(parts))
});
tera.register_json_filter(
"contains",
|value: &Value, args: &HashMap<String, Value>| {
let s = try_get_value!("contains", "value", String, value);
let substr = args.get("substr").and_then(|v| v.as_str()).ok_or_else(|| {
tera::Error::message("contains filter requires `substr` argument")
})?;
Ok(Value::Bool(s.contains(substr)))
},
);
tera.register_json_function(
"trim",
|args: &HashMap<String, Value>| -> TeraResult<Value> {
let s = args
.get("s")
.and_then(|v| v.as_str())
.ok_or_else(|| tera::Error::message("trim requires `s` argument"))?;
Ok(Value::String(s.trim().to_string()))
},
);
tera.register_json_function(
"title",
|args: &HashMap<String, Value>| -> TeraResult<Value> {
let s = args
.get("s")
.and_then(|v| v.as_str())
.ok_or_else(|| tera::Error::message("title requires `s` argument"))?;
let titled = s
.split_whitespace()
.map(|word| {
let mut chars = word.chars();
match chars.next() {
Some(c) => {
let upper: String = c.to_uppercase().collect();
format!("{}{}", upper, chars.as_str())
}
None => String::new(),
}
})
.collect::<Vec<_>>()
.join(" ");
Ok(Value::String(titled))
},
);
tera.register_json_function(
"tolower",
|args: &HashMap<String, Value>| -> TeraResult<Value> {
let s = args
.get("s")
.and_then(|v| v.as_str())
.ok_or_else(|| tera::Error::message("tolower requires `s` argument"))?;
Ok(Value::String(s.to_lowercase()))
},
);
tera.register_json_function(
"toupper",
|args: &HashMap<String, Value>| -> TeraResult<Value> {
let s = args
.get("s")
.and_then(|v| v.as_str())
.ok_or_else(|| tera::Error::message("toupper requires `s` argument"))?;
Ok(Value::String(s.to_uppercase()))
},
);
tera.register_json_function(
"trimprefix",
|args: &HashMap<String, Value>| -> TeraResult<Value> {
let s = args
.get("s")
.and_then(|v| v.as_str())
.ok_or_else(|| tera::Error::message("trimprefix requires `s` argument"))?;
let prefix = args
.get("prefix")
.and_then(|v| v.as_str())
.ok_or_else(|| tera::Error::message("trimprefix requires `prefix` argument"))?;
let result = s.strip_prefix(prefix).unwrap_or(s);
Ok(Value::String(result.to_string()))
},
);
tera.register_json_function(
"trimsuffix",
|args: &HashMap<String, Value>| -> TeraResult<Value> {
let s = args
.get("s")
.and_then(|v| v.as_str())
.ok_or_else(|| tera::Error::message("trimsuffix requires `s` argument"))?;
let suffix = args
.get("suffix")
.and_then(|v| v.as_str())
.ok_or_else(|| tera::Error::message("trimsuffix requires `suffix` argument"))?;
let result = s.strip_suffix(suffix).unwrap_or(s);
Ok(Value::String(result.to_string()))
},
);
tera.register_json_function(
"mdv2escape",
|args: &HashMap<String, Value>| -> TeraResult<Value> {
let s = args
.get("s")
.and_then(|v| v.as_str())
.ok_or_else(|| tera::Error::message("mdv2escape requires `s` argument"))?;
let escaped = s
.chars()
.map(|c| {
if "_*[]()~`>#+-=|{}.!".contains(c) {
format!("\\{}", c)
} else {
c.to_string()
}
})
.collect::<String>();
Ok(Value::String(escaped))
},
);
}