public void ProcessMarkdownTocWithRelativeHrefShouldSucceed() { var file1 = _fileCreator.CreateFile(string.Empty, FileType.MarkdownContent); var file2 = _fileCreator.CreateFile(string.Empty, FileType.MarkdownContent, "a"); var content = $@" #[Topic1](/href1) ##[Topic1.1]({file1}) ###[Topic1.1.1]({file2}) ##[Topic1.2]() #[Topic2](http://href.com) #[Topic3](invalid.md) "; var toc = _fileCreator.CreateFile(content, FileType.MarkdownToc); FileCollection files = new FileCollection(_inputFolder); files.Add(DocumentType.Article, new[] { file1, file2, toc }); BuildDocument(files); var outputRawModelPath = Path.Combine(_outputFolder, Path.ChangeExtension(toc, RawModelFileExtension)); Assert.True(File.Exists(outputRawModelPath)); var model = JsonUtility.Deserialize <TocItemViewModel>(outputRawModelPath); var expectedModel = new TocItemViewModel { Items = new TocViewModel { new TocItemViewModel { Name = "Topic1", Href = "/href1", TopicHref = "/href1", Items = new TocViewModel { new TocItemViewModel { Name = "Topic1.1", Href = file1, TopicHref = file1, Items = new TocViewModel { new TocItemViewModel { Name = "Topic1.1.1", Href = file2, TopicHref = file2 } } }, new TocItemViewModel { Name = "Topic1.2", Href = string.Empty, TopicHref = string.Empty } } }, new TocItemViewModel { Name = "Topic2", Href = "http://href.com", TopicHref = "http://href.com" }, new TocItemViewModel { Name = "Topic3", Href = "invalid.md", TopicHref = "invalid.md" } } }; AssertTocEqual(expectedModel, model); }
public void ProcessYamlTocWithFolderShouldSucceed() { var file1 = _fileCreator.CreateFile(string.Empty, FileType.MarkdownContent); var file2 = _fileCreator.CreateFile(string.Empty, FileType.MarkdownContent, "sub"); var subToc = _fileCreator.CreateFile($@" #[Topic]({Path.GetFileName(file2)}) ", FileType.MarkdownToc, "sub"); var content = $@" - name: Topic1 href: {file1} items: - name: Topic1.1 href: {file1} homepage: {file2} - name: Topic1.2 href: sub/ homepage: {file1} - name: Topic2 href: sub/ "; var toc = _fileCreator.CreateFile(content, FileType.YamlToc); FileCollection files = new FileCollection(_inputFolder); files.Add(DocumentType.Article, new[] { file1, file2, toc, subToc }); BuildDocument(files); var outputRawModelPath = Path.Combine(_outputFolder, Path.ChangeExtension(toc, RawModelFileExtension)); Assert.True(File.Exists(outputRawModelPath)); var model = JsonUtility.Deserialize <TocItemViewModel>(outputRawModelPath); var expectedModel = new TocItemViewModel { Items = new TocViewModel { new TocItemViewModel { Name = "Topic1", Href = file1, TopicHref = file1, Items = new TocViewModel { new TocItemViewModel { Name = "Topic1.1", Href = file1, // For relative file, href keeps unchanged Homepage = file2, // Homepage always keeps unchanged TopicHref = file2, }, new TocItemViewModel { Name = "Topic1.2", Href = file1, // For relative folder, href should be overwritten by homepage Homepage = file1, TopicHref = file1, TocHref = "sub/toc.md", } } }, new TocItemViewModel { Name = "Topic2", Href = file2, TopicHref = file2, TocHref = "sub/toc.md", } } }; AssertTocEqual(expectedModel, model); }
private object ConvertToObject(TocItemViewModel model) { return(ConvertToObjectHelper.ConvertStrongTypeToObject(model)); }
private static void RestructureItem(TocItemViewModel item, List <TocItemViewModel> items, TreeItemRestructure restruction) { var index = items.IndexOf(item); if (index < 0) { Logger.LogWarning($"Unable to find {restruction.Key}, it is probably removed or replaced by other restructions."); return; } switch (restruction.ActionType) { case TreeItemActionType.ReplaceSelf: { if (restruction.RestructuredItems == null || restruction.RestructuredItems.Count == 0) { return; } if (restruction.RestructuredItems.Count > 1) { throw new InvalidOperationException($"{restruction.ActionType} does not allow multiple root nodes."); } var roots = GetRoots(restruction.RestructuredItems); items[index] = roots[0]; break; } case TreeItemActionType.DeleteSelf: { items.RemoveAt(index); break; } case TreeItemActionType.AppendChild: { if (restruction.RestructuredItems == null || restruction.RestructuredItems.Count == 0) { return; } if (item.Items == null) { item.Items = new TocViewModel(); } var roots = GetRoots(restruction.RestructuredItems); item.Items.AddRange(roots); break; } case TreeItemActionType.PrependChild: { if (restruction.RestructuredItems == null || restruction.RestructuredItems.Count == 0) { return; } if (item.Items == null) { item.Items = new TocViewModel(); } var roots = GetRoots(restruction.RestructuredItems); item.Items.InsertRange(0, roots); break; } case TreeItemActionType.InsertAfter: { if (restruction.RestructuredItems == null || restruction.RestructuredItems.Count == 0) { return; } var roots = GetRoots(restruction.RestructuredItems); items.InsertRange(index + 1, roots); break; } case TreeItemActionType.InsertBefore: { if (restruction.RestructuredItems == null || restruction.RestructuredItems.Count == 0) { return; } var roots = GetRoots(restruction.RestructuredItems); items.InsertRange(index, roots); break; } default: break; } }
private static void SplitToc(string originalTocPath) { if (!Path.IsPathRooted(originalTocPath)) { originalTocPath = Path.GetFullPath(originalTocPath); } if (!File.Exists(originalTocPath)) { throw new FileNotFoundException($"The path of toc file: {originalTocPath} can't be found"); } var originalTocDir = Path.GetDirectoryName(originalTocPath); if (originalTocDir == null) { throw new Exception($"The directory of {originalTocPath} can't be null"); } TocViewModel tocModel; using (var stream = File.OpenRead(originalTocPath)) using (var reader = new StreamReader(stream)) { try { tocModel = YamlUtility.Deserialize <TocViewModel>(reader); } catch (YamlException ex) { Console.WriteLine($"Error occurs while parsing toc {originalTocPath}, please check if the format is correct. {ex.Message}"); throw; } } if (tocModel == null) { Console.WriteLine($"No toc model parsed for {originalTocPath}."); return; } var mergedTocModel = new TocViewModel(); foreach (var ns in tocModel) { var splittedTocPath = Path.Combine(originalTocDir, "_splitted", ns.Uid, "toc.yml"); var splittedTocRelativePath = PathUtility.MakeRelativePath(originalTocDir, splittedTocPath); var reversedRelativePath = PathUtility.MakeRelativePath(Path.GetDirectoryName(splittedTocPath), originalTocDir); ProcessHref(ns, reversedRelativePath.Replace('\\', '/')); var splittedTocDir = Path.GetDirectoryName(splittedTocPath); if (splittedTocDir == null) { throw new Exception($"The directory of {splittedTocPath} can't be null"); } if (!Directory.Exists(splittedTocDir)) { Directory.CreateDirectory(splittedTocDir); } var splittedTocItem = new TocItemViewModel { Uid = ns.Uid, Name = ns.Name, Items = ns.Items }; if (ns.Metadata != null) { splittedTocItem.Metadata = ns.Metadata; } var splittedTocModel = new TocViewModel(new List <TocItemViewModel> { splittedTocItem }); YamlUtility.Serialize(splittedTocPath, splittedTocModel); Console.WriteLine($"Create new splitted toc ({splittedTocPath})"); var mergedTocItem = new TocItemViewModel { Uid = ns.Uid, Name = ns.Name, Href = Path.GetDirectoryName(splittedTocRelativePath).Replace('\\', '/') + "/" }; mergedTocModel.Add(mergedTocItem); } YamlUtility.Serialize(originalTocPath, mergedTocModel); Console.WriteLine($"Rewrite original toc file ({originalTocPath})"); }
protected abstract void RegisterTocMapToContext(TocItemViewModel item, FileModel model, IDocumentBuildContext context);
public void ProcessMarkdownTocWithAbsoluteHrefShouldSucceed() { var content = @" #[Topic1 Language](/href1) # ##Topic1.1 Language C# ###[Topic1.1.1](/href1.1.1) ### ##[Topic1.2]() ## #[Topic2](http://href.com) # "; var toc = _fileCreator.CreateFile(content, FileType.MarkdownToc); FileCollection files = new FileCollection(_inputFolder); files.Add(DocumentType.Article, new[] { toc }); BuildDocument(files); var outputRawModelPath = Path.GetFullPath(Path.Combine(_outputFolder, Path.ChangeExtension(toc, RawModelFileExtension))); Assert.True(File.Exists(outputRawModelPath)); var model = JsonUtility.Deserialize <TocItemViewModel>(outputRawModelPath); var expectedModel = new TocItemViewModel { Items = new TocViewModel { new TocItemViewModel { Name = "Topic1 Language", Href = "/href1", TopicHref = "/href1", Items = new TocViewModel { new TocItemViewModel { Name = "Topic1.1 Language C#", Items = new TocViewModel { new TocItemViewModel { Name = "Topic1.1.1", Href = "/href1.1.1", TopicHref = "/href1.1.1" } } }, new TocItemViewModel { Name = "Topic1.2", Href = string.Empty, TopicHref = string.Empty } } }, new TocItemViewModel { Name = "Topic2", Href = "http://href.com", TopicHref = "http://href.com" } } }; AssertTocEqual(expectedModel, model); }
public void ProcessYamlTocWithTocHrefShouldSucceed() { var file1 = _fileCreator.CreateFile(string.Empty, FileType.MarkdownContent); var file2 = _fileCreator.CreateFile(string.Empty, FileType.MarkdownContent, "sub1/sub2"); var referencedToc = _fileCreator.CreateFile($@" - name: Topic href: {Path.GetFileName(file2)} ", FileType.YamlToc, "sub1/sub2"); var content = $@" - name: Topic1 tocHref: /Topic1/ topicHref: /Topic1/index.html items: - name: Topic1.1 tocHref: /Topic1.1/ topicHref: /Topic1.1/index.html - name: Topic1.2 tocHref: /Topic1.2/ topicHref: /Topic1.2/index.html - name: Topic2 tocHref: {referencedToc} topicHref: {file2} "; var toc = _fileCreator.CreateFile(content, FileType.YamlToc); FileCollection files = new FileCollection(_inputFolder); files.Add(DocumentType.Article, new[] { file1, file2, toc, referencedToc }); BuildDocument(files); var outputRawModelPath = Path.GetFullPath(Path.Combine(_outputFolder, Path.ChangeExtension(toc, RawModelFileExtension))); Assert.True(File.Exists(outputRawModelPath)); var model = JsonUtility.Deserialize <TocItemViewModel>(outputRawModelPath); var expectedModel = new TocItemViewModel { Items = new TocViewModel { new TocItemViewModel { Name = "Topic1", Href = "/Topic1/", TocHref = "/Topic1/", Homepage = "/Topic1/index.html", TopicHref = "/Topic1/index.html", Items = new TocViewModel { new TocItemViewModel { Name = "Topic1.1", Href = "/Topic1.1/", TocHref = "/Topic1.1/", Homepage = "/Topic1.1/index.html", TopicHref = "/Topic1.1/index.html", }, new TocItemViewModel { Name = "Topic1.2", Href = "/Topic1.2/", TocHref = "/Topic1.2/", Homepage = "/Topic1.2/index.html", TopicHref = "/Topic1.2/index.html", } } }, new TocItemViewModel { Name = "Topic2", TocHref = referencedToc, Href = referencedToc, TopicHref = file2, Homepage = file2, } } }; AssertTocEqual(expectedModel, model); }
public void ProcessYamlTocWithReferencedTocShouldSucceed() { var file1 = _fileCreator.CreateFile(string.Empty, FileType.MarkdownContent); var file2 = _fileCreator.CreateFile(string.Empty, FileType.MarkdownContent, "sub1"); var file3 = _fileCreator.CreateFile(string.Empty, FileType.MarkdownContent, "sub1/sub2"); var sub1sub2tocyaml = _fileCreator.CreateFile($@" - name: Topic href: {Path.GetFileName(file3)} - name: NotExistTopic href: a/b/c.md ", FileType.YamlToc, "sub1/sub2"); var sub1sub3tocmd = _fileCreator.CreateFile($@" #[Not-existed-md](sub2/notexist.md) ", FileType.MarkdownToc, "sub1/sub3"); var sub1tocmd = _fileCreator.CreateFile($@" #[Topic]({Path.GetFileName(file2)}) #[ReferencedToc](sub2/toc.yml) #[ReferencedToc2](sub3/toc.md) #[Not-existed-md](sub2/notexist.md) ", FileType.MarkdownToc, "sub1"); var content = $@" - name: Topic1 href: {file1} items: - name: Topic1.1 href: sub1/toc.md items: - name: Topic1.1.1 - name: Topic1.1.2 - name: Topic1.2 href: sub1/toc.md homepage: {file1} - name: Topic2 href: sub1/sub2/toc.yml "; // Test for OS sensitive file path if (PathUtility.IsPathCaseInsensitive()) { sub1tocmd = sub1tocmd.ToUpperInvariant(); } var toc = _fileCreator.CreateFile(content, FileType.YamlToc); FileCollection files = new FileCollection(_inputFolder); files.Add(DocumentType.Article, new[] { file1, file2, file3, toc, sub1tocmd, sub1sub3tocmd }); BuildDocument(files); var outputRawModelPath = Path.GetFullPath(Path.Combine(_outputFolder, Path.ChangeExtension(toc, RawModelFileExtension))); Assert.True(File.Exists(outputRawModelPath)); var model = JsonUtility.Deserialize <TocItemViewModel>(outputRawModelPath); var expectedModel = new TocItemViewModel { Items = new TocViewModel { new TocItemViewModel { Name = "Topic1", Href = file1, TopicHref = file1, Items = new TocViewModel { new TocItemViewModel { Name = "Topic1.1", Href = null, // For referenced toc, the content from the referenced toc is expanded as the items of current toc, and href is cleared TopicHref = null, Items = new TocViewModel { new TocItemViewModel { Name = "Topic", Href = file2, TopicHref = file2, }, new TocItemViewModel { Name = "ReferencedToc", Items = new TocViewModel { new TocItemViewModel { Name = "Topic", Href = file3, TopicHref = file3, }, new TocItemViewModel { Name = "NotExistTopic", Href = "sub1/sub2/a/b/c.md", TopicHref = "sub1/sub2/a/b/c.md", } } }, new TocItemViewModel { Name = "ReferencedToc2", Items = new TocViewModel { new TocItemViewModel { Name = "Not-existed-md", Href = "sub1/sub3/sub2/notexist.md", TopicHref = "sub1/sub3/sub2/notexist.md", }, } }, new TocItemViewModel { Name = "Not-existed-md", Href = "sub1/sub2/notexist.md", TopicHref = "sub1/sub2/notexist.md", } } }, new TocItemViewModel { Name = "Topic1.2", Href = file1, // For referenced toc, href should be overwritten by homepage TopicHref = file1, Homepage = file1, Items = new TocViewModel { new TocItemViewModel { Name = "Topic", Href = file2, TopicHref = file2, }, new TocItemViewModel { Name = "ReferencedToc", Items = new TocViewModel { new TocItemViewModel { Name = "Topic", Href = file3, TopicHref = file3, }, new TocItemViewModel { Name = "NotExistTopic", Href = "sub1/sub2/a/b/c.md", TopicHref = "sub1/sub2/a/b/c.md", } } }, new TocItemViewModel { Name = "ReferencedToc2", Items = new TocViewModel { new TocItemViewModel { Name = "Not-existed-md", Href = "sub1/sub3/sub2/notexist.md", TopicHref = "sub1/sub3/sub2/notexist.md", } } }, new TocItemViewModel { Name = "Not-existed-md", Href = "sub1/sub2/notexist.md", TopicHref = "sub1/sub2/notexist.md", } } } } }, new TocItemViewModel { Name = "Topic2", Href = null, Items = new TocViewModel { new TocItemViewModel { Name = "Topic", Href = file3, TopicHref = file3, }, new TocItemViewModel { Name = "NotExistTopic", Href = "sub1/sub2/a/b/c.md", TopicHref = "sub1/sub2/a/b/c.md", } } } } }; AssertTocEqual(expectedModel, model); // Referenced TOC File should not exist var referencedTocPath = Path.Combine(_outputFolder, Path.ChangeExtension(sub1tocmd, RawModelFileExtension)); Assert.False(File.Exists(referencedTocPath)); }
private void CopyMetadataToTocItem(TocItemViewModel item) { ApplyTocMetadata(item, _metaTable); ApplyTocMetadata(item, _propTable); }
/// <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)))); }