markdown_composer/
transforms.rs

1//! Contains extension traits that can used to transform text elements into
2//! special markdown formats.
3//!
4//! The module does add 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    /// # Example
16    ///
17    /// ```rust
18    /// use markdown_composer::transforms::BlockQuote;
19    ///
20    /// let text = "To quote";
21    /// let quoted = text.to_block_quote();
22    /// assert_eq!(quoted, "> To quote");
23    /// ```
24    ///
25    /// # Note
26    ///
27    /// Multiline quotes should be created using
28    /// [block_quote_multi_line](trait.BlockQuote.html#tymethod.
29    /// block_quote_multi_line) function.
30    fn to_block_quote(&self) -> String;
31
32    /// Transforms the given text into a multiline block quote.
33    ///
34    /// This method does take newlines into account and splits the text after
35    /// them to create a block quote that spans over multiple lines instead of a
36    /// single one.
37    ///
38    /// # Example
39    ///
40    /// ```rust
41    /// use markdown_composer::transforms::BlockQuote;
42    ///
43    /// let text = "To quote\nor not to quote";
44    /// let quoted = text.to_block_quote_multi_line();
45    /// assert_eq!(quoted, "> To quote\n> or not to quote");
46    /// ```
47    fn to_block_quote_multi_line(&self) -> String;
48}
49
50impl<T> BlockQuote for T
51where
52    T: AsRef<str>,
53{
54    fn to_block_quote(&self) -> String {
55        format!("> {}", self.as_ref())
56    }
57
58    fn to_block_quote_multi_line(&self) -> String {
59        let mut lines = Vec::new();
60        for line in self.as_ref().lines() {
61            let quoted = format!("> {}", line);
62            lines.push(quoted);
63        }
64        lines.join("\n")
65    }
66}
67
68/// An extension trait for bold transformations.
69pub trait Bold {
70    /// Transforms the given text into its bold version.
71    ///
72    /// # Example
73    ///
74    /// ```rust
75    /// use markdown_composer::transforms::Bold;
76    ///
77    /// let text = "To bold";
78    /// let bold = text.to_bold();
79    /// assert_eq!(bold, "**To bold**");
80    /// ```
81    fn to_bold(&self) -> String;
82}
83
84impl<T> Bold for T
85where
86    T: AsRef<str>,
87{
88    fn to_bold(&self) -> String {
89        format!("**{}**", self.as_ref())
90    }
91}
92
93/// An extension trait for code block transformations.
94pub trait CodeBlock {
95    /// Transforms the given text into a code block.
96    ///
97    /// # Example
98    ///
99    /// ```rust
100    /// use markdown_composer::transforms::CodeBlock;
101    ///
102    /// let text = "print(\"Hello world!\")";
103    /// let code_block = text.to_code_block();
104    /// assert_eq!(code_block, "```\nprint(\"Hello world!\")\n```");
105    /// ```
106    fn to_code_block(&self) -> String;
107
108    /// Transforms the given text into a code block, allowing to specify the
109    /// language to use for highlighting.
110    ///
111    /// # Example
112    ///
113    /// ```rust
114    /// use markdown_composer::transforms::CodeBlock;
115    ///
116    /// let text = "print(\"Hello world!\")";
117    /// let code_block = text.to_code_block_with_language("python");
118    /// assert_eq!(code_block, "```python\nprint(\"Hello world!\")\n```");
119    /// ```
120    fn to_code_block_with_language<S: AsRef<str>>(&self, language: S) -> String;
121}
122
123impl<T> CodeBlock for T
124where
125    T: AsRef<str>,
126{
127    fn to_code_block(&self) -> String {
128        format!("```\n{}\n```", self.as_ref())
129    }
130
131    fn to_code_block_with_language<S: AsRef<str>>(&self, language: S) -> String {
132        format!("```{}\n{}\n```", language.as_ref(), self.as_ref())
133    }
134}
135
136/// An extension trait for inline transformations.
137pub trait Inline {
138    /// Transforms the given text into an inline code block.
139    ///
140    /// # Example
141    ///
142    /// ```rust
143    /// use markdown_composer::transforms::Inline;
144    ///
145    /// let text = "Inline text";
146    /// let inline = text.to_inline();
147    /// assert_eq!(inline, "`Inline text`");
148    /// ```
149    fn to_inline(&self) -> String;
150}
151
152impl<T> Inline for T
153where
154    T: AsRef<str>,
155{
156    fn to_inline(&self) -> String {
157        format!("`{}`", self.as_ref())
158    }
159}
160
161/// An extension trait for italic transformations.
162pub trait Italic {
163    /// Transforms the given text into its italic variant.
164    ///
165    /// # Example
166    ///
167    /// ```rust
168    /// use markdown_composer::transforms::Italic;
169    ///
170    /// let text = "Italic text";
171    /// let inline = text.to_italic();
172    /// assert_eq!(inline, "*Italic text*");
173    /// ```
174    fn to_italic(&self) -> String;
175}
176
177impl<T> Italic for T
178where
179    T: AsRef<str>,
180{
181    fn to_italic(&self) -> String {
182        format!("*{}*", self.as_ref())
183    }
184}
185
186#[cfg(test)]
187mod tests {
188    use super::{BlockQuote, Bold, Inline, Italic};
189
190    #[test]
191    fn test_block_quote_single_line() {
192        let text = "This is a single line block quote";
193        let expected = "> This is a single line block quote";
194
195        assert_eq!(expected, text.to_block_quote());
196    }
197
198    #[test]
199    fn test_block_quote_multi_line() {
200        let text = "This is a single line block quote\nThis is the second line";
201        let expected = "> This is a single line block quote\n> This is the second line";
202
203        assert_eq!(expected, text.to_block_quote_multi_line());
204    }
205
206    #[test]
207    fn test_bold() {
208        // &str
209        let text = "text";
210        assert_eq!("**text**", text.to_bold());
211
212        // String
213        let text = String::from("text");
214        assert_eq!(String::from("**text**"), text.to_bold());
215    }
216
217    #[test]
218    fn test_inline() {
219        let text = "text";
220        assert_eq!("`text`", text.to_inline());
221
222        let text = String::from("text");
223        assert_eq!(String::from("`text`"), text.to_inline());
224    }
225
226    #[test]
227    fn test_italic() {
228        let text = "text";
229        assert_eq!("*text*", text.to_italic());
230
231        let text = String::from("text");
232        assert_eq!(String::from("*text*"), text.to_italic());
233    }
234}