Skip to content

Commit 4c92fe5

Browse files
committed
Fix regression when parsing link reference definitions (#543)
1 parent 27f625f commit 4c92fe5

File tree

5 files changed

+38
-25
lines changed

5 files changed

+38
-25
lines changed

src/Markdig.Tests/TestPlayParser.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,16 @@ namespace Markdig.Tests
1212
[TestFixture]
1313
public class TestPlayParser
1414
{
15+
[Test]
16+
public void TestLinksWithCarriageReturn()
17+
{
18+
{
19+
var text = "[Link 1][link-1], [link 2][link-2].\r\n\r\n[link-1]: https://example.com\r\n[link-2]: https://example.com";
20+
var result = Markdown.ToHtml(text).TrimEnd();
21+
Assert.AreEqual("<p><a href=\"https://example.com\">Link 1</a>, <a href=\"https://example.com\">link 2</a>.</p>", result);
22+
}
23+
}
24+
1525
[Test]
1626
public void TestLink()
1727
{

src/Markdig.Tests/TestRoundtrip.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ internal static void RoundTrip(string markdown)
2323

2424
nr.Write(markdownDocument);
2525

26-
Assert.AreEqual(markdown, sw.ToString());
26+
var result = sw.ToString();
27+
Assert.AreEqual(markdown, result);
2728
}
2829
}
2930
}

src/Markdig/Helpers/LinkHelper.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1231,7 +1231,9 @@ public static bool TryParseLinkReferenceDefinitionTrivia<T>(
12311231
var saved = text;
12321232
var hasWhiteSpaces = CharIteratorHelper.TrimStartAndCountNewLines(ref text, out int newLineCount, out newLine);
12331233

1234-
triviaBeforeTitle = new SourceSpan(triviaBeforeTitleStart, text.Start - 1);
1234+
// Remove the newline from the trivia (as it may have multiple lines)
1235+
var triviaBeforeTitleEnd = text.Start - 1;
1236+
triviaBeforeTitle = new SourceSpan(triviaBeforeTitleStart, triviaBeforeTitleEnd);
12351237
var c = text.CurrentChar;
12361238
if (c == '\'' || c == '"' || c == '(')
12371239
{
@@ -1246,6 +1248,9 @@ public static bool TryParseLinkReferenceDefinitionTrivia<T>(
12461248
{
12471249
return false;
12481250
}
1251+
1252+
// Discard the newline if we have a title
1253+
newLine = NewLine.None;
12491254
}
12501255
else
12511256
{
@@ -1256,6 +1261,8 @@ public static bool TryParseLinkReferenceDefinitionTrivia<T>(
12561261
{
12571262
if (text.IsEmpty || newLineCount > 0)
12581263
{
1264+
// If we have an end of line, we need to remove it from the trivia
1265+
triviaBeforeTitle.End -= newLine.Length();
12591266
triviaAfterTitle = new SourceSpan(text.Start, text.Start - 1);
12601267
return true;
12611268
}
@@ -1277,6 +1284,7 @@ public static bool TryParseLinkReferenceDefinitionTrivia<T>(
12771284
{
12781285
text = saved;
12791286
title = null;
1287+
newLine = NewLine.None;
12801288
unescapedTitle = SourceSpan.Empty;
12811289
triviaAfterTitle = SourceSpan.Empty;
12821290
return true;

src/Markdig/Helpers/StringLineGroup.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ public char NextChar()
299299
CurrentChar = '\r';
300300
}
301301
}
302-
else if (_offset + 1 == slice.Length)
302+
else if (_offset - 1 == slice.Length)
303303
{
304304
if (newLine == NewLine.CarriageReturnLineFeed)
305305
{

src/Markdig/Syntax/CharIteratorHelper.cs

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,45 +13,39 @@ public static class CharIteratorHelper
1313
{
1414
public static bool TrimStartAndCountNewLines<T>(ref T iterator, out int countNewLines) where T : ICharIterator
1515
{
16-
countNewLines = 0;
17-
var c = iterator.CurrentChar;
18-
bool hasWhitespaces = false;
19-
while (c.IsWhitespace())
20-
{
21-
if (c == '\n')
22-
{
23-
countNewLines++;
24-
}
25-
hasWhitespaces = true;
26-
c = iterator.NextChar();
27-
}
28-
return hasWhitespaces;
16+
return TrimStartAndCountNewLines(ref iterator, out countNewLines, out _);
2917
}
3018

31-
public static bool TrimStartAndCountNewLines<T>(ref T iterator, out int countNewLines, out NewLine firstNewline) where T : ICharIterator
19+
public static bool TrimStartAndCountNewLines<T>(ref T iterator, out int countNewLines, out NewLine lastLine) where T : ICharIterator
3220
{
3321
countNewLines = 0;
3422
var c = iterator.CurrentChar;
3523
bool hasWhitespaces = false;
36-
firstNewline = NewLine.None;
37-
while (c.IsWhitespace())
24+
lastLine = NewLine.None;
25+
while (c != '\0' && c.IsWhitespace())
3826
{
3927
if (c == '\n' || c == '\r')
4028
{
41-
if (c == '\r' && iterator.PeekChar() == '\n' && firstNewline != NewLine.None)
29+
if (c == '\r' && iterator.PeekChar() == '\n')
4230
{
43-
firstNewline = NewLine.CarriageReturnLineFeed;
31+
lastLine = NewLine.CarriageReturnLineFeed;
32+
iterator.SkipChar(); // skip \n
4433
}
45-
else if (c == '\n' && firstNewline != NewLine.None)
34+
else if (c == '\n')
4635
{
47-
firstNewline = NewLine.LineFeed;
36+
lastLine = NewLine.LineFeed;
4837
}
49-
else if (c == '\r' && firstNewline != NewLine.None)
38+
else if (c == '\r')
5039
{
51-
firstNewline = NewLine.CarriageReturn;
40+
lastLine = NewLine.CarriageReturn;
5241
}
5342
countNewLines++;
5443
}
44+
else
45+
{
46+
// reset last line if if have a whitespace after
47+
lastLine = NewLine.None;
48+
}
5549
hasWhitespaces = true;
5650
c = iterator.NextChar();
5751
}

0 commit comments

Comments
 (0)