using System.Text.RegularExpressions;
using ZelWiki.Engine.Function;
using ZelWiki.Models;
namespace ZelWiki.Engine
{
///
///
///
public class WikifierLite
{
public static string Process(string? unprocessedText)
{
unprocessedText = unprocessedText?.Trim() ?? string.Empty;
if (string.IsNullOrWhiteSpace(unprocessedText))
{
return string.Empty;
}
for (var i = 0; i < 100; i++)
{
var processedMatches = false;
var matchStore = new Dictionary();
var content = new WikiString(unprocessedText);
TransformEmoji(content, matchStore);
TransformLinks(content, matchStore);
TransformMarkup(content, matchStore);
foreach (var match in matchStore)
{
processedMatches = true;
content.Replace(match.Key, match.Value);
}
if (!processedMatches)
{
break;
}
unprocessedText = content.ToString();
}
return unprocessedText;
}
private static string StoreMatch(Dictionary matchStore, string value)
{
var guid = Guid.NewGuid().ToString();
matchStore.Add(guid, value);
return guid;
}
private static void TransformEmoji(WikiString pageContent, Dictionary matchStore)
{
var rgx = new Regex(@"(%%.+?%%)", RegexOptions.IgnoreCase);
var matches = WikiUtility.OrderMatchesByLengthDescending(rgx.Matches(pageContent.ToString()));
foreach (var match in matches)
{
string key = match.Value.Trim().ToLower().Trim('%');
int scale = 100;
var parts = key.Split(',');
if (parts.Length > 1)
{
key = parts[0]; //Image key;
scale = int.Parse(parts[1]); //Image scale.
}
key = $"%%{key}%%";
var emoji = GlobalConfiguration.Emojis.FirstOrDefault(o => o.Shortcut == key);
if (GlobalConfiguration.Emojis.Exists(o => o.Shortcut == key))
{
if (scale != 100 && scale > 0 && scale <= 500)
{
var emojiImage =
$"
";
pageContent.Replace(match.Value, StoreMatch(matchStore, emojiImage));
}
else
{
var emojiImage = $"
";
pageContent.Replace(match.Value, StoreMatch(matchStore, emojiImage));
}
}
else
{
pageContent.Replace(match.Value, StoreMatch(matchStore, string.Empty));
}
}
}
///
/// 转换单行和多行的基本标记,如粗体、斜体、下划线等.
///
///
private static void TransformMarkup(WikiString pageContent, Dictionary matchStore)
{
var symbols = WikiUtility.GetApplicableSymbols(pageContent.Value);
foreach (var symbol in symbols)
{
var sequence = new string(symbol, 2);
var escapedSequence = Regex.Escape(sequence);
var rgx = new Regex(@$"{escapedSequence}(.*?){escapedSequence}", RegexOptions.IgnoreCase);
var orderedMatches = WikiUtility.OrderMatchesByLengthDescending(rgx.Matches(pageContent.ToString()));
foreach (var match in orderedMatches)
{
string body = match.Value.Substring(sequence.Length, match.Value.Length - sequence.Length * 2);
var markup = symbol switch
{
'~' => $"{body}",
'*' => $"{body}",
'_' => $"{body}",
'/' => $"{body}",
'!' => $"{body}",
_ => body,
};
pageContent.Replace(match.Value, StoreMatch(matchStore, markup));
}
}
}
///
/// 转换链接,这些链接可以是内部Wiki链接或外部链接.
///
///
private static void TransformLinks(WikiString pageContent, Dictionary matchStore)
{
//解析外部链接 [[http://test.net]].
var rgx = new Regex(@"(\[\[http\:\/\/.+?\]\])", RegexOptions.IgnoreCase);
var matches = WikiUtility.OrderMatchesByLengthDescending(rgx.Matches(pageContent.ToString()));
foreach (var match in matches)
{
string keyword = match.Value.Substring(2, match.Value.Length - 4).Trim();
var args = FunctionParser.ParseRawArgumentsAddParenthesis(keyword);
if (args.Count > 1)
{
pageContent.Replace(match.Value, StoreMatch(matchStore, $"{args[1]}"));
}
else
{
pageContent.Replace(match.Value, StoreMatch(matchStore, $"{args[0]}"));
}
}
//解析外部链接. [[https://test.net]].
rgx = new Regex(@"(\[\[https\:\/\/.+?\]\])", RegexOptions.IgnoreCase);
matches = WikiUtility.OrderMatchesByLengthDescending(rgx.Matches(pageContent.ToString()));
foreach (var match in matches)
{
string keyword = match.Value.Substring(2, match.Value.Length - 4).Trim();
var args = FunctionParser.ParseRawArgumentsAddParenthesis(keyword);
if (args.Count == 1)
{
pageContent.Replace(match.Value, StoreMatch(matchStore, $"{args[1]}"));
}
else if (args.Count > 1)
{
pageContent.Replace(match.Value, StoreMatch(matchStore, $"{args[0]}"));
}
}
//解析内部链接 [[AboutUs|About Us]].
rgx = new Regex(@"(\[\[.+?\]\])", RegexOptions.IgnoreCase);
matches = WikiUtility.OrderMatchesByLengthDescending(rgx.Matches(pageContent.ToString()));
foreach (var match in matches)
{
string keyword = match.Value.Substring(2, match.Value.Length - 4);
var args = FunctionParser.ParseRawArgumentsAddParenthesis(keyword);
if (args.Count == 1)
{
pageContent.Replace(match.Value,
StoreMatch(matchStore, $"{args[0]}"));
}
else if (args.Count > 1)
{
pageContent.Replace(match.Value,
StoreMatch(matchStore, $"{args[1]}"));
}
}
}
}
}