Skip to content

Commit d6b668f

Browse files
authored
Add support for "previous" and "next" document navigation (#258)
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. https://github.com/user-attachments/assets/dda58a4e-5684-4c18-a409-3fca5f74f782 Video inspired by @reakaleek's PR's :)
1 parent 8269091 commit d6b668f

File tree

8 files changed

+48
-12
lines changed

8 files changed

+48
-12
lines changed

src/Elastic.Markdown/IO/DocumentationSet.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
33
// See the LICENSE file in the project root for more information
44

5+
using System.Collections.Frozen;
56
using System.IO.Abstractions;
67
using Elastic.Markdown.Diagnostics;
78
using Elastic.Markdown.IO.Configuration;
@@ -56,17 +57,24 @@ public DocumentationSet(BuildContext context)
5657

5758
LastWrite = Files.Max(f => f.SourceFile.LastWriteTimeUtc);
5859

59-
FlatMappedFiles = Files.ToDictionary(file => file.RelativePath, file => file);
60+
FlatMappedFiles = Files.ToDictionary(file => file.RelativePath, file => file).ToFrozenDictionary();
61+
6062
var folderFiles = Files
6163
.GroupBy(file => file.RelativeFolder)
6264
.ToDictionary(g => g.Key, g => g.ToArray());
6365

64-
Tree = new DocumentationGroup(Configuration.TableOfContents, FlatMappedFiles, folderFiles)
66+
var fileIndex = 0;
67+
Tree = new DocumentationGroup(Configuration.TableOfContents, FlatMappedFiles, folderFiles, ref fileIndex)
6568
{
6669
Parent = null
6770
};
71+
72+
MarkdownFiles = Files.OfType<MarkdownFile>().ToDictionary(i => i.NavigationIndex, i => i).ToFrozenDictionary();
73+
6874
}
6975

76+
public FrozenDictionary<int, MarkdownFile> MarkdownFiles { get; }
77+
7078
public MarkdownFile? GetMarkdownFile(IFileInfo sourceFile)
7179
{
7280
var relativePath = Path.GetRelativePath(SourcePath.FullName, sourceFile.FullName);
@@ -104,9 +112,9 @@ private DocumentationFile CreateMarkDownFile(IFileInfo file, BuildContext contex
104112

105113
public DocumentationGroup Tree { get; }
106114

107-
public List<DocumentationFile> Files { get; }
115+
public IReadOnlyCollection<DocumentationFile> Files { get; }
108116

109-
public Dictionary<string, DocumentationFile> FlatMappedFiles { get; }
117+
public FrozenDictionary<string, DocumentationFile> FlatMappedFiles { get; }
110118

111119
public void ClearOutputDirectory()
112120
{

src/Elastic.Markdown/IO/MarkdownFile.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ public string? NavigationTitle
6161
public string FileName { get; }
6262
public string Url => $"{UrlPathPrefix}/{RelativePath.Replace(".md", ".html")}";
6363

64+
public int NavigationIndex { get; set; }
65+
6466
private bool _instructionsParsed;
6567
private DocumentationGroup? _parent;
6668

src/Elastic.Markdown/IO/Navigation/DocumentationGroup.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,13 @@ public DocumentationGroup(
3636
IReadOnlyCollection<ITocItem> toc,
3737
IDictionary<string, DocumentationFile> lookup,
3838
IDictionary<string, DocumentationFile[]> folderLookup,
39+
ref int fileIndex,
3940
int depth = 0,
4041
MarkdownFile? index = null
4142
)
4243
{
4344
Depth = depth;
44-
Index = ProcessTocItems(index, toc, lookup, folderLookup, depth, out var groups, out var files, out var navigationItems);
45+
Index = ProcessTocItems(index, toc, lookup, folderLookup, depth, ref fileIndex, out var groups, out var files, out var navigationItems);
4546

4647
GroupsInOrder = groups;
4748
FilesInOrder = files;
@@ -59,6 +60,7 @@ public DocumentationGroup(
5960
IDictionary<string, DocumentationFile> lookup,
6061
IDictionary<string, DocumentationFile[]> folderLookup,
6162
int depth,
63+
ref int fileIndex,
6264
out List<DocumentationGroup> groups,
6365
out List<MarkdownFile> files,
6466
out List<INavigationItem> navigationItems)
@@ -75,10 +77,11 @@ public DocumentationGroup(
7577
continue;
7678

7779
md.Parent = this;
80+
md.NavigationIndex = ++fileIndex;
7881

7982
if (file.Children.Count > 0 && d is MarkdownFile virtualIndex)
8083
{
81-
var group = new DocumentationGroup(file.Children, lookup, folderLookup, depth + 1, virtualIndex)
84+
var group = new DocumentationGroup(file.Children, lookup, folderLookup, ref fileIndex, depth + 1, virtualIndex)
8285
{
8386
Parent = this
8487
};
@@ -108,7 +111,7 @@ public DocumentationGroup(
108111
.ToArray();
109112
}
110113

111-
var group = new DocumentationGroup(children, lookup, folderLookup, depth + 1)
114+
var group = new DocumentationGroup(children, lookup, folderLookup, ref fileIndex, depth + 1)
112115
{
113116
Parent = this
114117
};

src/Elastic.Markdown/IO/State/LinkReference.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ public record LinkReference
2424
public static LinkReference Create(DocumentationSet set)
2525
{
2626
var crossLinks = set.Context.Collector.CrossLinks.ToHashSet().ToArray();
27-
var links = set.FlatMappedFiles.Values
28-
.OfType<MarkdownFile>()
27+
var links = set.MarkdownFiles.Values
2928
.Select(m => m.RelativePath).ToArray();
3029
return new LinkReference
3130
{

src/Elastic.Markdown/Slices/HtmlWriter.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ public async Task<string> RenderLayout(MarkdownFile markdown, Cancel ctx = defau
4545
await DocumentationSet.Tree.Resolve(ctx);
4646
var navigationHtml = await RenderNavigation(markdown, ctx);
4747

48-
var previous = DocumentationSet;
48+
var previous = DocumentationSet.MarkdownFiles.GetValueOrDefault(markdown.NavigationIndex - 1);
49+
var next = DocumentationSet.MarkdownFiles.GetValueOrDefault(markdown.NavigationIndex + 1);
4950

5051
var remote = DocumentationSet.Context.Git.RepositoryName;
5152
var branch = DocumentationSet.Context.Git.Branch;
@@ -59,6 +60,8 @@ public async Task<string> RenderLayout(MarkdownFile markdown, Cancel ctx = defau
5960
PageTocItems = markdown.TableOfContents.Values.ToList(),
6061
Tree = DocumentationSet.Tree,
6162
CurrentDocument = markdown,
63+
PreviousDocument = previous,
64+
NextDocument = next,
6265
NavigationHtml = navigationHtml,
6366
UrlPathPrefix = markdown.UrlPathPrefix,
6467
Applies = markdown.YamlFrontMatter?.AppliesTo,

src/Elastic.Markdown/Slices/Index.cshtml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
PageTocItems = Model.PageTocItems,
88
Tree = Model.Tree,
99
CurrentDocument = Model.CurrentDocument,
10+
Previous = Model.PreviousDocument,
11+
Next = Model.NextDocument,
1012
NavigationHtml = Model.NavigationHtml,
1113
UrlPathPrefix = Model.UrlPathPrefix,
1214
GithubEditUrl = Model.GithubEditUrl

src/Elastic.Markdown/Slices/_Layout.cshtml

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,30 @@
6464
<span>Back to top</span>
6565
</button>
6666
<div class="navigation flex print:hidden">
67+
@if (Model.Previous != null)
68+
{
69+
<div class="navigation-previous">
70+
<i class="i-lucide chevron-left"></i>
71+
<a href="@Model.Previous.Url">
72+
<div class="page-info">
73+
<span>Previous</span>
74+
<div class="title">@Model.Previous.NavigationTitle</div>
75+
</div>
76+
</a>
77+
</div>
78+
}
79+
@if (Model.Next != null)
80+
{
6781
<div class="navigation-next">
68-
<a href="elastic/index.html">
82+
<a href="@Model.Next.Url">
6983
<div class="page-info">
7084
<span>Next</span>
71-
<div class="title">Elastic content</div>
85+
<div class="title">@Model.Next.NavigationTitle</div>
7286
</div>
7387
<i class="i-lucide chevron-right"></i>
7488
</a>
7589
</div>
90+
}
7691
</div>
7792
</div>
7893
</div>

src/Elastic.Markdown/Slices/_ViewModels.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ public class IndexViewModel
1414
public required DocumentationGroup Tree { get; init; }
1515
public required IReadOnlyCollection<PageTocItem> PageTocItems { get; init; }
1616
public required MarkdownFile CurrentDocument { get; init; }
17+
public required MarkdownFile? PreviousDocument { get; init; }
18+
public required MarkdownFile? NextDocument { get; init; }
1719
public required string NavigationHtml { get; init; }
1820
public required string? UrlPathPrefix { get; init; }
1921
public required string? GithubEditUrl { get; init; }
@@ -26,6 +28,8 @@ public class LayoutViewModel
2628
public required IReadOnlyCollection<PageTocItem> PageTocItems { get; init; }
2729
public required DocumentationGroup Tree { get; init; }
2830
public required MarkdownFile CurrentDocument { get; init; }
31+
public required MarkdownFile? Previous { get; init; }
32+
public required MarkdownFile? Next { get; init; }
2933
public required string NavigationHtml { get; set; }
3034
public required string? UrlPathPrefix { get; set; }
3135
public required string? GithubEditUrl { get; set; }

0 commit comments

Comments
 (0)