⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 formatter.cs

📁 YetAnotherForum.Net+ScrewTurnWiki中文完美汉化增强版
💻 CS
📖 第 1 页 / 共 4 页
字号:

using System;
using System.Configuration;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.SessionState;
using System.Diagnostics;
using ScrewTurn.Wiki.PluginFramework;

namespace ScrewTurn.Wiki {

    /// <summary>
    /// Performs all the text formatting and parsing operations.
    /// </summary>
    public static class Formatter {

		private static Regex noWiki = new Regex(@"\<nowiki\>(.|\n|\r)+?\<\/nowiki\>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
		private static Regex link = new Regex(@"(\[\[.+?\]\])|(\[.+?\])", RegexOptions.Compiled);
		private static Regex redirection = new Regex(@"^\ *\>\>\>\ *.+\ *$", RegexOptions.Compiled | RegexOptions.Multiline);
		private static Regex h1 = new Regex(@"^==.+?==", RegexOptions.Compiled | RegexOptions.Multiline);
		private static Regex h2 = new Regex(@"^===.+?===", RegexOptions.Compiled | RegexOptions.Multiline);
		private static Regex h3 = new Regex(@"^====.+?====", RegexOptions.Compiled | RegexOptions.Multiline);
		private static Regex h4 = new Regex(@"^=====.+?=====", RegexOptions.Compiled | RegexOptions.Multiline);
		private static Regex bold = new Regex(@"'''.+?'''", RegexOptions.Compiled | RegexOptions.Singleline);
		private static Regex italic = new Regex(@"''.+?''", RegexOptions.Compiled | RegexOptions.Singleline);
		private static Regex boldItalic = new Regex(@"'''''.+?'''''", RegexOptions.Compiled | RegexOptions.Singleline);
		private static Regex underlined = new Regex(@"__.+?__", RegexOptions.Compiled | RegexOptions.Singleline);
		private static Regex striked = new Regex(@"(?<!\<\!)(\-\-(?!\>).+?\-\-)(?!\>)", RegexOptions.Compiled | RegexOptions.Singleline);
		private static Regex code = new Regex(@"\{\{.+?\}\}", RegexOptions.Compiled | RegexOptions.Singleline);
		private static Regex pre = new Regex(@"\{\{\{\{.+?\}\}\}\}", RegexOptions.Compiled | RegexOptions.Singleline);
		private static Regex box = new Regex(@"\(\(\(.+?\)\)\)", RegexOptions.Compiled | RegexOptions.Singleline);
		private static Regex specialTag = new Regex(@"\{(wikititle|wikiversion|mainurl|up|rsspage|themepath|clear|br|top|searchbox|pagecount|cloud)\}", RegexOptions.Compiled | RegexOptions.IgnoreCase);
		private static Regex list = new Regex(@"(?<=(\n|^))((\*|\#)+(\ )?.+?\n)+", RegexOptions.Compiled);
		private static Regex toc = new Regex(@"\{toc\}", RegexOptions.Compiled | RegexOptions.IgnoreCase);
		private static Regex transclusion = new Regex(@"\{T(\:|\|).+}", RegexOptions.Compiled | RegexOptions.IgnoreCase);
		private static Regex hr = new Regex(@"(?<=(\n|^))(\ )*----(\ )*\n", RegexOptions.Compiled);
		private static Regex snippet = new Regex(@"\{S(\:|\|).+?}", RegexOptions.Compiled | RegexOptions.IgnoreCase);
		private static Regex table = new Regex(@"\{\|(\ [^\n]*)?\n.+?\|\}", RegexOptions.Compiled | RegexOptions.Singleline);
		private static Regex indent = new Regex(@"(?<=(\n|^))\:+(\ )?.+?\n", RegexOptions.Compiled);
		private static Regex esc = new Regex(@"\<esc\>(.|\n|\r)*?\<\/esc\>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
		private static Regex sign = new Regex(@"Ё\(.+?\)Ё", RegexOptions.Compiled | RegexOptions.IgnoreCase);
		private static Regex fullCode = new Regex(@"@@.+?@@", RegexOptions.Compiled | RegexOptions.Singleline);
		private static Regex username = new Regex(@"\{username\}", RegexOptions.Compiled | RegexOptions.IgnoreCase);

		private static string tocTitlePlaceHolder = "%%%%TocTitlePlaceHolder%%%%";
		private static string editSectionPlaceHolder = "%%%%EditSectionPlaceHolder%%%%"; // This string is also used in History.aspx.cs
		private static string upReplacement = "GetFile.aspx?File=";

		public static string Format(string raw, PageInfo current) {
			PageInfo[] lp;
			return Format(raw, current, out lp);
		}

		/// <summary>
		/// Formats WikiMarkup, converting it into XHTML.
		/// </summary>
		/// <param name="raw">The raw WikiMarkup text.</param>
		/// <param name="pages">The Pages.</param>
		/// <param name="current">The current Page (can be null).</param>
		/// <returns>The formatted text.</returns>
		public static string Format(string raw, PageInfo current, out PageInfo[] linkedPages) {

			linkedPages = new PageInfo[0];
			List<PageInfo> lp = new List<PageInfo>();

			StringBuilder sb = new StringBuilder(raw);
			Match match;
			string tmp, a, n, url, title, bigUrl;
			StringBuilder dummy; // Used for temporary string manipulation inside formatting cycles
			bool done = false;
			List<int> noWikiBegin = new List<int>(), noWikiEnd = new List<int>();
			int end = 0;
			List<HPosition> hPos = new List<HPosition>();

			sb.Replace("\r", "");
			if(!sb.ToString().EndsWith("\n")) sb.Append("\n"); // Very important to make Regular Expressions work!

			ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);

			if(current != null) {
				// Check redirection
				match = redirection.Match(sb.ToString());
				if(match.Success) {
					if(!IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end)) {
						sb.Remove(match.Index, match.Length);
						string destination = match.Value.Trim().Substring(4).Trim();
						while(destination.StartsWith("[") && destination.EndsWith("]")) {
							destination = destination.Substring(1, destination.Length - 2);
						}
						while(sb[match.Index] == '\n' && match.Index < sb.Length - 1) sb.Remove(match.Index, 1);
						PageInfo dest = Pages.Instance.FindPage(destination);
						if(dest != null) {
							Redirections.Instance.AddRedirection(current, dest);
						}
					}
					ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
				}
			}

			// Before Producing HTML
			match = fullCode.Match(sb.ToString());
			while(match.Success) {
				if(!IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end)) {
					sb.Remove(match.Index, match.Length);
					string content = match.Value.Substring(2, match.Length - 4);
					dummy = new StringBuilder();
					dummy.Append("<pre>");
					dummy.Append(EscapeWikiMarkup(content));
					dummy.Append("</pre>");
					sb.Insert(match.Index, dummy.ToString());
				}
				ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
				match = fullCode.Match(sb.ToString(), end);
			}

			// No more needed (Striked Regex modified)
			// Temporarily "escape" comments
			//sb.Replace("<!--", "($_^)");
			//sb.Replace("-->", "(^_$)");

			ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);

			// Before Producing HTML
			match = esc.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.Substring(5, match.Length - 11).Replace("<", "&lt;").Replace(">", "&gt;"));
				}
				ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
				match = esc.Match(sb.ToString(), end);
			}

			// Snippets were here
			// Moved to solve problems with lists and tables

			match = table.Match(sb.ToString());
			while(match.Success) {
				if(!IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end)) {
					sb.Remove(match.Index, match.Length);
					sb.Insert(match.Index, BuildTable(match.Value));
				}
				ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
				match = table.Match(sb.ToString(), end);
			}

			match = indent.Match(sb.ToString());
			while(match.Success) {
				if(!IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end)) {
					sb.Remove(match.Index, match.Length);
					sb.Insert(match.Index, BuildIndent(match.Value) + "\n");
				}
				ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
				match = indent.Match(sb.ToString(), end);
			}

			match = specialTag.Match(sb.ToString());
			while(match.Success) {
				if(!IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end)) {
					sb.Remove(match.Index, match.Length);
					switch(match.Value.Substring(1, match.Value.Length - 2).ToUpper()) {
						case "WIKITITLE":
							sb.Insert(match.Index, Settings.WikiTitle);
							break;
						case "WIKIVERSION":
							sb.Insert(match.Index, Settings.WikiVersion);
							break;
						case "MAINURL":
							sb.Insert(match.Index, Settings.MainUrl);
							break;
						case "UP":
							sb.Insert(match.Index, upReplacement);
							break;
						case "RSSPAGE":
							if(current != null) {
								sb.Insert(match.Index, @"<a href=""RSS.aspx?Page=" + Tools.UrlEncode(current.Name) + @""" title=""" + Exchanger.ResourceExchanger.GetResource("RssForThisPage") + @"""><img src=""" + Settings.ThemePath + @"Images/RSS.png"" alt=""RSS"" /></a>");
							}
							break;
						case "THEMEPATH":
							sb.Insert(match.Index, Settings.ThemePath);
							break;
						case "CLEAR":
							sb.Insert(match.Index, @"<div style=""clear: both;""></div>");
							break;
						case "BR":
							sb.Insert(match.Index, "<br />");
							break;
						case "TOP":
							sb.Insert(match.Index, @"<a href=""#PageTop"">" + Exchanger.ResourceExchanger.GetResource("Top") + "</a>");
							break;
						case "SEARCHBOX":
							sb.Insert(match.Index, @"<nowiki><input type=""text"" id=""TxtSearchBox"" onkeydown=""javascript:var keycode; if(window.event) keycode = event.keyCode; else keycode = event.which; if(keycode == 10 || keycode == 13) { document.location = 'Search.aspx?Query=' + encodeURI(document.getElementById('TxtSearchBox').value); return false; }"" /></nowiki>");
							break;
						case "PAGECOUNT":
							sb.Insert(match.Index, Pages.Instance.AllPages.Count.ToString());
							break;
						case "CLOUD":
							sb.Insert(match.Index, BuildCloud());
							break;
					}
				}
				ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
				match = specialTag.Match(sb.ToString(), end);
			}

			match = list.Match(sb.ToString());
			while(match.Success) {
				if(!IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end)) {
					sb.Remove(match.Index, match.Length);
					int d = 0;
					try {
						sb.Insert(match.Index, GenerateList(match.Value.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries), 0, 0, ref d) + "\n");
					}
					catch {
						sb.Insert(match.Index, @"<b style=""color: #FF0000;"">FORMATTER ERROR (Malformed List)</b>");
					}
				}
				ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
				match = list.Match(sb.ToString(), end);
			}

			match = hr.Match(sb.ToString());
			while(match.Success) {
				if(!IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end)) {
					sb.Remove(match.Index, match.Length);
					sb.Insert(match.Index, @"<h1 style=""border-bottom: solid 1px #999999;""> </h1>" + "\n");
				}
				ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
				match = hr.Match(sb.ToString(), end);
			}

			// Replace \n with BR was here

			ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);

			// Transclusion (intra-Wiki)
			match = transclusion.Match(sb.ToString());
			while(match.Success) {
				if(!IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end)) {
					sb.Remove(match.Index, match.Length);
					PageInfo info = Pages.Instance.FindPage(match.Value.Substring(3, match.Value.Length - 4));
					if(info != null && info != current) { // Avoid circular transclusion!
						dummy = new StringBuilder();
						dummy.Append(@"<div class=""transcludedpage"">");
						// The current PageInfo is null to disable section editing and similar features
						dummy.Append(FormattingPipeline.FormatWithPhase1And2(Content.GetPageContent(info, true).Content, null));
						dummy.Append("</div>");
						sb.Insert(match.Index, dummy.ToString());
					}
				}
				ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
				match = transclusion.Match(sb.ToString(), end);
			}

			List<string> attachments = new List<string>();

			// Links and images
			match = link.Match(sb.ToString());
			while(match.Success) {
				if(IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end)) {
					match = link.Match(sb.ToString(), end);
					continue;
				}
				if(match.Value.Equals("[]") || match.Value.Equals("[[]]")) continue; // Prevents formatting emtpy links
				done = false;
				if(match.Value.StartsWith("[[")) tmp = match.Value.Substring(2, match.Length - 4).Trim();
				else tmp = match.Value.Substring(1, match.Length - 2).Trim();
				sb.Remove(match.Index, match.Length);
				a = "";
				n = "";
				if(tmp.IndexOf("|") != -1) {
					// There are some fields
					string[] fields = tmp.Split('|');
					if(fields.Length == 2) {
						// Link with title
						a = fields[0];
						n = fields[1];
					}
					else {
						StringBuilder img = new StringBuilder();
						// Image
						if(fields[0].ToLower().Equals("imageleft") || fields[0].ToLower().Equals("imageright") || fields[0].ToLower().Equals("imageauto")) {
							string c = "";
							switch(fields[0].ToLower()) {
								case "imageleft":
									c = "imageleft";
									break;
								case "imageright":
									c = "imageright";
									break;
								case "imageauto":
									c = "imageauto";
									break;
								default:
									c = "image";
									break;
							}
							title = fields[1];
							url = fields[2];
							if(fields.Length == 4) bigUrl = fields[3];
							else bigUrl = "";
							url = EscapeUrl(url);
							bigUrl = EscapeUrl(bigUrl);
							if(c.Equals("imageauto")) {
								img.Append(@"<table class=""imageauto"" cellpadding=""0"" cellspacing=""0"" align=""center""><tr><td>");
							}
							else {
								img.Append(@"<div class=""");
								img.Append(c);
								img.Append(@""">");
							}
							if(bigUrl.Length > 0) {
								dummy = new StringBuilder();
								dummy.Append(@"<img class=""image"" src=""");
								dummy.Append(url);
								dummy.Append(@""" alt=""");
								dummy.Append(Exchanger.ResourceExchanger.GetResource("Image"));
								dummy.Append(@""" />");
								img.Append(BuildLink(bigUrl, dummy.ToString(), true, lp));
							}
							else {
								img.Append(@"<img class=""image"" src=""");
								img.Append(url);
								img.Append(@""" alt=""");
								img.Append(Exchanger.ResourceExchanger.GetResource("Image"));
								img.Append(@""" />");
							}
							if(title.Length > 0) {
								img.Append(@"<p class=""imagedescription"">");
								img.Append(title);
								img.Append("</p>");
							}
							if(c.Equals("imageauto")) {
								img.Append("</td></tr></table>");
							}
							else {
								img.Append("</div>");
							}
							sb.Insert(match.Index, img);
						}
						else if(fields[0].ToLower().Equals("image")) {
							title = fields[1];
							url = fields[2];
							if(fields.Length == 4) bigUrl = fields[3];
							else bigUrl = "";
							url = EscapeUrl(url);
							bigUrl = EscapeUrl(bigUrl);
							if(bigUrl.Length > 0) {
								dummy = new StringBuilder();
								dummy.Append(@"<img src=""");
								dummy.Append(url);
								dummy.Append(@""" alt=""");
								dummy.Append(Exchanger.ResourceExchanger.GetResource("Image"));
								dummy.Append(@""" />");
								img.Append(BuildLink(bigUrl, dummy.ToString(), true, lp));
							}
							else {
								img.Append(@"<img src=""");
								img.Append(url);
								img.Append(@""" alt=""");
								img.Append(Exchanger.ResourceExchanger.GetResource("Image"));
								img.Append(@""" />");
							}
							sb.Insert(match.Index, img.ToString());
						}
						else {
							sb.Insert(match.Index, @"<b style=""color: #FF0000;"">FORMATTER ERROR (Malformed Image Tag)</b>");
						}
						done = true;
					}
				}
				else if(tmp.ToLower().StartsWith("attachment:")) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -