Skip to content

Use global navigation to compute prev/next #1095

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
Apr 11, 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
5 changes: 3 additions & 2 deletions src/Elastic.Markdown/DocumentationGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ public DocumentationGenerator(
IDocumentationFileOutputProvider? documentationFileOutputProvider = null,
IDocumentationFileExporter? documentationExporter = null,
IConversionCollector? conversionCollector = null,
IHistoryMapper? historyMapper = null
IHistoryMapper? historyMapper = null,
IPositionalNavigation? positionalNavigation = null
)
{
_documentationFileOutputProvider = documentationFileOutputProvider;
Expand All @@ -57,7 +58,7 @@ public DocumentationGenerator(
DocumentationSet = docSet;
Context = docSet.Build;
Resolver = docSet.LinkResolver;
HtmlWriter = new HtmlWriter(DocumentationSet, _writeFileSystem, new DescriptionGenerator(), navigationHtmlWriter, historyMapper);
HtmlWriter = new HtmlWriter(DocumentationSet, _writeFileSystem, new DescriptionGenerator(), navigationHtmlWriter, historyMapper, positionalNavigation);
_documentationFileExporter =
documentationExporter
?? docSet.Build.Configuration.EnabledExtensions.FirstOrDefault(e => e.FileExporter != null)?.FileExporter
Expand Down
8 changes: 7 additions & 1 deletion src/Elastic.Markdown/IO/DocumentationSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ public interface INavigationLookups
FrozenDictionary<string, DocumentationFile[]> FilesGroupedByFolder { get; }
}

public interface IPositionalNavigation
{
MarkdownFile? GetPrevious(MarkdownFile current);
MarkdownFile? GetNext(MarkdownFile current);
}

public record NavigationLookups : INavigationLookups
{
public required FrozenDictionary<string, DocumentationFile> FlatMappedFiles { get; init; }
Expand All @@ -33,7 +39,7 @@ public record NavigationLookups : INavigationLookups
//public required FrozenDictionary<Uri, TableOfContentsReference> IndexedTableOfContents { get; init; }
}

public class DocumentationSet : INavigationLookups
public class DocumentationSet : INavigationLookups, IPositionalNavigation
{
public BuildContext Build { get; }
public string Name { get; }
Expand Down
2 changes: 1 addition & 1 deletion src/Elastic.Markdown/IO/MarkdownFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ public string Url
}
}

public int NavigationIndex { get; internal set; } = -1;
public int NavigationIndex { get; set; } = -1;

public string? GroupId { get; set; }

Expand Down
10 changes: 7 additions & 3 deletions src/Elastic.Markdown/Slices/HtmlWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,16 @@ public class HtmlWriter(
IFileSystem writeFileSystem,
IDescriptionGenerator descriptionGenerator,
INavigationHtmlWriter? navigationHtmlWriter = null,
IHistoryMapper? historyMapper = null)
IHistoryMapper? historyMapper = null,
IPositionalNavigation? positionalNavigation = null
)
{
private DocumentationSet DocumentationSet { get; } = documentationSet;
public INavigationHtmlWriter NavigationHtmlWriter { get; } = navigationHtmlWriter ?? new IsolatedBuildNavigationHtmlWriter(documentationSet);
private StaticFileContentHashProvider StaticFileContentHashProvider { get; } = new(new EmbeddedOrPhysicalFileProvider(documentationSet.Build));
private IHistoryMapper HistoryMapper { get; } = historyMapper ?? new BypassHistoryMapper();
private IPositionalNavigation PositionalNavigation { get; } = positionalNavigation ?? documentationSet;

public async Task<string> RenderLayout(MarkdownFile markdown, Cancel ctx = default)
{
var document = await markdown.ParseFullAsync(ctx);
Expand All @@ -87,8 +91,8 @@ private async Task<string> RenderLayout(MarkdownFile markdown, MarkdownDocument

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

var previous = DocumentationSet.GetPrevious(markdown);
var next = DocumentationSet.GetNext(markdown);
var previous = PositionalNavigation.GetPrevious(markdown);
var next = PositionalNavigation.GetNext(markdown);

var remote = DocumentationSet.Build.Git.RepositoryName;
var branch = DocumentationSet.Build.Git.Branch;
Expand Down
12 changes: 9 additions & 3 deletions src/docs-assembler/Building/AssemblerBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ namespace Documentation.Assembler.Building;
public class AssemblerBuilder(
ILoggerFactory logger,
AssembleContext context,
GlobalNavigation navigation,
GlobalNavigationHtmlWriter writer,
GlobalNavigationPathProvider pathProvider,
IHistoryMapper? historyMapper
)
IHistoryMapper? historyMapper)
{
private GlobalNavigationHtmlWriter HtmlWriter { get; } = writer;

Expand Down Expand Up @@ -58,7 +58,13 @@ public async Task BuildAllAsync(FrozenDictionary<string, AssemblerDocumentationS

private async Task BuildAsync(AssemblerDocumentationSet set, Cancel ctx)
{
var generator = new DocumentationGenerator(set.DocumentationSet, logger, HtmlWriter, pathProvider, historyMapper: HistoryMapper);
var generator = new DocumentationGenerator(
set.DocumentationSet,
logger, HtmlWriter,
pathProvider,
historyMapper: HistoryMapper,
positionalNavigation: navigation
);
await generator.GenerateAll(ctx);
}

Expand Down
2 changes: 1 addition & 1 deletion src/docs-assembler/Cli/RepositoryCommands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ public async Task<int> BuildAll(

var historyMapper = new PageHistoryMapper(assembleSources.HistoryMappings);

var builder = new AssemblerBuilder(logger, assembleContext, htmlWriter, pathProvider, historyMapper);
var builder = new AssemblerBuilder(logger, assembleContext, navigation, htmlWriter, pathProvider, historyMapper);
await builder.BuildAllAsync(assembleSources.AssembleSets, ctx);

var sitemapBuilder = new SitemapBuilder(navigation.NavigationItems, assembleContext.WriteFileSystem, assembleContext.OutputDirectory);
Expand Down
84 changes: 72 additions & 12 deletions src/docs-assembler/Navigation/GlobalNavigation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace Documentation.Assembler.Navigation;

public record GlobalNavigation
public record GlobalNavigation : IPositionalNavigation
{
private readonly AssembleSources _assembleSources;
private readonly GlobalNavigationFile _navigationFile;
Expand All @@ -25,8 +25,40 @@ public GlobalNavigation(AssembleSources assembleSources, GlobalNavigationFile na
_assembleSources = assembleSources;
_navigationFile = navigationFile;
NavigationItems = BuildNavigation(navigationFile.TableOfContents, 0);
var navigationIndex = 0;
var markdownFiles = new HashSet<MarkdownFile>();
UpdateNavigationIndex(markdownFiles, NavigationItems, ref navigationIndex);
TopLevelItems = NavigationItems.OfType<TocNavigationItem>().ToList();
NavigationLookup = TopLevelItems.ToDictionary(kv => kv.Source, kv => kv);
var grouped = markdownFiles.GroupBy(f => f.NavigationIndex).ToList();
var files = grouped
.Select(g => g.First())
.ToList();

MarkdownFiles = files.Where(f => f.NavigationIndex > -1).ToDictionary(i => i.NavigationIndex, i => i).ToFrozenDictionary();
}

public FrozenDictionary<int, MarkdownFile> MarkdownFiles { get; set; }

private static void UpdateNavigationIndex(HashSet<MarkdownFile> markdownFiles, IReadOnlyCollection<INavigationItem> navigationItems, ref int navigationIndex)
{
foreach (var item in navigationItems)
{
switch (item)
{
case FileNavigationItem fileNavigationItem:
var fileIndex = Interlocked.Increment(ref navigationIndex);
fileNavigationItem.File.NavigationIndex = fileIndex;
_ = markdownFiles.Add(fileNavigationItem.File);
break;
case GroupNavigationItem { Group.Index: not null } groupNavigationItem:
var index = Interlocked.Increment(ref navigationIndex);
groupNavigationItem.Group.Index.NavigationIndex = index;
_ = markdownFiles.Add(groupNavigationItem.Group.Index);
UpdateNavigationIndex(markdownFiles, groupNavigationItem.Group.NavigationItems, ref navigationIndex);
break;
}
}
}

private IReadOnlyCollection<INavigationItem> BuildNavigation(IReadOnlyCollection<TocReference> node, int depth)
Expand All @@ -46,8 +78,8 @@ private IReadOnlyCollection<INavigationItem> BuildNavigation(IReadOnlyCollection
continue;
}

// TODO passing DocumentationSet to TableOfContentsTree constructr is temporary
// We only build this fallback in order to aid with bootstrapping the navigaton
// TODO passing DocumentationSet to TableOfContentsTree constructor is temporary
// We only build this fallback in order to aid with bootstrapping the navigation
if (!_assembleSources.TreeCollector.TryGetTableOfContentsTree(topLevel.TopLevelSource, out tree))
{
_navigationFile.EmitError(
Expand Down Expand Up @@ -86,13 +118,14 @@ private IReadOnlyCollection<INavigationItem> BuildNavigation(IReadOnlyCollection

var cleanNavigationItems = new List<INavigationItem>();
var seenSources = new HashSet<Uri>();
foreach (var allNavigationItem in allNavigationItems)
foreach (var item in allNavigationItems)
{
if (allNavigationItem is not TocNavigationItem tocNav)
if (item is not TocNavigationItem tocNav)
{
cleanNavigationItems.Add(allNavigationItem);
cleanNavigationItems.Add(item);
continue;
}

if (seenSources.Contains(tocNav.Source))
continue;

Expand All @@ -103,20 +136,47 @@ private IReadOnlyCollection<INavigationItem> BuildNavigation(IReadOnlyCollection
continue;

_ = seenSources.Add(tocNav.Source);
cleanNavigationItems.Add(allNavigationItem);
cleanNavigationItems.Add(item);
}

tree.NavigationItems = cleanNavigationItems.ToArray();
var navigationItem = new TocNavigationItem(i, depth, tree, toc.Source);
if (toc.Source == new Uri("docs-content://reference"))
{
}


list.Add(navigationItem);
i++;
}

return list.ToArray().AsReadOnly();
}

public MarkdownFile? GetPrevious(MarkdownFile current)
{
var index = current.NavigationIndex;
do
{
var previous = MarkdownFiles.GetValueOrDefault(index - 1);
if (previous is null)
return null;
if (!previous.Hidden)
return previous;
index--;
} while (index >= 0);

return null;
}

public MarkdownFile? GetNext(MarkdownFile current)
{
var index = current.NavigationIndex;
do
{
var previous = MarkdownFiles.GetValueOrDefault(index + 1);
if (previous is null)
return null;
if (!previous.Hidden)
return previous;
index++;
} while (index <= MarkdownFiles.Count);

return null;
}
}
Loading