Skip to content

Commit a9bd7c6

Browse files
prozolicCopilot
andauthored
Fix to calculate LinkReferenceDefinition span positions from StringLineGroup.Lines (#931)
* Fix to calculate LinkReferenceDefinition span positions from StringLineGroup.Lines * Add test case in TestMultilineInBlockquote * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Change from startPosition + span.End - span.Start to GetAbsolutePosition(lines, span.End) * Move ConvertToAbsoluteSpan and GetAbsolutePosition to StringLineGroup * Remove '\r' check in Write(ReadOnlySpan<char>) --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
1 parent 7cb7583 commit a9bd7c6

4 files changed

Lines changed: 61 additions & 19 deletions

File tree

src/Markdig.Tests/RoundtripSpecs/TestLinkReferenceDefinition.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,4 +209,16 @@ public void TestSetextHeader(string value)
209209
{
210210
RoundTrip(value);
211211
}
212+
213+
[TestCase("> [foo]: /url 'the title'\n")]
214+
[TestCase("> [foo]: /url\n> 'the title'\n")]
215+
[TestCase("> [foo]:\n> /url 'the title'\n")]
216+
[TestCase("> [foo]:\n> /url\n> 'the title'\n")]
217+
[TestCase("> [foo]:\n> /url\n>\n> [foo]\n")]
218+
[TestCase("> [foo]:\n> /url 'the title'\n>\n> [foo]\n")]
219+
[TestCase("> [foo]:\n> /url\n> 'the title'\n>\n> [foo]\n")]
220+
public void TestMultilineInBlockquote(string value)
221+
{
222+
RoundTrip(value);
223+
}
212224
}

src/Markdig/Helpers/StringLineGroup.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// This file is licensed under the BSD-Clause 2 license.
33
// See the license.txt file in the project root for more information.
44

5+
using Markdig.Syntax;
56
using System.Collections;
67
using System.Diagnostics;
78
using System.Runtime.CompilerServices;
@@ -190,6 +191,33 @@ public void Trim()
190191
}
191192
}
192193

194+
internal SourceSpan ConvertToAbsoluteSpan(SourceSpan span)
195+
{
196+
if (span.IsEmpty || Count == 0) return span;
197+
198+
var startPosition = GetAbsolutePosition(span.Start);
199+
var endPosition = GetAbsolutePosition(span.End);
200+
201+
return new SourceSpan(startPosition, endPosition);
202+
}
203+
204+
private int GetAbsolutePosition(int position)
205+
{
206+
int offset = 0;
207+
for (int i = 0; i < Count; i++)
208+
{
209+
ref StringSlice slice = ref Lines[i].Slice;
210+
var lineLength = slice.Length + slice.NewLine.Length();
211+
212+
if (i == Count - 1 || position < offset + lineLength)
213+
{
214+
return slice.Start + (position - offset);
215+
}
216+
offset += lineLength;
217+
}
218+
return Lines[Count - 1].Slice.End + 1;
219+
}
220+
193221
/// <summary>
194222
/// Gets or sets the enumerator.
195223
/// </summary>

src/Markdig/Parsers/ParagraphBlockParser.cs

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -212,13 +212,11 @@ private static bool TryMatchLinkReferenceDefinition(ref StringLineGroup lines, B
212212

213213
// Correct the locations of each field
214214
linkReferenceDefinition.Line = lines.Lines[0].Line;
215-
int startPosition = lines.Lines[0].Slice.Start;
216-
217-
linkReferenceDefinition.Span = linkReferenceDefinition.Span .MoveForward(startPosition);
218-
linkReferenceDefinition.LabelSpan = linkReferenceDefinition.LabelSpan .MoveForward(startPosition);
219-
linkReferenceDefinition.UrlSpan = linkReferenceDefinition.UrlSpan .MoveForward(startPosition);
220-
linkReferenceDefinition.TitleSpan = linkReferenceDefinition.TitleSpan .MoveForward(startPosition);
221215

216+
linkReferenceDefinition.Span = lines.ConvertToAbsoluteSpan(linkReferenceDefinition.Span);
217+
linkReferenceDefinition.LabelSpan = lines.ConvertToAbsoluteSpan(linkReferenceDefinition.LabelSpan);
218+
linkReferenceDefinition.UrlSpan = lines.ConvertToAbsoluteSpan(linkReferenceDefinition.UrlSpan);
219+
linkReferenceDefinition.TitleSpan = lines.ConvertToAbsoluteSpan(linkReferenceDefinition.TitleSpan);
222220
lines = iterator.Remaining();
223221
}
224222
else
@@ -256,24 +254,23 @@ private static bool TryMatchLinkReferenceDefinitionTrivia(ref StringLineGroup li
256254
// Correct the locations of each field
257255
lrd.Line = lines.Lines[0].Line;
258256
var text = lines.Lines[0].Slice.Text;
259-
int startPosition = lines.Lines[0].Slice.Start;
260-
261-
triviaBeforeLabel = triviaBeforeLabel.MoveForward(startPosition);
262-
labelWithTrivia = labelWithTrivia.MoveForward(startPosition);
263-
triviaBeforeUrl = triviaBeforeUrl.MoveForward(startPosition);
264-
unescapedUrl = unescapedUrl.MoveForward(startPosition);
265-
triviaBeforeTitle = triviaBeforeTitle.MoveForward(startPosition);
266-
unescapedTitle = unescapedTitle.MoveForward(startPosition);
267-
triviaAfterTitle = triviaAfterTitle.MoveForward(startPosition);
268-
lrd.Span = lrd.Span.MoveForward(startPosition);
257+
258+
triviaBeforeLabel = lines.ConvertToAbsoluteSpan(triviaBeforeLabel);
259+
labelWithTrivia = lines.ConvertToAbsoluteSpan(labelWithTrivia);
260+
triviaBeforeUrl = lines.ConvertToAbsoluteSpan(triviaBeforeUrl);
261+
unescapedUrl = lines.ConvertToAbsoluteSpan(unescapedUrl);
262+
triviaBeforeTitle = lines.ConvertToAbsoluteSpan(triviaBeforeTitle);
263+
unescapedTitle = lines.ConvertToAbsoluteSpan(unescapedTitle);
264+
triviaAfterTitle = lines.ConvertToAbsoluteSpan(triviaAfterTitle);
265+
lrd.Span = lines.ConvertToAbsoluteSpan(lrd.Span);
269266
lrd.TriviaBefore = new StringSlice(text, triviaBeforeLabel.Start, triviaBeforeLabel.End);
270-
lrd.LabelSpan = lrd.LabelSpan.MoveForward(startPosition);
267+
lrd.LabelSpan = lines.ConvertToAbsoluteSpan(lrd.LabelSpan);
271268
lrd.LabelWithTrivia = new StringSlice(text, labelWithTrivia.Start, labelWithTrivia.End);
272269
lrd.TriviaBeforeUrl = new StringSlice(text, triviaBeforeUrl.Start, triviaBeforeUrl.End);
273-
lrd.UrlSpan = lrd.UrlSpan.MoveForward(startPosition);
270+
lrd.UrlSpan = lines.ConvertToAbsoluteSpan(lrd.UrlSpan);
274271
lrd.UnescapedUrl = new StringSlice(text, unescapedUrl.Start, unescapedUrl.End);
275272
lrd.TriviaBeforeTitle = new StringSlice(text, triviaBeforeTitle.Start, triviaBeforeTitle.End);
276-
lrd.TitleSpan = lrd.TitleSpan.MoveForward(startPosition);
273+
lrd.TitleSpan = lines.ConvertToAbsoluteSpan(lrd.TitleSpan);
277274
lrd.UnescapedTitle = new StringSlice(text, unescapedTitle.Start, unescapedTitle.End);
278275
lrd.TriviaAfter = new StringSlice(text, triviaAfterTitle.Start, triviaAfterTitle.End);
279276
lrd.LinesBefore = paragraph.LinesBefore;
@@ -292,4 +289,5 @@ private static bool TryMatchLinkReferenceDefinitionTrivia(ref StringLineGroup li
292289

293290
return atLeastOneFound;
294291
}
292+
295293
}

src/Markdig/Renderers/TextRendererBase.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,10 @@ public void Write(ReadOnlySpan<char> content)
320320
{
321321
WriteIndent();
322322
WriteRaw(content);
323+
if (content[content.Length - 1] == '\n')
324+
{
325+
previousWasLine = true;
326+
}
323327
}
324328
}
325329

0 commit comments

Comments
 (0)