1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
//! Contains extension traits that can used to transform text elements into
//! special markdown formats.
//!
//! The module does add support for the following transformations:
//! - [Block quotes](trait.BlockQuote.html)
//! - [Bold](trait.Bold.html)
//! - [Code blocks](trait.CodeBlock.html)
//! - [Inline code](trait.Inline.html)
//! - [Italic](trait.Italic.html)

/// An extension trait for block quote transformation.
pub trait BlockQuote {
    /// Transforms the given text into a block quote.
    ///
    /// # Example
    ///
    /// ```rust
    /// use markdown_composer::transforms::BlockQuote;
    ///
    /// let text = "To quote";
    /// let quoted = text.to_block_quote();
    /// assert_eq!(quoted, "> To quote");
    /// ```
    ///
    /// # Note
    ///
    /// Multiline quotes should be created using
    /// [block_quote_multi_line](trait.BlockQuote.html#tymethod.
    /// block_quote_multi_line) function.
    fn to_block_quote(&self) -> String;

    /// Transforms the given text into a multiline block quote.
    ///
    /// This method does take newlines into account and splits the text after
    /// them to create a block quote that spans over multiple lines instead of a
    /// single one.
    ///
    /// # Example
    ///
    /// ```rust
    /// use markdown_composer::transforms::BlockQuote;
    ///
    /// let text = "To quote\nor not to quote";
    /// let quoted = text.to_block_quote_multi_line();
    /// assert_eq!(quoted, "> To quote\n> or not to quote");
    /// ```
    fn to_block_quote_multi_line(&self) -> String;
}

impl<T> BlockQuote for T
where
    T: AsRef<str>,
{
    fn to_block_quote(&self) -> String {
        format!("> {}", self.as_ref())
    }

    fn to_block_quote_multi_line(&self) -> String {
        let mut lines = Vec::new();
        for line in self.as_ref().lines() {
            let quoted = format!("> {}", line);
            lines.push(quoted);
        }
        lines.join("\n")
    }
}

/// An extension trait for bold transformations.
pub trait Bold {
    /// Transforms the given text into its bold version.
    ///
    /// # Example
    ///
    /// ```rust
    /// use markdown_composer::transforms::Bold;
    ///
    /// let text = "To bold";
    /// let bold = text.to_bold();
    /// assert_eq!(bold, "**To bold**");
    /// ```
    fn to_bold(&self) -> String;
}

impl<T> Bold for T
where
    T: AsRef<str>,
{
    fn to_bold(&self) -> String {
        format!("**{}**", self.as_ref())
    }
}

/// An extension trait for code block transformations.
pub trait CodeBlock {
    /// Transforms the given text into a code block.
    ///
    /// # Example
    ///
    /// ```rust
    /// use markdown_composer::transforms::CodeBlock;
    ///
    /// let text = "print(\"Hello world!\")";
    /// let code_block = text.to_code_block();
    /// assert_eq!(code_block, "```\nprint(\"Hello world!\")\n```");
    /// ```
    fn to_code_block(&self) -> String;

    /// Transforms the given text into a code block, allowing to specify the
    /// language to use for highlighting.
    ///
    /// # Example
    ///
    /// ```rust
    /// use markdown_composer::transforms::CodeBlock;
    ///
    /// let text = "print(\"Hello world!\")";
    /// let code_block = text.to_code_block_with_language("python");
    /// assert_eq!(code_block, "```python\nprint(\"Hello world!\")\n```");
    /// ```
    fn to_code_block_with_language<S: AsRef<str>>(&self, language: S) -> String;
}

impl<T> CodeBlock for T
where
    T: AsRef<str>,
{
    fn to_code_block(&self) -> String {
        format!("```\n{}\n```", self.as_ref())
    }

    fn to_code_block_with_language<S: AsRef<str>>(&self, language: S) -> String {
        format!("```{}\n{}\n```", language.as_ref(), self.as_ref())
    }
}

/// An extension trait for inline transformations.
pub trait Inline {
    /// Transforms the given text into an inline code block.
    ///
    /// # Example
    ///
    /// ```rust
    /// use markdown_composer::transforms::Inline;
    ///
    /// let text = "Inline text";
    /// let inline = text.to_inline();
    /// assert_eq!(inline, "`Inline text`");
    /// ```
    fn to_inline(&self) -> String;
}

impl<T> Inline for T
where
    T: AsRef<str>,
{
    fn to_inline(&self) -> String {
        format!("`{}`", self.as_ref())
    }
}

/// An extension trait for italic transformations.
pub trait Italic {
    /// Transforms the given text into its italic variant.
    ///
    /// # Example
    ///
    /// ```rust
    /// use markdown_composer::transforms::Italic;
    ///
    /// let text = "Italic text";
    /// let inline = text.to_italic();
    /// assert_eq!(inline, "*Italic text*");
    /// ```
    fn to_italic(&self) -> String;
}

impl<T> Italic for T
where
    T: AsRef<str>,
{
    fn to_italic(&self) -> String {
        format!("*{}*", self.as_ref())
    }
}

#[cfg(test)]
mod tests {
    use super::{BlockQuote, Bold, Inline, Italic};

    #[test]
    fn test_block_quote_single_line() {
        let text = "This is a single line block quote";
        let expected = "> This is a single line block quote";

        assert_eq!(expected, text.to_block_quote());
    }

    #[test]
    fn test_block_quote_multi_line() {
        let text = "This is a single line block quote\nThis is the second line";
        let expected = "> This is a single line block quote\n> This is the second line";

        assert_eq!(expected, text.to_block_quote_multi_line());
    }

    #[test]
    fn test_bold() {
        // &str
        let text = "text";
        assert_eq!("**text**", text.to_bold());

        // String
        let text = String::from("text");
        assert_eq!(String::from("**text**"), text.to_bold());
    }

    #[test]
    fn test_inline() {
        let text = "text";
        assert_eq!("`text`", text.to_inline());

        let text = String::from("text");
        assert_eq!(String::from("`text`"), text.to_inline());
    }

    #[test]
    fn test_italic() {
        let text = "text";
        assert_eq!("*text*", text.to_italic());

        let text = String::from("text");
        assert_eq!(String::from("*text*"), text.to_italic());
    }
}