markdown_builder/
transforms.rs

1//! Contains extension traits that can used to transform text elements into
2//! special markdown formats.
3//!
4//! The module adds support for the following transformations:
5//! - [Block quotes](trait.BlockQuote.html)
6//! - [Bold](trait.Bold.html)
7//! - [Code blocks](trait.CodeBlock.html)
8//! - [Inline code](trait.Inline.html)
9//! - [Italic](trait.Italic.html)
10
11/// An extension trait for block quote transformation.
12pub trait BlockQuote {
13    /// Transforms the given text into a block quote.
14    ///
15    /// Multiline quotes should be created using
16    /// [block_quote_multi_line](trait.BlockQuote.html#tymethod.
17    /// block_quote_multi_line) function.
18    fn to_block_quote(&self) -> String;
19
20    /// Transforms the given text into a multiline block quote.
21    ///
22    /// This method does take newlines into account and splits the text after
23    /// them to create a block quote that spans over multiple lines instead of a
24    /// single one.
25    fn to_block_quote_multi_line(&self) -> String;
26}
27
28impl<T> BlockQuote for T
29where
30    T: AsRef<str>,
31{
32    fn to_block_quote(&self) -> String {
33        format!("> {}", self.as_ref())
34    }
35
36    fn to_block_quote_multi_line(&self) -> String {
37        let mut lines = Vec::new();
38        for line in self.as_ref().lines() {
39            let quoted = format!("> {}", line);
40            lines.push(quoted);
41        }
42        lines.join("\n")
43    }
44}
45
46/// An extension trait for bold transformations.
47pub trait Bold {
48    /// Transforms the given text into its bold version.
49    fn to_bold(&self) -> String;
50}
51
52impl<T> Bold for T
53where
54    T: AsRef<str>,
55{
56    fn to_bold(&self) -> String {
57        format!("**{}**", self.as_ref())
58    }
59}
60
61/// An extension trait for code block transformations.
62pub trait CodeBlock {
63    /// Transforms the given text into a code block.
64    fn to_code_block(&self) -> String;
65
66    /// Transforms the given text into a code block, allowing to specify the
67    /// language to use for highlighting.
68    fn to_code_block_with_language<S: AsRef<str>>(&self, language: S) -> String;
69}
70
71impl<T> CodeBlock for T
72where
73    T: AsRef<str>,
74{
75    fn to_code_block(&self) -> String {
76        format!("```\n{}\n```", self.as_ref())
77    }
78
79    fn to_code_block_with_language<S: AsRef<str>>(&self, language: S) -> String {
80        format!("```{}\n{}\n```", language.as_ref(), self.as_ref())
81    }
82}
83
84/// An extension trait for inline transformations.
85pub trait Inline {
86    /// Transforms the given text into an inline code block.
87    fn to_inline(&self) -> String;
88}
89
90impl<T> Inline for T
91where
92    T: AsRef<str>,
93{
94    fn to_inline(&self) -> String {
95        format!("`{}`", self.as_ref())
96    }
97}
98
99/// An extension trait for italic transformations.
100pub trait Italic {
101    /// Transforms the given text into its italic variant.
102    fn to_italic(&self) -> String;
103}
104
105impl<T> Italic for T
106where
107    T: AsRef<str>,
108{
109    fn to_italic(&self) -> String {
110        format!("*{}*", self.as_ref())
111    }
112}
113
114/// An extension trait for strikethrough transformations.
115pub trait Strikethrough {
116    /// Transforms the given text to be strikethrough.
117    fn to_strikethrough(&self) -> String;
118}
119
120impl<T> Strikethrough for T
121where
122    T: AsRef<str>,
123{
124    fn to_strikethrough(&self) -> String {
125        format!("~~{}~~", self.as_ref())
126    }
127}
128
129#[cfg(test)]
130mod tests {
131    use super::{BlockQuote, Bold, Inline, Italic};
132    use crate::transforms::Strikethrough;
133
134    #[test]
135    fn test_block_quote_single_line() {
136        let text = "This is a single line block quote";
137        let expected = "> This is a single line block quote";
138
139        assert_eq!(expected, text.to_block_quote());
140    }
141
142    #[test]
143    fn test_block_quote_multi_line() {
144        let text = "This is a single line block quote\nThis is the second line";
145        let expected = "> This is a single line block quote\n> This is the second line";
146
147        assert_eq!(expected, text.to_block_quote_multi_line());
148    }
149
150    #[test]
151    fn test_bold() {
152        let text = "text";
153        assert_eq!("**text**", text.to_bold());
154
155        let text = String::from("text");
156        assert_eq!(String::from("**text**"), text.to_bold());
157    }
158
159    #[test]
160    fn test_inline() {
161        let text = "text";
162        assert_eq!("`text`", text.to_inline());
163
164        let text = String::from("text");
165        assert_eq!(String::from("`text`"), text.to_inline());
166    }
167
168    #[test]
169    fn test_italic() {
170        let text = "text";
171        assert_eq!("*text*", text.to_italic());
172
173        let text = String::from("text");
174        assert_eq!(String::from("*text*"), text.to_italic());
175    }
176
177    #[test]
178    fn test_strikethrough() {
179        let text = "text";
180        assert_eq!("~~text~~", text.to_strikethrough());
181
182        let text = String::from("text");
183        assert_eq!(String::from("~~text~~"), text.to_strikethrough())
184    }
185}