Skip to content

Commit

Permalink
Introduce toc.yml, allows toc's to be split one directory deep (#165)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mpdreamz authored Jan 10, 2025
1 parent 03c22a2 commit 085b9fe
Show file tree
Hide file tree
Showing 13 changed files with 112 additions and 24 deletions.
1 change: 1 addition & 0 deletions docs-builder.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/UserDictionary/Words/=docset/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=linenos/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=literalinclude/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
6 changes: 6 additions & 0 deletions docs/source/development/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
title: Development Guide
navigation_title: Development
---

TODO write development documentation here
2 changes: 2 additions & 0 deletions docs/source/development/toc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
toc:
- file: index.md
3 changes: 3 additions & 0 deletions docs/source/docset.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ toc:
- file: tabs.md
- file: tagged_regions.md
- file: titles.md
# nested TOCs are only allowed from docset.yml
# to prevent them from being nested deeply arbitrarily
- toc: development
- folder: testing
children:
- file: index.md
Expand Down
63 changes: 52 additions & 11 deletions src/Elastic.Markdown/IO/ConfigurationFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public record ConfigurationFile : DocumentationFile
private readonly IFileInfo _sourceFile;
private readonly IDirectoryInfo _rootPath;
private readonly BuildContext _context;
private readonly int _depth;
public string? Project { get; }
public Glob[] Exclude { get; } = [];

Expand All @@ -28,12 +29,13 @@ public record ConfigurationFile : DocumentationFile
private readonly Dictionary<string, string> _substitutions = new(StringComparer.OrdinalIgnoreCase);
public IReadOnlyDictionary<string, string> Substitutions => _substitutions;

public ConfigurationFile(IFileInfo sourceFile, IDirectoryInfo rootPath, BuildContext context)
public ConfigurationFile(IFileInfo sourceFile, IDirectoryInfo rootPath, BuildContext context, int depth = 0, string parentPath = "")
: base(sourceFile, rootPath)
{
_sourceFile = sourceFile;
_rootPath = rootPath;
_context = context;
_depth = depth;
if (!sourceFile.Exists)
{
Project = "unknown";
Expand Down Expand Up @@ -81,7 +83,13 @@ public ConfigurationFile(IFileInfo sourceFile, IDirectoryInfo rootPath, BuildCon
ExternalLinkHosts.Add(host);
break;
case "toc":
var entries = ReadChildren(entry, string.Empty);
if (depth > 1)
{
EmitError($"toc.yml files may only be linked from docset.yml", entry.Key);
break;
}

var entries = ReadChildren(entry, parentPath);

TableOfContents = entries;
break;
Expand Down Expand Up @@ -115,20 +123,19 @@ private List<ITocItem> ReadChildren(KeyValuePair<YamlNode, YamlNode> entry, stri
return entries;
}

foreach (var tocEntry in sequence.Children.OfType<YamlMappingNode>())
{
var tocItem = ReadChild(tocEntry, parentPath);
if (tocItem is not null)
entries.Add(tocItem);
}
entries.AddRange(
sequence.Children.OfType<YamlMappingNode>()
.SelectMany(tocEntry => ReadChild(tocEntry, parentPath) ?? [])
);

return entries;
}

private ITocItem? ReadChild(YamlMappingNode tocEntry, string parentPath)
private IEnumerable<ITocItem>? ReadChild(YamlMappingNode tocEntry, string parentPath)
{
string? file = null;
string? folder = null;
ConfigurationFile? toc = null;
var fileFound = false;
var folderFound = false;
IReadOnlyCollection<ITocItem>? children = null;
Expand All @@ -137,6 +144,9 @@ private List<ITocItem> ReadChildren(KeyValuePair<YamlNode, YamlNode> entry, stri
var key = ((YamlScalarNode)entry.Key).Value;
switch (key)
{
case "toc":
toc = ReadNestedToc(entry, parentPath, out fileFound);
break;
case "file":
file = ReadFile(entry, parentPath, out fileFound);
break;
Expand All @@ -150,15 +160,23 @@ private List<ITocItem> ReadChildren(KeyValuePair<YamlNode, YamlNode> entry, stri
}
}

if (toc is not null)
{
foreach (var f in toc.Files)
Files.Add(f);

return [new FolderReference($"{parentPath}".TrimStart('/'), folderFound, toc.TableOfContents)];
}

if (file is not null)
return new TocFile($"{parentPath}/{file}".TrimStart('/'), fileFound, children ?? []);
return [new FileReference($"{parentPath}/{file}".TrimStart('/'), fileFound, children ?? [])];

if (folder is not null)
{
if (children is null)
ImplicitFolders.Add(parentPath.TrimStart('/'));

return new TocFolder($"{parentPath}".TrimStart('/'), folderFound, children ?? []);
return [new FolderReference($"{parentPath}".TrimStart('/'), folderFound, children ?? [])];
}

return null;
Expand Down Expand Up @@ -226,6 +244,29 @@ private Dictionary<string, string> ReadDictionary(KeyValuePair<YamlNode, YamlNod
return file;
}

private ConfigurationFile? ReadNestedToc(KeyValuePair<YamlNode, YamlNode> entry, string parentPath, out bool found)
{
found = false;
var tocPath = ReadString(entry);
if (tocPath is null)
{
EmitError($"Empty toc: reference", entry.Key);
return null;
}

var rootPath = _context.ReadFileSystem.DirectoryInfo.New(Path.Combine(_rootPath.FullName, tocPath));
var path = Path.Combine(rootPath.FullName, "toc.yml");
var source = _context.ReadFileSystem.FileInfo.New(path);
if (!source.Exists)
EmitError($"Nested toc: '{source.FullName}' does not exist", entry.Key);
else
found = true;

var nestedConfiguration = new ConfigurationFile(source, _rootPath, _context, _depth + 1, tocPath);
return nestedConfiguration;
}


private string? ReadString(KeyValuePair<YamlNode, YamlNode> entry)
{
if (entry.Value is YamlScalarNode scalar)
Expand Down
9 changes: 3 additions & 6 deletions src/Elastic.Markdown/IO/DocumentationFolder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,7 @@ public DocumentationFolder(
Index = index ?? foundIndex;

if (Index is not null)
{
FilesInOrder = FilesInOrder.Except([Index]).ToList();
Index.Parent ??= this;
}

OwnFiles = [.. FilesInOrder];
}
Expand All @@ -55,7 +52,7 @@ out List<MarkdownFile> filesInOrder
MarkdownFile? index = null;
foreach (var tocItem in toc)
{
if (tocItem is TocFile file)
if (tocItem is FileReference file)
{
if (!lookup.TryGetValue(file.Path, out var d) || d is not MarkdownFile md)
continue;
Expand All @@ -76,14 +73,14 @@ out List<MarkdownFile> filesInOrder
if (file.Path.EndsWith("index.md") && d is MarkdownFile i)
index ??= i;
}
else if (tocItem is TocFolder folder)
else if (tocItem is FolderReference folder)
{
var children = folder.Children;
if (children.Count == 0
&& folderLookup.TryGetValue(folder.Path, out var documentationFiles))
{
children = documentationFiles
.Select(d => new TocFile(d.RelativePath, true, []))
.Select(d => new FileReference(d.RelativePath, true, []))
.ToArray();
}

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

public interface ITocItem;

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

public record TocFolder(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;
7 changes: 6 additions & 1 deletion src/Elastic.Markdown/IO/MarkdownFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ public MarkdownFile(IFileInfo sourceFile, IDirectoryInfo rootPath, MarkdownParse

private DiagnosticsCollector Collector { get; }

public DocumentationFolder? Parent { get; set; }
public DocumentationFolder? Parent
{
get => FileName == "index.md" ? _parent?.Parent : _parent;
set => _parent = value;
}

public string? UrlPathPrefix { get; }
private MarkdownParser MarkdownParser { get; }
Expand All @@ -55,6 +59,7 @@ public string? NavigationTitle
public string Url => $"{UrlPathPrefix}/{RelativePath.Replace(".md", ".html")}";

private bool _instructionsParsed;
private DocumentationFolder? _parent;

public MarkdownFile[] YieldParents()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using FluentAssertions;
using Xunit.Abstractions;

namespace Elastic.Markdown.Tests.SiteMap;
namespace Elastic.Markdown.Tests.DocSet;

public class BreadCrumbTests(ITestOutputHelper output) : NavigationTestsBase(output)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using FluentAssertions;
using Xunit.Abstractions;

namespace Elastic.Markdown.Tests.SiteMap;
namespace Elastic.Markdown.Tests.DocSet;

public class LinkReferenceTests(ITestOutputHelper output) : NavigationTestsBase(output)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using FluentAssertions;
using Xunit.Abstractions;

namespace Elastic.Markdown.Tests.SiteMap;
namespace Elastic.Markdown.Tests.DocSet;

public class NavigationTests(ITestOutputHelper output) : NavigationTestsBase(output)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
using FluentAssertions;
using Xunit.Abstractions;

namespace Elastic.Markdown.Tests.SiteMap;
namespace Elastic.Markdown.Tests.DocSet;

public class NavigationTestsBase : IAsyncLifetime
{
Expand Down
31 changes: 31 additions & 0 deletions tests/Elastic.Markdown.Tests/DocSet/NestedTocTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// 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 Elastic.Markdown.IO;
using FluentAssertions;
using Xunit.Abstractions;

namespace Elastic.Markdown.Tests.DocSet;

public class NestedTocTests(ITestOutputHelper output) : NavigationTestsBase(output)
{
[Fact]
public void InjectsNestedTocsIntoDocumentationSet()
{
var doc = Generator.DocumentationSet.Files.FirstOrDefault(f => f.RelativePath == "development/index.md") as MarkdownFile;

doc.Should().NotBeNull();

// ensure we link back up to main toc in docset yaml
doc!.Parent.Should().NotBeNull();

// its parent should be null
doc.Parent!.Parent.Should().BeNull();

// its parent should point to an index
doc.Parent.Index.Should().NotBeNull();
doc.Parent.Index!.RelativePath.Should().Be("index.md");

}
}

0 comments on commit 085b9fe

Please sign in to comment.