📄 formatter.cs
字号:
// This is an attachment
done = true;
string f = tmp.Substring("attachment:".Length);
if(f.StartsWith("{up}")) f = f.Substring(4);
if(f.ToLower().StartsWith(upReplacement.ToLower())) f = f.Substring(upReplacement.Length);
attachments.Add(HttpContext.Current.Server.UrlDecode(f));
// Remove all trailing \n, so that attachments have no effect on the output in any case
while(sb[match.Index] == '\n' && match.Index < sb.Length - 1) {
sb.Remove(match.Index, 1);
}
}
else {
a = tmp;
n = "";
}
if(!done) {
sb.Insert(match.Index, BuildLink(a, n, false, lp));
}
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = link.Match(sb.ToString(), end);
}
match = boldItalic.Match(sb.ToString());
while(match.Success) {
if(!IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end)) {
sb.Remove(match.Index, match.Length);
dummy = new StringBuilder("<b><i>");
dummy.Append(match.Value.Substring(5, match.Value.Length - 10));
dummy.Append("</i></b>");
sb.Insert(match.Index, dummy.ToString());
}
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = boldItalic.Match(sb.ToString(), end);
}
match = bold.Match(sb.ToString());
while(match.Success) {
if(!IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end)) {
sb.Remove(match.Index, match.Length);
dummy = new StringBuilder("<b>");
dummy.Append(match.Value.Substring(3, match.Value.Length - 6));
dummy.Append("</b>");
sb.Insert(match.Index, dummy.ToString());
}
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = bold.Match(sb.ToString(), end);
}
match = italic.Match(sb.ToString());
while(match.Success) {
if(!IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end)) {
sb.Remove(match.Index, match.Length);
dummy = new StringBuilder("<i>");
dummy.Append(match.Value.Substring(2, match.Value.Length - 4));
dummy.Append("</i>");
sb.Insert(match.Index, dummy.ToString());
}
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = italic.Match(sb.ToString(), end);
}
match = underlined.Match(sb.ToString());
while(match.Success) {
if(!IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end)) {
sb.Remove(match.Index, match.Length);
dummy = new StringBuilder("<u>");
dummy.Append(match.Value.Substring(2, match.Value.Length - 4));
dummy.Append("</u>");
sb.Insert(match.Index, dummy.ToString());
}
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = underlined.Match(sb.ToString(), end);
}
match = striked.Match(sb.ToString());
while(match.Success) {
if(!IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end)) {
sb.Remove(match.Index, match.Length);
dummy = new StringBuilder("<strike>");
dummy.Append(match.Value.Substring(2, match.Value.Length - 4));
dummy.Append("</strike>");
sb.Insert(match.Index, dummy.ToString());
}
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = striked.Match(sb.ToString(), end);
}
match = pre.Match(sb.ToString());
while(match.Success) {
if(!IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end)) {
sb.Remove(match.Index, match.Length);
dummy = new StringBuilder("<pre>");
dummy.Append(match.Value.Substring(4, match.Value.Length - 8));
dummy.Append("</pre>");
sb.Insert(match.Index, dummy.ToString());
}
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = pre.Match(sb.ToString(), end);
}
match = code.Match(sb.ToString());
while(match.Success) {
if(!IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end)) {
sb.Remove(match.Index, match.Length);
dummy = new StringBuilder("<code>");
dummy.Append(match.Value.Substring(2, match.Value.Length - 4));
dummy.Append("</code>");
sb.Insert(match.Index, dummy.ToString());
}
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = code.Match(sb.ToString(), end);
}
string h;
// Hx: detection pass (used for the TOC generation and section editing)
hPos = DetectHeaders(sb.ToString());
// Hx: formatting pass
int count = 0;
match = h4.Match(sb.ToString());
while(match.Success) {
if(!IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end)) {
sb.Remove(match.Index, match.Length);
h = match.Value.Substring(5, match.Value.Length - 10);
dummy = new StringBuilder();
dummy.Append(@"<a id=""");
dummy.Append(BuildHAnchor(h));
dummy.Append(@"""></a><h4>");
dummy.Append(h);
dummy.Append("</h4>");
sb.Insert(match.Index, dummy.ToString());
count++;
}
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = h4.Match(sb.ToString(), end);
}
match = h3.Match(sb.ToString());
while(match.Success) {
if(!IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end)) {
sb.Remove(match.Index, match.Length);
h = match.Value.Substring(4, match.Value.Length - 8);
dummy = new StringBuilder();
if(current != null) dummy.Append(BuildEditSectionLink(count, current.Name));
dummy.Append(@"<a id=""");
dummy.Append(BuildHAnchor(h));
dummy.Append(@"""></a><h3 class=""separator"">");
dummy.Append(h);
dummy.Append("</h3>");
sb.Insert(match.Index, dummy.ToString());
count++;
}
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = h3.Match(sb.ToString(), end);
}
match = h2.Match(sb.ToString());
while(match.Success) {
if(!IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end)) {
sb.Remove(match.Index, match.Length);
h = match.Value.Substring(3, match.Value.Length - 6);
dummy = new StringBuilder();
if(current != null) dummy.Append(BuildEditSectionLink(count, current.Name));
dummy.Append(@"<a id=""");
dummy.Append(BuildHAnchor(h));
dummy.Append(@"""></a><h2 class=""separator"">");
dummy.Append(h);
dummy.Append("</h2>");
sb.Insert(match.Index, dummy.ToString());
count++;
}
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = h2.Match(sb.ToString(), end);
}
match = h1.Match(sb.ToString());
while(match.Success) {
if(!IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end)) {
sb.Remove(match.Index, match.Length);
h = match.Value.Substring(2, match.Value.Length - 4);
dummy = new StringBuilder();
if(current != null) dummy.Append(BuildEditSectionLink(count, current.Name));
dummy.Append(@"<a id=""");
dummy.Append(BuildHAnchor(h));
dummy.Append(@"""></a><h1 class=""separator"">");
dummy.Append(h);
dummy.Append("</h1>");
sb.Insert(match.Index, dummy.ToString());
count++;
}
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = h1.Match(sb.ToString(), end);
}
match = box.Match(sb.ToString());
while(match.Success) {
if(!IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end)) {
sb.Remove(match.Index, match.Length);
dummy = new StringBuilder(@"<div class=""box"">");
dummy.Append(match.Value.Substring(3, match.Value.Length - 6));
dummy.Append("</div>");
sb.Insert(match.Index, dummy.ToString());
}
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = box.Match(sb.ToString(), end);
}
// "Disable" NoWiki'ed {Username} tags
match = username.Match(sb.ToString());
while(match.Success) {
if(IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end)) {
sb.Remove(match.Index, match.Length);
sb.Insert(match.Index, match.Value.Replace("{", "{").Replace("}", "}"));
}
else end = match.Index + match.Length + 1;
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = username.Match(sb.ToString(), end);
}
if(current != null) {
string tocString = BuildToc(hPos);
match = toc.Match(sb.ToString());
while(match.Success) {
if(!IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end)) {
sb.Remove(match.Index, match.Length);
sb.Insert(match.Index, tocString);
}
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = toc.Match(sb.ToString(), end);
}
}
match = snippet.Match(sb.ToString());
while(match.Success) {
if(!IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end)) {
sb.Remove(match.Index, match.Length);
Snippet s = Snippets.Instance.Find(match.Value.Substring(3, match.Length - 4));
if(s != null) {
string fs = Format(s.Content, null);
fs = fs.TrimEnd('\n').TrimStart('\n');
sb.Insert(match.Index, fs);
}
else {
sb.Insert(match.Index, @"<b style=""color: #FF0000;"">FORMATTER ERROR (Snippet Not Found)</b>");
}
}
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = snippet.Match(sb.ToString(), end);
}
// Remove <nowiki> tags
sb.Replace("<nowiki>", "");
sb.Replace("</nowiki>", "");
// No more needed (Striked Regex modified)
// Unescape comments
//sb.Replace("($_^)", "<!--");
//sb.Replace("(^_$)", "-->");
// Setup BRs
sb.Replace("\n\n", "<br /><br />");
sb.Replace("<br>", "<br />");
// Hacks
sb.Replace("</ul><br /><br />", "</ul><br />");
sb.Replace("</ol><br /><br />", "</ol><br />");
sb.Replace("</table><br /><br />", "</table><br />");
sb.Replace("</pre><br /><br />", "</pre><br />");
sb.Replace("</div><br /><br />", "</div><br />");
// Append Attachments
if(attachments.Count > 0) {
sb.Append(@"<div id=""AttachmentsDiv"">");
for(int i = 0; i < attachments.Count; i++) {
sb.Append(@"<a href=""");
sb.Append(upReplacement);
sb.Append(Tools.UrlEncode(attachments[i]));
sb.Append(@""" class=""attachment"">");
sb.Append(attachments[i]);
sb.Append("</a>");
if(i != attachments.Count - 1) sb.Append(" - ");
}
sb.Append("</div>");
}
linkedPages = lp.ToArray();
return sb.ToString();
}
/// <summary>
/// Escapes all the characters used by the WikiMarkup.
/// </summary>
/// <param name="content">The Content.</param>
/// <returns>The escaped Content.</returns>
private static string EscapeWikiMarkup(string content) {
StringBuilder sb = new StringBuilder(content);
sb.Replace("&", "&"); // Before all other escapes!
sb.Replace("#", "#");
sb.Replace("*", "*");
sb.Replace("<", "<");
sb.Replace(">", ">");
sb.Replace("[", "[");
sb.Replace("]", "]");
sb.Replace("{", "{");
sb.Replace("}", "}");
sb.Replace("'", "'");
sb.Replace("=", "=");
sb.Replace("§", "§");
sb.Replace("_", "_");
sb.Replace("-", "-");
sb.Replace("@", "@");
return sb.ToString();
}
/// <summary>
/// Builds a Link.
/// </summary>
/// <param name="a">The (raw) HREF.</param>
/// <param name="n">The name/title.</param>
/// <param name="isImage">True if the link contains an Image as "visible content".</param>
/// <param name="lp">The Linked Pages list.</param>
/// <returns>The formatted Link.</returns>
private static string BuildLink(string a, string n, bool isImage, List<PageInfo> lp) {
bool blank = false;
if(a.StartsWith("^")) {
blank = true;
a = a.Substring(1);
}
a = EscapeUrl(a);
StringBuilder sb = new StringBuilder();
if(a.ToLower().Equals("anchor") && n.StartsWith("#")) {
sb.Append(@"<a id=""");
sb.Append(n.Substring(1));
sb.Append(@"""></a>");
}
else if(a.StartsWith("#")) {
if(n.Length == 0) {
sb.Append(@"<a class=""internallink""");
if(blank) sb.Append(@" target=""_blank""");
sb.Append(@" href=""");
sb.Append(a);
sb.Append(@""" title=""");
sb.Append(a.Substring(1));
sb.Append(@""">");
sb.Append(a.Substring(1));
sb.Append("</a>");
}
else {
sb.Append(@"<a");
if(blank) sb.Append(@" target=""_blank""");
sb.Append(@" href=""");
sb.Append(a);
sb.Append(@"""");
if(!isImage) {
sb.Append(@" class=""internallink"" title=""");
sb.Append(n);
sb.Append(@"""");
}
sb.Append(">");
sb.Append(n);
sb.Append("</a>");
}
}
else if(a.StartsWith("http://") || a.StartsWith("https://") || a.StartsWith("ftp://") || a.StartsWith("file://")) {
// The link is complete
if(n.Length == 0) {
sb.Append(@"<a class=""externallink"" href=""");
sb.Append(a);
sb.Append(@""" title=""");
sb.Append(a);
sb.Append(@""" target=""_blank"">");
sb.Append(a);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -