How to preserve empty lines? #594

Closed
opened 2026-01-29 14:40:37 +00:00 by claunia · 5 comments
Owner

Originally created by @Jinjinov on GitHub (Mar 3, 2023).

Would it be possible to preserve empty lines?

Using UseSoftlineBreakAsHardlineBreak() preserves new lines, but not empty lines.

I tried using text.Replace("\n", "<br>") but then titles and lists don't work.

I tried using text.Replace("\n", "<br>\n") then titles and lists work, but there are too many empty lines.

I tried using text.Replace("\n\n", "<br><br>") but then all markdown after a list is wrong.

I tried using text.Replace("\n\n", "<br>\n") then titles and lists work, but not all empty lines are preserved.

I tried using text.Replace("\n\n", "<br><br>\n") then titles and lists work, but everything else is wrong.

Would it be possible to specify my own rule for this?

Originally created by @Jinjinov on GitHub (Mar 3, 2023). Would it be possible to preserve empty lines? Using `UseSoftlineBreakAsHardlineBreak()` preserves new lines, but not empty lines. I tried using `text.Replace("\n", "<br>")` but then titles and lists don't work. I tried using `text.Replace("\n", "<br>\n")` then titles and lists work, but there are too many empty lines. I tried using `text.Replace("\n\n", "<br><br>")` but then all markdown after a list is wrong. I tried using `text.Replace("\n\n", "<br>\n")` then titles and lists work, but not all empty lines are preserved. I tried using `text.Replace("\n\n", "<br><br>\n")` then titles and lists work, but everything else is wrong. Would it be possible to specify my own rule for this?
claunia added the question label 2026-01-29 14:40:37 +00:00
Author
Owner

@xoofx commented on GitHub (Mar 3, 2023):

Probably duplicate of #698.

Would it be possible to preserve empty lines?
Would it be possible to specify my own rule for this?

The CommonMark specs are treating empty lines in a specific way (e.g they are used to stop processing list..etc.) and they have many associated rules with them.

Changing this behavior (even with an opt-in switch) is not something I would like to maintain, and I'm not even sure it is practical, feasible without conflicting with existing rules. As you realized yourself, empty lines have a context dependent behavior.

So my main advice would be to not pursue this road 🙂

@xoofx commented on GitHub (Mar 3, 2023): Probably duplicate of #698. > Would it be possible to preserve empty lines? > Would it be possible to specify my own rule for this? The CommonMark specs are treating empty lines in a specific way (e.g they are used to stop processing list..etc.) and they have [many associated rules with them](https://spec.commonmark.org/0.30/#blank-lines). Changing this behavior (even with an opt-in switch) is not something I would like to maintain, and I'm not even sure it is practical, feasible without conflicting with existing rules. As you realized yourself, empty lines have a context dependent behavior. So my main advice would be to not pursue this road 🙂
Author
Owner

@Jinjinov commented on GitHub (Mar 3, 2023):

I understand that this is not compliant with CommonMark and would make no sense in implementing it in Markdig.

I am writing a note editor with these specifications:

  1. all url links must be converted from simple text to <a href>
  2. all empty lines must be preserved
  3. using Markdown for titles, lists, preformatted text is a bonus (optional)

I decided to use Markdig, because it covers 1. and 3. but the most important features are detecting links in simple text and preserving empty lines.

Can you give me a few starting points how could I write a custom Markdig extension that would preserve empty lines?

@Jinjinov commented on GitHub (Mar 3, 2023): I understand that this is not compliant with CommonMark and would make no sense in implementing it in Markdig. I am writing a note editor with these specifications: 1. all url links must be converted from simple text to `<a href>` 2. all empty lines must be preserved 3. using Markdown for titles, lists, preformatted text is a bonus (optional) I decided to use Markdig, because it covers 1. and 3. but the most important features are detecting links in simple text and preserving empty lines. Can you give me a few starting points how could I write a custom Markdig extension that would preserve empty lines?
Author
Owner

@Jinjinov commented on GitHub (Mar 3, 2023):

This is what ChatGPT wrote, but it doesn't work:

public class PreserveEmptyLinesExtension : IMarkdownExtension
{
    public void Setup(MarkdownPipelineBuilder pipeline)
    {
        // Add a block parser that preserves empty lines
        pipeline.BlockParsers.Insert(0, new PreserveEmptyLinesParser());
    }

    public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
    {
        // No renderer modifications necessary
    }

    private class PreserveEmptyLinesParser : BlockParser
    {
        public PreserveEmptyLinesParser()
        {
            OpeningCharacters = new char[0];
        }

        public override BlockState TryOpen(BlockProcessor processor)
        {
            // Preserve the empty line as a new line block
            if (processor.IsBlankLine)
            {
                processor.NewBlocks.Push(new ParagraphBlock(this));
                return BlockState.Continue;
            }

            return BlockState.None;
        }

        public override BlockState TryContinue(BlockProcessor processor, Block block)
        {
            // Continue the block normally
            return BlockState.None;
        }
    }
}
@Jinjinov commented on GitHub (Mar 3, 2023): This is what ChatGPT wrote, but it doesn't work: ``` public class PreserveEmptyLinesExtension : IMarkdownExtension { public void Setup(MarkdownPipelineBuilder pipeline) { // Add a block parser that preserves empty lines pipeline.BlockParsers.Insert(0, new PreserveEmptyLinesParser()); } public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer) { // No renderer modifications necessary } private class PreserveEmptyLinesParser : BlockParser { public PreserveEmptyLinesParser() { OpeningCharacters = new char[0]; } public override BlockState TryOpen(BlockProcessor processor) { // Preserve the empty line as a new line block if (processor.IsBlankLine) { processor.NewBlocks.Push(new ParagraphBlock(this)); return BlockState.Continue; } return BlockState.None; } public override BlockState TryContinue(BlockProcessor processor, Block block) { // Continue the block normally return BlockState.None; } } } ```
Author
Owner

@xoofx commented on GitHub (Mar 3, 2023):

Can you give me a few starting points how could I write a custom Markdig extension that would preserve empty lines?

This more likely not trivial and unlikely possible by extending Markdig. You would have to fork it and modify its internals.

@xoofx commented on GitHub (Mar 3, 2023): > Can you give me a few starting points how could I write a custom Markdig extension that would preserve empty lines? This more likely not trivial and unlikely possible by extending Markdig. You would have to fork it and modify its internals.
Author
Owner

@Jinjinov commented on GitHub (Mar 3, 2023):

Thank you for your explanations.

@Jinjinov commented on GitHub (Mar 3, 2023): Thank you for your explanations.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/markdig#594