anodizer_core/template/base_tera/
text.rs1use regex::Regex;
6use serde_json::Value;
7use std::collections::HashMap;
8use tera::TeraResult;
9
10use crate::template::engine_adapter::{JsonRegisterExt, try_get_value};
11
12pub fn ruby_escape_str(s: &str) -> String {
22 s.replace('\\', "\\\\").replace('"', "\\\"")
23}
24
25pub(crate) fn register_ruby_escape(tera: &mut tera::Tera) {
36 tera.register_json_filter(
37 "ruby_escape",
38 |value: &Value, _: &HashMap<String, Value>| {
39 let s = try_get_value!("ruby_escape", "value", String, value);
40 Ok(Value::String(ruby_escape_str(&s)))
41 },
42 );
43}
44
45pub(super) fn register(tera: &mut tera::Tera) {
46 tera.register_json_filter("tolower", |value: &Value, _: &HashMap<String, Value>| {
48 let s = try_get_value!("tolower", "value", String, value);
49 Ok(Value::String(s.to_lowercase()))
50 });
51 tera.register_json_filter("toupper", |value: &Value, _: &HashMap<String, Value>| {
52 let s = try_get_value!("toupper", "value", String, value);
53 Ok(Value::String(s.to_uppercase()))
54 });
55
56 tera.register_json_filter(
58 "trimprefix",
59 |value: &Value, args: &HashMap<String, Value>| {
60 let s = try_get_value!("trimprefix", "value", String, value);
61 let prefix = args
62 .get("prefix")
63 .and_then(|v| v.as_str())
64 .ok_or_else(|| tera::Error::message("trimprefix requires a `prefix` argument"))?;
65 let result = s.strip_prefix(prefix).unwrap_or(&s);
66 Ok(Value::String(result.to_string()))
67 },
68 );
69
70 tera.register_json_filter(
72 "trimsuffix",
73 |value: &Value, args: &HashMap<String, Value>| {
74 let s = try_get_value!("trimsuffix", "value", String, value);
75 let suffix = args
76 .get("suffix")
77 .and_then(|v| v.as_str())
78 .ok_or_else(|| tera::Error::message("trimsuffix requires a `suffix` argument"))?;
79 let result = s.strip_suffix(suffix).unwrap_or(&s);
80 Ok(Value::String(result.to_string()))
81 },
82 );
83
84 tera.register_json_filter("mdv2escape", |value: &Value, _: &HashMap<String, Value>| {
86 let s = try_get_value!("mdv2escape", "value", String, value);
87 let escaped = s
88 .chars()
89 .map(|c| {
90 if "_*[]()~`>#+-=|{}.!".contains(c) {
91 format!("\\{}", c)
92 } else {
93 c.to_string()
94 }
95 })
96 .collect::<String>();
97 Ok(Value::String(escaped))
98 });
99
100 tera.register_json_function(
104 "contains",
105 |args: &HashMap<String, Value>| -> TeraResult<Value> {
106 let s = args
107 .get("s")
108 .and_then(|v| v.as_str())
109 .ok_or_else(|| tera::Error::message("contains requires `s` argument"))?;
110 let substr = args
111 .get("substr")
112 .and_then(|v| v.as_str())
113 .ok_or_else(|| tera::Error::message("contains requires `substr` argument"))?;
114 Ok(Value::Bool(s.contains(substr)))
115 },
116 );
117
118 tera.register_json_function(
126 "reReplaceAll",
127 |args: &HashMap<String, Value>| -> TeraResult<Value> {
128 let pattern = args
129 .get("pattern")
130 .and_then(|v| v.as_str())
131 .ok_or_else(|| tera::Error::message("reReplaceAll requires `pattern` argument"))?;
132 let input = args
133 .get("input")
134 .and_then(|v| v.as_str())
135 .ok_or_else(|| tera::Error::message("reReplaceAll requires `input` argument"))?;
136 let replacement = args
137 .get("replacement")
138 .and_then(|v| v.as_str())
139 .ok_or_else(|| {
140 tera::Error::message("reReplaceAll requires `replacement` argument")
141 })?;
142 let re = Regex::new(pattern).map_err(|e| {
143 tera::Error::message(format!("reReplaceAll: invalid regex '{}': {}", pattern, e))
144 })?;
145 Ok(Value::String(
146 re.replace_all(input, replacement).to_string(),
147 ))
148 },
149 );
150
151 tera.register_json_filter(
155 "reReplaceAll",
156 |value: &Value, args: &HashMap<String, Value>| {
157 let input = try_get_value!("reReplaceAll", "value", String, value);
158 let pattern = args
159 .get("pattern")
160 .and_then(|v| v.as_str())
161 .ok_or_else(|| {
162 tera::Error::message("reReplaceAll filter requires `pattern` argument")
163 })?;
164 let replacement = args
165 .get("replacement")
166 .and_then(|v| v.as_str())
167 .ok_or_else(|| {
168 tera::Error::message("reReplaceAll filter requires `replacement` argument")
169 })?;
170 let re = Regex::new(pattern).map_err(|e| {
171 tera::Error::message(format!("reReplaceAll: invalid regex '{}': {}", pattern, e))
172 })?;
173 Ok(Value::String(
174 re.replace_all(&input, replacement).to_string(),
175 ))
176 },
177 );
178
179 tera.register_json_function(
182 "replace",
183 |args: &HashMap<String, Value>| -> TeraResult<Value> {
184 let s = args
185 .get("s")
186 .and_then(|v| v.as_str())
187 .ok_or_else(|| tera::Error::message("replace requires `s` argument"))?;
188 let old = args
189 .get("old")
190 .and_then(|v| v.as_str())
191 .ok_or_else(|| tera::Error::message("replace requires `old` argument"))?;
192 let new = args
193 .get("new")
194 .and_then(|v| v.as_str())
195 .ok_or_else(|| tera::Error::message("replace requires `new` argument"))?;
196 Ok(Value::String(s.replace(old, new)))
197 },
198 );
199 tera.register_json_filter("replace", |value: &Value, args: &HashMap<String, Value>| {
203 let s = try_get_value!("replace", "value", String, value);
204 let from = args
205 .get("from")
206 .and_then(|v| v.as_str())
207 .ok_or_else(|| tera::Error::message("replace filter requires `from` argument"))?;
208 let to = args
209 .get("to")
210 .and_then(|v| v.as_str())
211 .ok_or_else(|| tera::Error::message("replace filter requires `to` argument"))?;
212 Ok(Value::String(s.replace(from, to)))
213 });
214
215 tera.register_json_function(
218 "split",
219 |args: &HashMap<String, Value>| -> TeraResult<Value> {
220 let s = args
221 .get("s")
222 .and_then(|v| v.as_str())
223 .ok_or_else(|| tera::Error::message("split requires `s` argument"))?;
224 let sep = args
225 .get("sep")
226 .and_then(|v| v.as_str())
227 .ok_or_else(|| tera::Error::message("split requires `sep` argument"))?;
228 let parts: Vec<Value> = s.split(sep).map(|p| Value::String(p.to_string())).collect();
229 Ok(Value::Array(parts))
230 },
231 );
232 tera.register_json_filter("split", |value: &Value, args: &HashMap<String, Value>| {
234 let s = try_get_value!("split", "value", String, value);
235 let sep = args
236 .get("sep")
237 .and_then(|v| v.as_str())
238 .ok_or_else(|| tera::Error::message("split filter requires `sep` argument"))?;
239 let parts: Vec<Value> = s.split(sep).map(|p| Value::String(p.to_string())).collect();
240 Ok(Value::Array(parts))
241 });
242
243 tera.register_json_filter(
245 "contains",
246 |value: &Value, args: &HashMap<String, Value>| {
247 let s = try_get_value!("contains", "value", String, value);
248 let substr = args.get("substr").and_then(|v| v.as_str()).ok_or_else(|| {
249 tera::Error::message("contains filter requires `substr` argument")
250 })?;
251 Ok(Value::Bool(s.contains(substr)))
252 },
253 );
254
255 tera.register_json_function(
259 "trim",
260 |args: &HashMap<String, Value>| -> TeraResult<Value> {
261 let s = args
262 .get("s")
263 .and_then(|v| v.as_str())
264 .ok_or_else(|| tera::Error::message("trim requires `s` argument"))?;
265 Ok(Value::String(s.trim().to_string()))
266 },
267 );
268
269 tera.register_json_function(
273 "title",
274 |args: &HashMap<String, Value>| -> TeraResult<Value> {
275 let s = args
276 .get("s")
277 .and_then(|v| v.as_str())
278 .ok_or_else(|| tera::Error::message("title requires `s` argument"))?;
279 let titled = s
281 .split_whitespace()
282 .map(|word| {
283 let mut chars = word.chars();
284 match chars.next() {
285 Some(c) => {
286 let upper: String = c.to_uppercase().collect();
287 format!("{}{}", upper, chars.as_str())
288 }
289 None => String::new(),
290 }
291 })
292 .collect::<Vec<_>>()
293 .join(" ");
294 Ok(Value::String(titled))
295 },
296 );
297
298 tera.register_json_function(
302 "tolower",
303 |args: &HashMap<String, Value>| -> TeraResult<Value> {
304 let s = args
305 .get("s")
306 .and_then(|v| v.as_str())
307 .ok_or_else(|| tera::Error::message("tolower requires `s` argument"))?;
308 Ok(Value::String(s.to_lowercase()))
309 },
310 );
311
312 tera.register_json_function(
314 "toupper",
315 |args: &HashMap<String, Value>| -> TeraResult<Value> {
316 let s = args
317 .get("s")
318 .and_then(|v| v.as_str())
319 .ok_or_else(|| tera::Error::message("toupper requires `s` argument"))?;
320 Ok(Value::String(s.to_uppercase()))
321 },
322 );
323
324 tera.register_json_function(
326 "trimprefix",
327 |args: &HashMap<String, Value>| -> TeraResult<Value> {
328 let s = args
329 .get("s")
330 .and_then(|v| v.as_str())
331 .ok_or_else(|| tera::Error::message("trimprefix requires `s` argument"))?;
332 let prefix = args
333 .get("prefix")
334 .and_then(|v| v.as_str())
335 .ok_or_else(|| tera::Error::message("trimprefix requires `prefix` argument"))?;
336 let result = s.strip_prefix(prefix).unwrap_or(s);
337 Ok(Value::String(result.to_string()))
338 },
339 );
340
341 tera.register_json_function(
343 "trimsuffix",
344 |args: &HashMap<String, Value>| -> TeraResult<Value> {
345 let s = args
346 .get("s")
347 .and_then(|v| v.as_str())
348 .ok_or_else(|| tera::Error::message("trimsuffix requires `s` argument"))?;
349 let suffix = args
350 .get("suffix")
351 .and_then(|v| v.as_str())
352 .ok_or_else(|| tera::Error::message("trimsuffix requires `suffix` argument"))?;
353 let result = s.strip_suffix(suffix).unwrap_or(s);
354 Ok(Value::String(result.to_string()))
355 },
356 );
357
358 tera.register_json_function(
360 "mdv2escape",
361 |args: &HashMap<String, Value>| -> TeraResult<Value> {
362 let s = args
363 .get("s")
364 .and_then(|v| v.as_str())
365 .ok_or_else(|| tera::Error::message("mdv2escape requires `s` argument"))?;
366 let escaped = s
367 .chars()
368 .map(|c| {
369 if "_*[]()~`>#+-=|{}.!".contains(c) {
370 format!("\\{}", c)
371 } else {
372 c.to_string()
373 }
374 })
375 .collect::<String>();
376 Ok(Value::String(escaped))
377 },
378 );
379}