private void ValidateToc(TocItemViewModel item, FileModel model, IHostService hostService) { if (!PathUtility.IsRelativePath(item.Href)) return; var file = model.File; var originalFile = model.OriginalFileAndType.File; // Special handle for folder ends with '/' FileAndType originalTocFile = null; string fileName = Path.GetFileName(item.Href); if (string.IsNullOrEmpty(fileName)) { var href = item.Href + "toc.yml"; var absHref = (RelativePath)file + (RelativePath)href; string tocPath = absHref.GetPathFromWorkingFolder(); if (!hostService.SourceFiles.TryGetValue(tocPath, out originalTocFile)) { href = item.Href + "toc.md"; absHref = (RelativePath)file + (RelativePath)href; tocPath = absHref.GetPathFromWorkingFolder(); if (!hostService.SourceFiles.TryGetValue(tocPath, out originalTocFile)) { var error = $"Unable to find either toc.yml or toc.md inside {item.Href}. Make sure the file is included in config file docfx.json!"; Logger.LogError(error, file: model.LocalPathFromRepoRoot); throw new DocumentException(error); } } Logger.LogInfo($"TOC file {href} inside {item.Href} is used", file: model.LocalPathFromRepoRoot); item.Href = href; item.OriginalHref = item.Href; } // Set default homepage SetDefaultHomepage(item, originalTocFile, model); }
private void UpdateTocItemHref(TocItemViewModel toc, string path, Func<string, string, string> updater) { toc.Href = updater(toc.Href, path); toc.OriginalHref = updater(toc.OriginalHref, path); if (toc.Items != null && toc.Items.Count > 0) { foreach (var item in toc.Items) { UpdateTocItemHref(item, path, updater); } } }
private void UpdateTocItemHref(TocItemViewModel toc, FileModel model, IDocumentBuildContext context) { ResolveUid(toc, model, context); RegisterTocMap(toc, model.Key, context); if (!string.IsNullOrEmpty(toc.Homepage)) { toc.Href = toc.Homepage; } toc.Href = GetUpdatedHref(toc.Href, model, context); toc.OriginalHref = GetUpdatedHref(toc.OriginalHref, model, context); if (toc.Items != null && toc.Items.Count > 0) { foreach (var item in toc.Items) { UpdateTocItemHref(item, model, context); } } }
public static TocItemViewModel FromModel(MetadataItem item) { var result = new TocItemViewModel { Uid = item.Name, Name = item.DisplayNames.GetLanguageProperty(SyntaxLanguage.Default), Href = item.Href, }; var nameForCSharp = item.DisplayNames.GetLanguageProperty(SyntaxLanguage.CSharp); if (nameForCSharp != result.Name) { result.NameForCSharp = nameForCSharp; } var nameForVB = item.DisplayNames.GetLanguageProperty(SyntaxLanguage.VB); if (nameForVB != result.Name) { result.NameForVB = nameForVB; } if (item.Items != null) { result.Items = TocViewModel.FromModel(item); } return result; }
private void SetHomepage(TocItemViewModel item, FileAndType originalTocFile, FileModel model) { if (!string.IsNullOrEmpty(item.Homepage)) { if (PathUtility.IsRelativePath(item.Homepage)) { item.Href = ((RelativePath)model.File + (RelativePath)item.Homepage).GetPathFromWorkingFolder(); } else { item.Href = item.Homepage; } Logger.LogInfo($"Homepage {item.Homepage} is used.", file: model.LocalPathFromRepoRoot); } else if (originalTocFile != null) { var subTocPath = Path.Combine(originalTocFile.BaseDir, originalTocFile.File); var subToc = LoadSingleToc(subTocPath); var href = GetDefaultHomepage(subToc); if (href == null) { var error = $"Unable to get default page for {item.Href}: no item containing relative file link is defined inside TOC {subTocPath}"; Logger.LogError(error, file: model.LocalPathFromRepoRoot); throw new DocumentException(error); } item.Href = (RelativePath)item.Href + (RelativePath)href; } }
private void RegisterTocMap(TocItemViewModel item, string key, IDocumentBuildContext context) { var href = item.Href; // Should be original href from working folder starting with ~ if (!PathUtility.IsRelativePath(href)) return; context.RegisterToc(key, href); }
private void ResolveUid(TocItemViewModel item, FileModel model, IDocumentBuildContext context) { if (item.Uid != null) { var xref = GetXrefFromUid(item.Uid, model, context); item.Href = xref.Href; if (string.IsNullOrEmpty(item.Name)) { item.Name = xref.Name; } string nameForCSharp; if (string.IsNullOrEmpty(item.NameForCSharp) && xref.TryGetValue("name.csharp", out nameForCSharp)) { item.NameForCSharp = nameForCSharp; } string nameForVB; if (string.IsNullOrEmpty(item.NameForVB) && xref.TryGetValue("name.vb", out nameForVB)) { item.NameForVB = nameForVB; } } if (item.HomepageUid != null) { item.Homepage = GetXrefFromUid(item.HomepageUid, model, context).Href; } }
protected ParseState ApplyCore(ParseState state, int level, string text, string href) { if (level > state.Level + 1) { return new ErrorState(state, level, $"Skip level is not allowed. Toc content: {text}"); } // If current node is another node in higher or same level for (int i = state.Level; i >= level; --i) { state.Parents.Pop(); } var item = new TocItemViewModel { Name = text, Href = href, }; if (state.Parents.Count > 0) { var parent = state.Parents.Peek(); if (parent.Items == null) { parent.Items = new TocViewModel(); } parent.Items.Add(item); } else { state.Root.Add(item); } state.Parents.Push(item); if (state.Level == level) { return state; } return new NodeState(state, level); }
private void SetDefaultHomepage(TocItemViewModel item, FileAndType originalTocFile, FileModel model) { if (!string.IsNullOrEmpty(item.Homepage) || originalTocFile == null) return; var subTocPath = Path.Combine(originalTocFile.BaseDir, originalTocFile.File); var subToc = LoadSingleToc(subTocPath); var tocItem = GetDefaultHomepageItem(subToc); if (tocItem == null) { var error = $"Unable to get default page for {item.Href}: no item containing relative file link is defined inside TOC {subTocPath}"; Logger.LogError(error, file: model.LocalPathFromRepoRoot); throw new DocumentException(error); } if (!string.IsNullOrEmpty(tocItem.Uid)) { item.HomepageUid = tocItem.Uid; } else { item.Homepage = ((RelativePath)originalTocFile.File) + ((RelativePath)tocItem.Href); } }
/// <summary> /// Valid homepage href should: /// 1. relative file path /// 2. refer to a file /// 3. folder is not supported /// 4. refer to an `uid` /// </summary> /// <param name="href"></param> /// <returns></returns> private bool IsValidHomepageLink(TocItemViewModel tocItem) { return !string.IsNullOrEmpty(tocItem.Uid) || (PathUtility.IsRelativePath(tocItem.Href) && !string.IsNullOrEmpty(Path.GetFileName(tocItem.Href))); }