rumdl_lib/utils/
mkdocs_icons.rs1use regex::Regex;
12use std::sync::LazyLock;
13
14static ICON_SHORTCODE_PATTERN: LazyLock<Regex> =
17 LazyLock::new(|| Regex::new(r":([a-z][a-z0-9_]*(?:-[a-z0-9_]+)+):").unwrap());
18
19static EMOJI_SHORTCODE_PATTERN: LazyLock<Regex> = LazyLock::new(|| Regex::new(r":([a-zA-Z0-9_+-]+):").unwrap());
21
22pub fn is_in_any_shortcode(line: &str, position: usize) -> bool {
24 if !line.contains(':') {
25 return false;
26 }
27
28 for m in ICON_SHORTCODE_PATTERN.find_iter(line) {
29 if m.start() <= position && position < m.end() {
30 return true;
31 }
32 }
33
34 for m in EMOJI_SHORTCODE_PATTERN.find_iter(line) {
35 if m.start() <= position && position < m.end() {
36 return true;
37 }
38 }
39
40 false
41}
42
43#[cfg(test)]
44mod tests {
45 use super::*;
46
47 #[test]
48 fn test_is_in_any_shortcode_emoji() {
49 let line = ":smile: and :material-check:";
50 assert!(is_in_any_shortcode(line, 0));
51 assert!(is_in_any_shortcode(line, 3));
52 assert!(is_in_any_shortcode(line, 6));
53 }
54
55 #[test]
56 fn test_is_in_any_shortcode_between() {
57 let line = ":smile: and :material-check:";
58 assert!(!is_in_any_shortcode(line, 7));
59 assert!(!is_in_any_shortcode(line, 10));
60 }
61
62 #[test]
63 fn test_is_in_any_shortcode_icon() {
64 let line = ":smile: and :material-check:";
65 assert!(is_in_any_shortcode(line, 12));
66 assert!(is_in_any_shortcode(line, 20));
67 }
68
69 #[test]
70 fn test_is_in_any_shortcode_no_colon() {
71 assert!(!is_in_any_shortcode("plain text", 3));
72 }
73}