Skip to content

Commit

Permalink
Refactor navigation and model hierarchy. (#181)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Mpdreamz authored Jan 13, 2025
1 parent fbd89ea commit 80e512e
Show file tree
Hide file tree
Showing 20 changed files with 147 additions and 86 deletions.
5 changes: 3 additions & 2 deletions src/Elastic.Markdown/BuildContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.IO.Abstractions;
using Elastic.Markdown.Diagnostics;
using Elastic.Markdown.IO;
using Elastic.Markdown.IO.Discovery;

namespace Elastic.Markdown;

Expand All @@ -17,7 +18,7 @@ public record BuildContext

public IFileInfo ConfigurationPath { get; }

public GitConfiguration Git { get; }
public GitCheckoutInformation Git { get; }

public required DiagnosticsCollector Collector { get; init; }

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

Git = GitConfiguration.Create(ReadFileSystem);
Git = GitCheckoutInformation.Create(ReadFileSystem);
}

private IDirectoryInfo FindDocsFolderFromRoot(IDirectoryInfo rootPath)
Expand Down
20 changes: 1 addition & 19 deletions src/Elastic.Markdown/DocumentationGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,13 @@
using System.IO.Abstractions;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
using Elastic.Markdown.IO;
using Elastic.Markdown.IO.State;
using Elastic.Markdown.Slices;
using Microsoft.Extensions.Logging;

namespace Elastic.Markdown;

[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(GenerationState))]
[JsonSerializable(typeof(LinkReference))]
[JsonSerializable(typeof(GitConfiguration))]
internal partial class SourceGenerationContext : JsonSerializerContext;

public record GenerationState
{
[JsonPropertyName("last_seen_changes")]
public required DateTimeOffset LastSeenChanges { get; init; }

[JsonPropertyName("invalid_files")]
public required string[] InvalidFiles { get; init; } = [];

[JsonPropertyName("git")]
public required GitConfiguration Git { get; init; }
}

public class DocumentationGenerator
{
private readonly IFileSystem _readFileSystem;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
using YamlDotNet.Core;
using YamlDotNet.RepresentationModel;

namespace Elastic.Markdown.IO;
namespace Elastic.Markdown.IO.Configuration;

public record ConfigurationFile : DocumentationFile
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@
// 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

namespace Elastic.Markdown.IO;
namespace Elastic.Markdown.IO.Configuration;

public interface ITocItem;

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

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

public record TocReference(string Path, bool Found, IReadOnlyCollection<ITocItem> Children) : ITocItem;
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
using System.Text.Json.Serialization;
using SoftCircuits.IniFileParser;

namespace Elastic.Markdown.IO;
namespace Elastic.Markdown.IO.Discovery;

public record GitConfiguration
public record GitCheckoutInformation
{
private static GitConfiguration Unavailable { get; } = new()
private static GitCheckoutInformation Unavailable { get; } = new()
{
Branch = "unavailable",
Remote = "unavailable",
Expand All @@ -27,13 +27,13 @@ public record GitConfiguration
public required string Ref { get; init; }

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

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

return new GitConfiguration { Ref = gitRef, Branch = branch, Remote = remote };
return new GitCheckoutInformation { Ref = gitRef, Branch = branch, Remote = remote };

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

Expand Down
6 changes: 4 additions & 2 deletions src/Elastic.Markdown/IO/DocumentationSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

using System.IO.Abstractions;
using Elastic.Markdown.Diagnostics;
using Elastic.Markdown.IO.Configuration;
using Elastic.Markdown.IO.Navigation;
using Elastic.Markdown.Myst;

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

Tree = new DocumentationFolder(Configuration.TableOfContents, FlatMappedFiles, folderFiles)
Tree = new DocumentationGroup(Configuration.TableOfContents, FlatMappedFiles, folderFiles)
{
Parent = null
};
Expand Down Expand Up @@ -92,7 +94,7 @@ private DocumentationFile CreateMarkDownFile(IFileInfo file, BuildContext contex
return new ExcludedFile(file, SourcePath);
}

public DocumentationFolder Tree { get; }
public DocumentationGroup Tree { get; }

public List<DocumentationFile> Files { get; }

Expand Down
6 changes: 4 additions & 2 deletions src/Elastic.Markdown/IO/MarkdownFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information
using System.IO.Abstractions;
using Elastic.Markdown.Diagnostics;
using Elastic.Markdown.IO.Navigation;
using Elastic.Markdown.Myst;
using Elastic.Markdown.Myst.Directives;
using Elastic.Markdown.Myst.FrontMatter;
Expand All @@ -14,6 +15,7 @@

namespace Elastic.Markdown.IO;


public record MarkdownFile : DocumentationFile
{
private readonly SlugHelper _slugHelper = new();
Expand All @@ -31,7 +33,7 @@ public MarkdownFile(IFileInfo sourceFile, IDirectoryInfo rootPath, MarkdownParse

private DiagnosticsCollector Collector { get; }

public DocumentationFolder? Parent
public DocumentationGroup? Parent
{
get => FileName == "index.md" ? _parent?.Parent : _parent;
set => _parent = value;
Expand Down Expand Up @@ -59,7 +61,7 @@ public string? NavigationTitle
public string Url => $"{UrlPathPrefix}/{RelativePath.Replace(".md", ".html")}";

private bool _instructionsParsed;
private DocumentationFolder? _parent;
private DocumentationGroup? _parent;

public MarkdownFile[] YieldParents()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,50 @@
// 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

namespace Elastic.Markdown.IO;
using Elastic.Markdown.IO.Configuration;

public class DocumentationFolder
namespace Elastic.Markdown.IO.Navigation;

public interface INavigationItem
{
int Order { get; }
int Depth { get; }
}

public record GroupNavigation(int Order, int Depth, DocumentationGroup Group) : INavigationItem;
public record FileNavigation(int Order, int Depth, MarkdownFile File) : INavigationItem;


public class DocumentationGroup
{
public MarkdownFile? Index { get; set; }

public List<MarkdownFile> FilesInOrder { get; }
public List<DocumentationFolder> GroupsInOrder { get; }
private IReadOnlyCollection<MarkdownFile> FilesInOrder { get; }

private IReadOnlyCollection<DocumentationGroup> GroupsInOrder { get; }

public IReadOnlyCollection<INavigationItem> NavigationItems { get; }

public required DocumentationFolder? Parent { get; init; }
public required DocumentationGroup? Parent { get; init; }

private HashSet<MarkdownFile> OwnFiles { get; }

public int Level { get; }
public int Depth { get; }

public DocumentationFolder(
public DocumentationGroup(
IReadOnlyCollection<ITocItem> toc,
IDictionary<string, DocumentationFile> lookup,
IDictionary<string, DocumentationFile[]> folderLookup,
int level = 0,
int depth = 0,
MarkdownFile? index = null
)
{
Level = level;
var foundIndex = ProcessTocItems(toc, lookup, folderLookup, level, out var groupsInOrder, out var filesInOrder);
Depth = depth;
var foundIndex = ProcessTocItems(toc, lookup, folderLookup, depth, out var groups, out var files, out var navigationItems);

GroupsInOrder = groupsInOrder;
FilesInOrder = filesInOrder;
GroupsInOrder = groups;
FilesInOrder = files;
NavigationItems = navigationItems;
Index = index ?? foundIndex;

if (Index is not null)
Expand All @@ -42,15 +58,17 @@ public DocumentationFolder(
IReadOnlyCollection<ITocItem> toc,
IDictionary<string, DocumentationFile> lookup,
IDictionary<string, DocumentationFile[]> folderLookup,
int level,
out List<DocumentationFolder> groupsInOrder,
out List<MarkdownFile> filesInOrder
int depth,
out List<DocumentationGroup> groups,
out List<MarkdownFile> files,
out List<INavigationItem> navigationItems
)
{
groupsInOrder = [];
filesInOrder = [];
MarkdownFile? index = null;
foreach (var tocItem in toc)
groups = [];
navigationItems = [];
files = [];
MarkdownFile? indexFile = null;
foreach (var (tocItem, index) in toc.Select((t, i) => (t, i)))
{
if (tocItem is FileReference file)
{
Expand All @@ -61,17 +79,19 @@ out List<MarkdownFile> filesInOrder

if (file.Children.Count > 0 && d is MarkdownFile virtualIndex)
{
var group = new DocumentationFolder(file.Children, lookup, folderLookup, level + 1, virtualIndex)
var group = new DocumentationGroup(file.Children, lookup, folderLookup, depth + 1, virtualIndex)
{
Parent = this
};
groupsInOrder.Add(group);
groups.Add(group);
navigationItems.Add(new GroupNavigation(index, depth, group));
continue;
}

filesInOrder.Add(md);
files.Add(md);
navigationItems.Add(new FileNavigation(index, depth, md));
if (file.Path.EndsWith("index.md") && d is MarkdownFile i)
index ??= i;
indexFile ??= i;
}
else if (tocItem is FolderReference folder)
{
Expand All @@ -84,15 +104,16 @@ out List<MarkdownFile> filesInOrder
.ToArray();
}

var group = new DocumentationFolder(children, lookup, folderLookup, level + 1)
var group = new DocumentationGroup(children, lookup, folderLookup, depth + 1)
{
Parent = this
};
groupsInOrder.Add(group);
groups.Add(group);
navigationItems.Add(new GroupNavigation(index, depth, group));
}
}

return index ?? filesInOrder.FirstOrDefault();
return indexFile ?? files.FirstOrDefault();
}

public bool HoldsCurrent(MarkdownFile current) =>
Expand Down
20 changes: 20 additions & 0 deletions src/Elastic.Markdown/IO/State/GenerationState.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Licensed to Elasticsearch B.V under one or more agreements.
// 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.Text.Json.Serialization;
using Elastic.Markdown.IO.Discovery;

namespace Elastic.Markdown.IO.State;

public record GenerationState
{
[JsonPropertyName("last_seen_changes")]
public required DateTimeOffset LastSeenChanges { get; init; }

[JsonPropertyName("invalid_files")]
public required string[] InvalidFiles { get; init; } = [];

[JsonPropertyName("git")]
public required GitCheckoutInformation Git { get; init; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
// See the LICENSE file in the project root for more information

using System.Text.Json.Serialization;
using Elastic.Markdown.IO.Discovery;

namespace Elastic.Markdown.IO;
namespace Elastic.Markdown.IO.State;

public record LinkReference
{
[JsonPropertyName("origin")]
public required GitConfiguration Origin { get; init; }
public required GitCheckoutInformation Origin { get; init; }

[JsonPropertyName("url_path_prefix")]
public required string? UrlPathPrefix { get; init; }
Expand Down
1 change: 1 addition & 0 deletions src/Elastic.Markdown/Myst/Directives/IncludeBlock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.IO.Abstractions;
using Elastic.Markdown.Diagnostics;
using Elastic.Markdown.IO;
using Elastic.Markdown.IO.Configuration;
using Elastic.Markdown.Myst.FrontMatter;

namespace Elastic.Markdown.Myst.Directives;
Expand Down
1 change: 1 addition & 0 deletions src/Elastic.Markdown/Myst/Directives/SettingsBlock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.IO.Abstractions;
using Elastic.Markdown.Diagnostics;
using Elastic.Markdown.IO;
using Elastic.Markdown.IO.Configuration;
using Elastic.Markdown.Myst.FrontMatter;

namespace Elastic.Markdown.Myst.Directives;
Expand Down
1 change: 1 addition & 0 deletions src/Elastic.Markdown/Myst/MarkdownParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.IO.Abstractions;
using Cysharp.IO;
using Elastic.Markdown.IO;
using Elastic.Markdown.IO.Configuration;
using Elastic.Markdown.Myst.CodeBlocks;
using Elastic.Markdown.Myst.Comments;
using Elastic.Markdown.Myst.Directives;
Expand Down
1 change: 1 addition & 0 deletions src/Elastic.Markdown/Myst/ParserContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.IO.Abstractions;
using Elastic.Markdown.Diagnostics;
using Elastic.Markdown.IO;
using Elastic.Markdown.IO.Configuration;
using Elastic.Markdown.Myst.FrontMatter;
using Markdig;
using Markdig.Parsers;
Expand Down
2 changes: 1 addition & 1 deletion src/Elastic.Markdown/Slices/Layout/_TocTree.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
</p>
<ul class="current">@await RenderPartialAsync(Elastic.Markdown.Slices.Layout._TocTreeNav.Create(new NavigationTreeItem
{
Level = Model.Tree.Level,
Level = Model.Tree.Depth,
SubTree = Model.Tree,
CurrentDocument = Model.CurrentDocument
}))
Expand Down
Loading

0 comments on commit 80e512e

Please sign in to comment.