Class Sealed
public sealed class ChangelogParser : BlockParser

Namespace: Moka.Docs.Parsing.Markdown

Parses ::: changelog blocks. Collects all inner lines as raw text so the renderer can parse version entries, types, categories, and items.

Inheritance

Inherits from: BlockParser

Constructors

NameDescription
ChangelogParser()

Methods

Type Relationships
classDiagram
                    style ChangelogParser fill:#f9f,stroke:#333,stroke-width:2px
                    ChangelogParser --|> BlockParser : inherits
                
View Source
#endregion
#region Parser
/// <summary>
///     Parses <c>::: changelog</c> blocks. Collects all inner lines as raw text
///     so the renderer can parse version entries, types, categories, and items.
/// </summary>
public sealed class ChangelogParser : BlockParser
{
    public ChangelogParser()
    {
        OpeningCharacters = [':'];
    }

    /// <inheritdoc/>
    public override BlockState TryOpen(BlockProcessor processor)
    {
        if (processor.IsCodeIndent)
        {
            return BlockState.None;
        }

        StringSlice line = processor.Line;
        int start = line.Start;
        if (line.CurrentChar != ':')
        {
            return BlockState.None;
        }

        int colons = MarkdigHelpers.CountAndSkipChar(ref line, ':');
        if (colons < 3)
        {
            return BlockState.None;
        }

        line.TrimStart();
        string remaining = line.ToString().Trim();
        if (!string.Equals(remaining, "changelog", StringComparison.OrdinalIgnoreCase))
        {
            return BlockState.None;
        }

        var block = new ChangelogBlock(this)
        {
            Span = new SourceSpan(start, line.End),
            Column = processor.Column
        };
        processor.NewBlocks.Push(block);
        return BlockState.ContinueDiscard;
    }

    /// <inheritdoc/>
    public override BlockState TryContinue(BlockProcessor processor, Block block)
    {
        if (block is not ChangelogBlock changelogBlock)
        {
            return BlockState.None;
        }

        StringSlice line = processor.Line;
        // Check for closing :::
        if (line.CurrentChar == ':')
        {
            StringSlice saved = line;
            int colons = MarkdigHelpers.CountAndSkipChar(ref line, ':');
            if (colons >= 3)
            {
                string after = line.ToString().Trim();
                if (string.IsNullOrEmpty(after))
                {
                    block.UpdateSpanEnd(line.End);
                    return BlockState.BreakDiscard;
                }
            }

            processor.Line = saved;
        }

        // Collect the raw line
        changelogBlock.RawLines.Add(processor.Line.ToString());
        return BlockState.ContinueDiscard;
    }
}
Was this page helpful?