diff --git a/src/Discord.Net.Core/Format.cs b/src/Discord.Net.Core/Format.cs
index 07a9ec75c..0ab70f89c 100644
--- a/src/Discord.Net.Core/Format.cs
+++ b/src/Discord.Net.Core/Format.cs
@@ -1,10 +1,12 @@
+using System.Text;
+
namespace Discord
{
/// A helper class for formatting characters.
public static class Format
{
// Characters which need escaping
- private static readonly string[] SensitiveCharacters = { "\\", "*", "_", "~", "`", "|" };
+ private static readonly string[] SensitiveCharacters = { "\\", "*", "_", "~", "`", "|", ">" };
/// Returns a markdown-formatted string with bold formatting.
public static string Bold(string text) => $"**{text}**";
@@ -37,5 +39,57 @@ namespace Discord
text = text.Replace(unsafeChar, $"\\{unsafeChar}");
return text;
}
+
+ ///
+ /// Formats a string as a quote.
+ ///
+ /// The text to format.
+ /// Gets the formatted quote text.
+ public static string Quote(string text)
+ {
+ // do not modify null or whitespace text
+ // whitespace does not get quoted properly
+ if (string.IsNullOrWhiteSpace(text))
+ return text;
+
+ StringBuilder result = new StringBuilder();
+
+ int startIndex = 0;
+ int newLineIndex;
+ do
+ {
+ newLineIndex = text.IndexOf('\n', startIndex);
+ if (newLineIndex == -1)
+ {
+ // read the rest of the string
+ var str = text.Substring(startIndex);
+ result.Append($"> {str}");
+ }
+ else
+ {
+ // read until the next newline
+ var str = text.Substring(startIndex, newLineIndex - startIndex);
+ result.Append($"> {str}\n");
+ }
+ startIndex = newLineIndex + 1;
+ }
+ while (newLineIndex != -1 && startIndex != text.Length);
+
+ return result.ToString();
+ }
+
+ ///
+ /// Formats a string as a block quote.
+ ///
+ /// The text to format.
+ /// Gets the formatted block quote text.
+ public static string BlockQuote(string text)
+ {
+ // do not modify null or whitespace
+ if (string.IsNullOrWhiteSpace(text))
+ return text;
+
+ return $">>> {text}";
+ }
}
}
diff --git a/test/Discord.Net.Tests.Unit/FormatTests.cs b/test/Discord.Net.Tests.Unit/FormatTests.cs
index d5ab82362..2a5adbaae 100644
--- a/test/Discord.Net.Tests.Unit/FormatTests.cs
+++ b/test/Discord.Net.Tests.Unit/FormatTests.cs
@@ -14,6 +14,7 @@ namespace Discord
[InlineData(@"~text~", @"\~text\~")]
[InlineData(@"`text`", @"\`text\`")]
[InlineData(@"_text_", @"\_text\_")]
+ [InlineData(@"> text", @"\> text")]
public void Sanitize(string input, string expected)
{
Assert.Equal(expected, Format.Sanitize(input));
@@ -28,5 +29,35 @@ namespace Discord
Assert.Equal("```cs\ntest\n```", Format.Code("test", "cs"));
Assert.Equal("```cs\nanother\none\n```", Format.Code("another\none", "cs"));
}
+ [Fact]
+ public void QuoteNullString()
+ {
+ Assert.Null(Format.Quote(null));
+ }
+ [Theory]
+ [InlineData("", "")]
+ [InlineData("\n", "\n")]
+ [InlineData("foo\n\nbar", "> foo\n> \n> bar")]
+ [InlineData("input", "> input")] // single line
+ // should work with CR or CRLF
+ [InlineData("inb4\ngreentext", "> inb4\n> greentext")]
+ [InlineData("inb4\r\ngreentext", "> inb4\r\n> greentext")]
+ public void Quote(string input, string expected)
+ {
+ Assert.Equal(expected, Format.Quote(input));
+ }
+ [Theory]
+ [InlineData(null, null)]
+ [InlineData("", "")]
+ [InlineData("\n", "\n")]
+ [InlineData("foo\n\nbar", ">>> foo\n\nbar")]
+ [InlineData("input", ">>> input")] // single line
+ // should work with CR or CRLF
+ [InlineData("inb4\ngreentext", ">>> inb4\ngreentext")]
+ [InlineData("inb4\r\ngreentext", ">>> inb4\r\ngreentext")]
+ public void BlockQuote(string input, string expected)
+ {
+ Assert.Equal(expected, Format.BlockQuote(input));
+ }
}
}