From 265da99619a775d23b24326648fe4220bc6beeae Mon Sep 17 00:00:00 2001 From: Chris Johnston Date: Sun, 25 Aug 2019 06:14:24 -0700 Subject: [PATCH] feature: Add Quote Formatting (#1348) * Implement Quote Formatting Adds support for block quote text formatting. This feature is currently only implemented in the Canary client. This formatting adds a "> " to each new line from the input text. * add > char to character sanitization * change assumptions around whitespace strings * add blockquote (>>>) formatting + test --- src/Discord.Net.Core/Format.cs | 56 +++++++++++++++++++++- test/Discord.Net.Tests.Unit/FormatTests.cs | 31 ++++++++++++ 2 files changed, 86 insertions(+), 1 deletion(-) 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)); + } } }