diff --git a/src/Elastic.Markdown/IO/DocumentationSet.cs b/src/Elastic.Markdown/IO/DocumentationSet.cs index 5ce56772..1d22fd63 100644 --- a/src/Elastic.Markdown/IO/DocumentationSet.cs +++ b/src/Elastic.Markdown/IO/DocumentationSet.cs @@ -2,6 +2,7 @@ // Elasticsearch B.V licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information +using System.Collections.Frozen; using System.IO.Abstractions; using Elastic.Markdown.Diagnostics; using Elastic.Markdown.IO.Configuration; @@ -56,17 +57,24 @@ public DocumentationSet(BuildContext context) LastWrite = Files.Max(f => f.SourceFile.LastWriteTimeUtc); - FlatMappedFiles = Files.ToDictionary(file => file.RelativePath, file => file); + FlatMappedFiles = Files.ToDictionary(file => file.RelativePath, file => file).ToFrozenDictionary(); + var folderFiles = Files .GroupBy(file => file.RelativeFolder) .ToDictionary(g => g.Key, g => g.ToArray()); - Tree = new DocumentationGroup(Configuration.TableOfContents, FlatMappedFiles, folderFiles) + var fileIndex = 0; + Tree = new DocumentationGroup(Configuration.TableOfContents, FlatMappedFiles, folderFiles, ref fileIndex) { Parent = null }; + + MarkdownFiles = Files.OfType().ToDictionary(i => i.NavigationIndex, i => i).ToFrozenDictionary(); + } + public FrozenDictionary MarkdownFiles { get; } + public MarkdownFile? GetMarkdownFile(IFileInfo sourceFile) { var relativePath = Path.GetRelativePath(SourcePath.FullName, sourceFile.FullName); @@ -104,9 +112,9 @@ private DocumentationFile CreateMarkDownFile(IFileInfo file, BuildContext contex public DocumentationGroup Tree { get; } - public List Files { get; } + public IReadOnlyCollection Files { get; } - public Dictionary FlatMappedFiles { get; } + public FrozenDictionary FlatMappedFiles { get; } public void ClearOutputDirectory() { diff --git a/src/Elastic.Markdown/IO/MarkdownFile.cs b/src/Elastic.Markdown/IO/MarkdownFile.cs index 7be0484f..64ec90f5 100644 --- a/src/Elastic.Markdown/IO/MarkdownFile.cs +++ b/src/Elastic.Markdown/IO/MarkdownFile.cs @@ -61,6 +61,8 @@ public string? NavigationTitle public string FileName { get; } public string Url => $"{UrlPathPrefix}/{RelativePath.Replace(".md", ".html")}"; + public int NavigationIndex { get; set; } + private bool _instructionsParsed; private DocumentationGroup? _parent; diff --git a/src/Elastic.Markdown/IO/Navigation/DocumentationGroup.cs b/src/Elastic.Markdown/IO/Navigation/DocumentationGroup.cs index cae4847d..0faed81d 100644 --- a/src/Elastic.Markdown/IO/Navigation/DocumentationGroup.cs +++ b/src/Elastic.Markdown/IO/Navigation/DocumentationGroup.cs @@ -36,12 +36,13 @@ public DocumentationGroup( IReadOnlyCollection toc, IDictionary lookup, IDictionary folderLookup, + ref int fileIndex, int depth = 0, MarkdownFile? index = null ) { Depth = depth; - Index = ProcessTocItems(index, toc, lookup, folderLookup, depth, out var groups, out var files, out var navigationItems); + Index = ProcessTocItems(index, toc, lookup, folderLookup, depth, ref fileIndex, out var groups, out var files, out var navigationItems); GroupsInOrder = groups; FilesInOrder = files; @@ -59,6 +60,7 @@ public DocumentationGroup( IDictionary lookup, IDictionary folderLookup, int depth, + ref int fileIndex, out List groups, out List files, out List navigationItems) @@ -75,10 +77,11 @@ public DocumentationGroup( continue; md.Parent = this; + md.NavigationIndex = ++fileIndex; if (file.Children.Count > 0 && d is MarkdownFile virtualIndex) { - var group = new DocumentationGroup(file.Children, lookup, folderLookup, depth + 1, virtualIndex) + var group = new DocumentationGroup(file.Children, lookup, folderLookup, ref fileIndex, depth + 1, virtualIndex) { Parent = this }; @@ -108,7 +111,7 @@ public DocumentationGroup( .ToArray(); } - var group = new DocumentationGroup(children, lookup, folderLookup, depth + 1) + var group = new DocumentationGroup(children, lookup, folderLookup, ref fileIndex, depth + 1) { Parent = this }; diff --git a/src/Elastic.Markdown/IO/State/LinkReference.cs b/src/Elastic.Markdown/IO/State/LinkReference.cs index 73509da5..83d19908 100644 --- a/src/Elastic.Markdown/IO/State/LinkReference.cs +++ b/src/Elastic.Markdown/IO/State/LinkReference.cs @@ -24,8 +24,7 @@ public record LinkReference public static LinkReference Create(DocumentationSet set) { var crossLinks = set.Context.Collector.CrossLinks.ToHashSet().ToArray(); - var links = set.FlatMappedFiles.Values - .OfType() + var links = set.MarkdownFiles.Values .Select(m => m.RelativePath).ToArray(); return new LinkReference { diff --git a/src/Elastic.Markdown/Slices/HtmlWriter.cs b/src/Elastic.Markdown/Slices/HtmlWriter.cs index eb26957a..8f0a2525 100644 --- a/src/Elastic.Markdown/Slices/HtmlWriter.cs +++ b/src/Elastic.Markdown/Slices/HtmlWriter.cs @@ -45,7 +45,8 @@ public async Task RenderLayout(MarkdownFile markdown, Cancel ctx = defau await DocumentationSet.Tree.Resolve(ctx); var navigationHtml = await RenderNavigation(markdown, ctx); - var previous = DocumentationSet; + var previous = DocumentationSet.MarkdownFiles.GetValueOrDefault(markdown.NavigationIndex - 1); + var next = DocumentationSet.MarkdownFiles.GetValueOrDefault(markdown.NavigationIndex + 1); var remote = DocumentationSet.Context.Git.RepositoryName; var branch = DocumentationSet.Context.Git.Branch; @@ -59,6 +60,8 @@ public async Task RenderLayout(MarkdownFile markdown, Cancel ctx = defau PageTocItems = markdown.TableOfContents.Values.ToList(), Tree = DocumentationSet.Tree, CurrentDocument = markdown, + PreviousDocument = previous, + NextDocument = next, NavigationHtml = navigationHtml, UrlPathPrefix = markdown.UrlPathPrefix, Applies = markdown.YamlFrontMatter?.AppliesTo, diff --git a/src/Elastic.Markdown/Slices/Index.cshtml b/src/Elastic.Markdown/Slices/Index.cshtml index e41abfaa..9dc916fa 100644 --- a/src/Elastic.Markdown/Slices/Index.cshtml +++ b/src/Elastic.Markdown/Slices/Index.cshtml @@ -7,6 +7,8 @@ PageTocItems = Model.PageTocItems, Tree = Model.Tree, CurrentDocument = Model.CurrentDocument, + Previous = Model.PreviousDocument, + Next = Model.NextDocument, NavigationHtml = Model.NavigationHtml, UrlPathPrefix = Model.UrlPathPrefix, GithubEditUrl = Model.GithubEditUrl diff --git a/src/Elastic.Markdown/Slices/_Layout.cshtml b/src/Elastic.Markdown/Slices/_Layout.cshtml index 0b516391..e544fbc9 100644 --- a/src/Elastic.Markdown/Slices/_Layout.cshtml +++ b/src/Elastic.Markdown/Slices/_Layout.cshtml @@ -64,15 +64,30 @@ Back to top diff --git a/src/Elastic.Markdown/Slices/_ViewModels.cs b/src/Elastic.Markdown/Slices/_ViewModels.cs index 67683cd7..5d4b02cf 100644 --- a/src/Elastic.Markdown/Slices/_ViewModels.cs +++ b/src/Elastic.Markdown/Slices/_ViewModels.cs @@ -14,6 +14,8 @@ public class IndexViewModel public required DocumentationGroup Tree { get; init; } public required IReadOnlyCollection PageTocItems { get; init; } public required MarkdownFile CurrentDocument { get; init; } + public required MarkdownFile? PreviousDocument { get; init; } + public required MarkdownFile? NextDocument { get; init; } public required string NavigationHtml { get; init; } public required string? UrlPathPrefix { get; init; } public required string? GithubEditUrl { get; init; } @@ -26,6 +28,8 @@ public class LayoutViewModel public required IReadOnlyCollection PageTocItems { get; init; } public required DocumentationGroup Tree { get; init; } public required MarkdownFile CurrentDocument { get; init; } + public required MarkdownFile? Previous { get; init; } + public required MarkdownFile? Next { get; init; } public required string NavigationHtml { get; set; } public required string? UrlPathPrefix { get; set; } public required string? GithubEditUrl { get; set; }