using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
namespace ScrewTurn.Wiki.ImportWiki {
///
/// Implements a translator tool for importing FlexWiki data.
///
public class TranslatorFlex : ScrewTurn.Wiki.ImportWiki.ITranslator {
private Regex noWiki = new Regex(@"\(.|\s)+?\<\/nowiki\>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private Regex noFlex = new Regex(@"\(.|\s)+?\<\/noflex\>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
///
/// Executes the translation.
///
/// The input content.
/// The WikiMarkup.
public string Translate(string input) {
StringBuilder sb = new StringBuilder();
sb.Append(input);
List noWikiBegin = new List(), noWikiEnd = new List(), noFlexBegin = new List(), noFlexEnd = new List();
Match match;
Regex doubleDoubleBrackets = new Regex(@"\""{2}.+?\""{2}");
Regex italic = new Regex(@"_.+?_");
Regex bold = new Regex(@"\*.+?\*");
Regex underline = new Regex(@"\+.+?\+");
Regex strikethrough = new Regex(@"\-.*?\-");
Regex head = new Regex(@"^!{1,6}.+", RegexOptions.Multiline);
Regex wikiTalk = new Regex(@"@@.+?@@");
Regex code = new Regex(@"@.+?@");
Regex pascalCase = new Regex(@"(\""[^""]+?\""\:)?([A-Z][a-z]+){2,}(\.([A-Z][a-z]+){2,})?");
Regex camelCase = new Regex(@"(\""[^""]+?\""\:)?(([A-Z][a-z]+){2,}\.)?\[.+?\]");
Regex exlink = new Regex(@"(\""[^""]+?\""\:)?(?\w+):\/\/(?[\w.]+\/?)\S*");
Regex email = new Regex(@"(\""[^""]+?\""\:)?mailto\:.+");
Regex lists = new Regex(@"^(\t|\s{8})+(\*|(1\.))", RegexOptions.Multiline);
Regex table = new Regex(@"^\|{2}", RegexOptions.Multiline);
Regex newlinespace = new Regex(@"^\ .+", RegexOptions.Multiline);
sb.Replace("\r", "");
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = doubleDoubleBrackets.Match(sb.ToString());
while(match.Success) {
int end;
if(IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end))
match = doubleDoubleBrackets.Match(sb.ToString(), end);
else {
string s = "" + match.Value.Substring(2, match.Length - 4) + "";
sb.Remove(match.Index, match.Length);
sb.Insert(match.Index, s);
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = doubleDoubleBrackets.Match(sb.ToString(), match.Index + s.Length);
}
}
match = exlink.Match(sb.ToString());
while(match.Success) {
int end;
if(IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end))
match = exlink.Match(sb.ToString(), end);
else {
string s;
string[] split = match.Value.Split(new char[] { '"' });
if(split.Length == 1) {
if(match.Value.EndsWith(".jpeg", StringComparison.CurrentCultureIgnoreCase) | match.Value.EndsWith(".gif", StringComparison.CurrentCultureIgnoreCase) | match.Value.EndsWith(".jpg", StringComparison.CurrentCultureIgnoreCase)) {
string imgName = match.Value.Substring(match.Value.LastIndexOf('/') + 1, match.Length - match.Value.LastIndexOf('/') - 1);
s = "[image|" + imgName + "|{UP}" + imgName + "]";
}
else s = "[" + match.Value + "]";
}
else {
if(split[1].EndsWith(".jpeg", StringComparison.CurrentCultureIgnoreCase) | split[1].EndsWith(".gif", StringComparison.CurrentCultureIgnoreCase) | split[1].EndsWith(".jpg", StringComparison.CurrentCultureIgnoreCase)) {
string imgName = split[1].Substring(split[1].LastIndexOf('/') + 1, split[1].Length - split[1].LastIndexOf('/') - 1);
s = "[image|" + imgName + "|{UP}" + imgName + "|" + split[2].Substring(1, split[2].Length - 1) + "]";
}
else s = "[" + split[2].Substring(1, split[2].Length - 1) + "|" + split[1] + "]";
}
sb.Remove(match.Index, match.Length);
sb.Insert(match.Index, s);
ComputeNoFlex(sb.ToString(), ref noFlexBegin, ref noFlexEnd);
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = exlink.Match(sb.ToString(), match.Index + s.Length);
}
}
match = email.Match(sb.ToString());
while(match.Success) {
int end;
if(IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end))
match = email.Match(sb.ToString(), end);
else {
string mailLink = "";
if(match.Value.StartsWith("mailto:")) mailLink = "[" + match.Value.Replace("mailto:", "") + "]";
else mailLink = "[" + match.Value.Split(new char[] { ':' }, 2)[1].Replace("mailto:", "") + "|" + match.Value.Split(new char[] { ':' }, 2)[0].Substring(1, match.Value.Split(new char[] { ':' }, 2)[0].Length - 2) + "]";
sb.Remove(match.Index, match.Length);
sb.Insert(match.Index, mailLink);
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = email.Match(sb.ToString(), match.Index + mailLink.Length);
}
}
match = bold.Match(sb.ToString());
while(match.Success) {
int end;
if(IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end))
match = bold.Match(sb.ToString(), end);
else {
sb.Remove(match.Index, match.Length);
sb.Insert(match.Index, "'''" + match.Value.Substring(1, match.Length - 2) + @"'''");
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = bold.Match(sb.ToString());
}
}
match = underline.Match(sb.ToString());
while(match.Success) {
int end;
if(IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end))
match = underline.Match(sb.ToString(), end);
else {
sb.Remove(match.Index, match.Length);
sb.Insert(match.Index, "__" + match.Value.Substring(1, match.Length - 2) + @"__");
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = underline.Match(sb.ToString());
}
}
match = strikethrough.Match(sb.ToString());
while(match.Success) {
int end;
if(IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end))
match = strikethrough.Match(sb.ToString(), end);
else {
string s = "";
if(match.Value == "---") s = "---";
else if(match.Value == "--") s = "-";
else s = "--" + match.Value.Substring(1, match.Length - 2) + @"--";
sb.Remove(match.Index, match.Length);
sb.Insert(match.Index, s);
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = strikethrough.Match(sb.ToString(), match.Index + s.Length);
}
}
match = head.Match(sb.ToString());
while(match.Success) {
int end;
if(IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end))
match = head.Match(sb.ToString(), end);
else {
//Count the number of ! in order to put a corresponding
//number of =
int count = 1;
for(int i = 0; i < match.Length; i++) {
if(match.Value[i] == '!')
count++;
}
if(match.Value.EndsWith("!")) count--;
string s = "";
for(int i = 0; i < count; i++)
s += "=";
s += match.Value.Substring(count - 1, match.Length - (count - 1) - 1);
for(int i = 0; i < count; i++)
s += "=";
sb.Remove(match.Index, match.Length);
sb.Insert(match.Index, s);
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = head.Match(sb.ToString());
}
}
match = wikiTalk.Match(sb.ToString());
while(match.Success) {
int end;
if(IsNoWikied(match.Index, noFlexBegin, noFlexEnd, out end))
match = wikiTalk.Match(sb.ToString(), end);
else {
string s = @"" + match.Value + @"";
sb.Remove(match.Index, match.Length);
sb.Insert(match.Index, s);
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = wikiTalk.Match(sb.ToString(), match.Index + s.Length);
}
}
match = code.Match(sb.ToString());
while(match.Success) {
int end;
if(IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end))
match = code.Match(sb.ToString(), end);
else {
string s = "{{" + match.Value.Substring(1, match.Length - 2) + @"}}";
sb.Remove(match.Index, match.Length);
sb.Insert(match.Index, s);
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = code.Match(sb.ToString());
}
}
match = camelCase.Match(sb.ToString());
while(match.Success) {
int end;
if(IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end))
match = camelCase.Match(sb.ToString(), end);
else {
string s;
string[] split = match.Value.Split(new char[] { ':' }, 2);
if(split.Length == 1) {
string[] split1 = match.Value.Split(new char[] { '.' }, 2);
if(split1.Length == 1) s = match.Value;
else s = split1[1];
}
else {
string[] split1 = split[1].Split(new char[] { '.' }, 2);
if(split1.Length == 1) s = "[" + split[1].Substring(1, split[1].Length - 2) + "|" + split[0].Substring(1, split[0].Length - 2) + "]";
else s = "[" + split1[1].Substring(0, split1[1].Length - 1) + "|" + split[0].Substring(1, split[0].Length - 2) + "]";
}
sb.Remove(match.Index, match.Length);
sb.Insert(match.Index, s);
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = camelCase.Match(sb.ToString(), match.Index + s.Length);
}
}
match = pascalCase.Match(sb.ToString());
while(match.Success) {
int end;
if(IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end))
match = pascalCase.Match(sb.ToString(), end);
else {
string s;
string[] split = match.Value.Split(new char[] { ':' }, 2);
if(split.Length == 1) {
string[] split1 = match.Value.Split(new char[] { '.' }, 2);
if(split1.Length == 1) s = "[" + match.Value + "]";
else s = "[" + split1[1] + "]";
}
else {
string[] split1 = split[1].Split(new char[] { '.' });
if(split1.Length == 1) s = "[" + split[1] + "|" + split[0].Substring(1, split[0].Length - 2) + "]";
else s = "[" + split1[1] + "|" + split[0].Substring(1, split[0].Length - 2) + "]";
}
sb.Remove(match.Index, match.Length);
sb.Insert(match.Index, s);
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = pascalCase.Match(sb.ToString(), match.Index + s.Length);
}
}
match = lists.Match(sb.ToString());
while(match.Success) {
int end;
if(IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end))
match = lists.Match(sb.ToString(), end);
else {
string s = "";
char kindOfList;
int i = 0;
char[] ca = match.Value.ToCharArray();
while(ca[i] == ' ')
i++;
if(i > 0) {
kindOfList = ca[i];
i = i / 8;
}
else {
while(ca[i] == '\t')
i++;
kindOfList = ca[i];
}
for(int k = 1; k <= i; k++) {
if(kindOfList == '*') s += "*";
if(kindOfList == '1') s += "#";
}
sb.Remove(match.Index, match.Length);
sb.Insert(match.Index, s);
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = lists.Match(sb.ToString(), match.Index + s.Length);
}
}
bool tableBegin = true;
match = table.Match(sb.ToString());
while(match.Success) {
int end;
if(IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end))
match = table.Match(sb.ToString(), end);
else {
string s = "";
int indexEndOfLine = sb.ToString().IndexOf("\r\n", match.Index);
if(indexEndOfLine < 0) indexEndOfLine = sb.Length;
string[] split = sb.ToString().Substring(match.Index + 2, indexEndOfLine - match.Index - 4).Split(new string[] { "||" }, StringSplitOptions.None);
if(tableBegin) s = "{|\r\n| " + split[0];
else s = "|-\r\n| " + split[0];
for(int i = 1; i < split.Length; i++)
s += " || " + split[i];
if(indexEndOfLine != sb.Length) {
if(sb.ToString().Substring(indexEndOfLine + 2, 2) == "||") tableBegin = false;
else {
tableBegin = true;
s += "\r\n|}";
}
}
else {
tableBegin = true;
s += "\r\n|}";
}
sb.Remove(match.Index, indexEndOfLine - match.Index);
sb.Insert(match.Index, s);
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = table.Match(sb.ToString(), match.Index + s.Length);
}
}
match = italic.Match(sb.ToString());
while(match.Success) {
int end;
if(IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end))
match = italic.Match(sb.ToString(), end);
else {
if(IsNoFlexed(match.Index, noFlexBegin, noFlexEnd, out end))
match = italic.Match(sb.ToString(), end);
else {
sb.Remove(match.Index, match.Length);
sb.Insert(match.Index, "''" + match.Value.Substring(1, match.Length - 2) + @"''");
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
match = italic.Match(sb.ToString());
}
}
}
bool first = true;
match = newlinespace.Match(sb.ToString());
while(match.Success) {
int end;
if(IsNoWikied(match.Index, noWikiBegin, noWikiEnd, out end))
match = newlinespace.Match(sb.ToString(), end);
else {
string s = "";
if(first)
s += "{{{{" + match.Value.Substring(1, match.Value.Length - 1);
else
s += match.Value.Substring(1, match.Value.Length - 1);
if(sb.Length > match.Index + match.Length + 1) {
if(sb[match.Index + match.Length] == '\n' && sb[match.Index + match.Length + 1] == ' ') {
first = false;
}
else {
s += "}}}}";
first = true;
}
}
sb.Remove(match.Index, match.Length);
sb.Insert(match.Index, s);
match = newlinespace.Match(sb.ToString(), match.Index + s.Length);
ComputeNoWiki(sb.ToString(), ref noWikiBegin, ref noWikiEnd);
}
}
return sb.ToString().Replace("", "").Replace("", "");
}
private void ComputeNoWiki(string text, ref List noWikiBegin, ref List noWikiEnd) {
Match match;
noWikiBegin.Clear();
noWikiEnd.Clear();
match = noWiki.Match(text);
while(match.Success) {
noWikiBegin.Add(match.Index);
noWikiEnd.Add(match.Index + match.Length - 1);
match = noWiki.Match(text, match.Index + match.Length);
}
}
private bool IsNoWikied(int index, List noWikiBegin, List noWikiEnd, out int end) {
for(int i = 0; i < noWikiBegin.Count; i++) {
if(index >= noWikiBegin[i] && index <= noWikiEnd[i]) {
end = noWikiEnd[i];
return true;
}
}
end = 0;
return false;
}
private void ComputeNoFlex(string text, ref List noFlexBegin, ref List noFlexEnd) {
Match match;
noFlexBegin.Clear();
noFlexEnd.Clear();
match = noFlex.Match(text);
while(match.Success) {
noFlexBegin.Add(match.Index);
noFlexEnd.Add(match.Index + match.Length - 1);
match = noFlex.Match(text, match.Index + match.Length);
}
}
private bool IsNoFlexed(int index, List noFlexBegin, List noFlexEnd, out int end) {
for(int i = 0; i < noFlexBegin.Count; i++) {
if(index >= noFlexBegin[i] && index <= noFlexEnd[i]) {
end = noFlexEnd[i];
return true;
}
}
end = 0;
return false;
}
}
}