Files
markdig/src/Textamina.Markdig/Syntax/FencedCodeBlock.cs
2016-02-19 20:40:43 +09:00

110 lines
3.3 KiB
C#

using Textamina.Markdig.Parsing;
namespace Textamina.Markdig.Syntax
{
/// <summary>
/// Repressents a fenced code block.
/// </summary>
/// <remarks>
/// Related to CommonMark spec: 4.5 Fenced code blocks
/// </remarks>
public class FencedCodeBlock : CodeBlock
{
public new static readonly BlockParser Parser = new ParserInternal();
private int fencedCharCount;
private char fencedChar;
private bool hasFencedEnd;
private class ParserInternal : BlockParser
{
public override MatchLineResult Match(MatchLineState state)
{
var liner = state.Line;
var fenced = state.Block as FencedCodeBlock;
if (fenced != null)
{
var c = liner.Current;
var saveLiner = liner.Save();
liner.SkipLeadingSpaces3();
int count = fenced.fencedCharCount;
var matchChar = fenced.fencedChar;
while (!liner.IsEol)
{
if (c != matchChar || count < 0)
{
break;
}
c = liner.NextChar();
count--;
}
if (count <= 0)
{
fenced.hasFencedEnd = true;
return MatchLineResult.Last;
}
liner.Restore(ref saveLiner);
// TODO: It is unclear how to handle this correctly
// Break only if Eof
return MatchLineResult.Continue;
}
else
{
// TODO: We need to count the number of leading space to remove them on each line
liner.SkipLeadingSpaces3();
var c = liner.Current;
int count = 0;
var matchChar = (char)0;
while (!liner.IsEol)
{
if (count == 0 && (c == '`' || c == '~'))
{
matchChar = c;
}
else if (c != matchChar)
{
break;
}
c = liner.NextChar();
count++;
}
if (count >= 3)
{
// Store the number of matched string into the context
state.Block = new FencedCodeBlock()
{
fencedChar = matchChar,
fencedCharCount = count
};
return MatchLineResult.Continue;
}
return MatchLineResult.None;
}
}
public override void Close(Block block)
{
var fenced = (FencedCodeBlock) block;
fenced.Lines.RemoveAt(0);
if (fenced.hasFencedEnd)
{
fenced.Lines.RemoveAt(fenced.Lines.Count - 1);
}
}
}
}
}