Upstream xoofx/markdig state of the touched files before a9eea55dcf
This commit is contained in:
1 parent
2b9fbfb252
commit
5a326ef5b7
3 files changed
+535
No files matched your search
@@ -0,0 +1,195 @@
|
|||||||
|
|
||||||
|
// --------------------------------
|
||||||
|
// Definition Lists
|
||||||
|
// --------------------------------
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace Markdig.Tests.Specs.DefinitionLists
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TestExtensionsDefinitionLists
|
||||||
|
{
|
||||||
|
// # Extensions
|
||||||
|
//
|
||||||
|
// This section describes the different extensions supported:
|
||||||
|
//
|
||||||
|
// ## Definition lists
|
||||||
|
//
|
||||||
|
// A custom container is similar to a fenced code block, but it is using the character `:` to declare a block (with at least 3 characters), and instead of generating a `<pre><code>...</code></pre>` it will generate a `<div>...</div>` block.
|
||||||
|
[Test]
|
||||||
|
public void ExtensionsDefinitionLists_Example001()
|
||||||
|
{
|
||||||
|
// Example 1
|
||||||
|
// Section: Extensions / Definition lists
|
||||||
|
//
|
||||||
|
// The following Markdown:
|
||||||
|
//
|
||||||
|
// Term 1
|
||||||
|
// : This is a definition item
|
||||||
|
// With a paragraph
|
||||||
|
// > This is a block quote
|
||||||
|
//
|
||||||
|
// - This is a list
|
||||||
|
// - with an item2
|
||||||
|
//
|
||||||
|
// ```java
|
||||||
|
// Test
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
// And a last line
|
||||||
|
// : This ia another definition item
|
||||||
|
//
|
||||||
|
// Term2
|
||||||
|
// Term3 *with some inline*
|
||||||
|
// : This is another definition for term2
|
||||||
|
//
|
||||||
|
// Should be rendered as:
|
||||||
|
// <dl>
|
||||||
|
// <dt>Term 1</dt>
|
||||||
|
// <dd><p>This is a definition item
|
||||||
|
// With a paragraph</p>
|
||||||
|
// <blockquote>
|
||||||
|
// <p>This is a block quote</p>
|
||||||
|
// </blockquote>
|
||||||
|
// <ul>
|
||||||
|
// <li>This is a list</li>
|
||||||
|
// <li>with an item2</li>
|
||||||
|
// </ul>
|
||||||
|
// <pre><code class="language-java">Test
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// </code></pre>
|
||||||
|
// <p>And a last line</p>
|
||||||
|
// </dd>
|
||||||
|
// <dd>This ia another definition item</dd>
|
||||||
|
// <dt>Term2</dt>
|
||||||
|
// <dt>Term3 <em>with some inline</em></dt>
|
||||||
|
// <dd>This is another definition for term2</dd>
|
||||||
|
// </dl>
|
||||||
|
|
||||||
|
TestParser.TestSpec("\nTerm 1\n: This is a definition item\n With a paragraph\n > This is a block quote\n\n - This is a list\n - with an item2\n\n ```java\n Test\n\n\n ```\n\n And a last line\n: This ia another definition item\n\nTerm2\nTerm3 *with some inline*\n: This is another definition for term2", "<dl>\n<dt>Term 1</dt>\n<dd><p>This is a definition item\nWith a paragraph</p>\n<blockquote>\n<p>This is a block quote</p>\n</blockquote>\n<ul>\n<li>This is a list</li>\n<li>with an item2</li>\n</ul>\n<pre><code class=\"language-java\">Test\n\n\n</code></pre>\n<p>And a last line</p>\n</dd>\n<dd>This ia another definition item</dd>\n<dt>Term2</dt>\n<dt>Term3 <em>with some inline</em></dt>\n<dd>This is another definition for term2</dd>\n</dl>", "definitionlists+attributes|advanced", context: "Example 1\nSection Extensions / Definition lists\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// A definition term can be followed at most by one blank line. Lazy continuations are supported for definitions:
|
||||||
|
[Test]
|
||||||
|
public void ExtensionsDefinitionLists_Example002()
|
||||||
|
{
|
||||||
|
// Example 2
|
||||||
|
// Section: Extensions / Definition lists
|
||||||
|
//
|
||||||
|
// The following Markdown:
|
||||||
|
// Term 1
|
||||||
|
//
|
||||||
|
// : Definition
|
||||||
|
// with lazy continuation.
|
||||||
|
//
|
||||||
|
// Second paragraph of the definition.
|
||||||
|
//
|
||||||
|
// Should be rendered as:
|
||||||
|
// <dl>
|
||||||
|
// <dt>Term 1</dt>
|
||||||
|
// <dd><p>Definition
|
||||||
|
// with lazy continuation.</p>
|
||||||
|
// <p>Second paragraph of the definition.</p>
|
||||||
|
// </dd>
|
||||||
|
// </dl>
|
||||||
|
|
||||||
|
TestParser.TestSpec("Term 1\n\n: Definition\nwith lazy continuation.\n\n Second paragraph of the definition.", "<dl>\n<dt>Term 1</dt>\n<dd><p>Definition\nwith lazy continuation.</p>\n<p>Second paragraph of the definition.</p>\n</dd>\n</dl>", "definitionlists+attributes|advanced", context: "Example 2\nSection Extensions / Definition lists\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// The definition must be indented to 4 characters including the `:`.
|
||||||
|
[Test]
|
||||||
|
public void ExtensionsDefinitionLists_Example003()
|
||||||
|
{
|
||||||
|
// Example 3
|
||||||
|
// Section: Extensions / Definition lists
|
||||||
|
//
|
||||||
|
// The following Markdown:
|
||||||
|
// Term 1
|
||||||
|
// : Invalid with less than 3 characters
|
||||||
|
//
|
||||||
|
// Should be rendered as:
|
||||||
|
// <p>Term 1
|
||||||
|
// : Invalid with less than 3 characters</p>
|
||||||
|
|
||||||
|
TestParser.TestSpec("Term 1\n: Invalid with less than 3 characters", "<p>Term 1\n: Invalid with less than 3 characters</p>", "definitionlists+attributes|advanced", context: "Example 3\nSection Extensions / Definition lists\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// The `:` can be indented up to 3 spaces:
|
||||||
|
[Test]
|
||||||
|
public void ExtensionsDefinitionLists_Example004()
|
||||||
|
{
|
||||||
|
// Example 4
|
||||||
|
// Section: Extensions / Definition lists
|
||||||
|
//
|
||||||
|
// The following Markdown:
|
||||||
|
// Term 1
|
||||||
|
// : Valid even if `:` starts at most 3 spaces
|
||||||
|
//
|
||||||
|
// Should be rendered as:
|
||||||
|
// <dl>
|
||||||
|
// <dt>Term 1</dt>
|
||||||
|
// <dd>Valid even if <code>:</code> starts at most 3 spaces</dd>
|
||||||
|
// </dl>
|
||||||
|
|
||||||
|
TestParser.TestSpec("Term 1\n : Valid even if `:` starts at most 3 spaces", "<dl>\n<dt>Term 1</dt>\n<dd>Valid even if <code>:</code> starts at most 3 spaces</dd>\n</dl>", "definitionlists+attributes|advanced", context: "Example 4\nSection Extensions / Definition lists\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// But more than 3 spaces before `:` will trigger an indented code block:
|
||||||
|
[Test]
|
||||||
|
public void ExtensionsDefinitionLists_Example005()
|
||||||
|
{
|
||||||
|
// Example 5
|
||||||
|
// Section: Extensions / Definition lists
|
||||||
|
//
|
||||||
|
// The following Markdown:
|
||||||
|
// Term 1
|
||||||
|
//
|
||||||
|
// : Not valid
|
||||||
|
//
|
||||||
|
// Should be rendered as:
|
||||||
|
// <p>Term 1</p>
|
||||||
|
// <pre><code>: Not valid
|
||||||
|
// </code></pre>
|
||||||
|
|
||||||
|
TestParser.TestSpec("Term 1\n\n : Not valid", "<p>Term 1</p>\n<pre><code>: Not valid\n</code></pre>", "definitionlists+attributes|advanced", context: "Example 5\nSection Extensions / Definition lists\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Definition lists can be nested inside list items
|
||||||
|
[Test]
|
||||||
|
public void ExtensionsDefinitionLists_Example006()
|
||||||
|
{
|
||||||
|
// Example 6
|
||||||
|
// Section: Extensions / Definition lists
|
||||||
|
//
|
||||||
|
// The following Markdown:
|
||||||
|
// 1. First
|
||||||
|
//
|
||||||
|
// 2. Second
|
||||||
|
//
|
||||||
|
// Term 1
|
||||||
|
// : Definition
|
||||||
|
//
|
||||||
|
// Term 2
|
||||||
|
// : Second Definition
|
||||||
|
//
|
||||||
|
// Should be rendered as:
|
||||||
|
// <ol>
|
||||||
|
// <li><p>First</p></li>
|
||||||
|
// <li><p>Second</p>
|
||||||
|
// <dl>
|
||||||
|
// <dt>Term 1</dt>
|
||||||
|
// <dd>Definition</dd>
|
||||||
|
// <dt>Term 2</dt>
|
||||||
|
// <dd>Second Definition</dd>
|
||||||
|
// </dl></li>
|
||||||
|
// </ol>
|
||||||
|
|
||||||
|
TestParser.TestSpec("1. First\n \n2. Second\n \n Term 1\n : Definition\n \n Term 2\n : Second Definition", "<ol>\n<li><p>First</p></li>\n<li><p>Second</p>\n<dl>\n<dt>Term 1</dt>\n<dd>Definition</dd>\n<dt>Term 2</dt>\n<dd>Second Definition</dd>\n</dl></li>\n</ol>", "definitionlists+attributes|advanced", context: "Example 6\nSection Extensions / Definition lists\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
# Extensions
|
||||||
|
|
||||||
|
This section describes the different extensions supported:
|
||||||
|
|
||||||
|
## Definition lists
|
||||||
|
|
||||||
|
A custom container is similar to a fenced code block, but it is using the character `:` to declare a block (with at least 3 characters), and instead of generating a `<pre><code>...</code></pre>` it will generate a `<div>...</div>` block.
|
||||||
|
|
||||||
|
```````````````````````````````` example
|
||||||
|
|
||||||
|
Term 1
|
||||||
|
: This is a definition item
|
||||||
|
With a paragraph
|
||||||
|
> This is a block quote
|
||||||
|
|
||||||
|
- This is a list
|
||||||
|
- with an item2
|
||||||
|
|
||||||
|
```java
|
||||||
|
Test
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
And a last line
|
||||||
|
: This ia another definition item
|
||||||
|
|
||||||
|
Term2
|
||||||
|
Term3 *with some inline*
|
||||||
|
: This is another definition for term2
|
||||||
|
.
|
||||||
|
<dl>
|
||||||
|
<dt>Term 1</dt>
|
||||||
|
<dd><p>This is a definition item
|
||||||
|
With a paragraph</p>
|
||||||
|
<blockquote>
|
||||||
|
<p>This is a block quote</p>
|
||||||
|
</blockquote>
|
||||||
|
<ul>
|
||||||
|
<li>This is a list</li>
|
||||||
|
<li>with an item2</li>
|
||||||
|
</ul>
|
||||||
|
<pre><code class="language-java">Test
|
||||||
|
|
||||||
|
|
||||||
|
</code></pre>
|
||||||
|
<p>And a last line</p>
|
||||||
|
</dd>
|
||||||
|
<dd>This ia another definition item</dd>
|
||||||
|
<dt>Term2</dt>
|
||||||
|
<dt>Term3 <em>with some inline</em></dt>
|
||||||
|
<dd>This is another definition for term2</dd>
|
||||||
|
</dl>
|
||||||
|
````````````````````````````````
|
||||||
|
|
||||||
|
A definition term can be followed at most by one blank line. Lazy continuations are supported for definitions:
|
||||||
|
|
||||||
|
```````````````````````````````` example
|
||||||
|
Term 1
|
||||||
|
|
||||||
|
: Definition
|
||||||
|
with lazy continuation.
|
||||||
|
|
||||||
|
Second paragraph of the definition.
|
||||||
|
.
|
||||||
|
<dl>
|
||||||
|
<dt>Term 1</dt>
|
||||||
|
<dd><p>Definition
|
||||||
|
with lazy continuation.</p>
|
||||||
|
<p>Second paragraph of the definition.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
````````````````````````````````
|
||||||
|
|
||||||
|
The definition must be indented to 4 characters including the `:`.
|
||||||
|
|
||||||
|
```````````````````````````````` example
|
||||||
|
Term 1
|
||||||
|
: Invalid with less than 3 characters
|
||||||
|
.
|
||||||
|
<p>Term 1
|
||||||
|
: Invalid with less than 3 characters</p>
|
||||||
|
````````````````````````````````
|
||||||
|
|
||||||
|
The `:` can be indented up to 3 spaces:
|
||||||
|
|
||||||
|
```````````````````````````````` example
|
||||||
|
Term 1
|
||||||
|
: Valid even if `:` starts at most 3 spaces
|
||||||
|
.
|
||||||
|
<dl>
|
||||||
|
<dt>Term 1</dt>
|
||||||
|
<dd>Valid even if <code>:</code> starts at most 3 spaces</dd>
|
||||||
|
</dl>
|
||||||
|
````````````````````````````````
|
||||||
|
|
||||||
|
But more than 3 spaces before `:` will trigger an indented code block:
|
||||||
|
|
||||||
|
```````````````````````````````` example
|
||||||
|
Term 1
|
||||||
|
|
||||||
|
: Not valid
|
||||||
|
.
|
||||||
|
<p>Term 1</p>
|
||||||
|
<pre><code>: Not valid
|
||||||
|
</code></pre>
|
||||||
|
````````````````````````````````
|
||||||
|
|
||||||
|
Definition lists can be nested inside list items
|
||||||
|
|
||||||
|
```````````````````````````````` example
|
||||||
|
1. First
|
||||||
|
|
||||||
|
2. Second
|
||||||
|
|
||||||
|
Term 1
|
||||||
|
: Definition
|
||||||
|
|
||||||
|
Term 2
|
||||||
|
: Second Definition
|
||||||
|
.
|
||||||
|
<ol>
|
||||||
|
<li><p>First</p></li>
|
||||||
|
<li><p>Second</p>
|
||||||
|
<dl>
|
||||||
|
<dt>Term 1</dt>
|
||||||
|
<dd>Definition</dd>
|
||||||
|
<dt>Term 2</dt>
|
||||||
|
<dd>Second Definition</dd>
|
||||||
|
</dl></li>
|
||||||
|
</ol>
|
||||||
|
````````````````````````````````
|
||||||
@@ -0,0 +1,208 @@
|
|||||||
|
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||||
|
// This file is licensed under the BSD-Clause 2 license.
|
||||||
|
// See the license.txt file in the project root for more information.
|
||||||
|
|
||||||
|
using Markdig.Parsers;
|
||||||
|
using Markdig.Syntax;
|
||||||
|
|
||||||
|
namespace Markdig.Extensions.DefinitionLists;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The block parser for a <see cref="DefinitionList"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="BlockParser" />
|
||||||
|
public class DefinitionListParser : BlockParser
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="DefinitionListParser"/> class.
|
||||||
|
/// </summary>
|
||||||
|
public DefinitionListParser()
|
||||||
|
{
|
||||||
|
OpeningCharacters = [':', '~'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempts to open a block at the current parser position.
|
||||||
|
/// </summary>
|
||||||
|
public override BlockState TryOpen(BlockProcessor processor)
|
||||||
|
{
|
||||||
|
var paragraphBlock = processor.LastBlock as ParagraphBlock;
|
||||||
|
if (processor.IsCodeIndent || paragraphBlock is null || paragraphBlock.LastLine - processor.LineIndex > 1)
|
||||||
|
{
|
||||||
|
return BlockState.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
var startPosition = processor.Start;
|
||||||
|
|
||||||
|
var column = processor.ColumnBeforeIndent;
|
||||||
|
processor.NextChar();
|
||||||
|
processor.ParseIndent();
|
||||||
|
var delta = processor.Column - column;
|
||||||
|
|
||||||
|
// We expect to have a least
|
||||||
|
if (delta < 4)
|
||||||
|
{
|
||||||
|
// Return back to original position
|
||||||
|
processor.GoToColumn(column);
|
||||||
|
return BlockState.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (delta > 4)
|
||||||
|
{
|
||||||
|
processor.GoToColumn(column + 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
var previousParent = paragraphBlock.Parent!;
|
||||||
|
var currentDefinitionList = GetCurrentDefinitionList(paragraphBlock, previousParent);
|
||||||
|
|
||||||
|
processor.Discard(paragraphBlock);
|
||||||
|
|
||||||
|
// If the paragraph block was not part of the opened blocks, we need to remove it manually from its parent container
|
||||||
|
if (paragraphBlock.Parent != null)
|
||||||
|
{
|
||||||
|
paragraphBlock.Parent.Remove(paragraphBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentDefinitionList is null)
|
||||||
|
{
|
||||||
|
currentDefinitionList = new DefinitionList(this)
|
||||||
|
{
|
||||||
|
Span = new SourceSpan(paragraphBlock.Span.Start, processor.Line.End),
|
||||||
|
Column = paragraphBlock.Column,
|
||||||
|
Line = paragraphBlock.Line,
|
||||||
|
};
|
||||||
|
previousParent.Add(currentDefinitionList);
|
||||||
|
}
|
||||||
|
|
||||||
|
var definitionItem = new DefinitionItem(this)
|
||||||
|
{
|
||||||
|
Line = processor.LineIndex,
|
||||||
|
Column = column,
|
||||||
|
Span = new SourceSpan(paragraphBlock.Span.Start, processor.Line.End),
|
||||||
|
OpeningCharacter = processor.CurrentChar,
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; i < paragraphBlock.Lines.Count; i++)
|
||||||
|
{
|
||||||
|
var line = paragraphBlock.Lines.Lines[i];
|
||||||
|
var term = new DefinitionTerm(this)
|
||||||
|
{
|
||||||
|
Column = paragraphBlock.Column,
|
||||||
|
Line = line.Line,
|
||||||
|
Span = new SourceSpan(paragraphBlock.Span.Start, paragraphBlock.Span.End),
|
||||||
|
IsOpen = false
|
||||||
|
};
|
||||||
|
term.AppendLine(ref line.Slice, line.Column, line.Line, line.Position, processor.TrackTrivia);
|
||||||
|
definitionItem.Add(term);
|
||||||
|
}
|
||||||
|
currentDefinitionList.Add(definitionItem);
|
||||||
|
processor.Open(definitionItem);
|
||||||
|
|
||||||
|
// Update the end position
|
||||||
|
currentDefinitionList.UpdateSpanEnd(processor.Line.End);
|
||||||
|
|
||||||
|
return BlockState.Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DefinitionList? GetCurrentDefinitionList(ParagraphBlock paragraphBlock, ContainerBlock previousParent)
|
||||||
|
{
|
||||||
|
var index = previousParent.IndexOf(paragraphBlock) - 1;
|
||||||
|
if (index < 0) return null;
|
||||||
|
switch (previousParent[index])
|
||||||
|
{
|
||||||
|
case DefinitionList definitionList:
|
||||||
|
return definitionList;
|
||||||
|
|
||||||
|
case BlankLineBlock:
|
||||||
|
if (index > 0 && previousParent[index - 1] is DefinitionList definitionList2)
|
||||||
|
{
|
||||||
|
previousParent.RemoveAt(index);
|
||||||
|
return definitionList2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempts to continue parsing the specified block.
|
||||||
|
/// </summary>
|
||||||
|
public override BlockState TryContinue(BlockProcessor processor, Block block)
|
||||||
|
{
|
||||||
|
var definitionItem = (DefinitionItem)block;
|
||||||
|
if (processor.IsCodeIndent)
|
||||||
|
{
|
||||||
|
processor.GoToCodeIndent();
|
||||||
|
return BlockState.Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var list = (DefinitionList)definitionItem.Parent!;
|
||||||
|
var lastBlankLine = definitionItem.LastChild as BlankLineBlock;
|
||||||
|
|
||||||
|
// Check if we have another definition list
|
||||||
|
if (Array.IndexOf(OpeningCharacters!, processor.CurrentChar) >= 0)
|
||||||
|
{
|
||||||
|
var startPosition = processor.Start;
|
||||||
|
var column = processor.ColumnBeforeIndent;
|
||||||
|
processor.NextChar();
|
||||||
|
processor.ParseIndent();
|
||||||
|
var delta = processor.Column - column;
|
||||||
|
|
||||||
|
// We expect to have a least
|
||||||
|
if (delta < 4)
|
||||||
|
{
|
||||||
|
// Remove the blankline before breaking this definition item
|
||||||
|
if (lastBlankLine != null)
|
||||||
|
{
|
||||||
|
definitionItem.RemoveAt(definitionItem.Count - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
list.Span.End = list.LastChild!.Span.End;
|
||||||
|
return BlockState.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (delta > 4)
|
||||||
|
{
|
||||||
|
processor.GoToColumn(column + 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
processor.Close(definitionItem);
|
||||||
|
var nextDefinitionItem = new DefinitionItem(this)
|
||||||
|
{
|
||||||
|
Span = new SourceSpan(startPosition, processor.Line.End),
|
||||||
|
Line = processor.LineIndex,
|
||||||
|
Column = processor.Column,
|
||||||
|
OpeningCharacter = processor.CurrentChar,
|
||||||
|
};
|
||||||
|
list.Add(nextDefinitionItem);
|
||||||
|
processor.Open(nextDefinitionItem);
|
||||||
|
|
||||||
|
return BlockState.Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var isBreakable = definitionItem.LastChild?.IsBreakable ?? true;
|
||||||
|
if (processor.IsBlankLine)
|
||||||
|
{
|
||||||
|
if (lastBlankLine is null && isBreakable)
|
||||||
|
{
|
||||||
|
definitionItem.Add(new BlankLineBlock());
|
||||||
|
}
|
||||||
|
return isBreakable ? BlockState.ContinueDiscard : BlockState.Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var paragraphBlock = definitionItem.LastChild as ParagraphBlock;
|
||||||
|
if (lastBlankLine is null && paragraphBlock != null)
|
||||||
|
{
|
||||||
|
return BlockState.Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the blankline before breaking this definition item
|
||||||
|
if (lastBlankLine != null)
|
||||||
|
{
|
||||||
|
definitionItem.RemoveAt(definitionItem.Count - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
list.Span.End = list.LastChild!.Span.End;
|
||||||
|
return BlockState.Break;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user