markdown_builder/types/
link.rs

1use crate::traits::{AsFooter, MarkdownElement};
2use std::fmt;
3
4/// A markdown link.
5#[derive(Clone, Debug, Default)]
6pub struct Link {
7    /// The url of the link.
8    pub url: String,
9    /// The text of the link.
10    pub text: String,
11    /// Whether the `Link`'s url should be rendered as a footer.
12    pub footer: bool,
13    /// Whether the link should be inlined (no new line).
14    pub inlined: bool,
15}
16
17impl Link {
18    /// Creates a new default `Link`.
19    pub fn new() -> Self {
20        Self::default()
21    }
22
23    /// Creates a new `Link` with the given values.
24    pub fn from(
25        url: impl Into<String>,
26        text: impl Into<String>,
27        footer: bool,
28        inlined: bool,
29    ) -> Self {
30        Self {
31            url: url.into(),
32            text: text.into(),
33            footer,
34            inlined,
35        }
36    }
37}
38
39impl AsFooter for Link {
40    fn as_footer(&self) -> Box<dyn MarkdownElement> {
41        Box::new(format!("[{}]: {}", self.text, self.url))
42    }
43}
44
45impl fmt::Display for Link {
46    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47        let text = if self.footer {
48            format!("[{}][{}]", self.text, self.text)
49        } else {
50            format!("[{}]({})", self.text, self.url)
51        };
52
53        if self.inlined {
54            write!(f, "{}", text)
55        } else {
56            writeln!(f, "{}", text)
57        }
58    }
59}
60
61#[cfg(test)]
62mod tests {
63    use super::*;
64
65    #[test]
66    fn test_link_default() {
67        let link = Link::new();
68        assert_eq!(link.url, "");
69        assert_eq!(link.text, "");
70        assert_eq!(link.footer, false);
71        assert_eq!(link.inlined, false);
72    }
73
74    #[test]
75    fn test_link_from() {
76        let link = Link::from("https://example.com", "example.com", false, true);
77        assert_eq!(link.url, "https://example.com");
78        assert_eq!(link.text, "example.com");
79        assert_eq!(link.footer, false);
80        assert_eq!(link.inlined, true);
81    }
82
83    #[test]
84    fn test_link_url_text() {
85        assert_eq!(
86            Link::from("https://example.com", "example.com", false, false).render(),
87            "[example.com](https://example.com)\n"
88        );
89    }
90
91    #[test]
92    fn test_link_url_text_inline() {
93        assert_eq!(
94            Link::from("https://example.com", "example.com", false, true).render(),
95            "[example.com](https://example.com)"
96        );
97    }
98
99    #[test]
100    fn test_link_url_text_footer() {
101        let link = Link::from("https://example.com", "example.com", true, false);
102
103        assert_eq!(link.render(), "[example.com][example.com]\n");
104        assert_eq!(
105            link.as_footer().render(),
106            "[example.com]: https://example.com"
107        )
108    }
109}