nmd_core/codex/modifier/
standard_heading_modifier.rs

1use regex::Regex;
2
3use crate::codex::modifier::constants::{CHAPTER_STYLE_PATTERN, CHAPTER_TAGS_PATTERN};
4
5use super::base_modifier::BaseModifier;
6use super::constants::MAX_HEADING_LEVEL;
7use super::ModifiersBucket;
8use super::ModifierIdentifier;
9
10#[derive(Debug, PartialEq, Clone)]
11pub enum StandardHeading {
12
13    HeadingGeneralCompactVersion(u32),
14    HeadingGeneralExtendedVersion(u32),
15    MinorHeading,
16    MajorHeading,
17    SameHeading,
18
19}
20
21impl StandardHeading {
22    pub fn ordered() -> Vec<Self> {
23        let mut heading_modifiers: Vec<Self> = vec![Self::MinorHeading, Self::MajorHeading, Self::SameHeading];
24
25        for i in (1..=MAX_HEADING_LEVEL).rev() {
26            heading_modifiers.push(Self::HeadingGeneralExtendedVersion(i));
27            heading_modifiers.push(Self::HeadingGeneralCompactVersion(i));
28        }
29
30        heading_modifiers
31    }
32
33    pub fn heading_level(content: &str) -> Option<u32> {
34        let heading_modifiers = Self::ordered();
35
36        for heading_modifier in heading_modifiers {
37            let regex = Regex::new(&heading_modifier.modifier_pattern()).unwrap();
38
39            if regex.is_match(content) {
40                match heading_modifier {
41                    Self::HeadingGeneralExtendedVersion(level) => return Option::Some(level),
42                    Self::HeadingGeneralCompactVersion(level) => return Option::Some(level),
43                    _ => panic!("unexpected modifier: {:?}", heading_modifier)
44                }
45            }
46        }
47
48        Option::None
49    }
50
51    pub fn str_is_heading(content: &str) -> bool {
52        Self::heading_level(content).is_some()
53    }
54
55    pub fn identifier(&self) -> ModifierIdentifier {
56        match *self {
57            Self::HeadingGeneralExtendedVersion(level) => {
58
59                if level == 0 || level > MAX_HEADING_LEVEL {
60                    panic!("{level} is an invalid heading level.")
61                }
62
63                format!(r"heading-{}-extended-version", level)
64            },
65            Self::HeadingGeneralCompactVersion(level) => {
66
67                if level == 0 || level > MAX_HEADING_LEVEL {
68                    panic!("{level} is an invalid heading level.")
69                }
70
71                format!(r"heading-{}-compact-version", level)
72            },
73            StandardHeading::MinorHeading => String::from("minor-heading"),
74            StandardHeading::MajorHeading => String::from("major-heading"),
75            StandardHeading::SameHeading => String::from("same-heading"),
76        }
77    }
78    
79    pub fn modifier_pattern(&self) -> String {
80        let specific_pattern = match *self {
81            Self::HeadingGeneralExtendedVersion(level) => {
82
83                if level == 0 || level > MAX_HEADING_LEVEL {
84                    panic!("{level} is an invalid heading level.")
85                }
86
87                format!(r"(?m:^#{{{}}}\s+(.*))", level)
88            },
89            Self::HeadingGeneralCompactVersion(level) => {
90
91                if level == 0 || level > MAX_HEADING_LEVEL {
92                    panic!("{level} is an invalid heading level.")
93                }
94
95                format!(r"(?m:^#({})\s+(.*))", level)
96            },
97            StandardHeading::MinorHeading => String::from(r"(?m:^#-\s+(.*))"),
98            StandardHeading::MajorHeading => String::from(r"(?m:^#\+\s+(.*))"),
99            StandardHeading::SameHeading => String::from(r"(?m:^#=\s+(.*))"),
100        };
101
102        format!("{}{}{}", specific_pattern, CHAPTER_TAGS_PATTERN, CHAPTER_STYLE_PATTERN)
103    }
104
105    pub fn incompatible_modifiers(&self) -> ModifiersBucket {
106        ModifiersBucket::None
107    }
108}
109
110impl Into<BaseModifier> for StandardHeading {
111    fn into(self) -> BaseModifier {
112        BaseModifier::new(self.modifier_pattern(), Regex::new(&self.modifier_pattern()).unwrap(), self.incompatible_modifiers())
113    }
114}