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);
 }
Beispiel #10
0
 //--- 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;
 }