rumdl_lib/utils/
jinja_utils.rs1use regex::Regex;
2use std::sync::LazyLock;
3
4static JINJA_EXPRESSION_REGEX: LazyLock<Regex> =
6 LazyLock::new(|| Regex::new(r"\{\{.*?\}\}").expect("Failed to compile Jinja expression regex"));
7
8static JINJA_STATEMENT_REGEX: LazyLock<Regex> =
9 LazyLock::new(|| Regex::new(r"\{%.*?%\}").expect("Failed to compile Jinja statement regex"));
10
11pub fn find_jinja_ranges(content: &str) -> Vec<(usize, usize)> {
13 let mut ranges = Vec::new();
14
15 for mat in JINJA_EXPRESSION_REGEX.find_iter(content) {
17 ranges.push((mat.start(), mat.end()));
18 }
19
20 for mat in JINJA_STATEMENT_REGEX.find_iter(content) {
22 ranges.push((mat.start(), mat.end()));
23 }
24
25 ranges.sort_by_key(|r| r.0);
27 ranges
28}
29
30pub fn is_in_jinja_template(content: &str, pos: usize) -> bool {
32 for mat in JINJA_EXPRESSION_REGEX.find_iter(content) {
34 if pos >= mat.start() && pos < mat.end() {
35 return true;
36 }
37 }
38
39 for mat in JINJA_STATEMENT_REGEX.find_iter(content) {
41 if pos >= mat.start() && pos < mat.end() {
42 return true;
43 }
44 }
45
46 false
47}
48
49#[cfg(test)]
50mod tests {
51 use super::*;
52
53 #[test]
54 fn test_jinja_expression_detection() {
55 let content = "Some text {{ variable }} more text";
56
57 assert!(!is_in_jinja_template(content, 5));
59
60 assert!(is_in_jinja_template(content, 15));
62
63 assert!(!is_in_jinja_template(content, 30));
65 }
66
67 #[test]
68 fn test_jinja_statement_detection() {
69 let content = "{% if condition %} text {% endif %}";
70
71 assert!(is_in_jinja_template(content, 5));
73
74 assert!(!is_in_jinja_template(content, 20));
76
77 assert!(is_in_jinja_template(content, 28));
79 }
80
81 #[test]
82 fn test_complex_jinja_expression() {
83 let content = "{{ pd_read_csv()[index] | filter }}";
84
85 assert!(is_in_jinja_template(content, 10));
87 assert!(is_in_jinja_template(content, 20));
88 }
89}