73 lines
2.4 KiB
C#
73 lines
2.4 KiB
C#
using Markdig.Renderers.Normalize;
|
|
using Markdig.Syntax;
|
|
using MfGames.Markdown.Exceptions;
|
|
|
|
namespace MfGames.Markdown;
|
|
|
|
/// <summary>
|
|
/// A transformer that goes through a Markdown document alters the level of the
|
|
/// headings either higher or lower..
|
|
/// </summary>
|
|
public class HeadingLevelTransformer
|
|
{
|
|
public HeadingLevelTransformer(int offset = 1)
|
|
{
|
|
this.Offset = offset;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the value to offset the heading. A positive number would
|
|
/// increase the heading by that amount, a negative would reduce it. If
|
|
/// this would produce a negative heading, an exception is thrown. The
|
|
/// default is 1 to increase the heading level by one (H1 -> H2).
|
|
/// </summary>
|
|
public int Offset { get; } = 1;
|
|
|
|
/// <summary>
|
|
/// Parses the given input as Markdown, goes through and transforms all
|
|
/// the links, and then returns the modified Markdown.
|
|
/// </summary>
|
|
/// <param name="input">The input text as Markdown.</param>
|
|
/// <returns>Modified Markdown text.</returns>
|
|
public string? Transform(string? input)
|
|
{
|
|
// If we get a null or blank string, we return it.
|
|
if (string.IsNullOrWhiteSpace(input) || this.Offset == 0)
|
|
{
|
|
return input;
|
|
}
|
|
|
|
// Parse the Markdown into an abstract syntax tree (AST). We need the
|
|
// trivia because we want to round-trip as much as possible and it
|
|
// contains things like extra whitespace or indention.
|
|
MarkdownDocument document = Markdig.Markdown.Parse(input, true);
|
|
|
|
// Go through all the headings.
|
|
IEnumerable<HeadingBlock> blockList = document.Descendants<HeadingBlock>();
|
|
|
|
foreach (HeadingBlock block in blockList)
|
|
{
|
|
// Make sure we have sane values.
|
|
int oldLevel = block.Level;
|
|
int newLevel = oldLevel + this.Offset;
|
|
|
|
if (newLevel is < 1 or > 7)
|
|
{
|
|
throw new MarkdownHeaderOutOfRangeException(oldLevel, newLevel);
|
|
}
|
|
|
|
block.Level = newLevel;
|
|
}
|
|
|
|
// Convert the AST back into Markdown and return the results. The
|
|
// RoundtripRenderer doesn't work here, but NormalizeRenderer seems to
|
|
// allow us to modify the link above and get the results.
|
|
var writer = new StringWriter();
|
|
var renderer = new NormalizeRenderer(writer);
|
|
|
|
renderer.Write(document);
|
|
|
|
return writer.ToString();
|
|
}
|
|
}
|