pub use serde_json::{Value};
pub use regex::Regex;
pub use string_join::display::Join;
pub fn render(content: &str, data: Value) -> String {
let re = Regex::new(r"\{\{ for (\w+) in (\w+) \}\}([\s\S]*?)\{\{ endfor \}\}").unwrap();
let replaced = re.replace_all(content, |caps: ®ex::Captures| {
let loop_variable = &caps[1];
let loop_variable_formatted = "".join(["{{ ", loop_variable, " }}"]);
let loop_variable = loop_variable_formatted.as_str();
let loop_iterable = &caps[2];
let loop_body = &caps[3];
let iterable = &data[loop_iterable];
if !iterable.is_array() {
return "".to_string()
}
let mut result = "".to_string();
for (index, value) in iterable.as_array().unwrap().iter().enumerate() {
let mut loop_body_replaced = loop_body.trim_start_matches('\n').to_string();
let val = get_value_string(value);
loop_body_replaced = loop_body_replaced.replace(loop_variable, &val);
loop_body_replaced = loop_body_replaced.replace("{{ index }}", &index.to_string());
result.push_str(&loop_body_replaced);
}
result
});
let re = Regex::new(r"\{\{ if (\w+) \}\}\s*([\s\S]*?)\s*(?:\{\{ else \}\}\s*([\s\S]*?)\s*)?\{\{ endif \}\}").unwrap();
let replaced = re.replace_all(&replaced, |caps: ®ex::Captures| {
let matched_group_count = (1..caps.len()).filter(|i| caps.get(*i).is_some()).count();
let condition = &caps[1];
let if_body = &caps[2];
let else_body = if matched_group_count > 2 {
&caps[3]
} else {
""
};
let value = &data[condition];
if value.is_null() || value == "false" || value == false {
else_body.to_string()
} else {
if_body.to_string()
}
});
let re = Regex::new(r"\{\{ (\w+) \}\}").unwrap();
let replaced = re.replace_all(&replaced, |caps: ®ex::Captures| {
let key = &caps[1];
let value = &data[key];
if value.is_array() {
value.as_array()
.unwrap()
.iter()
.map(|v| get_value_string(v))
.collect::<Vec<_>>()
.join(", ")
} else {
get_value_string(value)
}
});
let re = Regex::new(r"\{\{ (\w+)\[(\d+)\] \}\}").unwrap();
let replaced = re.replace_all(&replaced, |caps: ®ex::Captures| {
let array_name = &caps[1];
let index = caps[2].parse::<usize>().unwrap();
let value = &data[array_name][index];
get_value_string(value)
});
replaced.to_string()
}
fn get_value_string(value: &Value) -> String {
if value.is_string() {
value.as_str().unwrap().to_string()
} else {
value.to_string()
}
}