public void MWToDWContent(Site site, PageBE page, bool isOld) { try { // check for template content overrides if (OverrideTemplate(site, page)) { return; } Plug converterUri = MediaWikiConverterContext.Current.MWConverterUri; if (null != converterUri) { string interwikiInfo = String.Empty; if (null != _MWInterwikiBySite) { _MWInterwikiBySite.TryGetValue(site, out interwikiInfo); } XDoc xml = converterUri.With("title", page.Title.AsPrefixedDbPath()).With("lang", site.Language).With("site", site.Name).With("interwiki", interwikiInfo).With("text", page.GetText(DbUtils.CurrentSession)).PostAsForm().ToDocument(); xml.UsePrefix("mediawiki", "#mediawiki"); // if this is a redirect, set the page text accordingly] if (page.IsRedirect) { ParserResult result = DekiXmlParser.Parse(page, ParserMode.SAVE, -1, false); if (result.RedirectsToTitle != null) { page.SetText(String.Format(REDIRECT_TEXT, MWToDWTitle(site, Title.FromUIUri(null, xml["//mediawiki:link/@href"].Contents, true)).AsPrefixedDbPath().Replace("&", "&"))); } else { page.SetText(String.Format(REDIRECT_TEXT, xml["//mediawiki:link/@href"].Contents.Replace("&", "&"), true)); } page.ContentType = DekiMimeType.DEKI_XML0805; return; } // remove extra paragraph tags from templates if (page.Title.IsTemplate) { List<XDoc> topLevelParagraphs = xml["/html/body/p"].ToList(); if (1 == topLevelParagraphs.Count) { topLevelParagraphs[0].ReplaceWithNodes(topLevelParagraphs[0]); } } // Map MediaWiki titles to MindTouch MWToDWTitles(site, page, isOld, xml); // Convert from MediaWiki output to MindTouch WikiTextProcessor.Convert(site, xml, page.Title.IsTemplate); // If the page is available in other languages, insert wiki.languages List<XDoc> languageList = xml["//mediawiki:meta[@type='language']"].ToList(); if (0 < languageList.Count) { StringBuilder languageData = new StringBuilder("{{ wiki.languages( { "); for (int i = 0; i < languageList.Count; i++) { if (0 < i) { languageData.Append(", "); } string relatedLanguage = languageList[i]["@language"].AsText; Title relatedTitle = Title.FromUIUri(null, languageList[i].Contents, false); Site relatedSite = MediaWikiConverterContext.Current.GetMWSite(relatedLanguage); languageData.AppendFormat("{0}: {1}", StringUtil.QuoteString(relatedLanguage), StringUtil.QuoteString(MWToDWTitle(relatedSite, relatedTitle).AsPrefixedDbPath())); languageList[i].Remove(); } languageData.Append(" } ) }}"); xml["//body"].Value(languageData.ToString()); } string contents = xml.ToString(); int first = contents.IndexOf("<body>"); int last = contents.LastIndexOf("</body>"); if ((first >= 0) && (last >= 0)) { page.SetText(contents.Substring(first + 6, last - (first + 6))); page.ContentType = DekiMimeType.DEKI_TEXT; } } } catch (Exception e) { Console.Out.WriteLine("An unexpected exception has occurred:"); Console.Out.WriteLine(e.GetCoroutineStackTrace()); Console.Out.WriteLine("MediaWiki page text that produced the exception:"); Console.Out.WriteLine(page.GetText(DbUtils.CurrentSession)); } }
public Title DWMediaGalleryTitle(Site site) { return MWToDWTitle(site, Title.FromDbPath(NS.MAIN, "Media_Gallery", null)); }
public bool OverrideTemplate(Site site, PageBE page) { if (page.Title.IsTemplate && !String.IsNullOrEmpty(MediaWikiConverterContext.Current.MWTemplatePath)) { string templateFilename = GetTemplateFilename(page.Title); string templateOriginal = Path.Combine(OriginalTemplateDir, site.Language + "-" + templateFilename); // check the template against its base version to see if it's changed if (!File.Exists(templateOriginal)) { #region logging if (MediaWikiConverterContext.Current.LoggingEnabled) { log["/html/body/table[@id='outdatedtemplates']"].Add(new XDoc("tr").Elem("td", MWToDWTitle(site, page.Title).AsPrefixedDbPath())); } #endregion File.WriteAllLines(templateOriginal, new string[] { page.TimeStamp.ToString() }); File.AppendAllText(templateOriginal, page.GetText(DbUtils.CurrentSession)); } else { DateTime baseTimestamp = DateTime.MinValue; string[] lines = File.ReadAllLines(templateOriginal); if (0 < lines.Length) { DateTime.TryParse(lines[0], out baseTimestamp); } if (DateTime.MinValue == baseTimestamp || baseTimestamp < page.TimeStamp) { #region logging if (MediaWikiConverterContext.Current.LoggingEnabled) { log["/html/body/table[@id='outdatedtemplates']"].Add(new XDoc("tr").Elem("td", MWToDWTitle(site, page.Title).AsPrefixedDbPath())); } #endregion File.WriteAllLines(templateOriginal, new string[] { page.TimeStamp.ToString() }); File.AppendAllText(templateOriginal, page.GetText(DbUtils.CurrentSession)); } } // check if the template's content has been overriden string templateOverride = Path.Combine(OverrideTemplateDir, templateFilename); if (File.Exists(templateOverride)) { page.SetText(File.ReadAllText(templateOverride)); page.ContentType = DekiMimeType.DEKI_TEXT; ParserResult parserResult = DekiXmlParser.Parse(page, ParserMode.SAVE, -1, false); page.IsRedirect = (null != parserResult.RedirectsToTitle) || (null != parserResult.RedirectsToUri); return true; } } return false; }
/// <summary> /// Converts a MediaWiki title to its MindTouch format /// </summary> /// <param name="mwTitle">The title to convert</param> /// <param name="replaceSeparator">If true, replace ":" with "/"</param> /// <returns>The converted title</returns> public Title MWToDWTitle(Site site, Title mwTitle, bool useNewFormat) { string dbPrefix = null; string dbPath = mwTitle.AsUnprefixedDbPath(); string displayName = mwTitle.DisplayName; // create a language heirarchy in the main namespaces if (CreateLanguageHierarchyForNS(mwTitle.Namespace)) { dbPrefix = site.DWRootPage + "/"; if (site.MWRootPage == mwTitle.Path && useNewFormat) { displayName = displayName ?? mwTitle.AsUserFriendlyName(); dbPath = String.Empty; } } // prefix template pages with language to make unique accross langauges else if (mwTitle.IsTemplate || NS.TEMPLATE_TALK == mwTitle.Namespace || mwTitle.IsSpecial) { return mwTitle; } // if this is a user page that corresponds to a renamed user, rename the page. else if (mwTitle.IsUser || NS.USER_TALK == mwTitle.Namespace) { string parentSegment = mwTitle.AsUnprefixedDbSegments()[0]; string newParentSegment; if (_MWToDWUserNameMap.TryGetValue(parentSegment, out newParentSegment)) { dbPath = newParentSegment + mwTitle.Path.Substring(newParentSegment.Length - 1); } } if ('/' != MediaWikiConverterContext.Current.MWPageSeparator) { dbPath = dbPath.Replace("/", "//"); // If desired, replace the page separator with "/" if (useNewFormat && 0 < MediaWikiConverterContext.Current.MWPageSeparator) { String[] segments = dbPath.Split(MediaWikiConverterContext.Current.MWPageSeparator); if (1 < segments.Length) { StringBuilder result = new StringBuilder(); for (int i = 0; i < segments.Length; i++) { if ((0 < i && !String.IsNullOrEmpty(segments[i - 1])) && !(i == segments.Length - 1 && String.IsNullOrEmpty(segments[i]))) { result.Append("/"); } if (String.IsNullOrEmpty(segments[i])) { result.Append(MediaWikiConverterContext.Current.MWPageSeparator); } else { result.Append(segments[i].Trim(new char[] { '_' })); } } dbPath = result.ToString(); } } } dbPath = dbPrefix + dbPath; return Title.FromDbPath(mwTitle.Namespace, dbPath.Trim('/'), displayName, mwTitle.Filename, mwTitle.Anchor, mwTitle.Query); }
public void MWToDWTitles(Site site, PageBE page, bool isOld, XDoc xml) { // set the display name to the title-override value page.Title.DisplayName = xml["//mediawiki:extension[@function='title-override']"].AsText; // map each page include to its new MindTouch location foreach (XDoc template in xml["//mediawiki:template"].ToList()) { XDoc templateName = template["mediawiki:name"]; if (0 == templateName.Elements.ListLength) { string pagePath = template["mediawiki:name"].Contents.Trim(); if (pagePath.StartsWith(":")) { Title mwTitle = Title.FromUIUri(null, pagePath.Substring(1), false); templateName.ReplaceValue(":" + MWToDWTitle(site, mwTitle).AsPrefixedDbPath()); } else { Title mwTitle = null; mwTitle = Title.FromUIUri(null, pagePath, false); mwTitle.Namespace = NS.TEMPLATE; templateName.ReplaceValue(MWToDWTitle(site, mwTitle).AsUnprefixedDbPath()); } } #region logging if (MediaWikiConverterContext.Current.LoggingEnabled) { // log all template references StringBuilder templateString = new StringBuilder(); templateString.Append(template["mediawiki:name"].AsText); templateString.Append('('); bool isFirstArg = true; foreach (XDoc templateArg in template["mediawiki:arg"]) { if (!isFirstArg) { templateString.Append(", "); } else { isFirstArg = false; } templateString.Append(templateArg.Contents); } templateString.Append(")"); log["/html/body/table[@id='templates']"].Add(new XDoc("tr").Elem("td", (isOld ? String.Format("Revision ({0}): ", page.TimeStamp) : String.Empty) + MWToDWTitle(site, page.Title).AsPrefixedDbPath()).Elem("td", templateString.ToString())); } #endregion } foreach (XDoc function in xml["//mediawiki:function"].ToList()) { #region logging if (MediaWikiConverterContext.Current.LoggingEnabled) { // log all function references if (!page.Title.IsTemplate) { string functionString = String.Format("{0}({1})", function["@name"].AsText, function["@arg"].Contents); log["/html/body/table[@id='functions']"].Add(new XDoc("tr").Elem("td", (isOld ? String.Format("Revision ({0}): ", page.TimeStamp) : String.Empty) + MWToDWTitle(site, page.Title).AsPrefixedDbPath()).Elem("td", functionString)); } } #endregion } // map links to pages on the wiki in a different language to internal links foreach (XDoc link in xml["//mediawiki:link[@type='external']"].ToList()) { string href = link["@href"].Contents; XUri xuri; if (XUri.TryParse(href, out xuri)) { if ("lang" == xuri.Scheme.ToLowerInvariant()) { link.Attr("type", "internal"); } } } // map file links to image links foreach (XDoc link in xml["//mediawiki:link[@type='file']"].ToList()) { link.Attr("ns", 6); link.Attr("type", "internal"); link.Attr("href", "Image:" + link["@href"].Contents); } // map each internal link to its new MindTouch location foreach (XDoc link in xml["//mediawiki:link[@type='internal']"].ToList()) { Site linkSite = site; // if this is a link to a page on the wiki in a different language, map it accordingly XUri xuri; if (XUri.TryParse(link["@href"].Contents, out xuri)) { if ("lang" == xuri.Scheme.ToLowerInvariant()) { linkSite = MediaWikiConverterContext.Current.GetMWSite(xuri.Authority); link.Attr("href", xuri.PathQueryFragment); } } Title dwTitle = Title.FromUIUri(page.Title, link["@href"].Contents); switch (link["@ns"].AsInt) { case -1: dwTitle = Title.FromUIUri(page.Title, XUri.Decode(link["@href"].Contents)); dwTitle = MWToDWTitle(linkSite, dwTitle); #region logging PageBE specialPage = PageBL.GetPageByTitle(dwTitle); if ((specialPage == null || specialPage.ID == 0) && !StringUtil.StartsWithInvariantIgnoreCase(dwTitle.Path, "Contributions/")) { if (MediaWikiConverterContext.Current.LoggingEnabled) { log["/html/body/table[@id='specialpages']"].Add(new XDoc("tr").Elem("td", MWToDWTitle(site, page.Title).AsPrefixedDbPath()).Elem("td", dwTitle.AsPrefixedDbPath())); } } #endregion break; // media links are remapped to the a link to the image on the media gallery case 6: case 7: string filename = dwTitle.Path.Substring(6); dwTitle = DWMediaGalleryTitle(linkSite); dwTitle.Filename = filename; break; // category links are remapped to Special:Tags case 14: case 15: if (string.IsNullOrEmpty(link.Contents)) { link.ReplaceValue(dwTitle.AsUserFriendlyName()); } dwTitle = Title.FromDbPath(NS.SPECIAL, "Tags", null, null, null, String.Format("tag={0}&language={1}", dwTitle.Path.Substring(9), linkSite.Language)); break; default: dwTitle = MWToDWTitle(linkSite, dwTitle); break; }; if (string.IsNullOrEmpty(link.Contents)) { link.ReplaceValue(link["@href"].Contents); } if (!link["@href"].Contents.StartsWith("#")) { link.Attr("href", dwTitle.AsUiUriPath()); } } // map each internal image to its new MindTouch location foreach (XDoc image in xml["//mediawiki:image[@type='internal']"].ToList()) { Title mediaGalleryTitle = DWMediaGalleryTitle(site); mediaGalleryTitle.Filename = image["@href"].Contents; image.Attr("href", mediaGalleryTitle.AsUiUriPath()); } }
private static void Convert(Site site, XDoc doc, bool isTemplate, XmlNode node, ContextState state, XmlNamespaceManager ns) { List<XmlNode> list = new List<XmlNode>(); foreach(XmlNode child in node.ChildNodes) { list.Add(child); } ContextState original = state; bool firstChild = true; foreach(XmlNode child in list) { // only first arguments can be expressions if(original == ContextState.FirstExpressionThenArgument) { if(!firstChild) { state = ContextState.Argument; } else { state = ContextState.Expression; } } firstChild = false; // determine what kinf of child element this is XDoc current = doc[child]; if((child.NodeType == XmlNodeType.Element) && (child.NamespaceURI == "#mediawiki")) { switch(child.LocalName) { case "internal": { // check if this element contains elements that would prevent it from being an internal link if(current.AtPath(".//m:link | .//m:internal | .//m:external", ns).IsEmpty) { Convert(site, doc, isTemplate, child, ContextState.Argument, ns); StringBuilder code = new StringBuilder(); code.Append("mediawiki.internal").Append("("); code.Append(AsArgument(child)); if(!string.IsNullOrEmpty(site.Language)) { code.Append(", ").Append(DekiScriptString.QuoteString(site.Language)); } code.Append(")"); current.Replace(Scripted(code.ToString(), state, true)); } else { Convert(site, doc, isTemplate, child, state, ns); if(state == ContextState.Argument) { current.AddBefore("'[['"); current.AddAfter("']]'"); } else { current.AddBefore("[["); current.AddAfter("]]"); } current.ReplaceWithNodes(current); } } break; case "external": { // check if this element contains elements that would prevent it from being an external link if(current.AtPath(".//m:link | .//m:internal | .//m:external", ns).IsEmpty) { Convert(site, doc, isTemplate, child, ContextState.Argument, ns); StringBuilder code = new StringBuilder(); code.Append("mediawiki.external").Append("("); code.Append(AsArgument(child)); code.Append(")"); current.Replace(Scripted(code.ToString(), state, true)); } else { Convert(site, doc, isTemplate, child, state, ns); if(state == ContextState.Argument) { current.AddBefore("'['"); current.AddAfter("']'"); } else { current.AddBefore("["); current.AddAfter("]"); } current.ReplaceWithNodes(current); } } break; case "link": Convert(site, doc, isTemplate, child, state, ns); switch(current["@type"].AsText) { case "internal": current.Replace(new XDoc("a").Attr("href", current["@href"].AsText).AddNodes(current)); break; case "external": current.Replace(new XDoc("a").Attr("class", "external").Attr("href", current["@href"].AsText).AddNodes(current)); break; case "external-free": if(state == ContextState.None) { current.Replace(current["@href"].AsText); } else { current.Replace(QuoteString(current["@href"].AsText)); } break; case "external-ref": current.Replace(new XDoc("a").Attr("class", "external").Attr("href", current["@href"].AsText)); break; default: // no idea what this link is, let's replace with a text version of itself current.Replace(child.OuterXml); break; } break; case "image": current.Replace(new XDoc("img").Attr("src", current["@href"].AsText).Attr("alt", current["@alt"].AsText).Attr("align", current["@align"].AsText)); break; case "comment": Convert(site, doc, isTemplate, child, state, ns); current.Replace(new XDoc("span").Attr("class", "comment").AddNodes(current)); break; case "nowiki": current.Replace(new XDoc("span").Attr("class", "plain").AddNodes(current)); break; case "extension": // TODO: should the behavior be different depending on 'state'? Convert(site, doc, isTemplate, child, state, ns); if (!current["@value"].IsEmpty) { current.Replace("{{" + current["@value"].AsText + "}}"); } else { switch (current["@function"].AsText) { case "math": current.Replace(new XDoc("pre").Attr("class", "script").Attr("function", "math.formula").Value(current.AsText)); break; case "kbd": case "abbr": case "object": current.Rename(current["@function"].AsText.ToLowerInvariant()); current.RemoveAttr("function"); break; case "rss": { StringBuilder code = new StringBuilder(); string[] rssParams = current.Contents.Split('|'); code.Append("ajaxrss{"); code.AppendFormat(" feed: '{0}' ", rssParams[0]); for (int i = 1; i < rssParams.Length; i++) { string rssParam = rssParams[i].Trim(); int index = rssParam.IndexOf('='); if (index >= 0) { code.AppendFormat(", {0}: {1}", rssParam.Substring(0, index), QuoteString(rssParam.Substring(index + 1))); } else { code.AppendFormat(", {0}: true", rssParam); } } code.Append(" }"); current.Replace(new XDoc("span").Attr("class", "script").Value(code.ToString())); } break; case "title-override": case "breadcrumbs": current.Remove(); break; default: current.Replace(child.OuterXml); break; } } break; case "magic": { string code = null; switch(current["@name"].AsText) { case "CONTENTLANGUAGE": code = "site.language"; break; case "CURRENTDAY": code = "date.format(date.now, '%d')"; break; case "CURRENTDAY2": code = "date.format(date.now, 'dd')"; break; case "CURRENTDAYNAME": code = "date.dayname(date.now)"; break; case "CURRENTDOW": code = "date.dayofweek(date.now)"; break; case "CURRENTMONTH": code = "date.month(date.now)"; break; case "CURRENTMONTHABBREV": code = "date.format(date.now, 'MMM')"; break; case "CURRENTMONTHNAME": code = "date.monthname(date.now)"; break; case "CURRENTTIME": code = "date.time(date.now)"; break; case "CURRENTHOUR": code = "date.format(date.now, 'HH')"; break; case "CURRENTWEEK": code = "date.week(date.now)"; break; case "CURRENTYEAR": code = "date.year(date.now)"; break; case "CURRENTTIMESTAMP": code = "date.format(date.now, 'yyyyMMddHHmmss')"; break; case "PAGENAME": case "PAGENAMEE": code = "page.unprefixedpath"; break; case "NUMBEROFARTICLES": code = "site.pagecount"; break; case "NUMBEROFUSERS": code = "site.usercount"; break; case "NAMESPACE": code = "page.namespace"; break; case "REVISIONDAY": code = "date.format(page.date, '%d')"; break; case "REVISIONDAY2": code = "date.format(page.date, 'dd')"; break; case "REVISIONMONTH": code = "date.month(page.date)"; break; case "REVISIONYEAR": code = "date.year(page.date)"; break; case "REVISIONTIMESTAMP": code = "date.format(page.date, 'yyyyMMddHHmmss')"; break; case "SITENAME": code = "site.name"; break; case "SERVER": code = "site.uri"; break; case "SERVERNAME": code = "site.host"; break; default: // unrecognized magic word - use the mediawiki magicword extension code = String.Format("mediawiki.variable('{0}')", DekiScriptString.EscapeString(current["@name"].AsText)); break; } current.Replace(Scripted(code, state, true)); } break; case "interwiki": { string code = String.Format("mediawiki.interwiki('{0}', '{1}', '{2}')", DekiScriptString.EscapeString(child.Attributes["prefix"].Value), DekiScriptString.EscapeString(child.Attributes["path"].Value + (((XmlElement)child).HasAttribute("fragment") ? ("#" + child.Attributes["fragment"].Value) : string.Empty)), DekiScriptString.EscapeString(child.InnerText)); current.Replace(Scripted(code, state, true)); break; } case "function": { Convert(site, doc, isTemplate, child, ContextState.Argument, ns); StringBuilder code = new StringBuilder(); bool withLang = false; switch (current["@name"].AsText) { case "formatnum": { code.Append("num.format"); // add one more parameter XmlElement arg = child.OwnerDocument.CreateElement("arg", "#mediawiki"); arg.AppendChild(child.OwnerDocument.CreateTextNode(QuoteString("N"))); child.AppendChild(arg); } break; case "fullurl": code.Append("wiki.uri"); break; case "lc": code.Append("string.tolower"); break; case "lcfirst": code.Append("string.tolowerfirst"); break; case "padleft": code.Append("string.padleft"); break; case "padright": code.Append("string.padright"); break; case "uc": code.Append("string.toupper"); break; case "ucfirst": code.Append("string.toupperfirst"); break; case "urlencode": code.Append("web.uriencode"); break; case "int": code.Append("wiki.page"); break; case "localurl": case "localurle": withLang = true; code.Append(At("mediawiki", current["@name"].AsText)); break; default: code.Append(At("mediawiki", current["@name"].AsText)); break; } // append parameters code.Append("("); if (withLang) { code.Append(null == site.Language ? "_" : DekiScriptString.QuoteString(site.Language)); } bool first = true && !withLang; foreach(XDoc arg in current.AtPath("m:arg", ns)) { if(!first) { code.Append(", "); } first = false; code.Append(AsArgument(arg.AsXmlNode)); } code.Append(")"); current.Replace(Scripted(code.ToString(), state, true)); } break; case "expression": { StringBuilder code = new StringBuilder(); switch(current["@name"].AsText) { case "#expr": Convert(site, doc, isTemplate, child, ContextState.Expression, ns); code.Append(AsExpression(current.AtPath("m:arg", ns).AsXmlNode)); break; case "#if": { Convert(site, doc, isTemplate, child, ContextState.Argument, ns); code.Append("string.trim("); code.Append(AsArgument(current.AtPath("m:arg[1]", ns).AsXmlNode)); code.Append(") !== '' ? "); code.Append(WebHtml(current.AtPath("m:arg[2]", ns).AsXmlNode)); code.Append(" : "); code.Append(WebHtml(current.AtPath("m:arg[3]", ns).AsXmlNode)); } break; case "#ifeq": { Convert(site, doc, isTemplate, child, ContextState.Argument, ns); code.Append(AsArgument(current.AtPath("m:arg[1]", ns).AsXmlNode)); code.Append(" == "); code.Append(AsArgument(current.AtPath("m:arg[2]", ns).AsXmlNode)); code.Append(" ? "); code.Append(WebHtml(current.AtPath("m:arg[3]", ns).AsXmlNode)); code.Append(" : "); code.Append(WebHtml(current.AtPath("m:arg[4]", ns).AsXmlNode)); } break; case "#ifexpr": { Convert(site, doc, isTemplate, child, ContextState.FirstExpressionThenArgument, ns); code.Append(AsExpression(current.AtPath("m:arg[1]", ns).AsXmlNode)); code.Append(" ? "); code.Append(WebHtml(current.AtPath("m:arg[2]", ns).AsXmlNode)); code.Append(" : "); code.Append(WebHtml(current.AtPath("m:arg[3]", ns).AsXmlNode)); } break; case "#ifexist": { bool simple; Convert(site, doc, isTemplate, child, ContextState.Argument, ns); code.Append("wiki.pageexists("); string title = AsPathArgument(site, current.AtPath("m:arg[1]", ns), false, out simple); code.Append(simple ? ("'" + title + "'") : title); code.Append(") ? "); code.Append(WebHtml(current.AtPath("m:arg[2]", ns).AsXmlNode)); code.Append(" : "); code.Append(WebHtml(current.AtPath("m:arg[3]", ns).AsXmlNode)); } break; case "#switch": case "#time": case "#rel2abs": case "#titleparts": case "#iferror": // TODO (steveb): missing code, falling through to default case default: code.Append(At("mediawiki", current["@name"].AsText)); // append parameters code.Append("("); bool first = true; foreach(XDoc arg in current.AtPath("m:arg", ns)) { if(!first) { code.Append(", "); } first = false; code.Append(AsArgument(arg.AsXmlNode)); } code.Append(")"); break; } current.Replace(Scripted(code.ToString(), state, false)); } break; case "template": { Convert(site, doc, isTemplate, child, ContextState.Argument, ns); StringBuilder code = new StringBuilder(); // check if we need to decode the page name bool simpleTitle; bool simpleArgs; string title = AsPathArgument(site, current.AtPath("m:name", ns), true, out simpleTitle); XDoc args = current.AtPath("m:arg", ns); string argCode = AppendTemplateArguments(args, out simpleArgs); // append parameters if(simpleTitle && simpleArgs) { code.Append("template."); code.Append(title.Substring(1, title.Length - 2)); if(string.IsNullOrEmpty(argCode)) { code.Append("()"); } else if(argCode.StartsWith("[") && argCode.EndsWith("]")) { code.Append("(" + argCode.Substring(2, argCode.Length - 4) + ")"); } else { code.Append(argCode); } } else { code.Append("wiki.template").Append("("); code.Append(title); if(!string.IsNullOrEmpty(argCode)) { code.Append(", "); code.Append(argCode); } code.Append(")"); } current.Replace(Scripted(code.ToString(), state, true)); } break; case "arg": Convert(site, doc, isTemplate, child, state, ns); break; case "name": Convert(site, doc, isTemplate, child, state, ns); break; case "ref": { if(isTemplate || (state != ContextState.None)) { Convert(site, doc, isTemplate, child, state, ns); string code; int? index = current["@index"].AsInt; if(index != null) { code = "$" + (index.Value - 1); } else { code = "$" + current["@name"].AsText; } switch(state) { case ContextState.None: if(current["@alt"].IsEmpty) { current.Replace(Scripted("web.html(" + code + ")", state, true)); } else { current.Replace(Scripted("web.html(" + code + " ?? " + AsArgument(current.AsXmlNode) + ")", state, true)); } break; default: if(current["@alt"].IsEmpty) { current.Replace(Scripted(code, state, true)); } else { current.Replace(Scripted(code + " ?? " + AsArgument(current.AsXmlNode), state, false)); } break; } } else { string code = current["@index"].AsText ?? current["@name"].AsText; if(!current["@alt"].IsEmpty) { code += "|" + current["@alt"].AsText; } current.Replace(new XDoc("span").Attr("class", "plain").Value("{{{" + code + "}}}")); } } break; } } else if(child.NodeType == XmlNodeType.Element) { Convert(site, doc, isTemplate, child, state, ns); // loop over attribute nodes foreach(XDoc attribute in current.AtPath("@m:*", ns)) { XDoc code = XDocFactory.From("<code xmlns:mediawiki=\"#mediawiki\">" + attribute.Contents + "</code>", MimeType.XML); Convert(site, code, isTemplate, code.AsXmlNode, ContextState.Argument, ns); attribute.Parent.Attr(attribute.Name, "{{" + AsArgument(code.AsXmlNode) + "}}"); attribute.Remove(); } } else { Convert(site, doc, isTemplate, child, state, ns); if((state == ContextState.Argument) && ((child.NodeType == XmlNodeType.Text) || (child.NodeType == XmlNodeType.Whitespace) || (child.NodeType == XmlNodeType.SignificantWhitespace))) { if(!string.IsNullOrEmpty(child.Value)) { double value; if(double.TryParse(child.Value, out value)) { current.Replace(child.Value); } else { current.Replace(QuoteString(child.Value)); } } else { current.Remove(); } } } } }
/// <summary> /// Converts a MediaWiki title to its MindTouch format /// </summary> /// <param name="mwTitle">The title to convert</param> /// <returns>The converted title</returns> public Title MWToDWTitle(Site site, Title mwTitle) { return MWToDWTitle(site, mwTitle, true); }
private static string AsPathArgument(Site site, XDoc arg, bool useTemplateNamespace, out bool simple) { simple = false; string name = AsArgument(arg.AsXmlNode); if((name.Length >= 3) && (SafeParse(name.Substring(1, name.Length - 2)) is DekiScriptVar)) { simple = true; return name; } if(SafeParse(name) is DekiScriptString) { if(useTemplateNamespace && name.Substring(1).StartsWith("Template:")) { name = "'" + name.Substring(10, name.Length - 11) + "'"; if(SafeParse(name.Substring(1, name.Length - 2)) is DekiScriptVar) { simple = true; return name; } } return name; } if(useTemplateNamespace) { if(string.IsNullOrEmpty(site.Language)) { return "mediawiki.path(" + name + ")"; } else { return "mediawiki.path(" + name + ", " + DekiScriptString.QuoteString(site.Language) + ")"; } } else { return "mediawiki.localurl(" + (string.IsNullOrEmpty(site.Language) ? "_" : DekiScriptString.QuoteString(site.Language)) + ", " + name + ")"; } }
//--- Class Methods --- public static void Convert(Site site, XDoc doc, bool isTemplate) { XmlNamespaceManager ns = new XmlNamespaceManager(XDoc.XmlNameTable); ns.AddNamespace("m", "#mediawiki"); DetectWikiTextLinks(doc.AsXmlNode); Convert(site, doc, isTemplate, doc.AsXmlNode, ContextState.None, ns); }
//--- Methods --- internal bool RunTest(Plug converter) { foreach(KeyValuePair<string, string> setting in Settings) { converter = converter.With(setting.Key, setting.Value); } DreamMessage message = converter.With("text", Test).PostQuery(); string result = message.AsText(); string[] received = result.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None); XDoc converted = XDocFactory.From(result, MimeType.HTML); Site site = new Site(); string lang; if(Settings.TryGetValue("lang", out lang)) { site.Language = lang; } string title; if(!Settings.TryGetValue("title", out title)) { title = "None"; } WikiTextProcessor.Convert(site, converted, StringUtil.StartsWithInvariantIgnoreCase(title, "Template:")); string[] actual = converted.ToPrettyString().Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None); bool success = true; if(actual.Length == Expected.Length) { for(int i = 0; i < Expected.Length; ++i) { if(actual[i] != Expected[i]) { success = false; break; } } } else { success = false; } if(!success) { string bug; if(Settings.TryGetValue("bug", out bug)) { Console.WriteLine("Line {0}, Bug# {1}", Line, bug); } else { Console.WriteLine("Line {0}", Line); } Console.WriteLine(); Console.WriteLine("Sent"); Console.WriteLine("----"); Console.WriteLine(Test); Console.WriteLine(); Console.WriteLine("Received"); Console.WriteLine("--------"); foreach(string line in received) { Console.WriteLine(line); } Console.WriteLine(); Console.WriteLine("Converted"); Console.WriteLine("---------"); Console.WriteLine(converted.ToPrettyString()); Console.WriteLine(); Console.WriteLine("Expected"); Console.WriteLine("--------"); foreach(string line in Expected) { Console.WriteLine(line); } Console.WriteLine(); Console.WriteLine("========================================"); return false; } return true; }
public static List<string> GetParentCategoryNames(Site site, string category, List<string> previousCategories) { List<string> parentCategories = new List<string>(); previousCategories.Add(category); MediaWikiConverterContext.Current.MWCatalog.NewQuery(String.Format("SELECT cl_from, cl_to from {0}categorylinks where cl_from=(select page_id from {0}page where page_namespace=14 and page_title=\"{1}\")", site.DbPrefix, category)).Execute(delegate(IDataReader dr) { while (dr.Read()) { string parentCategory = GetUTF8String(dr, "cl_to"); if (parentCategory != category && parentCategory != "All_Categories" && !previousCategories.Contains(parentCategory)) { parentCategories.Add(GetUTF8String(dr, "cl_to")); GetParentCategoryNames(site, parentCategory, previousCategories); } } }); return parentCategories; }
public static PageBE GetPopulatedRevision(Site site, PageBE revision) { PageBE result = null; MediaWikiConverterContext.Current.MWCatalog.NewQuery(String.Format( @"SELECT rev_id, page_namespace, page_title, old_text, rev_comment, rev_user, rev_user_text, rev_timestamp, rev_minor_edit, old_flags FROM {0}revision JOIN {0}page on rev_page = page_id JOIN {0}text on rev_text_id = old_id WHERE rev_id={1}", site.DbPrefix, revision.ID)).Execute(delegate(IDataReader dr) { while (dr.Read()) { result = PopulateOld(dr); result.Language = site.Language; } }); return result; }