Skip to content

Keep track of navigation source on markdown files for easier root navigation lookups in assembler #862

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/Elastic.Markdown/IO/MarkdownFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,15 @@ DocumentationSet set
//todo refactor mutability of MarkdownFile as a whole
ScopeDirectory = build.Configuration.ScopeDirectory;
NavigationRoot = set.Tree;
NavigationSource = set.Source;
}

public IDirectoryInfo ScopeDirectory { get; set; }

public INavigation NavigationRoot { get; set; }

public Uri NavigationSource { get; set; }

public string Id { get; } = Guid.NewGuid().ToString("N")[..8];

private DiagnosticsCollector Collector { get; }
Expand Down
24 changes: 16 additions & 8 deletions src/Elastic.Markdown/IO/Navigation/DocumentationGroup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public TableOfContentsTree(
NavigationLookups lookups,
TableOfContentsTreeCollector treeCollector,
ref int fileIndex)
: base(treeCollector, context, lookups, ref fileIndex)
: base(treeCollector, context, lookups, source, ref fileIndex)
{
TreeCollector = treeCollector;
NavigationRoot = this;
Expand All @@ -101,7 +101,7 @@ internal TableOfContentsTree(
DocumentationGroup? toplevelTree,
DocumentationGroup? parent,
MarkdownFile? index = null
) : base(folderName, treeCollector, context, lookups, ref fileIndex, depth, toplevelTree, parent, index)
) : base(folderName, treeCollector, context, lookups, source, ref fileIndex, depth, toplevelTree, parent, index)
{
Source = source;
TreeCollector = treeCollector;
Expand All @@ -123,6 +123,8 @@ public class DocumentationGroup : INavigation

public INavigation NavigationRoot { get; set; }

public Uri NavigationSource { get; set; }

public MarkdownFile? Index { get; set; }

private IReadOnlyCollection<MarkdownFile> FilesInOrder { get; }
Expand All @@ -141,20 +143,25 @@ public class DocumentationGroup : INavigation

protected virtual DocumentationGroup DefaultNavigation => this;

public DocumentationGroup(
protected DocumentationGroup(
TableOfContentsTreeCollector treeCollector,
BuildContext context,
NavigationLookups lookups,
Uri navigationSource,
ref int fileIndex
)
: this(".", treeCollector, context, lookups, ref fileIndex, depth: 0, null, null) =>
: this(".", treeCollector, context, lookups, navigationSource, ref fileIndex, depth: 0, null, null)
{
NavigationSource = navigationSource;
_treeCollector = treeCollector;
}

internal DocumentationGroup(
string folderName,
TableOfContentsTreeCollector treeCollector,
BuildContext context,
NavigationLookups lookups,
Uri navigationSource,
ref int fileIndex,
int depth,
DocumentationGroup? toplevelTree,
Expand All @@ -163,6 +170,7 @@ internal DocumentationGroup(
)
{
FolderName = folderName;
NavigationSource = navigationSource;
_treeCollector = treeCollector;
Depth = depth;
Parent = parent;
Expand Down Expand Up @@ -227,6 +235,7 @@ internal DocumentationGroup(
md.NavigationIndex = navigationIndex;
md.ScopeDirectory = file.TableOfContentsScope.ScopeDirectory;
md.NavigationRoot = topLevelGroup;
md.NavigationSource = NavigationSource;

foreach (var extension in context.Configuration.EnabledExtensions)
extension.Visit(d, tocItem);
Expand All @@ -239,7 +248,7 @@ internal DocumentationGroup(
_treeCollector, context, lookups with
{
TableOfContents = file.Children
}, ref fileIndex, depth + 1, topLevelGroup, this, virtualIndex);
}, NavigationSource, ref fileIndex, depth + 1, topLevelGroup, this, virtualIndex);
groups.Add(group);
navigationItems.Add(new GroupNavigationItem(index, depth, group));
continue;
Expand Down Expand Up @@ -267,6 +276,7 @@ .. documentationFiles
.Select(d => new FileReference(folder.TableOfContentsScope, d.RelativePath, true, false, []))
];
}

DocumentationGroup group;
if (folder is TocReference tocReference)
{
Expand All @@ -275,8 +285,6 @@ .. documentationFiles
TableOfContents = children
}, ref fileIndex, depth + 1, topLevelGroup, this);

//if (lookups.IndexedTableOfContents.TryGetValue(tocReference.Source, out var indexedToc))
// toc.NavigationItems = toc.NavigationItems.Concat(indexedToc.Children).ToArray();
group = toc;
navigationItems.Add(new TocNavigationItem(index, depth, toc, tocReference.Source));
}
Expand All @@ -285,7 +293,7 @@ .. documentationFiles
group = new DocumentationGroup(folder.Path, _treeCollector, context, lookups with
{
TableOfContents = children
}, ref fileIndex, depth + 1, topLevelGroup, this);
}, NavigationSource, ref fileIndex, depth + 1, topLevelGroup, this);
navigationItems.Add(new GroupNavigationItem(index, depth, group));
}

Expand Down
6 changes: 3 additions & 3 deletions src/Elastic.Markdown/Slices/HtmlWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace Elastic.Markdown.Slices;

public interface INavigationHtmlWriter
{
Task<string> RenderNavigation(INavigation currentRootNavigation, Cancel ctx = default);
Task<string> RenderNavigation(INavigation currentRootNavigation, Uri navigationSource, Cancel ctx = default);

async Task<string> Render(NavigationViewModel model, Cancel ctx)
{
Expand All @@ -30,7 +30,7 @@ public class IsolatedBuildNavigationHtmlWriter(DocumentationSet set) : INavigati

private readonly ConcurrentDictionary<string, string> _renderedNavigationCache = [];

public async Task<string> RenderNavigation(INavigation currentRootNavigation, Cancel ctx = default)
public async Task<string> RenderNavigation(INavigation currentRootNavigation, Uri navigationSource, Cancel ctx = default)
{
var navigation = Set.Configuration.Features.IsPrimaryNavEnabled
? currentRootNavigation
Expand Down Expand Up @@ -84,7 +84,7 @@ private async Task<string> RenderLayout(MarkdownFile markdown, MarkdownDocument
var html = markdown.CreateHtml(document);
await DocumentationSet.Tree.Resolve(ctx);

var navigationHtml = await NavigationHtmlWriter.RenderNavigation(markdown.NavigationRoot, ctx);
var navigationHtml = await NavigationHtmlWriter.RenderNavigation(markdown.NavigationRoot, markdown.NavigationSource, ctx);

var previous = DocumentationSet.GetPrevious(markdown);
var next = DocumentationSet.GetNext(markdown);
Expand Down
46 changes: 26 additions & 20 deletions src/docs-assembler/Navigation/GlobalNavigationHtmlWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

using System.Collections.Concurrent;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using Elastic.Markdown.IO.Navigation;
using Elastic.Markdown.Slices;

Expand All @@ -19,46 +20,51 @@ public class GlobalNavigationHtmlWriter(

private ImmutableHashSet<Uri> Phantoms { get; } = [.. navigationFile.Phantoms.Select(p => p.Source)];

private (DocumentationGroup, Uri) GetRealNavigationRoot(TableOfContentsTree tree)
private bool TryGetNavigationRoot(
Uri navigationSource,
[NotNullWhen(true)] out TableOfContentsTree? navigationRoot,
[NotNullWhen(true)] out Uri? navigationRootSource
)
{
if (!assembleSources.TocTopLevelMappings.TryGetValue(tree.Source, out var topLevelUri))
navigationRoot = null;
navigationRootSource = null;
if (!assembleSources.TocTopLevelMappings.TryGetValue(navigationSource, out var topLevelMapping))
{
assembleContext.Collector.EmitWarning(assembleContext.NavigationPath.FullName, $"Could not find a top level mapping for {tree.Source}");
return (tree, tree.Source);
assembleContext.Collector.EmitWarning(assembleContext.NavigationPath.FullName, $"Could not find a top level mapping for {navigationSource}");
return false;
}

if (!assembleSources.TreeCollector.TryGetTableOfContentsTree(topLevelUri.TopLevelSource, out var topLevel))
if (!assembleSources.TreeCollector.TryGetTableOfContentsTree(topLevelMapping.TopLevelSource, out navigationRoot))
{
assembleContext.Collector.EmitWarning(assembleContext.NavigationPath.FullName, $"Could not find a toc tree for {topLevelUri.TopLevelSource}");
return (tree, tree.Source);

assembleContext.Collector.EmitWarning(assembleContext.NavigationPath.FullName, $"Could not find a toc tree for {topLevelMapping.TopLevelSource}");
return false;
}
return (topLevel, topLevelUri.TopLevelSource);
navigationRootSource = topLevelMapping.TopLevelSource;
return true;
}

public async Task<string> RenderNavigation(INavigation currentRootNavigation, Cancel ctx = default)
public async Task<string> RenderNavigation(INavigation currentRootNavigation, Uri navigationSource, Cancel ctx = default)
{
if (currentRootNavigation is not TableOfContentsTree tree)
throw new InvalidOperationException($"Expected a {nameof(DocumentationGroup)}");
if (!TryGetNavigationRoot(navigationSource, out var navigationRoot, out var navigationRootSource))
return string.Empty;

if (Phantoms.Contains(tree.Source))
if (Phantoms.Contains(navigationRootSource))
return string.Empty;

var (navigation, source) = GetRealNavigationRoot(tree);
if (_renderedNavigationCache.TryGetValue(source, out var value))
if (_renderedNavigationCache.TryGetValue(navigationRootSource, out var value))
return value;

if (source == new Uri("docs-content:///"))
if (navigationRootSource == new Uri("docs-content:///"))
{
_renderedNavigationCache[source] = string.Empty;
_renderedNavigationCache[navigationRootSource] = string.Empty;
return string.Empty;
}

Console.WriteLine($"Rendering navigation for {source}");
Console.WriteLine($"Rendering navigation for {navigationRootSource}");

var model = CreateNavigationModel(navigation);
var model = CreateNavigationModel(navigationRoot);
value = await ((INavigationHtmlWriter)this).Render(model, ctx);
_renderedNavigationCache[source] = value;
_renderedNavigationCache[navigationRootSource] = value;

return value;
}
Expand Down
Loading