mirror of
https://github.com/xoofx/markdig.git
synced 2026-10-07 22:28:38 +00:00
respect TrackTrivia flag much more widely, restore intentionally broken behaviors
This commit is contained in:
@@ -62,21 +62,21 @@ namespace Markdig.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase("", "<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("", "<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("", "<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("", "<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("", "<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("", "<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("", "<p><video width=\"500\" height=\"281\" controls=\"\"><source type=\"video/mp4\" src=\"//sample.com/video.mp4\"></source></video></p>\n", "")]
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -22,7 +22,6 @@ namespace Markdig.Parsers
|
||||
{
|
||||
result = new ListInfo(state.CurrentChar);
|
||||
state.NextChar();
|
||||
//state.NextChar();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user