Skip to content

Commit 38ec5a2

Browse files
authored
Merge 89a3195 into c6c6c35
2 parents c6c6c35 + 89a3195 commit 38ec5a2

File tree

6 files changed

+63
-31
lines changed

6 files changed

+63
-31
lines changed

docs/docs/table-of-contents.md

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,15 @@ To add a TOC, create a file named `toc.yml`. Here's the structure for a simple Y
1010
items:
1111
- name: Tutorial
1212
items:
13-
- name: Introduction
14-
href: tutorial.md
15-
- name: Step 1
16-
href: step-1.md
17-
- name: Step 2
18-
href: step-2.md
19-
- name: Step 3
20-
href: step-3.md
13+
- href: tutorial.md
14+
- href: step-1.md
15+
- href: step-2.md
16+
- href: step-3.md
2117
```
2218
2319
The YAML document is a tree of TOC nodes, each of which has these properties:
2420
25-
- `name`: The display name for the TOC node.
21+
- `name`: An optional display name for the TOC node. When not specified, uses the `title` metadata or the first Heading 1 element from the referenced article as the display name.
2622
- `href`: The path the TOC node leads to. Optional because a node can exist just to parent other nodes.
2723
- `items`: If a node has children, they're listed in the items array.
2824
- `uid`: The uid of the article. Can be used instead of `href`.

samples/seed/articles/toc.yml

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
11
pdfFileName: seed.pdf
22
pdfCoverPage: pdf/cover.html
33
items:
4-
- name: Getting Started
5-
href: docfx_getting_started.md
4+
- href: docfx_getting_started.md
65
- name: Engineering Docs
76
expanded: true
87
items:
98
- name: Section 1
10-
- name: Engineering Guidelines
11-
href: engineering_guidelines.md
12-
- name: CSharp Coding Standards
13-
href: csharp_coding_standards.md
14-
- name: Markdown
15-
href: markdown.md
9+
- href: engineering_guidelines.md
10+
- href: csharp_coding_standards.md
11+
- href: markdown.md
1612
- name: Microsoft Docs
1713
href: https://docs.microsoft.com/en-us/

src/Docfx.Build/ManifestProcessor.cs

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Collections.Concurrent;
55

66
using Docfx.Common;
7+
using Docfx.DataContracts.Common;
78
using Docfx.Plugins;
89

910
namespace Docfx.Build.Engine;
@@ -33,6 +34,8 @@ public ManifestProcessor(List<ManifestItemWithContext> manifestWithContext, Docu
3334

3435
public void Process()
3536
{
37+
UpdateTocName();
38+
3639
UpdateContext();
3740

3841
// Afterwards, m.Item.Model.Content is always IDictionary
@@ -53,8 +56,6 @@ public void Process()
5356
}
5457
}
5558

56-
#region Private
57-
5859
private void UpdateContext()
5960
{
6061
_context.ResolveExternalXRefSpec();
@@ -181,5 +182,49 @@ private List<ManifestItem> ProcessTemplate()
181182
return _templateProcessor.Process(_manifestWithContext.Select(s => s.Item).ToList(), _context.ApplyTemplateSettings, _globalMetadata);
182183
}
183184

184-
#endregion
185+
private void UpdateTocName()
186+
{
187+
var titles = (
188+
from item in _manifestWithContext
189+
let title = GetTitle(item)
190+
where !string.IsNullOrEmpty(title)
191+
group title
192+
by item.FileModel.Key).ToDictionary(g => g.Key, g => g.First());
193+
194+
foreach (var item in _manifestWithContext)
195+
{
196+
if (item.FileModel.Content is not TocItemViewModel toc)
197+
continue;
198+
199+
UpdateTocNameCore(toc.Items);
200+
}
201+
202+
void UpdateTocNameCore(List<TocItemViewModel> items)
203+
{
204+
if (items is null)
205+
return;
206+
207+
foreach (var node in items)
208+
{
209+
if (string.IsNullOrEmpty(node.Name))
210+
{
211+
if (node.Href is not null && titles.TryGetValue(UriUtility.GetPath(node.Href), out var title))
212+
node.Name = title;
213+
else
214+
Logger.LogWarning(
215+
$"TOC item ({node}) with empty name found. Missing a name?",
216+
code: WarningCodes.Build.EmptyTocItemName);
217+
}
218+
219+
UpdateTocNameCore(node.Items);
220+
}
221+
}
222+
223+
string GetTitle(ManifestItemWithContext item)
224+
{
225+
return item.FileModel.Content is Dictionary<string, object> dict &&
226+
dict.TryGetValue("title", out var title) &&
227+
title is string result ? result : null;
228+
}
229+
}
185230
}

src/Docfx.Build/TableOfContents/TocResolver.cs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,6 @@ private TocItemInfo ResolveItemCore(TocItemInfo wrapper, Stack<FileAndType> stac
8383
// validate href
8484
ValidateHref(item);
8585

86-
// validate if name is missing
87-
if (!isRoot && string.IsNullOrEmpty(item.Name) && string.IsNullOrEmpty(item.TopicUid))
88-
{
89-
Logger.LogWarning(
90-
$"TOC item ({item}) with empty name found. Missing a name?",
91-
code: WarningCodes.Build.EmptyTocItemName);
92-
}
93-
9486
// TocHref supports 2 forms: absolute path and local toc file.
9587
// When TocHref is set, using TocHref as Href in output, and using Href as Homepage in output
9688
var tocHrefType = Utility.GetHrefType(item.TocHref);

templates/modern/src/helper.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@ export function loc(id: string, args?: { [key: string]: string }): string {
3333
/**
3434
* Add <wbr> into long word.
3535
*/
36-
export function breakWord(text: string): string[] {
36+
export function breakWord(text?: string): string[] {
37+
if (!text) {
38+
return []
39+
}
3740
const regex = /([a-z0-9])([A-Z]+[a-z])|([a-zA-Z0-9][.,/<>_])/g
3841
const result = []
3942
let start = 0
@@ -55,7 +58,7 @@ export function breakWord(text: string): string[] {
5558
/**
5659
* Add <wbr> into long word.
5760
*/
58-
export function breakWordLit(text: string): TemplateResult {
61+
export function breakWordLit(text?: string): TemplateResult {
5962
const result = []
6063
breakWord(text).forEach(word => {
6164
if (result.length > 0) {

templates/modern/src/toc.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { classMap } from 'lit-html/directives/class-map.js'
66
import { breakWordLit, meta, isExternalHref, loc, isSameURL } from './helper'
77

88
export type TocNode = {
9-
name: string
9+
name?: string
1010
href?: string
1111
expanded?: boolean
1212
items?: TocNode[]

0 commit comments

Comments
 (0)