|
|
@@ -1,23 +1,91 @@ |
|
|
|
using System.Text; |
|
|
|
using Discord.Net.API; |
|
|
|
using System.Text; |
|
|
|
using System.Text.RegularExpressions; |
|
|
|
|
|
|
|
namespace Discord |
|
|
|
{ |
|
|
|
public static class Format |
|
|
|
public static class Format |
|
|
|
{ |
|
|
|
private static readonly Regex _escapeRegex; |
|
|
|
private static readonly MatchEvaluator _escapeEvaluator; |
|
|
|
private static readonly string[] _patterns; |
|
|
|
private static readonly StringBuilder _builder; |
|
|
|
|
|
|
|
static Format() |
|
|
|
{ |
|
|
|
const string innerPattern = "[_*]|~~"; |
|
|
|
_escapeRegex = new Regex($@"(?<=^|\W)(?:{innerPattern})|(?:{innerPattern})(?=\W|$)|\\", RegexOptions.Compiled); |
|
|
|
_escapeEvaluator = new MatchEvaluator(e => '\\' + e.Value); |
|
|
|
} |
|
|
|
_patterns = new string[] { "__", "_", "**", "*", "~~" }; |
|
|
|
_builder = new StringBuilder(DiscordAPIClient.MaxMessageSize); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary> Removes all special formatting characters from the provided text. </summary> |
|
|
|
private static string Escape(string text) |
|
|
|
=> _escapeRegex.Replace(text, _escapeEvaluator); |
|
|
|
{ |
|
|
|
lock (_builder) |
|
|
|
{ |
|
|
|
_builder.Clear(); |
|
|
|
|
|
|
|
//Escape all backslashes |
|
|
|
for (int i = 0; i < text.Length; i++) |
|
|
|
{ |
|
|
|
_builder.Append(text[i]); |
|
|
|
if (text[i] == '\\') |
|
|
|
_builder.Append('\\'); |
|
|
|
} |
|
|
|
|
|
|
|
EscapeSubstring(0, _builder.Length); |
|
|
|
|
|
|
|
return _builder.ToString(); |
|
|
|
} |
|
|
|
} |
|
|
|
private static int EscapeSubstring(int start, int end) |
|
|
|
{ |
|
|
|
int totalAddedChars = 0; |
|
|
|
for (int i = start; i < end + totalAddedChars; i++) |
|
|
|
{ |
|
|
|
for (int p = 0; p < _patterns.Length; p++) |
|
|
|
{ |
|
|
|
string pattern = _patterns[p]; |
|
|
|
if (i + pattern.Length * 2 > _builder.Length) |
|
|
|
continue; |
|
|
|
int s = FindPattern(pattern, i, i + 1); |
|
|
|
if (s == -1) continue; |
|
|
|
int e = FindPattern(pattern, i + 1, end + totalAddedChars); |
|
|
|
if (e == -1) continue; |
|
|
|
|
|
|
|
if (e - s - pattern.Length > 0) |
|
|
|
{ |
|
|
|
//By going right to left, we dont need to adjust any offsets |
|
|
|
for (int k = pattern.Length - 1; k >= 0; k--) |
|
|
|
_builder.Insert(e + k, '\\'); |
|
|
|
for (int k = pattern.Length - 1; k >= 0; k--) |
|
|
|
_builder.Insert(s + k, '\\'); |
|
|
|
int addedChars = pattern.Length * 2; |
|
|
|
addedChars += EscapeSubstring(s + pattern.Length * 2, e + pattern.Length); |
|
|
|
i = e + addedChars + pattern.Length - 1; |
|
|
|
totalAddedChars += addedChars; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return totalAddedChars; |
|
|
|
} |
|
|
|
private static int FindPattern(string pattern, int start, int end) |
|
|
|
{ |
|
|
|
for (int j = start; j < end; j++) |
|
|
|
{ |
|
|
|
if (_builder[j] == '\\') |
|
|
|
{ |
|
|
|
j++; |
|
|
|
continue; |
|
|
|
} |
|
|
|
for (int k = 0; k < pattern.Length; k++) |
|
|
|
{ |
|
|
|
if (_builder[j + k] != pattern[k]) |
|
|
|
goto nextpos; |
|
|
|
} |
|
|
|
return j; |
|
|
|
nextpos:; |
|
|
|
} |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary> Returns a markdown-formatted string with no formatting, optionally escaping the contents. </summary> |
|
|
|
public static string Normal(string text, bool escape = true) |
|
|
|