Skip to content

Commit 80e512e

Browse files
authored
Refactor navigation and model hierarchy. (#181)
Replaces `DocumentationFolder` with `DocumentationGroup` and introduces new abstractions for navigation management. Updates hierarchy structure, adds `NavigationItems` for improved flexibility, and adjusts related components to align with the new design. This now orders files and groups as a whole. Before we were listing files before folders always
1 parent fbd89ea commit 80e512e

20 files changed

+147
-86
lines changed

src/Elastic.Markdown/BuildContext.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.IO.Abstractions;
55
using Elastic.Markdown.Diagnostics;
66
using Elastic.Markdown.IO;
7+
using Elastic.Markdown.IO.Discovery;
78

89
namespace Elastic.Markdown;
910

@@ -17,7 +18,7 @@ public record BuildContext
1718

1819
public IFileInfo ConfigurationPath { get; }
1920

20-
public GitConfiguration Git { get; }
21+
public GitCheckoutInformation Git { get; }
2122

2223
public required DiagnosticsCollector Collector { get; init; }
2324

@@ -57,7 +58,7 @@ public BuildContext(IFileSystem readFileSystem, IFileSystem writeFileSystem, str
5758
if (ConfigurationPath.FullName != SourcePath.FullName)
5859
SourcePath = ConfigurationPath.Directory!;
5960

60-
Git = GitConfiguration.Create(ReadFileSystem);
61+
Git = GitCheckoutInformation.Create(ReadFileSystem);
6162
}
6263

6364
private IDirectoryInfo FindDocsFolderFromRoot(IDirectoryInfo rootPath)

src/Elastic.Markdown/DocumentationGenerator.cs

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,13 @@
44
using System.IO.Abstractions;
55
using System.Reflection;
66
using System.Text.Json;
7-
using System.Text.Json.Serialization;
87
using Elastic.Markdown.IO;
8+
using Elastic.Markdown.IO.State;
99
using Elastic.Markdown.Slices;
1010
using Microsoft.Extensions.Logging;
1111

1212
namespace Elastic.Markdown;
1313

14-
[JsonSourceGenerationOptions(WriteIndented = true)]
15-
[JsonSerializable(typeof(GenerationState))]
16-
[JsonSerializable(typeof(LinkReference))]
17-
[JsonSerializable(typeof(GitConfiguration))]
18-
internal partial class SourceGenerationContext : JsonSerializerContext;
19-
20-
public record GenerationState
21-
{
22-
[JsonPropertyName("last_seen_changes")]
23-
public required DateTimeOffset LastSeenChanges { get; init; }
24-
25-
[JsonPropertyName("invalid_files")]
26-
public required string[] InvalidFiles { get; init; } = [];
27-
28-
[JsonPropertyName("git")]
29-
public required GitConfiguration Git { get; init; }
30-
}
31-
3214
public class DocumentationGenerator
3315
{
3416
private readonly IFileSystem _readFileSystem;

src/Elastic.Markdown/IO/ConfigurationFile.cs renamed to src/Elastic.Markdown/IO/Configuration/ConfigurationFile.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
using YamlDotNet.Core;
99
using YamlDotNet.RepresentationModel;
1010

11-
namespace Elastic.Markdown.IO;
11+
namespace Elastic.Markdown.IO.Configuration;
1212

1313
public record ConfigurationFile : DocumentationFile
1414
{

src/Elastic.Markdown/IO/ITocItem.cs renamed to src/Elastic.Markdown/IO/Configuration/ITocItem.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@
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-
namespace Elastic.Markdown.IO;
5+
namespace Elastic.Markdown.IO.Configuration;
66

77
public interface ITocItem;
88

99
public record FileReference(string Path, bool Found, IReadOnlyCollection<ITocItem> Children) : ITocItem;
1010

1111
public record FolderReference(string Path, bool Found, IReadOnlyCollection<ITocItem> Children) : ITocItem;
12-
13-
public record TocReference(string Path, bool Found, IReadOnlyCollection<ITocItem> Children) : ITocItem;

src/Elastic.Markdown/IO/GitConfiguration.cs renamed to src/Elastic.Markdown/IO/Discovery/GitCheckoutInformation.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66
using System.Text.Json.Serialization;
77
using SoftCircuits.IniFileParser;
88

9-
namespace Elastic.Markdown.IO;
9+
namespace Elastic.Markdown.IO.Discovery;
1010

11-
public record GitConfiguration
11+
public record GitCheckoutInformation
1212
{
13-
private static GitConfiguration Unavailable { get; } = new()
13+
private static GitCheckoutInformation Unavailable { get; } = new()
1414
{
1515
Branch = "unavailable",
1616
Remote = "unavailable",
@@ -27,13 +27,13 @@ public record GitConfiguration
2727
public required string Ref { get; init; }
2828

2929
// manual read because libgit2sharp is not yet AOT ready
30-
public static GitConfiguration Create(IFileSystem fileSystem)
30+
public static GitCheckoutInformation Create(IFileSystem fileSystem)
3131
{
3232
// filesystem is not real so return a dummy
3333
if (fileSystem is not FileSystem)
3434
{
3535
var fakeRef = Guid.NewGuid().ToString().Substring(0, 16);
36-
return new GitConfiguration { Branch = $"test-{fakeRef}", Remote = "elastic/docs-builder", Ref = fakeRef, };
36+
return new GitCheckoutInformation { Branch = $"test-{fakeRef}", Remote = "elastic/docs-builder", Ref = fakeRef, };
3737
}
3838

3939
var gitConfig = Git(".git/config");
@@ -66,7 +66,7 @@ public static GitConfiguration Create(IFileSystem fileSystem)
6666
if (string.IsNullOrEmpty(remote))
6767
remote = Environment.GetEnvironmentVariable("GITHUB_REPOSITORY") ?? "elastic/docs-builder-unknown";
6868

69-
return new GitConfiguration { Ref = gitRef, Branch = branch, Remote = remote };
69+
return new GitCheckoutInformation { Ref = gitRef, Branch = branch, Remote = remote };
7070

7171
IFileInfo Git(string path) => fileSystem.FileInfo.New(Path.Combine(Paths.Root.FullName, path));
7272

src/Elastic.Markdown/IO/DocumentationSet.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
using System.IO.Abstractions;
66
using Elastic.Markdown.Diagnostics;
7+
using Elastic.Markdown.IO.Configuration;
8+
using Elastic.Markdown.IO.Navigation;
79
using Elastic.Markdown.Myst;
810

911
namespace Elastic.Markdown.IO;
@@ -56,7 +58,7 @@ public DocumentationSet(BuildContext context)
5658
.GroupBy(file => file.RelativeFolder)
5759
.ToDictionary(g => g.Key, g => g.ToArray());
5860

59-
Tree = new DocumentationFolder(Configuration.TableOfContents, FlatMappedFiles, folderFiles)
61+
Tree = new DocumentationGroup(Configuration.TableOfContents, FlatMappedFiles, folderFiles)
6062
{
6163
Parent = null
6264
};
@@ -92,7 +94,7 @@ private DocumentationFile CreateMarkDownFile(IFileInfo file, BuildContext contex
9294
return new ExcludedFile(file, SourcePath);
9395
}
9496

95-
public DocumentationFolder Tree { get; }
97+
public DocumentationGroup Tree { get; }
9698

9799
public List<DocumentationFile> Files { get; }
98100

src/Elastic.Markdown/IO/MarkdownFile.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// See the LICENSE file in the project root for more information
44
using System.IO.Abstractions;
55
using Elastic.Markdown.Diagnostics;
6+
using Elastic.Markdown.IO.Navigation;
67
using Elastic.Markdown.Myst;
78
using Elastic.Markdown.Myst.Directives;
89
using Elastic.Markdown.Myst.FrontMatter;
@@ -14,6 +15,7 @@
1415

1516
namespace Elastic.Markdown.IO;
1617

18+
1719
public record MarkdownFile : DocumentationFile
1820
{
1921
private readonly SlugHelper _slugHelper = new();
@@ -31,7 +33,7 @@ public MarkdownFile(IFileInfo sourceFile, IDirectoryInfo rootPath, MarkdownParse
3133

3234
private DiagnosticsCollector Collector { get; }
3335

34-
public DocumentationFolder? Parent
36+
public DocumentationGroup? Parent
3537
{
3638
get => FileName == "index.md" ? _parent?.Parent : _parent;
3739
set => _parent = value;
@@ -59,7 +61,7 @@ public string? NavigationTitle
5961
public string Url => $"{UrlPathPrefix}/{RelativePath.Replace(".md", ".html")}";
6062

6163
private bool _instructionsParsed;
62-
private DocumentationFolder? _parent;
64+
private DocumentationGroup? _parent;
6365

6466
public MarkdownFile[] YieldParents()
6567
{

src/Elastic.Markdown/IO/DocumentationFolder.cs renamed to src/Elastic.Markdown/IO/Navigation/DocumentationGroup.cs

Lines changed: 47 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,50 @@
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-
namespace Elastic.Markdown.IO;
5+
using Elastic.Markdown.IO.Configuration;
66

7-
public class DocumentationFolder
7+
namespace Elastic.Markdown.IO.Navigation;
8+
9+
public interface INavigationItem
10+
{
11+
int Order { get; }
12+
int Depth { get; }
13+
}
14+
15+
public record GroupNavigation(int Order, int Depth, DocumentationGroup Group) : INavigationItem;
16+
public record FileNavigation(int Order, int Depth, MarkdownFile File) : INavigationItem;
17+
18+
19+
public class DocumentationGroup
820
{
921
public MarkdownFile? Index { get; set; }
1022

11-
public List<MarkdownFile> FilesInOrder { get; }
12-
public List<DocumentationFolder> GroupsInOrder { get; }
23+
private IReadOnlyCollection<MarkdownFile> FilesInOrder { get; }
24+
25+
private IReadOnlyCollection<DocumentationGroup> GroupsInOrder { get; }
26+
27+
public IReadOnlyCollection<INavigationItem> NavigationItems { get; }
1328

14-
public required DocumentationFolder? Parent { get; init; }
29+
public required DocumentationGroup? Parent { get; init; }
1530

1631
private HashSet<MarkdownFile> OwnFiles { get; }
1732

18-
public int Level { get; }
33+
public int Depth { get; }
1934

20-
public DocumentationFolder(
35+
public DocumentationGroup(
2136
IReadOnlyCollection<ITocItem> toc,
2237
IDictionary<string, DocumentationFile> lookup,
2338
IDictionary<string, DocumentationFile[]> folderLookup,
24-
int level = 0,
39+
int depth = 0,
2540
MarkdownFile? index = null
2641
)
2742
{
28-
Level = level;
29-
var foundIndex = ProcessTocItems(toc, lookup, folderLookup, level, out var groupsInOrder, out var filesInOrder);
43+
Depth = depth;
44+
var foundIndex = ProcessTocItems(toc, lookup, folderLookup, depth, out var groups, out var files, out var navigationItems);
3045

31-
GroupsInOrder = groupsInOrder;
32-
FilesInOrder = filesInOrder;
46+
GroupsInOrder = groups;
47+
FilesInOrder = files;
48+
NavigationItems = navigationItems;
3349
Index = index ?? foundIndex;
3450

3551
if (Index is not null)
@@ -42,15 +58,17 @@ public DocumentationFolder(
4258
IReadOnlyCollection<ITocItem> toc,
4359
IDictionary<string, DocumentationFile> lookup,
4460
IDictionary<string, DocumentationFile[]> folderLookup,
45-
int level,
46-
out List<DocumentationFolder> groupsInOrder,
47-
out List<MarkdownFile> filesInOrder
61+
int depth,
62+
out List<DocumentationGroup> groups,
63+
out List<MarkdownFile> files,
64+
out List<INavigationItem> navigationItems
4865
)
4966
{
50-
groupsInOrder = [];
51-
filesInOrder = [];
52-
MarkdownFile? index = null;
53-
foreach (var tocItem in toc)
67+
groups = [];
68+
navigationItems = [];
69+
files = [];
70+
MarkdownFile? indexFile = null;
71+
foreach (var (tocItem, index) in toc.Select((t, i) => (t, i)))
5472
{
5573
if (tocItem is FileReference file)
5674
{
@@ -61,17 +79,19 @@ out List<MarkdownFile> filesInOrder
6179

6280
if (file.Children.Count > 0 && d is MarkdownFile virtualIndex)
6381
{
64-
var group = new DocumentationFolder(file.Children, lookup, folderLookup, level + 1, virtualIndex)
82+
var group = new DocumentationGroup(file.Children, lookup, folderLookup, depth + 1, virtualIndex)
6583
{
6684
Parent = this
6785
};
68-
groupsInOrder.Add(group);
86+
groups.Add(group);
87+
navigationItems.Add(new GroupNavigation(index, depth, group));
6988
continue;
7089
}
7190

72-
filesInOrder.Add(md);
91+
files.Add(md);
92+
navigationItems.Add(new FileNavigation(index, depth, md));
7393
if (file.Path.EndsWith("index.md") && d is MarkdownFile i)
74-
index ??= i;
94+
indexFile ??= i;
7595
}
7696
else if (tocItem is FolderReference folder)
7797
{
@@ -84,15 +104,16 @@ out List<MarkdownFile> filesInOrder
84104
.ToArray();
85105
}
86106

87-
var group = new DocumentationFolder(children, lookup, folderLookup, level + 1)
107+
var group = new DocumentationGroup(children, lookup, folderLookup, depth + 1)
88108
{
89109
Parent = this
90110
};
91-
groupsInOrder.Add(group);
111+
groups.Add(group);
112+
navigationItems.Add(new GroupNavigation(index, depth, group));
92113
}
93114
}
94115

95-
return index ?? filesInOrder.FirstOrDefault();
116+
return indexFile ?? files.FirstOrDefault();
96117
}
97118

98119
public bool HoldsCurrent(MarkdownFile current) =>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Licensed to Elasticsearch B.V under one or more agreements.
2+
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
3+
// See the LICENSE file in the project root for more information
4+
5+
using System.Text.Json.Serialization;
6+
using Elastic.Markdown.IO.Discovery;
7+
8+
namespace Elastic.Markdown.IO.State;
9+
10+
public record GenerationState
11+
{
12+
[JsonPropertyName("last_seen_changes")]
13+
public required DateTimeOffset LastSeenChanges { get; init; }
14+
15+
[JsonPropertyName("invalid_files")]
16+
public required string[] InvalidFiles { get; init; } = [];
17+
18+
[JsonPropertyName("git")]
19+
public required GitCheckoutInformation Git { get; init; }
20+
}

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
// See the LICENSE file in the project root for more information
44

55
using System.Text.Json.Serialization;
6+
using Elastic.Markdown.IO.Discovery;
67

7-
namespace Elastic.Markdown.IO;
8+
namespace Elastic.Markdown.IO.State;
89

910
public record LinkReference
1011
{
1112
[JsonPropertyName("origin")]
12-
public required GitConfiguration Origin { get; init; }
13+
public required GitCheckoutInformation Origin { get; init; }
1314

1415
[JsonPropertyName("url_path_prefix")]
1516
public required string? UrlPathPrefix { get; init; }

src/Elastic.Markdown/Myst/Directives/IncludeBlock.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.IO.Abstractions;
55
using Elastic.Markdown.Diagnostics;
66
using Elastic.Markdown.IO;
7+
using Elastic.Markdown.IO.Configuration;
78
using Elastic.Markdown.Myst.FrontMatter;
89

910
namespace Elastic.Markdown.Myst.Directives;

src/Elastic.Markdown/Myst/Directives/SettingsBlock.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.IO.Abstractions;
55
using Elastic.Markdown.Diagnostics;
66
using Elastic.Markdown.IO;
7+
using Elastic.Markdown.IO.Configuration;
78
using Elastic.Markdown.Myst.FrontMatter;
89

910
namespace Elastic.Markdown.Myst.Directives;

src/Elastic.Markdown/Myst/MarkdownParser.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.IO.Abstractions;
66
using Cysharp.IO;
77
using Elastic.Markdown.IO;
8+
using Elastic.Markdown.IO.Configuration;
89
using Elastic.Markdown.Myst.CodeBlocks;
910
using Elastic.Markdown.Myst.Comments;
1011
using Elastic.Markdown.Myst.Directives;

src/Elastic.Markdown/Myst/ParserContext.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.IO.Abstractions;
66
using Elastic.Markdown.Diagnostics;
77
using Elastic.Markdown.IO;
8+
using Elastic.Markdown.IO.Configuration;
89
using Elastic.Markdown.Myst.FrontMatter;
910
using Markdig;
1011
using Markdig.Parsers;

src/Elastic.Markdown/Slices/Layout/_TocTree.cshtml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
</p>
99
<ul class="current">@await RenderPartialAsync(Elastic.Markdown.Slices.Layout._TocTreeNav.Create(new NavigationTreeItem
1010
{
11-
Level = Model.Tree.Level,
11+
Level = Model.Tree.Depth,
1212
SubTree = Model.Tree,
1313
CurrentDocument = Model.CurrentDocument
1414
}))

0 commit comments

Comments
 (0)