Skip to content

Commit 085b9fe

Browse files
authored
Introduce toc.yml, allows toc's to be split one directory deep (#165)
1 parent 03c22a2 commit 085b9fe

File tree

13 files changed

+112
-24
lines changed

13 files changed

+112
-24
lines changed

docs-builder.sln.DotSettings

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
<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">
2+
<s:Boolean x:Key="/Default/UserDictionary/Words/=docset/@EntryIndexedValue">True</s:Boolean>
23
<s:Boolean x:Key="/Default/UserDictionary/Words/=linenos/@EntryIndexedValue">True</s:Boolean>
34
<s:Boolean x:Key="/Default/UserDictionary/Words/=literalinclude/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

docs/source/development/index.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
title: Development Guide
3+
navigation_title: Development
4+
---
5+
6+
TODO write development documentation here

docs/source/development/toc.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
toc:
2+
- file: index.md

docs/source/docset.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ toc:
6969
- file: tabs.md
7070
- file: tagged_regions.md
7171
- file: titles.md
72+
# nested TOCs are only allowed from docset.yml
73+
# to prevent them from being nested deeply arbitrarily
74+
- toc: development
7275
- folder: testing
7376
children:
7477
- file: index.md

src/Elastic.Markdown/IO/ConfigurationFile.cs

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public record ConfigurationFile : DocumentationFile
1515
private readonly IFileInfo _sourceFile;
1616
private readonly IDirectoryInfo _rootPath;
1717
private readonly BuildContext _context;
18+
private readonly int _depth;
1819
public string? Project { get; }
1920
public Glob[] Exclude { get; } = [];
2021

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

31-
public ConfigurationFile(IFileInfo sourceFile, IDirectoryInfo rootPath, BuildContext context)
32+
public ConfigurationFile(IFileInfo sourceFile, IDirectoryInfo rootPath, BuildContext context, int depth = 0, string parentPath = "")
3233
: base(sourceFile, rootPath)
3334
{
3435
_sourceFile = sourceFile;
3536
_rootPath = rootPath;
3637
_context = context;
38+
_depth = depth;
3739
if (!sourceFile.Exists)
3840
{
3941
Project = "unknown";
@@ -81,7 +83,13 @@ public ConfigurationFile(IFileInfo sourceFile, IDirectoryInfo rootPath, BuildCon
8183
ExternalLinkHosts.Add(host);
8284
break;
8385
case "toc":
84-
var entries = ReadChildren(entry, string.Empty);
86+
if (depth > 1)
87+
{
88+
EmitError($"toc.yml files may only be linked from docset.yml", entry.Key);
89+
break;
90+
}
91+
92+
var entries = ReadChildren(entry, parentPath);
8593

8694
TableOfContents = entries;
8795
break;
@@ -115,20 +123,19 @@ private List<ITocItem> ReadChildren(KeyValuePair<YamlNode, YamlNode> entry, stri
115123
return entries;
116124
}
117125

118-
foreach (var tocEntry in sequence.Children.OfType<YamlMappingNode>())
119-
{
120-
var tocItem = ReadChild(tocEntry, parentPath);
121-
if (tocItem is not null)
122-
entries.Add(tocItem);
123-
}
126+
entries.AddRange(
127+
sequence.Children.OfType<YamlMappingNode>()
128+
.SelectMany(tocEntry => ReadChild(tocEntry, parentPath) ?? [])
129+
);
124130

125131
return entries;
126132
}
127133

128-
private ITocItem? ReadChild(YamlMappingNode tocEntry, string parentPath)
134+
private IEnumerable<ITocItem>? ReadChild(YamlMappingNode tocEntry, string parentPath)
129135
{
130136
string? file = null;
131137
string? folder = null;
138+
ConfigurationFile? toc = null;
132139
var fileFound = false;
133140
var folderFound = false;
134141
IReadOnlyCollection<ITocItem>? children = null;
@@ -137,6 +144,9 @@ private List<ITocItem> ReadChildren(KeyValuePair<YamlNode, YamlNode> entry, stri
137144
var key = ((YamlScalarNode)entry.Key).Value;
138145
switch (key)
139146
{
147+
case "toc":
148+
toc = ReadNestedToc(entry, parentPath, out fileFound);
149+
break;
140150
case "file":
141151
file = ReadFile(entry, parentPath, out fileFound);
142152
break;
@@ -150,15 +160,23 @@ private List<ITocItem> ReadChildren(KeyValuePair<YamlNode, YamlNode> entry, stri
150160
}
151161
}
152162

163+
if (toc is not null)
164+
{
165+
foreach (var f in toc.Files)
166+
Files.Add(f);
167+
168+
return [new FolderReference($"{parentPath}".TrimStart('/'), folderFound, toc.TableOfContents)];
169+
}
170+
153171
if (file is not null)
154-
return new TocFile($"{parentPath}/{file}".TrimStart('/'), fileFound, children ?? []);
172+
return [new FileReference($"{parentPath}/{file}".TrimStart('/'), fileFound, children ?? [])];
155173

156174
if (folder is not null)
157175
{
158176
if (children is null)
159177
ImplicitFolders.Add(parentPath.TrimStart('/'));
160178

161-
return new TocFolder($"{parentPath}".TrimStart('/'), folderFound, children ?? []);
179+
return [new FolderReference($"{parentPath}".TrimStart('/'), folderFound, children ?? [])];
162180
}
163181

164182
return null;
@@ -226,6 +244,29 @@ private Dictionary<string, string> ReadDictionary(KeyValuePair<YamlNode, YamlNod
226244
return file;
227245
}
228246

247+
private ConfigurationFile? ReadNestedToc(KeyValuePair<YamlNode, YamlNode> entry, string parentPath, out bool found)
248+
{
249+
found = false;
250+
var tocPath = ReadString(entry);
251+
if (tocPath is null)
252+
{
253+
EmitError($"Empty toc: reference", entry.Key);
254+
return null;
255+
}
256+
257+
var rootPath = _context.ReadFileSystem.DirectoryInfo.New(Path.Combine(_rootPath.FullName, tocPath));
258+
var path = Path.Combine(rootPath.FullName, "toc.yml");
259+
var source = _context.ReadFileSystem.FileInfo.New(path);
260+
if (!source.Exists)
261+
EmitError($"Nested toc: '{source.FullName}' does not exist", entry.Key);
262+
else
263+
found = true;
264+
265+
var nestedConfiguration = new ConfigurationFile(source, _rootPath, _context, _depth + 1, tocPath);
266+
return nestedConfiguration;
267+
}
268+
269+
229270
private string? ReadString(KeyValuePair<YamlNode, YamlNode> entry)
230271
{
231272
if (entry.Value is YamlScalarNode scalar)

src/Elastic.Markdown/IO/DocumentationFolder.cs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,7 @@ public DocumentationFolder(
3333
Index = index ?? foundIndex;
3434

3535
if (Index is not null)
36-
{
3736
FilesInOrder = FilesInOrder.Except([Index]).ToList();
38-
Index.Parent ??= this;
39-
}
4037

4138
OwnFiles = [.. FilesInOrder];
4239
}
@@ -55,7 +52,7 @@ out List<MarkdownFile> filesInOrder
5552
MarkdownFile? index = null;
5653
foreach (var tocItem in toc)
5754
{
58-
if (tocItem is TocFile file)
55+
if (tocItem is FileReference file)
5956
{
6057
if (!lookup.TryGetValue(file.Path, out var d) || d is not MarkdownFile md)
6158
continue;
@@ -76,14 +73,14 @@ out List<MarkdownFile> filesInOrder
7673
if (file.Path.EndsWith("index.md") && d is MarkdownFile i)
7774
index ??= i;
7875
}
79-
else if (tocItem is TocFolder folder)
76+
else if (tocItem is FolderReference folder)
8077
{
8178
var children = folder.Children;
8279
if (children.Count == 0
8380
&& folderLookup.TryGetValue(folder.Path, out var documentationFiles))
8481
{
8582
children = documentationFiles
86-
.Select(d => new TocFile(d.RelativePath, true, []))
83+
.Select(d => new FileReference(d.RelativePath, true, []))
8784
.ToArray();
8885
}
8986

src/Elastic.Markdown/IO/ITocItem.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ namespace Elastic.Markdown.IO;
66

77
public interface ITocItem;
88

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

11-
public record TocFolder(string Path, bool Found, IReadOnlyCollection<ITocItem> Children) : ITocItem;
11+
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/MarkdownFile.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,11 @@ public MarkdownFile(IFileInfo sourceFile, IDirectoryInfo rootPath, MarkdownParse
3131

3232
private DiagnosticsCollector Collector { get; }
3333

34-
public DocumentationFolder? Parent { get; set; }
34+
public DocumentationFolder? Parent
35+
{
36+
get => FileName == "index.md" ? _parent?.Parent : _parent;
37+
set => _parent = value;
38+
}
3539

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

5761
private bool _instructionsParsed;
62+
private DocumentationFolder? _parent;
5863

5964
public MarkdownFile[] YieldParents()
6065
{

tests/Elastic.Markdown.Tests/SiteMap/BreadCrumbTests.cs renamed to tests/Elastic.Markdown.Tests/DocSet/BreadCrumbTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
using FluentAssertions;
77
using Xunit.Abstractions;
88

9-
namespace Elastic.Markdown.Tests.SiteMap;
9+
namespace Elastic.Markdown.Tests.DocSet;
1010

1111
public class BreadCrumbTests(ITestOutputHelper output) : NavigationTestsBase(output)
1212
{

tests/Elastic.Markdown.Tests/SiteMap/LinkReferenceTests.cs renamed to tests/Elastic.Markdown.Tests/DocSet/LinkReferenceTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
using FluentAssertions;
77
using Xunit.Abstractions;
88

9-
namespace Elastic.Markdown.Tests.SiteMap;
9+
namespace Elastic.Markdown.Tests.DocSet;
1010

1111
public class LinkReferenceTests(ITestOutputHelper output) : NavigationTestsBase(output)
1212
{

0 commit comments

Comments
 (0)