tempera/
custom.rs

1//! Module that allows define and use custom styles.
2
3use lazy_static::lazy_static;
4use regex::Regex;
5use std::collections::HashMap;
6use std::sync::Mutex;
7
8lazy_static! {
9  static ref INVALID_STYLE_MATCHER: Regex = Regex::new(r"(?i)[\s\{\}]").unwrap();
10  static ref CUSTOM: Mutex<HashMap<String, Vec<String>>> = Mutex::new(HashMap::new());
11}
12
13/// An error that occurred when adding a new custom style.
14pub enum CustomStyleError {
15  /// Error raised when the style name contains spaces or curly braces.
16  InvalidSyntax,
17}
18
19/// Adds a new custom style.
20pub fn add_style(name: &str, styles: &[&str]) -> Result<(), CustomStyleError> {
21  // Check syntax
22  if INVALID_STYLE_MATCHER.is_match(&name) {
23    return Err(CustomStyleError::InvalidSyntax);
24  }
25
26  // Add the style and return
27  CUSTOM
28    .lock()
29    .unwrap()
30    .insert(name.to_string(), styles.iter().map(|c| c.to_string()).collect());
31
32  Ok(())
33}
34
35/// Deletes one or more custom styles.
36pub fn delete_styles(names: &[&str]) {
37  for name in names.iter() {
38    CUSTOM.lock().unwrap().remove(&name.to_string());
39  }
40}
41
42/// Resolve all custom styles.
43pub fn resolve_styles(names: &[&str]) -> Vec<String> {
44  let mut resolved: Vec<String> = vec![];
45
46  // For each name
47  for name in names.iter() {
48    // Attempt to find it
49    match CUSTOM.lock().unwrap().get(&name.to_string()) {
50      // Custom style found, add it
51      Some(styles) => {
52        resolved.extend_from_slice(styles);
53      }
54      // No result, add the token unchanged
55      None => resolved.push(name.to_string()),
56    }
57  }
58
59  resolved
60}