private static string GenerateToc(WikiToc toc) { StringBuilder result = new StringBuilder(); int headerIndex = 0; result.Append(@"<div id=""toc""><div id=""toc_title"">"); result.Append(SECTION_TOC_TITLE); result.Append("</div>"); result.Append(GenerateToc(toc.Nodes, ref headerIndex)); result.Append(@"</div><br clear=""left"" />"); return result.ToString(); }
private static string ParseTitles(string text, string articleTitle, bool mustDisplayToc) { // - Replace the Wiki titles with HTML ones of same level. // - Downgrade any <h1> titles to <h2> since there can only be one <h1> on the page and that is the article title. // - Find all the (now HTML) headers and apply the following transformations: // Generates a unique ID for the header based on its level and location (e.g. 1.2.1). // Generate the TOC using all the IDs and insert it before the first header. // Insert an anchor using that ID. // Insert the header (escape any HTML). // Add a span link to edit with section = [sequential number of the header]. StringBuilder result = new StringBuilder(); WikiToc toc = new WikiToc(); // First replace all the wiki titles with HTML ones. text = ReplaceWikiTitles(text); // Demotes the <h1> headers down to <h2>. text = DowngradH1Titles(text); string htmlHeader = string.Format(HEADER_HTML, "[1-9]"); Regex htmlRegex = new Regex(string.Format(HEADER_LINE, htmlHeader), RegexOptions.Multiline); string GUID = Tools.GetRandomGUID(); int headerIndex = 0; while (text.Length > 0) { string[]textParts = htmlRegex.Split(text, 2); result.Append(textParts[0]); if (textParts.Length == 1) break; else if (textParts.Length != 4) throw new Exception("How is this possible?"); // If we're just before the first header, insert a unique ID marking the future location of the TOC. if (headerIndex == 0) result.Append(GUID); int headerLevel = Convert.ToInt32(textParts[1]); string headerTitle = textParts[2]; text = textParts[3]; headerIndex++; // [KDE]: headerId used to carry the numeric prefix of the headers in the TOC hiearchy (e.g. "1.2.1"). // [KDE]: It is now generated automatically by the CSS using the counters() CSS function. string headerId = toc.InsertHeader(headerLevel, headerTitle); // If the title of the article was provided, an "[Edit]" link is created to be displayed at the right of each title. string editLink = string.Empty; if (!string.IsNullOrEmpty(articleTitle)) editLink = string.Format(@"<span class=""title_link"">[{0}]</span>", Tools.GetLinkToEdit(articleTitle, "Edit", headerIndex)); // Each title is embedded within two spans acting as link anchor targets. // The first span uses a simple sequential header index while the second is the text of the title itself. // Example of use: // "[[Article#3]]" => Used by the TOC and shouldn't be used by the users since the title order is subject to change upon edition. // "[[Article#My header]]" => To be used by the user. The text of each header is a little less dynamic than their order. result.AppendLine(string.Format(@"<h{0}><span id=""{1}""><span id=""{2}"">{3}</span></span>{4}</h{0}>", headerLevel, headerIndex, headerTitle, Tools.TextToXml(headerTitle), editLink)); } // If a TOC must be displayed, replace the unique ID with the actual TOC. Erase the unique ID otherwise. if (mustDisplayToc && toc.HeaderCount >= NUMBER_OF_CHAPTERS_BEFORE_DISPLAYING_TOC) result = result.Replace(GUID, GenerateToc(toc) + Environment.NewLine); else result = result.Replace(GUID, ""); // Fix a bug where \r\n becomes \r\n\n after a title. This can probably be fixed in one of the regexes above. result = result.Replace("\r\n\n", "\r\n"); return result.ToString(); }