To expand on @e-shcherbo's dotnetfiddle, and for anyone wanting to leverage more functionality provided by Markdig's header parsing, the following query enables the generation of a table of contents using the headers parsed by Markdig.
The presentation result would be similar to the 'In this article' list provided in the sidebar of a MDN article.
Add the.UseAutoIdentifiers()
extension to the Markdig pipeline so that an id
attribute is assigned to each HeadingBlock
AST node during parsing. The ID is generated using the text of the header.
IEnumerable<Header> headers = document
.Descendants<HeadingBlock>()
.Where(hb => hb?.Level != null && !string.IsNullOrWhiteSpace(hb?.Inline?.FirstChild?.ToString()))
.Select(hb => new Header()
{
Id = hb?.GetAttributes().Id,
Level = hb?.Level,
Text = hb?.Inline?.FirstChild?.ToString(),
});
The following is the result of the above LINQ query on the Markdown sample listed in the original post:
The ID value is retrieved using the GetAttributes()
method on a HeadingBlock
node.
The Level
property on the HeadingBlock
node is the key value that enables a branching table of contents sidebar.
You can extend the Where()
predicate to retrieve only level 2 (h2
) headers (e.g. .Where(hb => hb?.Level == 2)
), similar to the list provided in the 'In this article' MDN article sidebar.
The .Where()
predicate skips HeadingBlock
nodes that have an empty string.
The Header
type in the .Select()
method is defined as:
public class Header
{
public string? Id { get; set; }
public string? Text { get; set; }
public int? Level { get; set; }
}