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; } } }