1209 lines
53 KiB
C#
1209 lines
53 KiB
C#
|
using System.Reflection;
|
||
|
using System.Text;
|
||
|
using System.Text.Json;
|
||
|
using System.Text.RegularExpressions;
|
||
|
|
||
|
namespace Whalers{
|
||
|
public class WMarkDown{
|
||
|
|
||
|
public class Module{
|
||
|
|
||
|
public int environment;
|
||
|
public Regex pattern;
|
||
|
|
||
|
public Module(int environment, Regex pattern){
|
||
|
|
||
|
this.environment = environment;
|
||
|
this.pattern = pattern;
|
||
|
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
public class Item{
|
||
|
|
||
|
public bool exists = true;
|
||
|
public int from = -1;
|
||
|
public int length = -1;
|
||
|
public Match? matches = null;
|
||
|
|
||
|
};
|
||
|
|
||
|
public class ListStructure{
|
||
|
|
||
|
public int separator;
|
||
|
public char type;
|
||
|
public char? subtype;
|
||
|
|
||
|
public ListStructure(int separator, bool unordenered, char? subtype){
|
||
|
|
||
|
this.separator = separator;
|
||
|
this.type = unordenered ? 'u' : 'o';
|
||
|
this.subtype = subtype;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
public class ProcessResults{
|
||
|
|
||
|
public string results;
|
||
|
public Dictionary<string, string> variables;
|
||
|
|
||
|
public ProcessResults(string results, Dictionary<string, string> variables){
|
||
|
|
||
|
this.results = results;
|
||
|
this.variables = variables;
|
||
|
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
public class ItemMark{
|
||
|
|
||
|
public string start;
|
||
|
public string end;
|
||
|
public Regex pattern;
|
||
|
|
||
|
public ItemMark(string start, string end, string pattern){
|
||
|
|
||
|
this.start = start;
|
||
|
this.end = end;
|
||
|
this.pattern = new Regex(pattern);
|
||
|
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
public class LinkPresententationModel{
|
||
|
|
||
|
public string title;
|
||
|
public List<string> avatars = new List<string>();
|
||
|
public List<string> links = new List<string>();
|
||
|
|
||
|
public LinkPresententationModel(string title)
|
||
|
{
|
||
|
|
||
|
this.title = title;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
// Languages
|
||
|
public const int HTML = 1 << 0;
|
||
|
|
||
|
// Analyse modes
|
||
|
public const int RAW = 0;
|
||
|
public const int SUBITEM = 1 << 0;
|
||
|
public const int LINKED = 1 << 1;
|
||
|
|
||
|
public static Dictionary<string, string> html_special_characters = new Dictionary<string, string>
|
||
|
{
|
||
|
{"<", "lt" },
|
||
|
{">", "gt" },
|
||
|
{"&", "amp" }
|
||
|
};
|
||
|
public static Dictionary<string, string> quote_special = new Dictionary<string, string>
|
||
|
{
|
||
|
{ "?", "ask"},
|
||
|
{"!", "warning" },
|
||
|
{">", "answer" },
|
||
|
{"Q", "comment" },
|
||
|
{"#", "note" }
|
||
|
};
|
||
|
public static WMarkDown.ItemMark item_mark = new WMarkDown.ItemMark("###@&&_", "_&&@###", @"\#{3}\@\&{2}_([0-9]+)_\&{2}\@\#{3}");
|
||
|
|
||
|
public static string re_block_html_pattern = @"^[ \t]*<\!\-{2}[ \t]*\[{2}[\t ]*(wmd|wmarkdown)[ \t]*\]{2}[\t ]*\-{2}>";
|
||
|
public static Regex re_block_html = new Regex(WMarkDown.re_block_html_pattern, RegexOptions.Multiline);
|
||
|
public static Regex re_block_mark = new Regex(@"^[ \t]*(("" ?){3}|(' ?){3}|(` ?){3})[ \t]*(wmd|wmarkdown)|" + WMarkDown.re_block_html_pattern, RegexOptions.Multiline);
|
||
|
public static Regex re_new_lines = new Regex(@"[\r\n]+");
|
||
|
public static Regex re_new_line = new Regex(@"\n|\r\n|\r");
|
||
|
public static Regex re_started_white_spaces = new Regex(@"^[ \t]*");
|
||
|
public static Regex re_lines = new Regex(@"^[^\r\n]+", RegexOptions.Multiline);
|
||
|
public static Regex re_list_line = new Regex(@"^([ \t]*)(([\-\*#\+]+)|([0-9]+|[a-z]+)\.)?(.*)$", RegexOptions.IgnoreCase | RegexOptions.Multiline);
|
||
|
public static Regex re_table_line = new Regex(@"^\|([^\r\n""']+|""([^""\\\\]+|\\\\(.|[\r\n])|[\r\n]+)*""|'([^'\\\\]+|\\\\(.|[\r\n])|[\r\n]+)*')*[\r\n]*", RegexOptions.Multiline);
|
||
|
public static Regex re_table_item = new Regex(@"(\|+)(([^\|'""]+|""([^""\\\\]+|\\\\(.|[\r\n])|[\r\n]+)*""|'([^'\\\\]+|\\\\(.|[\r\n])|[\r\n]+)*')*)");
|
||
|
public static Regex re_options = new Regex(@"`{3}[ \t]*(wmd|wmarkdown)\-options[ \t]*(\n|\r\n|\r)(([^\r\n`]+|[\r\n]+|`{1,2}[^`])*)`{3}");
|
||
|
public static Regex re_option = new Regex(@"^([^=\r\n]+)=([^\r\n]*)$", RegexOptions.Multiline);
|
||
|
public static Regex re_extension = new Regex(@"(([^\.\/\\\\]+)\.)?([^\.\/\\\\]+)$");
|
||
|
public static Regex re_characters_no_id = new Regex(@"[^a-z0-9]+", RegexOptions.Multiline);
|
||
|
public static Regex re_phone_number = new Regex(@"^\+?[0-9 ]{5,22}$");
|
||
|
public static Regex re_email_address = new Regex(@"^[a-z\.0-9_\-]+@[a-z\.0-9_\-]+\.[a-z0-9]+$");
|
||
|
public static Regex re_class_attribute = new Regex(@"(?<![a-z0-9_\-])(class="")([^""]+)("")");
|
||
|
public static Regex re_white_spaces = new Regex(@"[ \t]+");
|
||
|
public static Regex re_line_marks = new Regex(@"[\*#~\-_]+|\[[ \-x]\]|\([ \-x]\)", RegexOptions.IgnoreCase);
|
||
|
public static Regex re_integer = new Regex(@"^[0-9]+$");
|
||
|
public static Regex re_code_doc = new Regex(@"^(\[([^\]]+)\][ \t]+)?([\!\?])?(([^\(\[\]\?\!]+)([\:\.]))?([^\(\.\:\[\]\=]+)(\(((.+|[\r\n]+)*)\)|[ \t]*=[ \t]*((.+|[\r\n]+)*))?");
|
||
|
public static Regex re_code_doc_arguments = new Regex(@"([\!\?]{0,2})([^=]+)[ \t]+([^=]+)(=(.+))?");
|
||
|
public static Regex re_code_doc_subarguments = new Regex(@"<([^<>]+)>|(""[^""]*""|'[^']*')");
|
||
|
public static Regex re_start_with_white_spaces = new Regex(@"^[ \t]", RegexOptions.Multiline);
|
||
|
public static Regex re_domain = new Regex(@"^[^\:]+\:\/{2}[^\/]+");
|
||
|
public static Regex re_protocol = new Regex(@"^([a-z0-9_\-]+)\:", RegexOptions.IgnoreCase);
|
||
|
|
||
|
public Dictionary<string, WMarkDown.Module> modules = new Dictionary<string, WMarkDown.Module>
|
||
|
{
|
||
|
{"special_characters", new WMarkDown.Module(WMarkDown.SUBITEM, new Regex(@"\\([\(\{\[\*\\])"))},
|
||
|
{"title", new WMarkDown.Module(WMarkDown.RAW, new Regex(@"^((#{1,6})[\t ]*([^\r\n]+)|(={1,6})[\t ]*([^\r\n=]+)={1,6})(\n|\r\n|\r){2,}", RegexOptions.Multiline))},
|
||
|
{"list", new WMarkDown.Module(WMarkDown.RAW, new Regex(@"^([\-\*#\+]+|([0-9]+|[a-z]+)\.)[^\r\n]*(\n|\r\n|\r)([\t ]*(([\-\*#\+]+|([0-9]+|[a-z]+)\.)[^\r\n]*)(\n|\r\n|\r)?)*", RegexOptions.IgnoreCase| RegexOptions.Multiline))},
|
||
|
{"code_block", new WMarkDown.Module(WMarkDown.RAW, new Regex(@"^(""{3}([^\r\n]*)(((?!""{3})(.|[\r\n]))+)""{3}|"" "" ""([^\r\n]*)(((?!"" "" "")(.|[\r\n]))+)"" "" ""|'{3}([^\r\n]*)(((?!'{3})(.|[\r\n]))+)'{3}|' ' '([^\r\n]*)(((?!' ' ')(.|[\r\n]))+)' ' '|`{3}([^\r\n]*)(((?!`{3})(.|[\r\n]))+)`{3}|` ` `([^\r\n]*)(((?!` ` `)(.|[\r\n]))+)` ` `)", RegexOptions.Multiline))},
|
||
|
{"table", new WMarkDown.Module(WMarkDown.RAW, new Regex(@"^\[\|([^\r\n]*)[\r\n]+((^\|([^\]]([^\r\n""']|""([^""\\\\]+|\\\\(.|[\r\n])|[\r\n]+)*""|'([^'\\\\]+|\\\\(.|[\r\n])|[\r\n]+)*')*)?[\r\n]+)*)^\|\]", RegexOptions.Multiline))},
|
||
|
{"quote", new WMarkDown.Module(WMarkDown.RAW, new Regex(@"^>[ \t]*(\[\![\t ]*([^\] \t]+)([ \t]+([^\]]+))?\])?(([^\r\n]+(\r\n|[\r\n])?)*)", RegexOptions.Multiline))},
|
||
|
{"include", new WMarkDown.Module(WMarkDown.RAW, new Regex(@"^\[{2}include[ \t]+([^\]]+)\]{2}", RegexOptions.Multiline))},
|
||
|
{"media", new WMarkDown.Module(WMarkDown.SUBITEM | WMarkDown.LINKED, new Regex(@"\({2}\!(image|icon|video|audio|sound|picture)[ \t]+(""(([^""]+|[\r\n]+))""|'(([^']+|[\r\n]+))'|([^ \t\)]+))([ \t]*|[ \t]+(""(([^\\\\""]+|\\\\.|[\r\n]+)*)""|'(([^'\\\\]+|\\\\.|[\r\n]+)*)'|([^\)]+)))\){2}", RegexOptions.IgnoreCase))},
|
||
|
{"code_doc", new WMarkDown.Module(WMarkDown.RAW, new Regex(@"^\[{2}@(([^\]]+|\][^\]])+)\]{2}", RegexOptions.Multiline))},
|
||
|
{"presentation_links", new WMarkDown.Module(WMarkDown.RAW, new Regex(@"^\[{2}""{3}(([^""]+|[\r\n]+|""{1,2}[^""])*)""{3}\]{2}", RegexOptions.Multiline))},
|
||
|
{"paragraph", new WMarkDown.Module(WMarkDown.RAW, new Regex(@"^(([^\r\n]+(\n|\r\n|\r)?)+)", RegexOptions.Multiline))},
|
||
|
{"bold", new WMarkDown.Module(WMarkDown.RAW, new Regex(@"(?<!\\)\*{2}((?:\\\*|\*[^\*]|[^*\r\n]|[\r\n]|(?!\*{2}[^\*])\*)*)\*{2}"))},
|
||
|
{"italic", new WMarkDown.Module(WMarkDown.RAW, new Regex(@"(?<!\\)\*((?:\\\*|[^*\r\n]|[\r\n]|\*{2})*)\*"))},
|
||
|
{"underline", new WMarkDown.Module(WMarkDown.RAW, new Regex(@"_{2}(([^_]+|_[^_])+)_{2}"))},
|
||
|
{"strike", new WMarkDown.Module(WMarkDown.RAW, new Regex(@"~{2}(([^~]+|~[^~])+)~{2}"))},
|
||
|
{"code_item", new WMarkDown.Module(WMarkDown.RAW, new Regex(@"`{2}(([^`]+|`[^`])+)`{2}"))},
|
||
|
{"checkbox", new WMarkDown.Module(WMarkDown.RAW, new Regex(@"\[((\-)|(x)|( ))\]", RegexOptions.IgnoreCase))},
|
||
|
{"radio", new WMarkDown.Module(WMarkDown.RAW, new Regex(@"\(((\-)|(x)|( ))\)", RegexOptions.IgnoreCase))},
|
||
|
{"tick", new WMarkDown.Module(WMarkDown.RAW, new Regex(@"\{((w)|(v)|(x))\}", RegexOptions.IgnoreCase))},
|
||
|
{"color_sample", new WMarkDown.Module(WMarkDown.RAW, new Regex(@"\[{2}((\#[a-f0-9]{3,8})|color[ \t]+([^\[\]\t\r\n]+))\]{2}", RegexOptions.IgnoreCase))},
|
||
|
{"exclude", new WMarkDown.Module(WMarkDown.RAW, new Regex(@"\[{2}\!(([^\]]+|\][^\]]|[\r\n])*)\]{2}"))},
|
||
|
{"link", new WMarkDown.Module(WMarkDown.RAW, new Regex(@"(\[([^\[\]]+)\])?\((([^\(\) \t]+)[ \t]+(""(([^\\\\""]+|\\\\.|[\r\n]+)*)""|\'(([^\\\\\']+|\\\\.|[\r\n]+)*)\'|([^\(\)]+)?))[ \t]*\)|\[(\+?[0-9 ]{5,22}|[^ \]]+)([\t ]+([^\]]*))?\]|([a-z0-9]{3,8}\:\/{2}[^ \(\[\)\]>]+|[a-z\.0-9_\-]+@[a-z\.0-9_\-]+\.[a-z0-9]+)", RegexOptions.IgnoreCase))}
|
||
|
};
|
||
|
private List<string> ids_cache = new List<string>();
|
||
|
|
||
|
public WMarkDown() { }
|
||
|
|
||
|
private string id(string _string)
|
||
|
{
|
||
|
|
||
|
string id = WMarkDown.re_characters_no_id.Replace(_string, "-");
|
||
|
|
||
|
if (id[0] == '-')
|
||
|
id = id.Substring(1);
|
||
|
if (id[id.Length - 1] == '-')
|
||
|
id = id.Substring(0, id.Length - 1);
|
||
|
|
||
|
if (this.ids_cache.Contains(id))
|
||
|
{
|
||
|
|
||
|
int i = 1;
|
||
|
|
||
|
while (this.ids_cache.Contains(id + "-" + ++i)) ;
|
||
|
id += "-" + i;
|
||
|
|
||
|
}
|
||
|
this.ids_cache.Add(id);
|
||
|
|
||
|
return id;
|
||
|
}
|
||
|
|
||
|
public void reset_ids() => this.ids_cache = new List<string>();
|
||
|
|
||
|
public string? module_title(Match matches, int language = WMarkDown.HTML, string? path = null)
|
||
|
{
|
||
|
if ((language & WMarkDown.HTML) != 0)
|
||
|
{
|
||
|
|
||
|
int level = ("" + (matches.Groups[2] ?? matches.Groups[4])).Length;
|
||
|
string content = ("" + (matches.Groups[3] ?? matches.Groups[5])).Trim();
|
||
|
string id = this.id(content);
|
||
|
|
||
|
return ("<h" + level + " class=\"wmd-title\" id=\"" + id + "\" title=\"" + content + "\">" +
|
||
|
"<span>" + this.analyse(content, language, WMarkDown.SUBITEM, path) + "</span>" +
|
||
|
"<a href=\"#" + id + "\" target=\"_blank\">" +
|
||
|
"<span data-icon=\"link\"></span>" +
|
||
|
"</a>" +
|
||
|
"</h" + level + ">");
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public string? module_paragraph(Match matches, int language = WMarkDown.HTML, string? path = null)
|
||
|
{
|
||
|
if ((language & WMarkDown.HTML) != 0)
|
||
|
return "<p>" + this.analyse(("" + matches.Groups[0]).Trim(), language, WMarkDown.SUBITEM, path) + "</p>";
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public string? module_bold_italic(Match matches, int language = WMarkDown.HTML, string? path = null)
|
||
|
{
|
||
|
if ((language & WMarkDown.HTML) != 0)
|
||
|
return "<b><i>" + this.analyse(("" + matches.Groups[1]).Trim(), language, WMarkDown.SUBITEM, path) + "</i></b>";
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public string? module_bold(Match matches, int language = WMarkDown.HTML, string? path = null)
|
||
|
{
|
||
|
if ((language & WMarkDown.HTML) != 0)
|
||
|
return "<b>" + this.analyse(("" + matches.Groups[1]).Trim(), language, WMarkDown.SUBITEM, path) + "</b>";
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public string? module_italic(Match matches, int language = WMarkDown.HTML, string? path = null)
|
||
|
{
|
||
|
if ((language & WMarkDown.HTML) != 0)
|
||
|
return "<i>" + this.analyse(("" + matches.Groups[1]).Trim(), language, WMarkDown.SUBITEM, path) + "</i>";
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public string? module_strike(Match matches, int language = WMarkDown.HTML, string? path = null)
|
||
|
{
|
||
|
if ((language & WMarkDown.HTML) != 0)
|
||
|
return "<del>" + this.analyse(("" + matches.Groups[1]).Trim(), language, WMarkDown.SUBITEM, path) + "</del>";
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public string? module_underline(Match matches, int language = WMarkDown.HTML, string? path = null)
|
||
|
{
|
||
|
if ((language & WMarkDown.HTML) != 0)
|
||
|
return "<u>" + this.analyse(("" + matches.Groups[1]).Trim(), language, WMarkDown.SUBITEM, path) + "</u>";
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public string? module_code_item(Match matches, int language = WMarkDown.HTML, string? path = null)
|
||
|
{
|
||
|
if ((language & WMarkDown.HTML) != 0)
|
||
|
return "<code>" + this.analyse(("" + matches.Groups[1]).Trim(), language, WMarkDown.SUBITEM, path) + "</code>";
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
private static string check_html_module(string type, Match matches)
|
||
|
{
|
||
|
|
||
|
bool is_radio = type == "radio";
|
||
|
|
||
|
return ("<label class=\"wmd-icon " + (is_radio ? "radio-button" : type) + "\">" +
|
||
|
"<input type=\"" + (type == "tick" ? "checkbox" : type) + "\" readonly onclick=\"return false;\"" + (
|
||
|
matches.Groups[2] != null ? " disabled" :
|
||
|
matches.Groups[3] != null ? " checked" :
|
||
|
"") + " />" +
|
||
|
"<span data-icon=\"" + (is_radio ? "radio_button" : type) + "\"></span>" +
|
||
|
"</label>");
|
||
|
}
|
||
|
|
||
|
public string? module_checkbox(Match matches, int language = WMarkDown.HTML, string? path = null)
|
||
|
{
|
||
|
if ((language & WMarkDown.HTML) != 0)
|
||
|
return WMarkDown.check_html_module("checkbox", matches);
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public string? module_radio(Match matches, int language = WMarkDown.HTML, string? path = null)
|
||
|
{
|
||
|
if ((language & WMarkDown.HTML) != 0)
|
||
|
return WMarkDown.check_html_module("radio", matches);
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public string? module_tick(Match matches, int language = WMarkDown.HTML, string? path = null)
|
||
|
{
|
||
|
if ((language & WMarkDown.HTML) != 0)
|
||
|
return WMarkDown.check_html_module("tick", matches);
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
private static string list_deployed(WMarkDown.ListStructure level, string? last_mark, int l)
|
||
|
{
|
||
|
|
||
|
string type = l != 0 && !String.IsNullOrEmpty(last_mark) ? last_mark : "" + level.subtype;
|
||
|
bool deployable = l != 0 && type != "" && "+-".Contains(type);
|
||
|
string deployed = (
|
||
|
!deployable ? "null" :
|
||
|
type == "-" ? "false" :
|
||
|
"true");
|
||
|
|
||
|
return " data-deployed=\"" + deployed + "\"" + (deployable ? " data-list-unprocessed=\"true\"" : "");
|
||
|
}
|
||
|
|
||
|
private static string list_start(bool unordered, string type)
|
||
|
{
|
||
|
if (!unordered)
|
||
|
{
|
||
|
type = type.Substring(0, type.Length - 1);
|
||
|
if (WMarkDown.re_integer.Match(type) != null)
|
||
|
return " start=\"" + type + "\"";
|
||
|
}
|
||
|
return "";
|
||
|
}
|
||
|
|
||
|
public string? module_list(Match matches, int language = WMarkDown.HTML, string? path = null)
|
||
|
{
|
||
|
if ((language & WMarkDown.HTML) != 0)
|
||
|
{
|
||
|
|
||
|
string html = "";
|
||
|
List<WMarkDown.ListStructure> levels = new List<ListStructure> { new ListStructure(0, true, null) };
|
||
|
int l = 0;
|
||
|
string? last_mark = null;
|
||
|
char[] roman_number_marks = new char[] { 'a', 'A', 'i', 'I' };
|
||
|
char? subtype = null;
|
||
|
|
||
|
foreach (string line in WMarkDown.re_new_line.Split("" + matches.Groups[0]))
|
||
|
{
|
||
|
|
||
|
Match line_matches = WMarkDown.re_list_line.Match(line);
|
||
|
|
||
|
if (line_matches == null)
|
||
|
continue;
|
||
|
|
||
|
int separator_by_marks = (line_matches.Groups[3] == null ? "" : "" + line_matches.Groups[3]).Length;
|
||
|
int separator = separator_by_marks > 1 ? separator_by_marks : ("" + line_matches.Groups[1]).Length;
|
||
|
string type = "" + line_matches.Groups[2];
|
||
|
string key = "" + line_matches.Groups[4];
|
||
|
string _string = this.analyse("" + line_matches.Groups[5], language, WMarkDown.SUBITEM, path).Trim();
|
||
|
bool has_type = type != "";
|
||
|
bool unordered = has_type && new char[] { '-', '*', '+' }.Contains(type[type.Length - 1]);
|
||
|
|
||
|
subtype = has_type ? type[type.Length - 1] : null;
|
||
|
|
||
|
if (has_type)
|
||
|
{
|
||
|
if (levels[l].separator == separator)
|
||
|
{
|
||
|
levels[l].type = unordered ? 'u' : 'o';
|
||
|
levels[l].subtype = subtype;
|
||
|
html += (html != "" ? "<li>" : "<" + levels[l].type + "l class=\"wmd-list\"" + WMarkDown.list_start(unordered, type) + WMarkDown.list_deployed(levels[l - 1], last_mark, l) + (
|
||
|
key != "" && !unordered && roman_number_marks.Contains<char>(key[0]) ? " type=\"" + key[0] + "\"" :
|
||
|
"") + ">") + "</li>" + _string;
|
||
|
} else if (levels[l].separator < separator)
|
||
|
{
|
||
|
levels.Add(new ListStructure(separator, unordered, subtype));
|
||
|
html += "<" + levels[++l].type + "l class=\"wmd-list\"" + WMarkDown.list_start(unordered, type) + WMarkDown.list_deployed(levels[l - 1], last_mark, l) + (
|
||
|
key != "" && !unordered && roman_number_marks.Contains<char>(key[0]) ? " type=\"" + key[0] + "\"" :
|
||
|
"") + "><li>" + _string;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
while (levels[l].separator > separator)
|
||
|
{
|
||
|
html += "</li></" + levels[--l].type + "l>";
|
||
|
levels.Remove(levels[l + 1]);
|
||
|
if (l == 0)
|
||
|
break;
|
||
|
}
|
||
|
html += "</li><li>" + _string;
|
||
|
}
|
||
|
} else
|
||
|
html += " " + _string;
|
||
|
|
||
|
last_mark = subtype == null ? "" : "" + subtype;
|
||
|
|
||
|
}
|
||
|
|
||
|
while (levels.Count != 0)
|
||
|
{
|
||
|
|
||
|
WMarkDown.ListStructure level = levels[levels.Count - 1];
|
||
|
|
||
|
html += "</li></" + level.type + "l>";
|
||
|
levels.Remove(level);
|
||
|
|
||
|
}
|
||
|
|
||
|
return html;
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public static string set_class(string html, string[] _class)
|
||
|
{
|
||
|
|
||
|
if (!html.Contains("class=\""))
|
||
|
html = (html != "" ? " " : "") + "class=\"" + String.Join<string>(" ", _class) + "\"";
|
||
|
|
||
|
return WMarkDown.re_class_attribute.Replace(html, (Match matches) => {
|
||
|
|
||
|
string attribute = "" + matches.Groups[1];
|
||
|
string classes_str = "" + matches.Groups[2];
|
||
|
string closer = "" + matches.Groups[3];
|
||
|
string[] classes = WMarkDown.re_white_spaces.Split(classes_str);
|
||
|
string subclasses = "";
|
||
|
|
||
|
foreach (string class_key in _class)
|
||
|
if (!classes.Contains(class_key))
|
||
|
subclasses += (subclasses == "" ? "" : " ") + class_key;
|
||
|
|
||
|
return attribute + classes_str + (classes_str != "" ? " " : "") + subclasses + closer;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
public static string set_class(string html, string _class) => WMarkDown.set_class(html, [_class]);
|
||
|
|
||
|
public string? module_table(Match matches, int language = WMarkDown.HTML, string? path = null)
|
||
|
{
|
||
|
if ((language & WMarkDown.HTML) != 0)
|
||
|
{
|
||
|
|
||
|
Dictionary<string, string> html = new Dictionary<string, string>
|
||
|
{
|
||
|
{"thead", "" },
|
||
|
{"tbody", "" },
|
||
|
{"tfoot", "" }
|
||
|
};
|
||
|
string attributes = matches.Groups[1] == null ? "" : ("" + matches.Groups[1]).Trim();
|
||
|
string data = ("" + matches.Groups[3]).Trim();
|
||
|
char[] header_type_marks = new char[] { '^', '_', '=' };
|
||
|
string[] string_empty = new string[] { "''", "\"\"" };
|
||
|
string table_body = "";
|
||
|
|
||
|
while (true)
|
||
|
{
|
||
|
|
||
|
Match line_matches = WMarkDown.re_table_line.Match(data);
|
||
|
|
||
|
if (line_matches == null)
|
||
|
break;
|
||
|
|
||
|
string line = "" + line_matches.Groups[0];
|
||
|
char cell_type = header_type_marks.Contains<char>(line[1]) ? 'h' : 'd';
|
||
|
string[] tags = (
|
||
|
line[1] == '^' ? ["thead"] :
|
||
|
line[1] == '_' ? ["tfoot"] :
|
||
|
line[1] == '=' ? ["thead", "tfoot"] :
|
||
|
["tbody"]);
|
||
|
string row = "<tr>";
|
||
|
|
||
|
if (cell_type == 'h')
|
||
|
line = line[0] + line.Substring(2);
|
||
|
|
||
|
while (true)
|
||
|
{
|
||
|
|
||
|
Match cell_matches = WMarkDown.re_table_item.Match(line);
|
||
|
|
||
|
if (cell_matches == null)
|
||
|
break;
|
||
|
|
||
|
int column_span_i = ("" + cell_matches.Groups[1]).Length;
|
||
|
string colunm_span = column_span_i > 1 ? " colspan=\"" + column_span_i + "\"" : "";
|
||
|
string content = cell_matches.Groups[2] == null ? "" : ("" + cell_matches.Groups[2]).Trim();
|
||
|
|
||
|
row += "<t" + cell_type + column_span_i + ">" + this.analyse(
|
||
|
content != "" && string_empty.Contains<string>("" + content[0] + content[content.Length - 1]) ? content.Substring(1, content.Length - 2) : content,
|
||
|
WMarkDown.HTML,
|
||
|
WMarkDown.SUBITEM,
|
||
|
path
|
||
|
) + "</t" + cell_type + ">";
|
||
|
|
||
|
line = line.Substring(cell_matches.Index + cell_matches.Length);
|
||
|
|
||
|
}
|
||
|
|
||
|
row += "</tr>";
|
||
|
|
||
|
for (int i = 0, l = tags.Length; i < l; i++)
|
||
|
{
|
||
|
if (i != 0)
|
||
|
html[tags[i]] = row + html[tags[i]];
|
||
|
else
|
||
|
html[tags[i]] += row;
|
||
|
}
|
||
|
|
||
|
data = data.Substring(line_matches.Index + line_matches.Length);
|
||
|
|
||
|
}
|
||
|
|
||
|
foreach (string tag in html.Keys)
|
||
|
if (html[tag] != "")
|
||
|
table_body += "<" + tag + ">" + html[tag] + "</" + tag + ">";
|
||
|
|
||
|
return ("<div class=\"wmd-table\">" +
|
||
|
"<table " + attributes + ">" + table_body + "</table>" +
|
||
|
"</div>");
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public string? module_exclude(Match matches, int language = WMarkDown.HTML, string? path = null)
|
||
|
{
|
||
|
if ((language & WMarkDown.HTML) != 0)
|
||
|
return "<span class=\"wmd-excluded\">" + (matches.Groups[1] == null ? "" : "" + matches.Groups[1]) + "</span>";
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public string? module_link(Match matches, int language = WMarkDown.HTML, string? path = null)
|
||
|
{
|
||
|
if ((language & WMarkDown.HTML) != 0)
|
||
|
{
|
||
|
|
||
|
string raw_url = ("" + (matches.Groups[4] ?? matches.Groups[11] ?? matches.Groups[14])).Trim();
|
||
|
string url = (
|
||
|
WMarkDown.re_phone_number.Match(raw_url) != null ? "tel:" + raw_url.Replace(" ", "") :
|
||
|
WMarkDown.re_email_address.Match(raw_url) != null ? "mailto:" + raw_url :
|
||
|
raw_url);
|
||
|
string text = (
|
||
|
matches.Groups[2] != null ? "" + matches.Groups[2] :
|
||
|
matches.Groups[13] != null ? "" + matches.Groups[13] :
|
||
|
raw_url);
|
||
|
Match protocol_matches = WMarkDown.re_protocol.Match(url);
|
||
|
|
||
|
return "<a herf=\"" + url + "\" target=\"_" + (url.Contains("://") ? "blank" : "self") + "\" title=\"" + WMarkDown.re_line_marks.Replace((
|
||
|
matches.Groups[6] != null ? "" + matches.Groups[6] :
|
||
|
matches.Groups[8] != null ? "" + matches.Groups[8] :
|
||
|
matches.Groups[10] != null ? "" + matches.Groups[10] :
|
||
|
text).Trim(), "") + "\" data-protocol=\"" + (
|
||
|
protocol_matches != null ? ("" + protocol_matches.Groups[1]).Trim() : "http"
|
||
|
) + "\">" + this.analyse(text.Trim(), language, WMarkDown.SUBITEM | WMarkDown.LINKED, path) + "</a>";
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public string? module_quote(Match matches, int language = WMarkDown.HTML, string? path = null)
|
||
|
{
|
||
|
if ((language & WMarkDown.HTML) != 0)
|
||
|
{
|
||
|
|
||
|
string? type = matches.Groups[2] == null ? null : "" + matches.Groups[2];
|
||
|
string? type_text = matches.Groups[4] == null ? null : "" + matches.Groups[4];
|
||
|
bool has_type = !String.IsNullOrEmpty(type);
|
||
|
|
||
|
if (has_type && WMarkDown.quote_special.ContainsKey(type))
|
||
|
type = WMarkDown.quote_special[type];
|
||
|
|
||
|
return ("<blockquote class=\"wmd-quote\"" + (has_type ? " data-quote-type=\"" + type + "\"" : "") + ">" +
|
||
|
(has_type ? ("<div class=\"qupte-type\">" + (type[0] == '@' ? (
|
||
|
"<span data-avatar=\"" + type.Substring(1).ToLower() + "\"></span>" +
|
||
|
"<spanclass=\"user\">" + type.Substring(1) + "</span>"
|
||
|
) : (
|
||
|
"<span data-icon=\"" + type + "\"></span>" +
|
||
|
(type_text != "" ? "<span class=\"quote-type-name\">" + type_text + "</span>" : "")
|
||
|
)) + "</div>") : "") +
|
||
|
"<div class=\"text\">" + this.analyse("" + matches.Groups[5], language, WMarkDown.SUBITEM, path) + "</div>" +
|
||
|
"</blockquote>");
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public static string? code_block_data(string key, string value, int language = WMarkDown.HTML, string? path = null)
|
||
|
{
|
||
|
if ((language & WMarkDown.HTML) != 0)
|
||
|
return ("<li data-i18n=\"" + key + "\" data-i18n-without=\"true\" title=\"" + key + "\">" +
|
||
|
"<span data-icon=\"" + key + "\"></span>" +
|
||
|
"<span data-i18n=\"" + key + "\">" + key + "</span>" +
|
||
|
"<span class=\"value\">" + value + "</span>" +
|
||
|
"</li>");
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public static string? code_block_data(string key, int value, int language = WMarkDown.HTML, string? path = null) => WMarkDown.code_block_data(key, value, language, path);
|
||
|
|
||
|
public static string filter_html_special_characters(string _string)
|
||
|
{
|
||
|
|
||
|
int l = _string.Length;
|
||
|
int?[] index = Enumerable.Repeat<int?>(-1, l).ToArray<int?>();
|
||
|
string response = "";
|
||
|
string[] characters = WMarkDown.html_special_characters.Keys.ToArray<string>();
|
||
|
int m = characters.Length;
|
||
|
|
||
|
while (true)
|
||
|
{
|
||
|
|
||
|
int? i = null;
|
||
|
|
||
|
for(int j = 0; j < l; j++)
|
||
|
{
|
||
|
if (index[j] == null)
|
||
|
continue;
|
||
|
|
||
|
if (index[j] < 0 && (index[j] = _string.IndexOf(characters[j])) < 0)
|
||
|
index[j] = null;
|
||
|
|
||
|
if(i == null || index[i ?? 0] > index[j])
|
||
|
i = j;
|
||
|
|
||
|
}
|
||
|
|
||
|
if(i == null)
|
||
|
{
|
||
|
response += _string;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
int length = index[i ?? 0] ?? 0;
|
||
|
|
||
|
response += _string.Substring(0, length) + "&" + WMarkDown.html_special_characters[characters[i ?? 0]] + ";";
|
||
|
_string = _string.Substring(length + 1);
|
||
|
|
||
|
for (int j = 0; j < l; j++)
|
||
|
if (index[j] != null)
|
||
|
index[j] -= length + 1;
|
||
|
|
||
|
}
|
||
|
|
||
|
return response;
|
||
|
}
|
||
|
|
||
|
public static string? module_code_block(Match matches, int language = WMarkDown.HTML, string? path = null)
|
||
|
{
|
||
|
if ((language & WMarkDown.HTML) != 0)
|
||
|
{
|
||
|
|
||
|
string type = "";
|
||
|
string content = "";
|
||
|
|
||
|
for(int i = 2; i < 6; i += 4)
|
||
|
{
|
||
|
type = "" + matches.Groups[i];
|
||
|
content = "" + matches.Groups[i + 1];
|
||
|
if(type != "" || content != "")
|
||
|
{
|
||
|
type = (type == "" ? "unamed" : type.Trim().ToLower());
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(type != "")
|
||
|
{
|
||
|
|
||
|
string[] lines = WMarkDown.re_new_line.Split(content).Skip<string>(2).ToArray<string>();
|
||
|
string lines_string = "";
|
||
|
|
||
|
foreach (string line in lines)
|
||
|
lines_string += "<li></li>";
|
||
|
|
||
|
return ("<div class=\"wmd-code-block\" data-type=\"" + type + "\" data-processed=\"false\">" +
|
||
|
"<ul class=\"data\">" +
|
||
|
"<li><span data-icon=\"" + type + "\"></span></li>" +
|
||
|
WMarkDown.code_block_data("type", type, language) +
|
||
|
WMarkDown.code_block_data("characters", content.Length, language) +
|
||
|
WMarkDown.code_block_data("lines", lines.Length, language) +
|
||
|
"</ul>" +
|
||
|
"<div class=\"code\">" +
|
||
|
"<ol class=\"lines\">" + lines_string + "</ol>" +
|
||
|
"<pre class=\"ccontent\">" + WMarkDown.filter_html_special_characters(content) + "</pre>" +
|
||
|
"</div>" +
|
||
|
"</div>");
|
||
|
}
|
||
|
return "UNKNOWN_BLOCK";
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public string? module_special_characters(Match matches, int language = WMarkDown.HTML, string? path = null)
|
||
|
{
|
||
|
if ((language & WMarkDown.HTML) != 0)
|
||
|
return "" + matches.Groups[1];
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public static string? load_file(string path)
|
||
|
{
|
||
|
if(File.Exists(path))
|
||
|
try
|
||
|
{
|
||
|
return File.ReadAllText(path);
|
||
|
}catch(Exception exception) { };
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public string? module_include(Match matches, int language = WMarkDown.HTML, string? path = null)
|
||
|
{
|
||
|
if ((language & WMarkDown.HTML) != 0)
|
||
|
{
|
||
|
|
||
|
string relative_path = "" + matches.Groups[1];
|
||
|
string new_path = path + relative_path;
|
||
|
string[] extension = Array.ConvertAll<Group, string>(WMarkDown.re_extension.Match(new_path).Groups.Values.Skip<Group>(1).ToArray<Group>(), (Group group) => "" + group);
|
||
|
string? content = WMarkDown.load_file(new_path);
|
||
|
string directory = (Path.GetDirectoryName(new_path) ?? "") + "/";
|
||
|
string? results = (
|
||
|
content == null ? null :
|
||
|
String.Join<string>('.', extension) == "w.md" ? this.process(content, language, directory).results :
|
||
|
extension[extension.Length - 1] == "md" ? this.analyse(content, language, WMarkDown.RAW, directory) :
|
||
|
content);
|
||
|
|
||
|
return ("<section data-path=\"" + relative_path + "\" data-include=\"" + (results == null ? "false" : "true") + "\">" +
|
||
|
"<div class=\"link\"><a href=\"" + relative_path + "\" target=\"_self\" title=\"" + relative_path + "\">" + relative_path + "</a></div>" +
|
||
|
(results ?? "") +
|
||
|
"</section>");
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public static string build_html_image(List<string> links, string type = "image", string? title = null)
|
||
|
{
|
||
|
|
||
|
bool has_title = !String.IsNullOrEmpty(title);
|
||
|
string attributes = has_title ? " title=\"" + title + "\" alt=\"" + title + "\"" : "";
|
||
|
string links_html = "";
|
||
|
|
||
|
foreach (string link in links)
|
||
|
links_html += "<img src=\"" + link + "\"" + attributes + " />";
|
||
|
|
||
|
return ("<span class=\"wmd-media wmd-image\" data-type=\"" + type + "\" data-status=\"unprocessed\">" +
|
||
|
"<noscript>" + links_html + "</noscript>" +
|
||
|
"<img src=\"/images/WMarkDown.png\"" + attributes + " data-sources=\"" + Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonSerializer.Serialize(links))) + " />" +
|
||
|
"<span class=\"image\"></span>" +
|
||
|
(has_title ? "<span class=\"text\">" + title + "</span>" : "") +
|
||
|
"</span>");
|
||
|
}
|
||
|
|
||
|
public string? module_media(Match matches, int language = WMarkDown.HTML, string? path = null)
|
||
|
{
|
||
|
if ((language & WMarkDown.HTML) != 0)
|
||
|
{
|
||
|
|
||
|
string type = ("" + matches.Groups[1]).ToLower();
|
||
|
List<string> links = WMarkDown.re_white_spaces.Split("" + (matches.Groups[3] ?? matches.Groups[5] ?? matches.Groups[7])).ToList<string>();
|
||
|
string text = ("" + (matches.Groups[10] ?? matches.Groups[12] ?? matches.Groups[14])).Trim();
|
||
|
|
||
|
switch (type)
|
||
|
{
|
||
|
case "image":
|
||
|
case "picture":
|
||
|
case "icon":
|
||
|
return WMarkDown.build_html_image(links, type, text);
|
||
|
case "video":
|
||
|
|
||
|
switch (links[0])
|
||
|
{
|
||
|
case "youtube.com":
|
||
|
case "youtu.be":
|
||
|
type = "youtube";
|
||
|
break;
|
||
|
case "vimeo.com":
|
||
|
type = "vimeo";
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return ("<span class=\"wmd-media wmd-video\" data-type=\"" + type + "\" data-status=\"unprocessed\">" +
|
||
|
"<noscript></noscript>" +
|
||
|
(
|
||
|
type == "youtube" ? "<b>YOUTUBE</b>" :
|
||
|
type == "vimeo" ? "<b>VIMEO</b>" :
|
||
|
"<video src=\"" + links[0] + "\"" + (links.Count > 1 ? " poster=\"" + links[1] + "\"" : "") + "></video>") +
|
||
|
"</span>");
|
||
|
case "sound":
|
||
|
case "audio":
|
||
|
|
||
|
switch (links[0])
|
||
|
{
|
||
|
case "soundcloud.com":
|
||
|
type = "soundcloud";
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return ("<span class=\"wmd-media wmd-video\" data-type=\"" + type + "\" data-status=\"unprocessed\">" +
|
||
|
"<noscript></noscript>" +
|
||
|
(
|
||
|
type == "soundcloud" ? "<b>SOUNDCLOUD</b>" :
|
||
|
"<audio src=\"" + links[0] + "\" controls></audio>") +
|
||
|
"</span>");
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public static string mark_replace(string _string, Match matches, List<string> fragments)
|
||
|
{
|
||
|
|
||
|
if(matches != null)
|
||
|
{
|
||
|
_string = _string.Substring(0, matches.Index) + WMarkDown.item_mark.start + fragments.Count + WMarkDown.item_mark.end + _string.Substring(matches.Index + matches.Length);
|
||
|
fragments.Add("" + matches.Groups[0]);
|
||
|
}
|
||
|
|
||
|
return _string;
|
||
|
}
|
||
|
|
||
|
public static string restore_marks(string _string, List<string> fragments)
|
||
|
{
|
||
|
|
||
|
while (true)
|
||
|
{
|
||
|
|
||
|
Match matches = WMarkDown.item_mark.pattern.Match(_string);
|
||
|
|
||
|
if (matches == null)
|
||
|
break;
|
||
|
|
||
|
int i = ("" + matches.Groups[1]).Length;
|
||
|
|
||
|
_string = _string.Substring(0, matches.Index) + (i >= 0 && i < fragments.Count ? fragments[i] : "") + _string.Substring(matches.Index + matches.Length);
|
||
|
|
||
|
}
|
||
|
|
||
|
return _string;
|
||
|
}
|
||
|
|
||
|
private static string doc_typed_format(string typed) => WMarkDown.filter_html_special_characters(typed.Replace(" ", "").Replace(",", ", "));
|
||
|
|
||
|
public string? module_code_doc(Match matches, int language = WMarkDown.HTML, string? path = null)
|
||
|
{
|
||
|
if((language & WMarkDown.HTML) != 0)
|
||
|
{
|
||
|
|
||
|
string data = ("" + matches.Groups[1]).Trim();
|
||
|
Match _base = WMarkDown.re_code_doc.Match(data);
|
||
|
string return_type = WMarkDown.doc_typed_format(_base.Groups[2] == null ? "void" : "" + _base.Groups[2]);
|
||
|
string access = _base.Groups[3] == null ? "public" : "" + _base.Groups[3];
|
||
|
string? name_space = _base.Groups[5] == null ? null : "" + _base.Groups[5];
|
||
|
string environment = _base.Groups[6] == null ? "global" : "" + _base.Groups[6];
|
||
|
string method = "" + _base.Groups[7];
|
||
|
string? parameters = _base.Groups[8] == null ? null : "" + _base.Groups;
|
||
|
bool has_parameters = parameters != null;
|
||
|
string? default_value = _base.Groups[11] == null ? null : "" + _base.Groups[11];
|
||
|
string full_method = (String.IsNullOrEmpty(name_space) ? "" : name_space + ".") + method.Trim();
|
||
|
string arguments = "";
|
||
|
string arguments_definition = "";
|
||
|
string header = ("<tr>" +
|
||
|
"<th data-i18n=\"name\" title=\"Name\">Name</th>" +
|
||
|
"<th data-i18n=\"required\" title=\"Required\">Required</th>" +
|
||
|
"<th data-i18n=\"nullable\" title=\"Nullable\">Nullable</th>" +
|
||
|
"<th data-i18n=\"typed\" title=\"Typed\">Typed</th>" +
|
||
|
"<th data-i18n=\"default_value\" title=\"Default Value\">Default Value</th>" +
|
||
|
"</tr>");
|
||
|
List<string> fragments = new List<string>();
|
||
|
int arguments_l = 0;
|
||
|
|
||
|
switch (access)
|
||
|
{
|
||
|
case "?":
|
||
|
access = "protected";
|
||
|
break;
|
||
|
case "!":
|
||
|
access = "protected";
|
||
|
break;
|
||
|
};
|
||
|
|
||
|
switch (environment)
|
||
|
{
|
||
|
case ":":
|
||
|
environment = "static";
|
||
|
break;
|
||
|
case ".":
|
||
|
environment = "object";
|
||
|
break;
|
||
|
};
|
||
|
|
||
|
if (parameters != "")
|
||
|
{
|
||
|
while (true)
|
||
|
{
|
||
|
|
||
|
matches = WMarkDown.re_code_doc_subarguments.Match(parameters);
|
||
|
|
||
|
if (matches != null)
|
||
|
parameters = WMarkDown.mark_replace(parameters, matches, fragments);
|
||
|
else
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
parameters = "";
|
||
|
|
||
|
foreach(string parameter in parameters.Split(","))
|
||
|
{
|
||
|
|
||
|
matches = WMarkDown.re_code_doc_arguments.Match(parameter.Trim());
|
||
|
|
||
|
if(matches != null)
|
||
|
{
|
||
|
|
||
|
string scopes = "" + matches.Groups[1];
|
||
|
bool required = scopes.Contains("!");
|
||
|
bool nullish = scopes.Contains("?");
|
||
|
string typed = WMarkDown.doc_typed_format(WMarkDown.restore_marks("" + matches.Groups[2], fragments));
|
||
|
string name = ("" + matches.Groups[3]).Trim();
|
||
|
string default_subvalue = WMarkDown.filter_html_special_characters(WMarkDown.restore_marks(("" + matches.Groups[5]).Trim(), fragments));
|
||
|
|
||
|
arguments += ("<span class=\"arguments\">" +
|
||
|
(required ? "<span class=\"required\" data-i18n=\"required\" title=\"Required\">Required</span>" : "") +
|
||
|
(nullish ? "<span class=\"nullish\" data-i18n=\"nullish\" title=\"Nullish\">Nullish</span>" : "") +
|
||
|
"<span class=\"typed\" data-i18n=\"typed\" title=\"Typed\">" + typed + "</span>" +
|
||
|
"<span class=\"name\" data-i18n=\"name\" title=\"Named\">" + name + "</span>" +
|
||
|
(default_subvalue != "" ? "<span class=\"default_value\" data-i18n=\"default_value\" title=\"Default value\">" + default_subvalue + "</span>" : "") +
|
||
|
"</span>");
|
||
|
arguments_definition = ("<tr>" +
|
||
|
"<td class=\"name\" data-i18n=\"name\" title=\"Named\">" + name + "</td>" +
|
||
|
"<td class=\"required\" data-i18n=\"required\" title=\"Required\">" + (required ? "True" : "False") + "</td>" +
|
||
|
"<td class=\"nullish\" data-i18n=\"nullish\" title=\"Nullish\">" + (nullish ? "True" : "False") + "</td>" +
|
||
|
"<td class=\"typed\" data-i18n=\"typed\" title=\"Typed\">" + typed + "</td>" +
|
||
|
"<td class=\"default-value\" data-i18n=\"default_value\" title=\"Default value\">" + default_subvalue + "</td>" +
|
||
|
"</tr>");
|
||
|
arguments_l++;
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ("<fieldset class=\"wmd-code-doc\" data-arguments-l=\"" + arguments_l + "\">" +
|
||
|
"<legend>" + full_method + "</legend>" +
|
||
|
"<div class=\"description\">" +
|
||
|
"<span class=\"return-type\" data-i18n=\"return\" title=\"Return\">" + return_type + "</span>" +
|
||
|
"<span class=\"environment\" data-i18n=\"environment\" title=\"Environment\">" + environment + "</span>" +
|
||
|
"<span class=\"access\" data-i18n=\"access\" title=\"Access\">" + access + "</span>" +
|
||
|
"<span class=\"full-method\" data-i18n=\"full_method\" title=\"Method\">" + full_method + "</span>" +
|
||
|
(has_parameters ? "<span class=\"arguments\" data-i18n=\"arguments\" title=\"Arguments\">" + arguments + "</span>" : "") +
|
||
|
(default_value != "" ? "<span class=\"default-value\" data-i18n=\"default_value\" title=\"Default value\">" + default_value + "</span>" : "") +
|
||
|
"</div>" +
|
||
|
"<div class=\"wmd-table definition\">" +
|
||
|
"<table>" +
|
||
|
"<thead>" + header + "</thead>" +
|
||
|
"<tbody>" + arguments_definition + "</tbody>" +
|
||
|
"<tfoot>" + header + "</tfoot>" +
|
||
|
"</table>" +
|
||
|
"</div>" +
|
||
|
"</fieldset>");
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public string? module_color_sample(Match matches, int language = WMarkDown.HTML, string? path = null)
|
||
|
{
|
||
|
if ((language & WMarkDown.HTML) != 0)
|
||
|
{
|
||
|
|
||
|
string color = "" + (matches.Groups[2] ?? matches.Groups[3]);
|
||
|
|
||
|
return ("<span class=\"wmd-color-sample\" style=\"background-color:" + color + "\" title=\"" + color + "\">" +
|
||
|
"<span data-sample=\"" + color + "\"></span>" +
|
||
|
"<span class=\"color\">" + color + "</span>" +
|
||
|
"</span>");
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public string? module_presentation_links(Match matches, int language = WMarkDown.HTML, string? path = null)
|
||
|
{
|
||
|
if ((language & WMarkDown.HTML) != 0)
|
||
|
{
|
||
|
|
||
|
List<WMarkDown.LinkPresententationModel> items = new List<LinkPresententationModel>();
|
||
|
int j = -1;
|
||
|
string html_avatars = "";
|
||
|
string html_list = "";
|
||
|
|
||
|
foreach (string line in WMarkDown.re_new_lines.Split("" + matches.Groups[1]))
|
||
|
{
|
||
|
|
||
|
bool has_spaces = WMarkDown.re_start_with_white_spaces.Match(line) != null;
|
||
|
string data = line.Trim();
|
||
|
|
||
|
if (data == "")
|
||
|
continue;
|
||
|
|
||
|
if (has_spaces)
|
||
|
{
|
||
|
if (j == -1)
|
||
|
continue;
|
||
|
if (data[0] == '*')
|
||
|
{
|
||
|
items[j].avatars.Add(data.Substring(1));
|
||
|
if (data.Contains(".k3y.pw/"))
|
||
|
items[j].avatars.Add(data.Substring(1).Replace(".k3y.pw/", ".local/"));
|
||
|
}
|
||
|
else
|
||
|
items[j].links.Add(data);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
j++;
|
||
|
items.Add(new LinkPresententationModel(line));
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
for(int i = 0, l = items.Count; i < l; i++)
|
||
|
{
|
||
|
|
||
|
string avatars_html = "";
|
||
|
string links_html = "";
|
||
|
|
||
|
foreach (string avatar in items[i].avatars)
|
||
|
avatars_html += "<a href=\"" + avatar + "\" target=\"_blank\" class=\"wmd-favicon\" style=\"background-image:" + (
|
||
|
"url('" + WMarkDown.re_domain.Match(avatar).Groups[0] + "/favicon.ico')" +
|
||
|
(avatar.Contains(".k3y.pw/") ? ",url('" + WMarkDown.re_domain.Match(avatar.Replace(".k3y.pw/", ".local/")).Groups[0] + "/favicon.ico')" : "")
|
||
|
) + ";\"></a>";
|
||
|
|
||
|
foreach (string link in items[i].links)
|
||
|
links_html += "<li class=\"link\"><<a href=\"" + link + "\" target=\"_blank\" title=\"" + link + "\">" + link + "</a></li>";
|
||
|
|
||
|
html_avatars += ("<li title=\"" + items[i].title + "\" data-i=\"" + i + "\" data-links=\"" + items[i].links.Count + "\">" +
|
||
|
(items[i].links.Count != 0 ? "<a href=\"" + items[i].links[0] + "\" target=\"_blank\">" +
|
||
|
WMarkDown.build_html_image(items[i].avatars) +
|
||
|
"</a>" : WMarkDown.build_html_image(items[i].avatars)) +
|
||
|
avatars_html +
|
||
|
"</li>");
|
||
|
html_list += ("<li class=\"name\">" +
|
||
|
"<span>" + items[i].title + "</span>" +
|
||
|
"<ul class=\"links\">" + links_html + "</ul>" +
|
||
|
"</li>");
|
||
|
|
||
|
}
|
||
|
|
||
|
return ("<div class=\"wmd-presentation-links\">" +
|
||
|
"<ul class=\"wmd-avatars\">" + html_avatars + "</ul>" +
|
||
|
"<ul class=\"wmd-list\">" + html_list + "</ul>" +
|
||
|
"</div>");
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public static string remove_default_tabulations(string data)
|
||
|
{
|
||
|
|
||
|
int spaces = data.Length;
|
||
|
|
||
|
foreach(string line in WMarkDown.re_new_lines.Split(data))
|
||
|
{
|
||
|
if (line == "")
|
||
|
continue;
|
||
|
|
||
|
int white_spaces = ("" + WMarkDown.re_started_white_spaces.Match(line).Groups[0]).Length;
|
||
|
|
||
|
if (white_spaces < spaces)
|
||
|
spaces = white_spaces;
|
||
|
|
||
|
}
|
||
|
|
||
|
return WMarkDown.re_lines.Replace(data, (Match matches) => ("" + matches.Groups[0]).Substring(spaces));
|
||
|
}
|
||
|
|
||
|
private string build(string data, int language, string? path)
|
||
|
{
|
||
|
return ("<div class=\"wmd wmarkdown\" data-dictionary-processed=\"false\" data-menu-processed=\"false\">" +
|
||
|
this.analyse(WMarkDown.remove_default_tabulations(data), language, WMarkDown.RAW, path) +
|
||
|
"<div class=\"wmd-process-and-loaded\"></div>" +
|
||
|
"</div>");
|
||
|
}
|
||
|
|
||
|
public WMarkDown.ProcessResults process(string data, int language = WMarkDown.HTML, string? path = null)
|
||
|
{
|
||
|
|
||
|
string results = "";
|
||
|
Dictionary<string, string> variables = new Dictionary<string, string>();
|
||
|
Match options = WMarkDown.re_options.Match(data);
|
||
|
|
||
|
if(options != null)
|
||
|
{
|
||
|
|
||
|
string options_data = "" + options.Groups[3];
|
||
|
|
||
|
while (true)
|
||
|
{
|
||
|
|
||
|
Match option = WMarkDown.re_option.Match(options_data);
|
||
|
|
||
|
if (option == null)
|
||
|
break;
|
||
|
|
||
|
variables[("" + option.Groups[1]).Trim()] = ("" + option.Groups[2]).Trim();
|
||
|
options_data = options_data.Substring(option.Index);
|
||
|
|
||
|
}
|
||
|
|
||
|
data = data.Substring(0, options.Index) + data.Substring(options.Index + options.Length);
|
||
|
|
||
|
}
|
||
|
|
||
|
while (true)
|
||
|
{
|
||
|
|
||
|
Match matches = WMarkDown.re_block_mark.Match(data);
|
||
|
|
||
|
if(matches == null)
|
||
|
{
|
||
|
results += data;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
string mark = "" + matches.Groups[1];
|
||
|
Regex re_close = mark != "" ? new Regex(@"^\s*" + mark, RegexOptions.Multiline) : WMarkDown.re_block_html;
|
||
|
|
||
|
results += data.Substring(0, matches.Index);
|
||
|
data = data.Substring(matches.Index + matches.Length);
|
||
|
|
||
|
Match close_matches = re_close.Match(data);
|
||
|
|
||
|
if(close_matches != null)
|
||
|
{
|
||
|
results += this.build(data.Substring(0, close_matches.Index), language, path);
|
||
|
data = data.Substring(close_matches.Index + close_matches.Length);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
results += this.build(data, language, path);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
return new WMarkDown.ProcessResults(results, variables);
|
||
|
}
|
||
|
|
||
|
public string analyse(string data, int language = WMarkDown.HTML, int mode = WMarkDown.RAW, string? path = null)
|
||
|
{
|
||
|
|
||
|
string response = "";
|
||
|
string[] keys = this.modules.Keys.ToArray<string>();
|
||
|
int l = keys.Length;
|
||
|
Dictionary<string, WMarkDown.Item> items = new Dictionary<string, WMarkDown.Item>();
|
||
|
|
||
|
for (int i = 0; i < l; i++)
|
||
|
items[keys[i]] = new WMarkDown.Item();
|
||
|
|
||
|
while (true)
|
||
|
{
|
||
|
|
||
|
string? selected = null;
|
||
|
|
||
|
l = data.Length;
|
||
|
|
||
|
foreach(KeyValuePair<string, WMarkDown.Item> block in items)
|
||
|
{
|
||
|
|
||
|
string key = block.Key;
|
||
|
WMarkDown.Item item = block.Value;
|
||
|
|
||
|
if (!item.exists)
|
||
|
continue;
|
||
|
|
||
|
if(item.from < 0)
|
||
|
{
|
||
|
if((item.matches = this.modules[key].pattern.Match(data)) != null)
|
||
|
item.length = (item.from = item.matches.Index) + item.matches.Length;
|
||
|
else
|
||
|
{
|
||
|
item.exists = false;
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (item.from < l)
|
||
|
{
|
||
|
l = item.from;
|
||
|
selected = key;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
if(selected == null)
|
||
|
{
|
||
|
response += data;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
MethodInfo? method = this.GetType().GetMethod("module_" + (selected ?? ""));
|
||
|
int to = items[selected].from + items[selected].length;
|
||
|
|
||
|
if (method != null)
|
||
|
{
|
||
|
|
||
|
string fragment = data.Substring(items[selected].from, items[selected].length);
|
||
|
|
||
|
response += data.Substring(0, items[selected].from) + method.Invoke(this, [items[selected].matches, language, path]);
|
||
|
|
||
|
}
|
||
|
else
|
||
|
response += data.Substring(0, to);
|
||
|
|
||
|
foreach (WMarkDown.Item item in items.Values)
|
||
|
if (item.exists)
|
||
|
item.from -= to;
|
||
|
|
||
|
}
|
||
|
|
||
|
return response;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|