/// <summary> /// Write the table of contents based on annotations in the page files to the destination filename /// </summary> /// <param name="destination"></param> /// <returns></returns> protected async Task WriteTableOfContentsFileAsync(string destination) { List <TocItem> allTocEntries = new List <TocItem>(); foreach (var file in this.Documents.Files) { allTocEntries.AddRange(TocItem.TocItemsForFile(file)); } // Convert the Url properties to be usable by the output system foreach (var item in allTocEntries) { item.Url = this.QualifyUrl(item.Url.Replace('\\', '/')); } allTocEntries = allTocEntries.OrderBy(x => x.TocPath).ToList(); var tree = BuildTreeFromList(allTocEntries, addLevelForSections: true); var data = new { toc = tree }; string output = JsonConvert.SerializeObject(data, Formatting.Indented); using (var writer = new StreamWriter(destination, false, new System.Text.UTF8Encoding(false))) { await writer.WriteLineAsync(output); await writer.FlushAsync(); } }
/// <summary> /// Collpase headers into Headers and NextLevel items based on path hierarchy /// </summary> /// <param name="headers"></param> /// <param name="currentPage"></param> /// <returns></returns> private List <TocItem> BuildTreeFromList(List <TocItem> headers, DocFile currentPage = null, bool addLevelForSections = false) { List <TocItem> topLevelHeaders = new List <TocItem>(); foreach (var header in headers) { string pathForHeader = header.TocPath; if (addLevelForSections) { pathForHeader = header.Section + "\\" + pathForHeader; } var pathComponents = pathForHeader.Split(new char[] { '\\', '/' }, StringSplitOptions.RemoveEmptyEntries).ToList(); List <TocItem> headersForTargetLevel = topLevelHeaders; while (pathComponents.Count > 1) { // Point headersForTargetLevel to the proper level var headerForNextLevel = (from h in headersForTargetLevel where h.Title == pathComponents[0] select h).FirstOrDefault(); if (headerForNextLevel == null) { // We encountered a header that doesn't exist yet. Bummer. We should do something about that. headerForNextLevel = new TocItem() { Title = pathComponents[0], Section = header.Section }; headersForTargetLevel.Add(headerForNextLevel); } headersForTargetLevel = headerForNextLevel.NextLevel; pathComponents.RemoveAt(0); } headersForTargetLevel.Add(header); } if (this.CollapseTocToActiveGroup && null != currentPage) { var pageTocComponents = currentPage.Annotation.TocPath.FirstPathComponent(); foreach (var header in topLevelHeaders) { if (header.Title != pageTocComponents) { header.NextLevel.Clear(); } } } return(SortTocTree(topLevelHeaders)); }
/// <summary> /// Collpase headers into Headers and NextLevel items based on path hierarchy /// </summary> /// <param name="headers"></param> /// <param name="currentPage"></param> /// <returns></returns> private List <TocItem> CollapseHeadersByPath(List <TocItem> headers, DocFile currentPage) { List <TocItem> topLevelHeaders = new List <TocItem>(); foreach (var header in headers) { var pathComponents = header.TocPath.Split(new char[] { '\\', '/' }, StringSplitOptions.RemoveEmptyEntries).ToList(); List <TocItem> headersForTargetLevel = topLevelHeaders; while (pathComponents.Count > 1) { // Point headersForTargetLevel to the proper level var headerForNextLevel = (from h in headersForTargetLevel where h.Title == pathComponents[0] select h).FirstOrDefault(); if (headerForNextLevel == null) { // We encountered a header that doesn't exist yet. Bummer. We should do something about that. headerForNextLevel = new TocItem() { Title = pathComponents[0] }; headersForTargetLevel.Add(headerForNextLevel); } headersForTargetLevel = headerForNextLevel.NextLevel; pathComponents.RemoveAt(0); } headersForTargetLevel.Add(header); } if (this.CollapseTocToActiveGroup) { var pageTocComponents = currentPage.Annotation.TocPath.FirstPathComponent(); foreach (var header in topLevelHeaders) { if (header.Title != pageTocComponents) { header.NextLevel.Clear(); } } } return(topLevelHeaders.OrderBy(v => v.Title).ToList()); }