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}