From b8bc77b2c1b56b7676453d4b777a8e1684f6ba40 Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Thu, 16 Jan 2025 16:43:11 +0100 Subject: [PATCH 1/3] Add support for "previous" and "next" document navigation Introduced navigation indices for Markdown files, enabling seamless transitions between "previous" and "next" documents. Updated views and models to reflect these changes, improving navigation usability. --- src/Elastic.Markdown/IO/DocumentationSet.cs | 16 ++++++++++++---- src/Elastic.Markdown/IO/MarkdownFile.cs | 7 +++++++ .../IO/Navigation/DocumentationGroup.cs | 9 ++++++--- .../IO/State/LinkReference.cs | 3 +-- src/Elastic.Markdown/Slices/HtmlWriter.cs | 5 ++++- src/Elastic.Markdown/Slices/Index.cshtml | 2 ++ src/Elastic.Markdown/Slices/_Layout.cshtml | 19 +++++++++++++++++-- src/Elastic.Markdown/Slices/_ViewModels.cs | 4 ++++ 8 files changed, 53 insertions(+), 12 deletions(-) diff --git a/src/Elastic.Markdown/IO/DocumentationSet.cs b/src/Elastic.Markdown/IO/DocumentationSet.cs index 5ce56772a..1d22fd635 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 7be0484f2..963f5bc26 100644 --- a/src/Elastic.Markdown/IO/MarkdownFile.cs +++ b/src/Elastic.Markdown/IO/MarkdownFile.cs @@ -61,8 +61,15 @@ public string? NavigationTitle public string FileName { get; } public string Url => $"{UrlPathPrefix}/{RelativePath.Replace(".md", ".html")}"; + public int NavigationIndex + { + get { return _navigationIndex; } + set { _navigationIndex = value; } + } + private bool _instructionsParsed; private DocumentationGroup? _parent; + private int _navigationIndex; public MarkdownFile[] YieldParents() { diff --git a/src/Elastic.Markdown/IO/Navigation/DocumentationGroup.cs b/src/Elastic.Markdown/IO/Navigation/DocumentationGroup.cs index cae4847d7..0faed81dd 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 73509da50..83d19908d 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 eb26957a8..112c2afc2 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 e41abfaa2..9dc916fad 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 0b5163912..e544fbc92 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 67683cd78..5d4b02cf1 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; } From 9212f7a424551a87cdbf6a7cccdd6b9ebe360e6d Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Thu, 16 Jan 2025 17:04:49 +0100 Subject: [PATCH 2/3] dotnet format --- src/Elastic.Markdown/Slices/HtmlWriter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Elastic.Markdown/Slices/HtmlWriter.cs b/src/Elastic.Markdown/Slices/HtmlWriter.cs index 112c2afc2..8f0a25253 100644 --- a/src/Elastic.Markdown/Slices/HtmlWriter.cs +++ b/src/Elastic.Markdown/Slices/HtmlWriter.cs @@ -45,8 +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.MarkdownFiles.GetValueOrDefault(markdown.NavigationIndex -1); - var next = DocumentationSet.MarkdownFiles.GetValueOrDefault(markdown.NavigationIndex +1); + 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; From f905ae7905f18ae6f8c9fe56c1407e2531c426a6 Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Thu, 16 Jan 2025 17:14:02 +0100 Subject: [PATCH 3/3] fix property to not have backing variable --- src/Elastic.Markdown/IO/MarkdownFile.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/Elastic.Markdown/IO/MarkdownFile.cs b/src/Elastic.Markdown/IO/MarkdownFile.cs index 963f5bc26..64ec90f52 100644 --- a/src/Elastic.Markdown/IO/MarkdownFile.cs +++ b/src/Elastic.Markdown/IO/MarkdownFile.cs @@ -61,15 +61,10 @@ public string? NavigationTitle public string FileName { get; } public string Url => $"{UrlPathPrefix}/{RelativePath.Replace(".md", ".html")}"; - public int NavigationIndex - { - get { return _navigationIndex; } - set { _navigationIndex = value; } - } + public int NavigationIndex { get; set; } private bool _instructionsParsed; private DocumentationGroup? _parent; - private int _navigationIndex; public MarkdownFile[] YieldParents() {