MarkdownSharp
1.12
|
00001 using System; 00002 using System.Collections.Generic; 00003 using System.Text; 00004 using System.Text.RegularExpressions; 00005 00006 namespace MarkdownSharp 00007 { 00008 internal static class Escapes 00009 { 00010 private const string _escapeCharacters = @"\`*_{}[]()>#+-.!"; 00011 private static readonly KeyValuePair<char, string>[] _escapeTable; 00012 private static readonly Regex _hashFinder; 00013 00014 static Escapes() 00015 { 00016 _escapeTable = new KeyValuePair<char, string>[_escapeCharacters.Length]; 00017 string pattern = ""; 00018 for (int i = 0; i < _escapeCharacters.Length; ++i) 00019 { 00020 char c = _escapeCharacters[i]; 00021 string hash = c.ToString().GetHashCode().ToString(); 00022 _escapeTable[i] = new KeyValuePair<char,string>(c, hash); 00023 00024 if (pattern != "") pattern += "|(" + hash + ")"; 00025 else pattern += "(" + hash + ")"; 00026 } 00027 _hashFinder = new Regex(pattern, RegexOptions.Compiled | RegexOptions.ExplicitCapture); 00028 } 00029 00033 public static string get(char c) 00034 { 00035 foreach(var pair in _escapeTable) 00036 if (pair.Key == c) 00037 return pair.Value; 00038 throw new IndexOutOfRangeException("The requested character can not be escaped"); 00039 } 00040 00044 private static char getInverse(string s) 00045 { 00046 foreach (var pair in _escapeTable) 00047 if (pair.Value == s) 00048 return pair.Key; 00049 throw new IndexOutOfRangeException("The requested hash can not be found"); 00050 } 00051 00055 public static string BackslashEscapes(string text) 00056 { 00057 int len = text.Length, first = 0, i = 0; 00058 var sb = new StringBuilder(len); 00059 while (i < len) 00060 { 00061 if (text[i] == '\\' && i + 1 < len && Contains(_escapeCharacters, text[i + 1])) 00062 { 00063 sb.Append(text, first, i - first); 00064 sb.Append(get(text[++i])); 00065 first = ++i; 00066 } 00067 else ++i; 00068 } 00069 if (first == 0) return text; 00070 sb.Append(text, first, i - first); 00071 return sb.ToString(); 00072 } 00073 00077 public static string BoldItalic(string text) 00078 { 00079 int len = text.Length, first = 0, i = 0; 00080 var sb = new StringBuilder(len); 00081 while (i < len) 00082 { 00083 if ('*' == text[i]) 00084 { 00085 sb.Append(text, first, i - first); 00086 sb.Append(get('*')); 00087 first = ++i; 00088 } 00089 else if ('_' == text[i]) 00090 { 00091 sb.Append(text, first, i - first); 00092 sb.Append(get('_')); 00093 first = ++i; 00094 } 00095 else ++i; 00096 } 00097 if (first == 0) return text; 00098 sb.Append(text, first, i - first); 00099 return sb.ToString(); 00100 } 00101 00105 public static string Escape(string text, string escapes) 00106 { 00107 int len = text.Length, first = 0, i = 0; 00108 var sb = new StringBuilder(len); 00109 while (i < len) 00110 { 00111 if (Contains(escapes, text[i])) 00112 { 00113 sb.Append(text, first, i - first); 00114 sb.Append(get(text[i])); 00115 first = ++i; 00116 } 00117 else ++i; 00118 } 00119 if (first == 0) return text; 00120 sb.Append(text, first, i - first); 00121 return sb.ToString(); 00122 } 00123 00129 public static string ProblemUrlChars(string url) 00130 { 00131 url = url.Replace("*", "%2A"); 00132 url = url.Replace("_", "%5F"); 00133 url = url.Replace("'", "%27"); 00134 url = url.Replace("(", "%28"); 00135 url = url.Replace(")", "%29"); 00136 url = url.Replace("[", "%5B"); 00137 url = url.Replace("]", "%5D"); 00138 if (url.Length > 7 && Contains(url.Substring(7), ':')) 00139 { 00140 // replace any colons in the body of the URL that are NOT followed by 2 or more numbers 00141 url = url.Substring(0, 7) + Regex.Replace(url.Substring(7), @":(?!\d{2,})", "%3A"); 00142 } 00143 00144 return url; 00145 } 00146 00147 private static bool Contains(string s, char c) 00148 { 00149 int len = s.Length; 00150 for (int i = 0; i < len; ++i) 00151 if (s[i] == c) 00152 return true; 00153 return false; 00154 } 00155 00159 public static string Unescape(string text) 00160 { 00161 return _hashFinder.Replace(text, match => getInverse(match.Value).ToString()); 00162 } 00163 } 00164 }