2016-02-10 00:54:08 +09:00
|
|
|
|
|
|
|
|
|
2016-02-10 20:30:38 +09:00
|
|
|
|
|
|
|
|
using Textamina.Markdig.Parsing;
|
|
|
|
|
|
|
|
|
|
namespace Textamina.Markdig.Syntax
|
2016-02-10 00:54:08 +09:00
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Repressents a fenced code block.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <remarks>
|
|
|
|
|
/// Related to CommonMark spec: 4.5 Fenced code blocks
|
|
|
|
|
/// </remarks>
|
|
|
|
|
public class FencedCodeBlock : BlockLeaf
|
|
|
|
|
{
|
|
|
|
|
public static readonly BlockMatcher DefaultMatcher = new MatcherInternal();
|
|
|
|
|
|
2016-02-10 20:30:38 +09:00
|
|
|
public FencedCodeBlock() : base(DefaultMatcher)
|
2016-02-10 00:54:08 +09:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private class MatcherInternal : BlockMatcher
|
|
|
|
|
{
|
|
|
|
|
public override MatchLineState Match(ref StringLiner liner, MatchLineState matchLineState, ref object matchContext)
|
|
|
|
|
{
|
2016-02-10 20:30:38 +09:00
|
|
|
liner.SkipLeadingSpaces3();
|
|
|
|
|
|
2016-02-10 00:54:08 +09:00
|
|
|
if (matchLineState == MatchLineState.Continue)
|
|
|
|
|
{
|
|
|
|
|
var match = (MatchContext) matchContext;
|
|
|
|
|
|
|
|
|
|
var c = liner.Current;
|
|
|
|
|
|
|
|
|
|
int count = match.Count;
|
|
|
|
|
var matchChar = match.FencedChar;
|
|
|
|
|
while (!liner.IsEol)
|
|
|
|
|
{
|
|
|
|
|
if (c != matchChar || count < 0)
|
|
|
|
|
{
|
|
|
|
|
if (count > 0)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return MatchLineState.Break;
|
|
|
|
|
}
|
|
|
|
|
c = liner.NextChar();
|
|
|
|
|
count--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: It is unclear how to handle this correctly
|
|
|
|
|
return MatchLineState.BreakAndKeepOnlyIfEof;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var c = liner.Current;
|
|
|
|
|
|
|
|
|
|
int count = 0;
|
|
|
|
|
var matchChar = (char)0;
|
|
|
|
|
while (!liner.IsEol)
|
|
|
|
|
{
|
|
|
|
|
if (count == 0 && (c == '-' || c == '_' || c == '*'))
|
|
|
|
|
{
|
|
|
|
|
matchChar = c;
|
|
|
|
|
}
|
|
|
|
|
else if (c != matchChar)
|
|
|
|
|
{
|
|
|
|
|
if (count < 3)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Store the number of matched string into the context
|
|
|
|
|
matchContext = new MatchContext(matchChar, count);
|
|
|
|
|
return MatchLineState.Continue;
|
|
|
|
|
}
|
|
|
|
|
c = liner.NextChar();
|
|
|
|
|
count++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return MatchLineState.Discard;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-10 20:30:38 +09:00
|
|
|
public override Block New()
|
2016-02-10 00:54:08 +09:00
|
|
|
{
|
2016-02-10 20:30:38 +09:00
|
|
|
return new FencedCodeBlock();
|
2016-02-10 00:54:08 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private class MatchContext
|
|
|
|
|
{
|
|
|
|
|
public MatchContext(char fencedChar, int count)
|
|
|
|
|
{
|
|
|
|
|
FencedChar = fencedChar;
|
|
|
|
|
Count = count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public char FencedChar;
|
|
|
|
|
|
|
|
|
|
public int Count;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|