Skip to content

Commit 3b58bc3

Browse files
committed
Track Source Positions
1 parent f27483f commit 3b58bc3

2 files changed

Lines changed: 182 additions & 68 deletions

File tree

commonmark-ext-gfm-alerts/src/main/java/org/commonmark/ext/gfm/alerts/internal/AlertBlockParser.java

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.commonmark.ext.gfm.alerts.internal;
22

3+
import java.util.List;
34
import java.util.Locale;
45
import java.util.Set;
56
import java.util.regex.Pattern;
@@ -26,11 +27,11 @@ public class AlertBlockParser extends AbstractBlockParser {
2627
private static final Pattern ALERT_PATTERN_CUSTOM_TITLE = Pattern.compile("^\\[!([a-zA-Z]+)](.*)$");
2728

2829
private final Alert block;
29-
private final String titleContent;
30+
private final SourceLine titleLine;
3031

31-
private AlertBlockParser(String type, String titleContent) {
32+
private AlertBlockParser(String type, SourceLine titleLine) {
3233
this.block = new Alert(type);
33-
this.titleContent = titleContent;
34+
this.titleLine = titleLine;
3435
}
3536

3637
@Override
@@ -72,7 +73,7 @@ public BlockContinue tryContinue(ParserState state) {
7273

7374
@Override
7475
public void parseInlines(InlineParser inlineParser) {
75-
if (titleContent.isEmpty()) {
76+
if (titleLine == null || titleLine.getContent().length() == 0) {
7677
return;
7778
}
7879

@@ -84,7 +85,13 @@ public void parseInlines(InlineParser inlineParser) {
8485
* > But 3*3 = 9
8586
*/
8687
var titleNode = new AlertTitle();
87-
inlineParser.parse(SourceLines.of(SourceLine.of(titleContent, null)), titleNode);
88+
inlineParser.parse(SourceLines.of(titleLine), titleNode);
89+
90+
// Set source spans on the title node from the source line
91+
var sourceSpan = titleLine.getSourceSpan();
92+
if (sourceSpan != null) {
93+
titleNode.setSourceSpans(List.of(sourceSpan));
94+
}
8895

8996
// Body blocks were attached as children during block parsing. Prepend the title.
9097
block.prependChild(titleNode);
@@ -181,13 +188,30 @@ private BlockStart tryStartFresh(CharSequence line, int nextNonSpace, ParserStat
181188
return BlockStart.none();
182189
}
183190

184-
var titleContent = "";
191+
SourceLine titleLine = null;
185192
if (customTitlesAllowed) {
186-
titleContent = matcher.group(2).replaceFirst("^[ \\t]+", "").stripTrailing();
193+
var fullSourceLine = state.getLine();
194+
var fullContent = fullSourceLine.getContent();
195+
196+
var groupStart = matcher.start(2);
197+
var groupEnd = matcher.end(2);
198+
var absStart = afterGt + groupStart;
199+
var absEnd = afterGt + groupEnd;
200+
201+
// Trim leading spaces/tabs
202+
while (absStart < absEnd && Characters.isSpaceOrTab(fullContent, absStart)) {
203+
absStart++;
204+
}
205+
// Trim trailing spaces/tabs
206+
while (absEnd > absStart && Characters.isSpaceOrTab(fullContent, absEnd - 1)) {
207+
absEnd--;
208+
}
209+
210+
titleLine = fullSourceLine.substring(absStart, absEnd);
187211
}
188212

189213
// Consume the rest of the first line.
190-
var start = BlockStart.of(new AlertBlockParser(type, titleContent)).atIndex(line.length());
214+
var start = BlockStart.of(new AlertBlockParser(type, titleLine)).atIndex(line.length());
191215

192216
// If we got here via the promotion path, replace the empty BlockQuote.
193217
var matched = state.getActiveBlockParser().getBlock();

0 commit comments

Comments
 (0)