mirror of
https://github.com/xoofx/markdig.git
synced 2026-02-12 05:44:48 +00:00
Better handle YAML frontmatter in case the opening --- is never actually closed (#160)
This commit is contained in:
@@ -20617,7 +20617,7 @@ namespace Markdig.Tests
|
||||
TestParser.TestSpec("---\nthis: is a frontmatter\n...\nThis is a text", "<p>This is a text</p>", "yaml");
|
||||
}
|
||||
}
|
||||
// It expects exactly three dots `...`:
|
||||
// If the end front matter marker (`...` or `---`) is not present, it will render the `---` has a `<hr>`:
|
||||
[TestFixture]
|
||||
public partial class TestExtensionsYAMLfrontmatterdiscard
|
||||
{
|
||||
@@ -20630,17 +20630,18 @@ namespace Markdig.Tests
|
||||
// The following CommonMark:
|
||||
// ---
|
||||
// this: is a frontmatter
|
||||
// ....
|
||||
// This is a text
|
||||
//
|
||||
// Should be rendered as:
|
||||
//
|
||||
// <hr />
|
||||
// <p>this: is a frontmatter
|
||||
// This is a text</p>
|
||||
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 5, "Extensions YAML frontmatter discard");
|
||||
TestParser.TestSpec("---\nthis: is a frontmatter\n....\nThis is a text", "", "yaml");
|
||||
TestParser.TestSpec("---\nthis: is a frontmatter\nThis is a text", "<hr />\n<p>this: is a frontmatter\nThis is a text</p>", "yaml");
|
||||
}
|
||||
}
|
||||
// Front matter ends with the first line containing three dots `...` or three dashes `...`:
|
||||
// It expects exactly three dots `...`:
|
||||
[TestFixture]
|
||||
public partial class TestExtensionsYAMLfrontmatterdiscard
|
||||
{
|
||||
@@ -20654,6 +20655,32 @@ namespace Markdig.Tests
|
||||
// ---
|
||||
// this: is a frontmatter
|
||||
// ....
|
||||
// This is a text
|
||||
//
|
||||
// Should be rendered as:
|
||||
// <hr />
|
||||
// <p>this: is a frontmatter
|
||||
// ....
|
||||
// This is a text</p>
|
||||
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 6, "Extensions YAML frontmatter discard");
|
||||
TestParser.TestSpec("---\nthis: is a frontmatter\n....\nThis is a text", "<hr />\n<p>this: is a frontmatter\n....\nThis is a text</p>", "yaml");
|
||||
}
|
||||
}
|
||||
// Front matter ends with the first line containing three dots `...` or three dashes `...`:
|
||||
[TestFixture]
|
||||
public partial class TestExtensionsYAMLfrontmatterdiscard
|
||||
{
|
||||
[Test]
|
||||
public void Example007()
|
||||
{
|
||||
// Example 7
|
||||
// Section: Extensions YAML frontmatter discard
|
||||
//
|
||||
// The following CommonMark:
|
||||
// ---
|
||||
// this: is a frontmatter
|
||||
// ....
|
||||
//
|
||||
// Hello
|
||||
// ---
|
||||
@@ -20662,7 +20689,7 @@ namespace Markdig.Tests
|
||||
// Should be rendered as:
|
||||
// <p>This is a text</p>
|
||||
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 6, "Extensions YAML frontmatter discard");
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 7, "Extensions YAML frontmatter discard");
|
||||
TestParser.TestSpec("---\nthis: is a frontmatter\n....\n\nHello\n---\nThis is a text", "<p>This is a text</p>", "yaml");
|
||||
}
|
||||
}
|
||||
@@ -20671,9 +20698,9 @@ namespace Markdig.Tests
|
||||
public partial class TestExtensionsYAMLfrontmatterdiscard
|
||||
{
|
||||
[Test]
|
||||
public void Example007()
|
||||
public void Example008()
|
||||
{
|
||||
// Example 7
|
||||
// Example 8
|
||||
// Section: Extensions YAML frontmatter discard
|
||||
//
|
||||
// The following CommonMark:
|
||||
@@ -20685,7 +20712,7 @@ namespace Markdig.Tests
|
||||
// Should be rendered as:
|
||||
// <p>This is a text</p>
|
||||
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 7, "Extensions YAML frontmatter discard");
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 8, "Extensions YAML frontmatter discard");
|
||||
TestParser.TestSpec("--- \nthis: is a frontmatter\n...\nThis is a text", "<p>This is a text</p>", "yaml");
|
||||
}
|
||||
}
|
||||
@@ -20694,9 +20721,9 @@ namespace Markdig.Tests
|
||||
public partial class TestExtensionsYAMLfrontmatterdiscard
|
||||
{
|
||||
[Test]
|
||||
public void Example008()
|
||||
public void Example009()
|
||||
{
|
||||
// Example 8
|
||||
// Example 9
|
||||
// Section: Extensions YAML frontmatter discard
|
||||
//
|
||||
// The following CommonMark:
|
||||
@@ -20708,7 +20735,7 @@ namespace Markdig.Tests
|
||||
// Should be rendered as:
|
||||
// <p>This is a text</p>
|
||||
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 8, "Extensions YAML frontmatter discard");
|
||||
Console.WriteLine("Example {0}" + Environment.NewLine + "Section: {0}" + Environment.NewLine, 9, "Extensions YAML frontmatter discard");
|
||||
TestParser.TestSpec("---\nthis: is a frontmatter\n... \nThis is a text", "<p>This is a text</p>", "yaml");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,18 @@ This is a text
|
||||
<p>This is a text</p>
|
||||
````````````````````````````````
|
||||
|
||||
If the end front matter marker (`...` or `---`) is not present, it will render the `---` has a `<hr>`:
|
||||
|
||||
```````````````````````````````` example
|
||||
---
|
||||
this: is a frontmatter
|
||||
This is a text
|
||||
.
|
||||
<hr />
|
||||
<p>this: is a frontmatter
|
||||
This is a text</p>
|
||||
````````````````````````````````
|
||||
|
||||
It expects exactly three dots `...`:
|
||||
|
||||
```````````````````````````````` example
|
||||
@@ -61,6 +73,10 @@ this: is a frontmatter
|
||||
....
|
||||
This is a text
|
||||
.
|
||||
<hr />
|
||||
<p>this: is a frontmatter
|
||||
....
|
||||
This is a text</p>
|
||||
````````````````````````````````
|
||||
|
||||
Front matter ends with the first line containing three dots `...` or three dashes `...`:
|
||||
|
||||
@@ -67,17 +67,55 @@ namespace Markdig.Extensions.Yaml
|
||||
// this is a YAML front matter blcok
|
||||
if (count == 3 && (c == '\0' || c.IsWhitespace()) && line.TrimEnd())
|
||||
{
|
||||
// Create a front matter block
|
||||
var block = this.CreateFrontMatterBlock(processor);
|
||||
block.Column = processor.Column;
|
||||
block.Span.Start = 0;
|
||||
block.Span.End = line.Start;
|
||||
bool hasFullYamlFrontMatter = false;
|
||||
// We make sure that there is a closing frontmatter somewhere in the document
|
||||
// so here we work on the full document instead of just the line
|
||||
var fullLine = new StringSlice(line.Text, line.Start, line.Text.Length - 1);
|
||||
c = fullLine.CurrentChar;
|
||||
while (c != '\0')
|
||||
{
|
||||
c = fullLine.NextChar();
|
||||
if (c == '\n' || c == '\r')
|
||||
{
|
||||
var nc = fullLine.PeekChar();
|
||||
if (c == '\r' && nc == '\n')
|
||||
{
|
||||
c = fullLine.NextChar();
|
||||
}
|
||||
nc = fullLine.NextChar(); // skip \n
|
||||
if (nc == '-')
|
||||
{
|
||||
if (fullLine.NextChar() == '-' && fullLine.NextChar() == '-' && (fullLine.NextChar() == '\0' || fullLine.SkipSpacesToEndOfLineOrEndOfDocument()))
|
||||
{
|
||||
hasFullYamlFrontMatter = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (nc == '.')
|
||||
{
|
||||
if (fullLine.NextChar() == '.' && fullLine.NextChar() == '.' && (fullLine.NextChar() == '\0' || fullLine.SkipSpacesToEndOfLineOrEndOfDocument()))
|
||||
{
|
||||
hasFullYamlFrontMatter = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store the number of matched string into the context
|
||||
processor.NewBlocks.Push(block);
|
||||
if (hasFullYamlFrontMatter)
|
||||
{
|
||||
// Create a front matter block
|
||||
var block = this.CreateFrontMatterBlock(processor);
|
||||
block.Column = processor.Column;
|
||||
block.Span.Start = 0;
|
||||
block.Span.End = line.Start;
|
||||
|
||||
// Discard the current line as it is already parsed
|
||||
return BlockState.ContinueDiscard;
|
||||
// Store the number of matched string into the context
|
||||
processor.NewBlocks.Push(block);
|
||||
|
||||
// Discard the current line as it is already parsed
|
||||
return BlockState.ContinueDiscard;
|
||||
}
|
||||
}
|
||||
|
||||
return BlockState.None;
|
||||
|
||||
@@ -106,7 +106,7 @@ namespace Markdig.Helpers
|
||||
/// <param name="offset">The offset.</param>
|
||||
/// <returns>The character at offset, returns `\0` if none.</returns>
|
||||
[MethodImpl(MethodImplOptionPortable.AggressiveInlining)]
|
||||
public char PeekChar(int offset)
|
||||
public char PeekChar(int offset = 1)
|
||||
{
|
||||
var index = Start + offset;
|
||||
return index >= Start && index <= End ? Text[index] : (char) 0;
|
||||
@@ -168,6 +168,28 @@ namespace Markdig.Helpers
|
||||
return i == text.Length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Expect spaces until a end of line. Return <c>false</c> otherwise.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if whitespaces where matched until a end of line</returns>
|
||||
public bool SkipSpacesToEndOfLineOrEndOfDocument()
|
||||
{
|
||||
for (int i = Start; i <= End; i++)
|
||||
{
|
||||
var c = Text[i];
|
||||
if (c.IsWhitespace())
|
||||
{
|
||||
if (c == '\0' || c == '\n' || (c == '\r' && i + 1 <= End && Text[i + 1] != '\n'))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Matches the specified text using lowercase comparison.
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user