19 using Highlight.Engines;
20 using Highlight.Patterns;
22 using System.Collections.Generic;
25 using System.Text.RegularExpressions;
37 public string Text {
get; }
75 private static Dictionary<string, string[]> LanguageAliases =
new Dictionary<string, string[]>()
77 {
"ASPX",
new string[] {
"ASP.NET",
"aspx",
"aspx-vb" } },
78 {
"C",
new string[] { } },
79 {
"C++",
new string[] {
"cpp" } },
80 {
"C#",
new string[] {
"csharp" } },
81 {
"COBOL",
new string[] { } },
82 {
"Eiffel",
new string[] { } },
83 {
"Fortran",
new string[] { } },
84 {
"Haskell",
new string[] { } },
85 {
"HTML",
new string[] {
"xhtml" } },
86 {
"Java",
new string[] { } },
87 {
"JavaScript",
new string[] {
"js",
"node" } },
88 {
"Mercury",
new string[] { } },
89 {
"MSIL",
new string[] { } },
90 {
"Pascal",
new string[] {
"delphi",
"objectpascal" } },
91 {
"Perl",
new string[] {
"cperl" } },
92 {
"PHP",
new string[] {
"inc" } },
93 {
"Python",
new string[] {
"python3",
"rusthon" } },
94 {
"Ruby",
new string[] {
"jruby",
"macruby",
"rake",
"rb",
"rbx" } },
95 {
"SQL",
new string[] { } },
96 {
"Visual Basic",
new string[] {
"vba",
"vb6",
"visual basic 6",
"visual basic for applications" } },
97 {
"VBScript",
new string[] { } },
98 {
"VB.NET",
new string[] {
"Visual Basic .NET",
"vbnet",
"vb .net" } },
99 {
"XML",
new string[] {
"rss",
"xsd",
"wsdl" } },
102 private static string GetLanguage(
string language)
104 foreach (KeyValuePair<
string,
string[]> element
in LanguageAliases)
106 if (element.Key.Equals(language, StringComparison.OrdinalIgnoreCase))
111 foreach (
string alias
in element.Value)
113 if (alias.Equals(language, StringComparison.OrdinalIgnoreCase))
131 language = GetLanguage(language);
133 if (
string.IsNullOrEmpty(language))
138 HighlighterEngine engine =
new HighlighterEngine();
140 Highlighter highlighter =
new Highlighter(engine);
142 highlighter.Highlight(language, sourceCode);
144 List<List<FormattedString>> tbr =
new List<List<FormattedString>>();
146 List<FormattedString> currentLine =
new List<FormattedString>();
148 for (
int i = 0; i < engine.HighlightedSpans.Count; i++)
150 string[] split = engine.HighlightedSpans[i].Text.Replace(
"\r",
"").Split(
'\n');
152 for (
int j = 0; j < split.Length; j++)
154 currentLine.Add(
new FormattedString(split[j], engine.HighlightedSpans[i].Colour, engine.HighlightedSpans[i].IsBold, engine.HighlightedSpans[i].IsItalic));
156 if (j < split.Length - 1)
158 tbr.Add(currentLine);
159 currentLine =
new List<FormattedString>();
164 tbr.Add(currentLine);
170 internal class HighlighterEngine : Engine, IEngine
172 private const RegexOptions DefaultRegexOptions = RegexOptions.ExplicitCapture | RegexOptions.IgnorePatternWhitespace;
174 public List<FormattedString> HighlightedSpans {
get; } =
new List<FormattedString>();
176 protected override string ProcessBlockPatternMatch(Definition definition, BlockPattern pattern, Match match)
178 if (!
string.IsNullOrEmpty(pattern.RawRegex))
180 Match reMatch = Regex.Match(match.Value, pattern.RawRegex);
182 if (reMatch.Groups.Count > 1)
184 HighlightedSpans.Add(
new FormattedString(match.Value.Substring(0, reMatch.Groups[1].Index), Colours.Black,
false,
false));
185 HighlightedSpans.Add(
new FormattedString(reMatch.Groups[1].Value, pattern.Style.Colors.ForeColor, pattern.Style.Font.IsBold, pattern.Style.Font.IsItalic));
186 HighlightedSpans.Add(
new FormattedString(match.Value.Substring(reMatch.Groups[1].Index + reMatch.Groups[1].Length), Colours.Black,
false,
false));
190 HighlightedSpans.Add(
new FormattedString(match.Value, pattern.Style.Colors.ForeColor, pattern.Style.Font.IsBold, pattern.Style.Font.IsItalic));
195 HighlightedSpans.Add(
new FormattedString(match.Value, pattern.Style.Colors.ForeColor, pattern.Style.Font.IsBold, pattern.Style.Font.IsItalic));
200 protected override string ProcessMarkupPatternMatch(Definition definition, MarkupPattern pattern, Match match)
202 HighlightedSpans.Add(
new FormattedString(match.Value, pattern.Style.Colors.ForeColor, pattern.Style.Font.IsBold, pattern.Style.Font.IsItalic));
206 protected override string ProcessWordPatternMatch(Definition definition, WordPattern pattern, Match match)
208 HighlightedSpans.Add(
new FormattedString(match.Value, pattern.Style.Colors.ForeColor, pattern.Style.Font.IsBold, pattern.Style.Font.IsItalic));
212 string IEngine.Highlight(Definition definition,
string input)
214 if (definition ==
null)
216 throw new ArgumentNullException(
"definition");
219 var output = PreHighlight(definition, input);
220 output = HighlightUsingRegex(definition, output);
221 output = PostHighlight(definition, output);
226 private string HighlightUsingRegex(Definition definition,
string input)
228 var regexOptions = GetRegexOptions(definition);
229 var evaluator = GetMatchEvaluator(definition);
230 var regexPattern = definition.GetRegexPattern();
232 int currentIndex = 0;
234 foreach (Match match
in Regex.Matches(input, regexPattern))
236 if (match.Index > currentIndex)
238 this.HighlightedSpans.Add(
new FormattedString(input.Substring(currentIndex, match.Index - currentIndex), Colours.Black,
false,
false));
241 currentIndex = match.Index + match.Length;
246 if (currentIndex < input.Length)
248 this.HighlightedSpans.Add(
new FormattedString(input.Substring(currentIndex, input.Length - currentIndex), Colours.Black,
false,
false));
254 private RegexOptions GetRegexOptions(Definition definition)
256 if (definition.CaseSensitive)
258 return DefaultRegexOptions | RegexOptions.IgnoreCase;
261 return DefaultRegexOptions;
264 private string ElementMatchHandler(Definition definition, Match match)
266 if (definition ==
null)
268 throw new ArgumentNullException(
"definition");
272 throw new ArgumentNullException(
"match");
275 var pattern = definition.Patterns.First(x => match.Groups[x.Key].Success).Value;
278 if (pattern is BlockPattern)
280 return ProcessBlockPatternMatch(definition, (BlockPattern)pattern, match);
282 if (pattern is MarkupPattern)
284 return ProcessMarkupPatternMatch(definition, (MarkupPattern)pattern, match);
286 if (pattern is WordPattern)
288 return ProcessWordPatternMatch(definition, (WordPattern)pattern, match);
295 private MatchEvaluator GetMatchEvaluator(Definition definition)
297 return match => ElementMatchHandler(definition, match);