markdown_composer/types/
header.rs

1#[cfg(feature = "serde")]
2use serde::{Deserialize, Serialize};
3use std::fmt;
4use tousize::ToUsize;
5
6/// The level of a header.
7#[derive(Clone, Debug, Eq, PartialEq)]
8#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
9pub struct HeaderLevel(usize);
10
11impl Default for HeaderLevel {
12    /// Returns the default header level (1).
13    fn default() -> Self {
14        HeaderLevel(1)
15    }
16}
17
18impl HeaderLevel {
19    /// Creates a new default header level of 1.
20    pub fn new() -> Self {
21        Self::default()
22    }
23
24    /// Creates a new header level.
25    ///
26    /// # Panics
27    ///
28    /// Panics if the header level is not valid (one to six inclusive).
29    pub fn from(level: impl ToUsize) -> Self {
30        let level = level.to_usize();
31        assert!(1 <= level && level <= 6);
32        Self(level)
33    }
34}
35
36impl<T> From<T> for HeaderLevel
37where
38    T: ToUsize,
39{
40    fn from(value: T) -> Self {
41        Self::from(value)
42    }
43}
44
45/// A markdown header.
46#[derive(Clone, Debug, Default, Eq, PartialEq)]
47#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
48pub struct Header {
49    /// The header text.
50    pub text: String,
51    /// The header level.
52    pub level: HeaderLevel,
53}
54
55impl Header {
56    /// Creates a new empty header with a level of 1.
57    pub fn new() -> Self {
58        Self::default()
59    }
60
61    /// Creates a new header.
62    ///
63    /// # Panics
64    ///
65    /// Panics if the header level is not valid (one to six inclusive).
66    pub fn from(text: impl Into<String>, level: impl Into<HeaderLevel>) -> Self {
67        Self {
68            text: text.into(),
69            level: level.into(),
70        }
71    }
72}
73
74impl fmt::Display for Header {
75    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76        writeln!(f, "{} {}", "#".repeat(self.level.0), self.text)
77    }
78}
79
80#[cfg(test)]
81mod tests {
82    use super::{Header, HeaderLevel};
83
84    #[test]
85    fn test_header_level() {
86        let level = 5usize;
87        assert_eq!(HeaderLevel::from(5usize), level.into());
88    }
89
90    #[test]
91    #[should_panic]
92    fn test_header_level_panic() {
93        let _: HeaderLevel = 0usize.into();
94    }
95
96    #[test]
97    fn test_header() {
98        let content = "Some header content";
99        let level = 5usize;
100        let header = Header::from(content, level);
101        assert_eq!(header.text, content);
102        assert_eq!(header.level, level.into());
103    }
104}