rumdl_lib/rules/
emphasis_style.rs1use regex::Regex;
2use std::fmt;
3use std::sync::LazyLock;
4
5#[derive(Debug, PartialEq, Eq, Clone, Copy, Default, Hash)]
7pub enum EmphasisStyle {
8 #[default]
10 Consistent,
11 Asterisk,
13 Underscore,
15}
16
17impl fmt::Display for EmphasisStyle {
18 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19 match self {
20 EmphasisStyle::Asterisk => write!(f, "asterisk"),
21 EmphasisStyle::Underscore => write!(f, "underscore"),
22 EmphasisStyle::Consistent => write!(f, "consistent"),
23 }
24 }
25}
26
27impl From<&str> for EmphasisStyle {
28 fn from(s: &str) -> Self {
29 match s {
30 "asterisk" => EmphasisStyle::Asterisk,
31 "underscore" => EmphasisStyle::Underscore,
32 _ => EmphasisStyle::Consistent,
33 }
34 }
35}
36
37pub fn get_emphasis_pattern(style: EmphasisStyle) -> &'static Regex {
39 static ASTERISK_EMPHASIS: LazyLock<Regex> =
40 LazyLock::new(|| Regex::new(r"\*([^\s*][^*]*?[^\s*]|[^\s*])\*").unwrap());
41 static UNDERSCORE_EMPHASIS: LazyLock<Regex> =
42 LazyLock::new(|| Regex::new(r"_([^\s_][^_]*?[^\s_]|[^\s_])_").unwrap());
43
44 match style {
45 EmphasisStyle::Asterisk => &ASTERISK_EMPHASIS,
46 EmphasisStyle::Underscore => &UNDERSCORE_EMPHASIS,
47 EmphasisStyle::Consistent => &ASTERISK_EMPHASIS, }
49}
50
51pub fn get_emphasis_style(marker: &str) -> Option<EmphasisStyle> {
53 match marker {
54 "*" => Some(EmphasisStyle::Asterisk),
55 "_" => Some(EmphasisStyle::Underscore),
56 _ => None,
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63
64 #[test]
65 fn test_emphasis_style_from_str() {
66 assert_eq!(EmphasisStyle::from("asterisk"), EmphasisStyle::Asterisk);
67 assert_eq!(EmphasisStyle::from("underscore"), EmphasisStyle::Underscore);
68 assert_eq!(EmphasisStyle::from(""), EmphasisStyle::Consistent);
69 assert_eq!(EmphasisStyle::from("unknown"), EmphasisStyle::Consistent);
70 }
71
72 #[test]
73 fn test_get_emphasis_pattern() {
74 let asterisk_pattern = get_emphasis_pattern(EmphasisStyle::Asterisk);
76 assert!(asterisk_pattern.is_match("*text*"));
77 assert!(asterisk_pattern.is_match("*t*"));
78 assert!(!asterisk_pattern.is_match("* text*"));
79 assert!(!asterisk_pattern.is_match("*text *"));
80
81 let underscore_pattern = get_emphasis_pattern(EmphasisStyle::Underscore);
83 assert!(underscore_pattern.is_match("_text_"));
84 assert!(underscore_pattern.is_match("_t_"));
85 assert!(!underscore_pattern.is_match("_ text_"));
86 assert!(!underscore_pattern.is_match("_text _"));
87
88 let consistent_pattern = get_emphasis_pattern(EmphasisStyle::Consistent);
90 assert!(consistent_pattern.is_match("*text*"));
91 assert!(!consistent_pattern.is_match("_text_"));
92 }
93
94 #[test]
95 fn test_get_emphasis_style() {
96 assert_eq!(get_emphasis_style("*"), Some(EmphasisStyle::Asterisk));
97 assert_eq!(get_emphasis_style("_"), Some(EmphasisStyle::Underscore));
98 assert_eq!(get_emphasis_style(""), None);
99 assert_eq!(get_emphasis_style("**"), None);
100 assert_eq!(get_emphasis_style("__"), None);
101 }
102}