Skip to content

Commit

Permalink
Merge b7d02ca into 983187e
Browse files Browse the repository at this point in the history
  • Loading branch information
MihaZupan committed Mar 13, 2022
2 parents 983187e + b7d02ca commit 485d5b6
Show file tree
Hide file tree
Showing 27 changed files with 499 additions and 301 deletions.
68 changes: 42 additions & 26 deletions src/Markdig/Helpers/LineReader.cs
Expand Up @@ -4,6 +4,8 @@

using System;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace Markdig.Helpers
{
Expand Down Expand Up @@ -39,41 +41,55 @@ public LineReader(string text)
/// <returns>A new line or null if the end of <see cref="TextReader"/> has been reached</returns>
public StringSlice ReadLine()
{
string text = _text;
string? text = _text;
int end = text.Length;
int sourcePosition = SourcePosition;
int newSourcePosition = int.MaxValue;
NewLine newLine = NewLine.None;

for (int i = sourcePosition; i < text.Length; i++)
if ((uint)sourcePosition >= (uint)end)
{
char c = text[i];
if (c == '\r')
text = null;
}
else
{
#if NETCOREAPP3_1_OR_GREATER
ReadOnlySpan<char> span = MemoryMarshal.CreateReadOnlySpan(ref Unsafe.Add(ref Unsafe.AsRef(text.GetPinnableReference()), sourcePosition), end - sourcePosition);
#else
ReadOnlySpan<char> span = text.AsSpan(sourcePosition);
#endif

int crlf = span.IndexOfAny('\r', '\n');
if (crlf >= 0)
{
int length = 1;
var newLine = NewLine.CarriageReturn;
if (c == '\r' && (uint)(i + 1) < (uint)text.Length && text[i + 1] == '\n')
end = sourcePosition + crlf;
newSourcePosition = end + 1;

#if NETCOREAPP3_1_OR_GREATER
if (Unsafe.Add(ref Unsafe.AsRef(text.GetPinnableReference()), end) == '\r')
#else
if ((uint)end < (uint)text.Length && text[end] == '\r')
#endif
{
i++;
length = 2;
newLine = NewLine.CarriageReturnLineFeed;
if ((uint)(newSourcePosition) < (uint)text.Length && text[newSourcePosition] == '\n')
{
newLine = NewLine.CarriageReturnLineFeed;
newSourcePosition++;
}
else
{
newLine = NewLine.CarriageReturn;
}
}
else
{
newLine = NewLine.LineFeed;
}

var slice = new StringSlice(text, sourcePosition, i - length, newLine);
SourcePosition = i + 1;
return slice;
}

if (c == '\n')
{
var slice = new StringSlice(text, sourcePosition, i - 1, NewLine.LineFeed);
SourcePosition = i + 1;
return slice;
}
}

if (sourcePosition >= text.Length)
return default;

SourcePosition = int.MaxValue;
return new StringSlice(text, sourcePosition, text.Length - 1);
SourcePosition = newSourcePosition;
return new StringSlice(text, sourcePosition, end - 1, newLine, dummy: false);
}
}
}
9 changes: 9 additions & 0 deletions src/Markdig/Helpers/StringSlice.cs
Expand Up @@ -82,6 +82,15 @@ public StringSlice(string text, int start, int end, NewLine newLine)
NewLine = newLine;
}

// Internal ctor to skip the null check
internal StringSlice(string text, int start, int end, NewLine newLine, bool dummy)
{
Text = text;
Start = start;
End = end;
NewLine = newLine;
}

/// <summary>
/// The text of this slice.
/// </summary>
Expand Down
10 changes: 7 additions & 3 deletions src/Markdig/Parsers/FencedBlockParserBase.cs
Expand Up @@ -332,9 +332,13 @@ public override BlockState TryContinue(BlockProcessor processor, Block block)

var fencedBlock = (IFencedBlock)block;
fencedBlock.ClosingFencedCharCount = closingCount;
fencedBlock.NewLine = processor.Line.NewLine;
fencedBlock.TriviaBeforeClosingFence = processor.UseTrivia(sourcePosition - 1);
fencedBlock.TriviaAfter = new StringSlice(processor.Line.Text, lastFenceCharPosition, endBeforeTrim);

if (processor.TrackTrivia)
{
fencedBlock.NewLine = processor.Line.NewLine;
fencedBlock.TriviaBeforeClosingFence = processor.UseTrivia(sourcePosition - 1);
fencedBlock.TriviaAfter = new StringSlice(processor.Line.Text, lastFenceCharPosition, endBeforeTrim);
}

// Don't keep the last line
return BlockState.BreakDiscard;
Expand Down
14 changes: 10 additions & 4 deletions src/Markdig/Parsers/FencedCodeBlockParser.cs
Expand Up @@ -26,13 +26,19 @@ public FencedCodeBlockParser()

protected override FencedCodeBlock CreateFencedBlock(BlockProcessor processor)
{
return new FencedCodeBlock(this)
var codeBlock = new FencedCodeBlock(this)
{
IndentCount = processor.Indent,
LinesBefore = processor.UseLinesBefore(),
TriviaBefore = processor.UseTrivia(processor.Start - 1),
NewLine = processor.Line.NewLine,
};

if (processor.TrackTrivia)
{
codeBlock.LinesBefore = processor.UseLinesBefore();
codeBlock.TriviaBefore = processor.UseTrivia(processor.Start - 1);
codeBlock.NewLine = processor.Line.NewLine;
}

return codeBlock;
}

public override BlockState TryContinue(BlockProcessor processor, Block block)
Expand Down
17 changes: 11 additions & 6 deletions src/Markdig/Parsers/HeadingBlockParser.cs
Expand Up @@ -82,20 +82,25 @@ public override BlockState TryOpen(BlockProcessor processor)
var headingBlock = new HeadingBlock(this)
{
HeaderChar = matchingChar,
TriviaAfterAtxHeaderChar = trivia,
Level = leadingCount,
Column = column,
Span = { Start = sourcePosition },
TriviaBefore = processor.UseTrivia(sourcePosition - 1),
LinesBefore = processor.UseLinesBefore(),
NewLine = processor.Line.NewLine,
};
processor.NewBlocks.Push(headingBlock);
if (!processor.TrackTrivia)

if (processor.TrackTrivia)
{
headingBlock.TriviaAfterAtxHeaderChar = trivia;
headingBlock.TriviaBefore = processor.UseTrivia(sourcePosition - 1);
headingBlock.LinesBefore = processor.UseLinesBefore();
headingBlock.NewLine = processor.Line.NewLine;
}
else
{
processor.GoToColumn(column + leadingCount + 1);
}

processor.NewBlocks.Push(headingBlock);

// Gives a chance to parse attributes
TryParseAttributes?.Invoke(processor, ref processor.Line, headingBlock);

Expand Down
14 changes: 10 additions & 4 deletions src/Markdig/Parsers/HtmlBlockParser.cs
Expand Up @@ -270,16 +270,22 @@ private BlockState MatchEnd(BlockProcessor state, HtmlBlock htmlBlock)

private BlockState CreateHtmlBlock(BlockProcessor state, HtmlBlockType type, int startColumn, int startPosition)
{
state.NewBlocks.Push(new HtmlBlock(this)
var htmlBlock = new HtmlBlock(this)
{
Column = startColumn,
Type = type,
// By default, setup to the end of line
Span = new SourceSpan(startPosition, startPosition + state.Line.End),
//BeforeWhitespace = state.PopBeforeWhitespace(startPosition - 1),
LinesBefore = state.UseLinesBefore(),
NewLine = state.Line.NewLine,
});
};

if (state.TrackTrivia)
{
htmlBlock.LinesBefore = state.UseLinesBefore();
htmlBlock.NewLine = state.Line.NewLine;
}

state.NewBlocks.Push(htmlBlock);
return BlockState.Continue;
}

Expand Down
30 changes: 21 additions & 9 deletions src/Markdig/Parsers/IndentedCodeBlockParser.cs
Expand Up @@ -36,9 +36,14 @@ public override BlockState TryOpen(BlockProcessor processor)
{
Column = processor.Column,
Span = new SourceSpan(processor.Start, processor.Line.End),
LinesBefore = processor.UseLinesBefore(),
NewLine = processor.Line.NewLine,
};

if (processor.TrackTrivia)
{
codeBlock.LinesBefore = processor.UseLinesBefore();
codeBlock.NewLine = processor.Line.NewLine;
}

var codeBlockLine = new CodeBlockLine
{
TriviaBefore = processor.UseTrivia(sourceStartPosition - 1)
Expand Down Expand Up @@ -68,8 +73,12 @@ public override BlockState TryContinue(BlockProcessor processor, Block? block)
if (line.Slice.IsEmpty)
{
codeBlock.Lines.RemoveAt(i);
processor.LinesBefore ??= new List<StringSlice>();
processor.LinesBefore.Add(line.Slice);

if (processor.TrackTrivia)
{
processor.LinesBefore ??= new List<StringSlice>();
processor.LinesBefore.Add(line.Slice);
}
}
else
{
Expand All @@ -92,12 +101,15 @@ public override BlockState TryContinue(BlockProcessor processor, Block? block)

// lines
var cb = (CodeBlock)block;
var codeBlockLine = new CodeBlockLine
{
TriviaBefore = processor.UseTrivia(processor.Start - 1)
};
var codeBlockLine = new CodeBlockLine();

cb.CodeBlockLines.Add(codeBlockLine);
cb.NewLine = processor.Line.NewLine; // ensure block newline is last newline

if (processor.TrackTrivia)
{
codeBlockLine.TriviaBefore = processor.UseTrivia(processor.Start - 1);
cb.NewLine = processor.Line.NewLine; // ensure block newline is last newline
}
}

return BlockState.Continue;
Expand Down
10 changes: 8 additions & 2 deletions src/Markdig/Parsers/Inlines/CodeInlineParser.cs
Expand Up @@ -113,15 +113,21 @@ public override bool Match(InlineProcessor processor, ref StringSlice slice)
int delimiterCount = Math.Min(openSticks, closeSticks);
var spanStart = processor.GetSourcePosition(startPosition, out int line, out int column);
var spanEnd = processor.GetSourcePosition(slice.Start - 1);
processor.Inline = new CodeInline(content)
var codeInline = new CodeInline(content)
{
Delimiter = match,
ContentWithTrivia = new StringSlice(slice.Text, contentStart, contentEnd - 1),
Span = new SourceSpan(spanStart, spanEnd),
Line = line,
Column = column,
DelimiterCount = delimiterCount,
};

if (processor.TrackTrivia)
{
codeInline.ContentWithTrivia = new StringSlice(slice.Text, contentStart, contentEnd - 1);
}

processor.Inline = codeInline;
isMatching = true;
}

Expand Down

0 comments on commit 485d5b6

Please sign in to comment.