Skip to content

Commit 217f56c

Browse files
authored
Merge pull request #39 from rwrife/split-child-toc
Option to split root TOC into multiple child TOC files
2 parents eeaf2fe + 023c5f4 commit 217f56c

File tree

3 files changed

+86
-12
lines changed

3 files changed

+86
-12
lines changed

src/DocFxTocGenerator/Domain/CommandlineOptions.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public class CommandlineOptions
3535
public bool UseOrder { get; set; }
3636

3737
/// <summary>
38-
/// Gets or sets a value indicating whether the .order files are used.
38+
/// Gets or sets a value indicating whether the .override files are used.
3939
/// </summary>
4040
[Option('r', "override", Required = false, HelpText = "Use the .override files for TOC file name override. Format are raws of: filename-without-extension;Title you want")]
4141
public bool UseOverride { get; set; }
@@ -58,5 +58,12 @@ public class CommandlineOptions
5858
/// </summary>
5959
[Option('n', "notwithone", Required = false, HelpText = "Do not auto-generate a file index when only contains 1 file. Additional to -i flag.")]
6060
public bool NoAutoIndexWithOneFile { get; set; }
61+
62+
/// <summary>
63+
/// Gets or sets a value indicating whether multiple toc files should be generated for each of the first child subfolders instead of building
64+
/// one large toc in the root output folder.
65+
/// </summary>
66+
[Option('m', "multitoc", Required = false, HelpText = "Indicates how deep in the tree toc files should be generated for child subfolders, a depth of 0 is the root only.")]
67+
public int SplitTocDepth { get; set; } = 0;
6168
}
6269
}

src/DocFxTocGenerator/README.md

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,16 @@ This tool allow to generate a yaml compatible `toc.yml` file for DocFX.
77
```text
88
TocGenerator -d <docs folder> [-o <output folder>] [-vsi]
99
10-
-d, --docfolder Required. Folder containing the documents.
11-
-o, --outputfolder Folder to write the resulting toc.yml in.
12-
-v, --verbose Show verbose messages.
13-
-s, --sequence Use the .order files for TOC sequence. Format are raws of: filename-without-extension
14-
-r, --override Use the .override files for TOC file name override. Format are raws of: filename-without-extension;Title you want
15-
-i, --index Auto-generate a file index in each folder.
16-
-g, --ignore Use the .ignore files for TOC directory ignore. Format are raws of directory names: directory-to-ignore
17-
--help Display this help screen.
18-
--version Display version information.
10+
-d, --docfolder Required. Folder containing the documents.
11+
-o, --outputfolder Folder to write the resulting toc.yml in.
12+
-v, --verbose Show verbose messages.
13+
-s, --sequence Use the .order files for TOC sequence. Format are raws of: filename-without-extension
14+
-r, --override Use the .override files for TOC file name override. Format are raws of: filename-without-extension;Title you want
15+
-i, --index Auto-generate a file index in each folder.
16+
-g, --ignore Use the .ignore files for TOC directory ignore. Format are raws of directory names: directory-to-ignore
17+
-m, --multitoc <depth> Generate multiple toc files for child folders down to a certain child depth, default is 0 (root only generation).
18+
--help Display this help screen.
19+
--version Display version information.
1920
```
2021

2122
If the `-o or --outputfolder` is not provided, the output folder is set to the docfolder.
@@ -62,3 +63,7 @@ If there are files or directories which are not in the .order file, they will be
6263
If the `-i or --index` parameter is provided, for every folder that doesn't have a README.md or INDEX.md, an INDEX.md is generated with the contents of that folder. That file is also added to the top of the list of files and directories in that folder.
6364

6465
The generated INDEX.md contains of an H1-header with the name of the folder, followed by a list of files and directories using their title and a link to the item.
66+
67+
## Generating mutiple child toc files
68+
69+
The `-m or --multitoc` option will control how far down the folder tree structure to generating toc files and allows you to generate multiple smaller, more managable TOC files for large DocFX projects. If the parameter is omitted, the default of 0 is assumed, which means only one large TOC at the root level will generated. Any value greater than 0 indicates how deep into the child folder structure TOC files will be generated, with the parent TOC having references to those located in the child folders.

src/DocFxTocGenerator/TocGenerator.cs

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ private static void RunLogic(CommandlineOptions o)
6666
_message.Verbose($"Use .override : {_options.UseOverride}");
6767
_message.Verbose($"Use .ignore : {_options.UseIgnore}");
6868
_message.Verbose($"Auto index : {_options.AutoIndex}\n");
69+
_message.Verbose($"Split toc depth : {_options.SplitTocDepth}\n");
6970

7071
if (!Directory.Exists(_options.DocFolder))
7172
{
@@ -86,6 +87,67 @@ private static void RunLogic(CommandlineOptions o)
8687
DirectoryInfo rootDir = new DirectoryInfo(_options.DocFolder);
8788
WalkDirectoryTree(rootDir, tocRootItems);
8889

90+
if (_options.SplitTocDepth > 0)
91+
{
92+
WriteChildTocItems(tocRootItems, string.Empty, 0);
93+
}
94+
else
95+
{
96+
// write the tocitems to disk as one large file
97+
WriteToc(tocRootItems, _options.OutputFolder);
98+
}
99+
}
100+
101+
/// <summary>
102+
/// Walks the yaml tree looking for child nodes that are parents to other children
103+
/// and corrects the paths to be relative the number toc files that should be generated.
104+
/// </summary>
105+
/// <param name="parentTocItem">Parent toc item to walk.</param>
106+
/// <param name="parentFolder">Location where the toc should be written.</param>
107+
/// <param name="treeDepth">Indicates the level the toc item is at in the tree.</param>
108+
private static ICollection<TocItem> WriteChildTocItems(TocItem parentTocItem, string parentFolder, int treeDepth = 0)
109+
{
110+
var childTocItems = new TocItem();
111+
foreach (var tocItem in parentTocItem.Items.OrderBy(x => x.Sequence))
112+
{
113+
ICollection<TocItem> childItems = null;
114+
115+
// split the href, may need the folder or filename later on
116+
var hrefParts = tocItem.Href.Split('/');
117+
118+
// if the child is a leaf, use the href and remove the parent folder so it's relative
119+
// if the child has children then the href will point to the toc in the child folder
120+
var childHref = ((tocItem.Items?.Any() ?? false) && treeDepth < _options.SplitTocDepth)
121+
? string.Join('/', hrefParts.Take(hrefParts.Length == 1 ? 1 : hrefParts.Length - 1))
122+
: tocItem.Href.Substring(parentFolder.Length).TrimStart('/');
123+
124+
if (tocItem.Items?.Any() ?? false)
125+
{
126+
childItems = WriteChildTocItems(tocItem, treeDepth < _options.SplitTocDepth ? childHref : parentFolder, treeDepth + 1);
127+
}
128+
129+
childTocItems.AddItem(new TocItem()
130+
{
131+
Title = tocItem.Title.Trim(),
132+
Filename = tocItem.Filename,
133+
Sequence = tocItem.Sequence,
134+
SortableTitle = tocItem.SortableTitle,
135+
Href = childItems != null && treeDepth < _options.SplitTocDepth ? null : childHref,
136+
Items = childItems,
137+
});
138+
}
139+
140+
if (treeDepth <= _options.SplitTocDepth)
141+
{
142+
WriteToc(childTocItems, Path.Combine(_options.OutputFolder, parentFolder));
143+
return null;
144+
}
145+
146+
return childTocItems.Items;
147+
}
148+
149+
private static void WriteToc(TocItem tocRootItems, string outputFolder)
150+
{
89151
// we have the TOC, so serialize to a string
90152
using (StringWriter sw = new StringWriter())
91153
{
@@ -96,10 +158,10 @@ private static void RunLogic(CommandlineOptions o)
96158
}
97159

98160
// now write the TOC to disc
99-
File.WriteAllText(Path.Combine(_options.OutputFolder, "toc.yml"), sw.ToString());
161+
File.WriteAllText(Path.Combine(outputFolder, "toc.yml"), sw.ToString());
100162
}
101163

102-
_message.Verbose($"{Path.Combine(_options.OutputFolder, "toc.yml")} created.");
164+
_message.Verbose($"{Path.Combine(outputFolder, "toc.yml")} created.");
103165
}
104166

105167
/// <summary>

0 commit comments

Comments
 (0)