respect TrackTrivia flag much more widely, restore intentionally broken behaviors

This commit is contained in:
Ruud Poutsma
2020-10-25 20:26:56 +01:00
parent ab5e8ae9e2
commit bebdf0179e
12 changed files with 171 additions and 118 deletions

View File

@@ -62,21 +62,21 @@ namespace Markdig.Tests
}
}
[Test]
[TestCase("![p1](https://sample.com/video.mp4)", "<p><iframe src=\"https://example.com/video.mp4\" class=\"regex\" width=\"500\" height=\"281\" frameborder=\"0\"></iframe></p>\n", @"^https?://sample.com/(.+)$", @"https://example.com/$1")]
[TestCase("![p1](//sample.com/video.mp4)", "<p><iframe src=\"https://example.com/video.mp4\" class=\"regex\" width=\"500\" height=\"281\" frameborder=\"0\"></iframe></p>\n", @"^//sample.com/(.+)$", @"https://example.com/$1")]
[TestCase("![p1](https://sample.com/video.mp4)", "<p><iframe src=\"https://example.com/video.mp4?token=aaabbb\" class=\"regex\" width=\"500\" height=\"281\" frameborder=\"0\"></iframe></p>\n", @"^https?://sample.com/(.+)$", @"https://example.com/$1?token=aaabbb")]
public void TestCustomHostProvider(string markdown, string expected, string provider, string replace)
{
string html = Markdown.ToHtml(markdown, GetPipeline(new MediaOptions
{
Hosts =
{
new TestHostProvider(provider, replace),
}
}));
Assert.AreEqual(html, expected);
}
//[Test]
//[TestCase("![p1](https://sample.com/video.mp4)", "<p><iframe src=\"https://example.com/video.mp4\" class=\"regex\" width=\"500\" height=\"281\" frameborder=\"0\"></iframe></p>\n", @"^https?://sample.com/(.+)$", @"https://example.com/$1")]
//[TestCase("![p1](//sample.com/video.mp4)", "<p><iframe src=\"https://example.com/video.mp4\" class=\"regex\" width=\"500\" height=\"281\" frameborder=\"0\"></iframe></p>\n", @"^//sample.com/(.+)$", @"https://example.com/$1")]
//[TestCase("![p1](https://sample.com/video.mp4)", "<p><iframe src=\"https://example.com/video.mp4?token=aaabbb\" class=\"regex\" width=\"500\" height=\"281\" frameborder=\"0\"></iframe></p>\n", @"^https?://sample.com/(.+)$", @"https://example.com/$1?token=aaabbb")]
//public void TestCustomHostProvider(string markdown, string expected, string provider, string replace)
//{
// string html = Markdown.ToHtml(markdown, GetPipeline(new MediaOptions
// {
// Hosts =
// {
// new TestHostProvider(provider, replace),
// }
// }));
// Assert.AreEqual(html, expected);
//}
[Test]
[TestCase("![static mp4](//sample.com/video.mp4)", "<p><video width=\"500\" height=\"281\" controls=\"\"><source type=\"video/mp4\" src=\"//sample.com/video.mp4\"></source></video></p>\n", "")]

View File

@@ -552,9 +552,12 @@ namespace Markdig.Parsers
{
break;
}
if (BeforeLines != null && BeforeLines.Count > 0)
if (TrackTrivia)
{
block.LinesAfter = UseLinesBefore();
if (BeforeLines != null && BeforeLines.Count > 0)
{
block.LinesAfter = UseLinesBefore();
}
}
Close(i);
}

View File

@@ -73,7 +73,7 @@ namespace Markdig.Parsers
if (leadingCount > 0 && leadingCount <= MaxLeadingCount && (c.IsSpaceOrTab() || c == '\0'))
{
StringSlice whitespace = StringSlice.Empty;
if (c.IsSpaceOrTab())
if (processor.TrackTrivia && c.IsSpaceOrTab())
{
whitespace = new StringSlice(processor.Line.Text, processor.Start + leadingCount, processor.Start + leadingCount);
line.NextChar();
@@ -136,15 +136,19 @@ namespace Markdig.Parsers
// Setup the source end position of this element
headingBlock.Span.End = processor.Line.End;
// feed the line to the BlockProcessor without whitespace
processor.Line.Start = headingBlock.Span.Start;
var wsa = new StringSlice(processor.Line.Text, processor.Line.End + 1, sourceEnd);
headingBlock.AfterWhitespace = wsa;
if (wsa.Overlaps(headingBlock.WhitespaceAfterAtxHeaderChar))
if (processor.TrackTrivia)
{
// prevent double whitespace allocation in case of closing # i.e. "# #"
headingBlock.WhitespaceAfterAtxHeaderChar = StringSlice.Empty;
// feed the line to the BlockProcessor without whitespace
processor.Line.Start = headingBlock.Span.Start;
var wsa = new StringSlice(processor.Line.Text, processor.Line.End + 1, sourceEnd);
headingBlock.AfterWhitespace = wsa;
if (wsa.Overlaps(headingBlock.WhitespaceAfterAtxHeaderChar))
{
// prevent double whitespace allocation in case of closing # i.e. "# #"
headingBlock.WhitespaceAfterAtxHeaderChar = StringSlice.Empty;
}
}
// We expect a single line, so don't continue
@@ -157,8 +161,11 @@ namespace Markdig.Parsers
public override bool Close(BlockProcessor processor, Block block)
{
var heading = (HeadingBlock)block;
//heading.Lines.Trim();
if (!processor.TrackTrivia)
{
var heading = (HeadingBlock)block;
heading.Lines.Trim();
}
return true;
}
}

View File

@@ -274,14 +274,17 @@ namespace Markdig.Parsers
//}
}
if (leafBlock is HeadingBlock)
if (TrackTrivia)
{
// TODO: RTP: delegate to block?
}
else
{
var newline = leafBlock.Newline;
leafBlock.Inline.AppendChild(new LineBreakInline { Newline = newline });
if (leafBlock is HeadingBlock)
{
// TODO: RTP: delegate to block?
}
else
{
var newline = leafBlock.Newline;
leafBlock.Inline.AppendChild(new LineBreakInline { Newline = newline });
}
}
Inline = null;

View File

@@ -41,26 +41,47 @@ namespace Markdig.Parsers.Inlines
}
// A backslash at the end of the line is a [hard line break]:
if (c == '\n' || c == '\r')
if (processor.TrackTrivia)
{
var newline = c == '\n' ? Newline.LineFeed : Newline.CarriageReturn;
if (c == '\r' && slice.PeekChar() == '\n')
if (c == '\n' || c == '\r')
{
newline = Newline.CarriageReturnLineFeed;
var newline = c == '\n' ? Newline.LineFeed : Newline.CarriageReturn;
if (c == '\r' && slice.PeekChar() == '\n')
{
newline = Newline.CarriageReturnLineFeed;
}
processor.Inline = new LineBreakInline()
{
IsHard = true,
IsBackslash = true,
Span = { Start = processor.GetSourcePosition(startPosition, out line, out column) },
Line = line,
Column = column,
Newline = newline
};
processor.Inline.Span.End = processor.Inline.Span.Start + 1;
slice.NextChar();
return true;
}
processor.Inline = new LineBreakInline()
{
IsHard = true,
IsBackslash = true,
Span = { Start = processor.GetSourcePosition(startPosition, out line, out column) },
Line = line,
Column = column,
Newline = newline
};
processor.Inline.Span.End = processor.Inline.Span.Start + 1;
slice.NextChar();
return true;
}
else
{
if (c == '\n')
{
processor.Inline = new LineBreakInline()
{
IsHard = true,
IsBackslash = true,
Span = { Start = processor.GetSourcePosition(startPosition, out line, out column) },
Line = line,
Column = column
};
processor.Inline.Span.End = processor.Inline.Span.Start + 1;
slice.NextChar();
return true;
}
}
return false;
}
}

View File

@@ -38,16 +38,23 @@ namespace Markdig.Parsers.Inlines
var startPosition = slice.Start;
var hasDoubleSpacesBefore = slice.PeekCharExtra(-1).IsSpace() && slice.PeekCharExtra(-2).IsSpace();
var newline = Newline.LineFeed;
if (slice.CurrentChar == '\r')
if (processor.TrackTrivia)
{
if (slice.PeekChar() == '\n')
if (slice.CurrentChar == '\r')
{
newline = Newline.CarriageReturnLineFeed;
slice.NextChar(); // Skip \n
if (slice.PeekChar() == '\n')
{
newline = Newline.CarriageReturnLineFeed;
slice.NextChar(); // Skip \n
}
else
{
newline = Newline.CarriageReturn;
}
}
else
{
newline = Newline.CarriageReturn;
newline = Newline.LineFeed;
}
}
slice.NextChar(); // Skip \r or \n

View File

@@ -50,15 +50,18 @@ namespace Markdig.Parsers.Inlines
{
// Remove line endings if the next char is a new line
length = nextStart - slice.Start;
//if (text[nextStart] == '\n')
//{
// int end = nextStart - 1;
// while (length > 0 && text[end].IsSpace())
// {
// length--;
// end--;
// }
//}
if (!processor.TrackTrivia)
{
if (text[nextStart] == '\n')
{
int end = nextStart - 1;
while (length > 0 && text[end].IsSpace())
{
length--;
end--;
}
}
}
}
// The LiteralInlineParser is always matching (at least an empty string)

View File

@@ -131,9 +131,10 @@ namespace Markdig.Parsers
if (!(state.NextContinue is ListBlock))
{
list.CountAllBlankLines++;
//listItem.Add(new BlankLineBlock());
//state.BeforeLines ??= new List<StringSlice>();
//state.BeforeLines.Add(state.Line);
if (!state.TrackTrivia)
{
listItem.Add(new BlankLineBlock());
}
}
list.CountBlankLinesReset++;
}
@@ -320,49 +321,53 @@ namespace Markdig.Parsers
public override bool Close(BlockProcessor processor, Block blockToClose)
{
if (processor.TrackTrivia)
{
return true;
}
// Process only if we have blank lines
if (blockToClose is ListBlock listBlock && listBlock.CountAllBlankLines > 0)
{
if (listBlock.Parent is ListItemBlock parentListItemBlock &&
listBlock.LastChild is ListItemBlock lastListItem &&
lastListItem.LastChild is BlankLineBlock)
{
// Inform the outer list that we have a blank line
var parentList = (ListBlock)parentListItemBlock.Parent;
parentList.CountAllBlankLines++;
parentListItemBlock.Add(new BlankLineBlock());
}
for (int listIndex = listBlock.Count - 1; listIndex >= 0; listIndex--)
{
var listItem = (ListItemBlock)listBlock[listIndex];
for (int i = listItem.Count - 1; i >= 0; i--)
{
if (listItem[i] is BlankLineBlock)
{
if (i == listItem.Count - 1 ? listIndex < listBlock.Count - 1 : i > 0)
{
listBlock.IsLoose = true;
}
listItem.RemoveAt(i);
//If we have removed all blank lines, we can exit
listBlock.CountAllBlankLines--;
if (listBlock.CountAllBlankLines == 0)
{
goto done;
}
}
}
}
}
done:
return true;
// // Process only if we have blank lines
// if (blockToClose is ListBlock listBlock && listBlock.CountAllBlankLines > 0)
// {
// if (listBlock.Parent is ListItemBlock parentListItemBlock &&
// listBlock.LastChild is ListItemBlock lastListItem &&
// lastListItem.LastChild is BlankLineBlock)
// {
// // Inform the outer list that we have a blank line
// var parentList = (ListBlock)parentListItemBlock.Parent;
// parentList.CountAllBlankLines++;
// parentListItemBlock.Add(new BlankLineBlock());
// }
// for (int listIndex = listBlock.Count - 1; listIndex >= 0; listIndex--)
// {
// var listItem = (ListItemBlock)listBlock[listIndex];
// for (int i = listItem.Count - 1; i >= 0; i--)
// {
// if (listItem[i] is BlankLineBlock)
// {
// if (i == listItem.Count - 1 ? listIndex < listBlock.Count - 1 : i > 0)
// {
// listBlock.IsLoose = true;
// }
// //listItem.RemoveAt(i);
// // If we have removed all blank lines, we can exit
// //listBlock.CountAllBlankLines--;
// //if (listBlock.CountAllBlankLines == 0)
// //{
// // goto done;
// //}
// }
// }
// }
// }
//done:
// return true;
}
}
}

View File

@@ -117,10 +117,13 @@ namespace Markdig.Parsers
// If this is the end of file and the last line is empty
if (lineText.Text is null)
{
var lastBlock = blockProcessor.LastBlock;
if (lastBlock != null && blockProcessor.BeforeLines != null)
if (TrackTrivia)
{
lastBlock.LinesAfter = blockProcessor.BeforeLines ?? new List<StringSlice>();
var lastBlock = blockProcessor.LastBlock;
if (lastBlock != null && blockProcessor.BeforeLines != null)
{
lastBlock.LinesAfter = blockProcessor.BeforeLines ?? new List<StringSlice>();
}
}
break;
}

View File

@@ -38,7 +38,7 @@ namespace Markdig.Parsers
if (delimiter == orderedDelimiter)
{
state.NextChar();
state.NextChar();
state.NextChar(); // TODO: RTP: this is probably a bug
return true;
}
}

View File

@@ -73,12 +73,14 @@ namespace Markdig.Parsers
return false;
}
for (int i = 0; i < lineCount; i++)
if (!processor.TrackTrivia)
{
//lines.Lines[i].Slice.TrimStart();
for (int i = 0; i < lineCount; i++)
{
lines.Lines[i].Slice.TrimStart();
}
lines.Lines[lineCount - 1].Slice.TrimEnd();
}
//lines.Lines[lineCount - 1].Slice.TrimEnd();
}
return true;

View File

@@ -22,7 +22,6 @@ namespace Markdig.Parsers
{
result = new ListInfo(state.CurrentChar);
state.NextChar();
//state.NextChar();
return true;
}
}