Skip to content

Commit 3111fed

Browse files
committed
footnotes: Fix multiple paragraphs separated by blank lines
1 parent 33737b7 commit 3111fed

File tree

9 files changed

+56
-13
lines changed

9 files changed

+56
-13
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
66
This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html),
77
with the exception that 0.x versions can break between minor versions.
88

9+
## Unreleased
10+
### Fixed
11+
- footnotes: Fix parsing of footnote definitions containing multiple paragraphs
12+
separated by blank lines. Before it only worked if paragraphs were separated
13+
by lines of 4 spaces. (#388)
14+
915
## [0.25.0] - 2025-06-20
1016
### Added
1117
- Include OSGi metadata in jars (`META-INF/MANIFEST.MF` files) (#378)

commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/internal/FootnoteBlockParser.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ public BlockContinue tryContinue(ParserState parserState) {
3939
if (parserState.getIndent() >= 4) {
4040
// It looks like content needs to be indented by 4 so that it's part of a footnote (instead of starting a new block).
4141
return BlockContinue.atColumn(4);
42+
} else if (parserState.isBlank()) {
43+
// A blank line doesn't finish a footnote yet. If there's another line with indent >= 4 after it,
44+
// that should result in another paragraph in this footnote definition.
45+
return BlockContinue.atIndex(parserState.getIndex());
4246
} else {
4347
// We're not continuing to give other block parsers a chance to interrupt this definition.
4448
// But if no other block parser applied (including another FootnotesBlockParser), we will

commonmark-ext-footnotes/src/main/java/org/commonmark/ext/footnotes/internal/FootnoteMarkdownNodeRenderer.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,7 @@ private void renderDefinition(FootnoteDefinition def) {
5555
writer.raw("]: ");
5656

5757
writer.pushPrefix(" ");
58-
writer.pushTight(true);
5958
renderChildren(def);
60-
writer.popTight();
6159
writer.popPrefix();
6260
}
6361

commonmark-ext-footnotes/src/test/java/org/commonmark/ext/footnotes/FootnoteMarkdownRendererTest.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public void testSimple() {
2323
@Test
2424
public void testUnreferenced() {
2525
// Whether a reference has a corresponding definition or vice versa shouldn't matter for Markdown rendering.
26-
assertRoundTrip("Test [^foo]\n\n[^foo]: one\n[^bar]: two\n");
26+
assertRoundTrip("Test [^foo]\n\n[^foo]: one\n\n[^bar]: two\n");
2727
}
2828

2929
@Test
@@ -36,6 +36,18 @@ public void testBackslashInLabel() {
3636
assertRoundTrip("[^\\foo]\n\n[^\\foo]: note\n");
3737
}
3838

39+
@Test
40+
public void testMultipleLines() {
41+
assertRoundTrip("Test [^1]\n\n[^1]: footnote l1\n footnote l2\n");
42+
}
43+
44+
@Test
45+
public void testMultipleParagraphs() {
46+
// Note that the line between p1 and p2 could be blank too (instead of 4 spaces), but we currently don't
47+
// preserve that information.
48+
assertRoundTrip("Test [^1]\n\n[^1]: footnote p1\n \n footnote p2\n");
49+
}
50+
3951
@Test
4052
public void testInline() {
4153
assertRoundTrip("^[test *foo*]\n");

commonmark-ext-footnotes/src/test/java/org/commonmark/ext/footnotes/FootnotesTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,26 @@ public void testDefContainsMultipleLines() {
102102
assertText("still", paragraph.getLastChild());
103103
}
104104

105+
@Test
106+
public void testDefContainsMultipleParagraphs() {
107+
var doc = PARSER.parse("[^1]: footnote p1\n\n footnote p2\n");
108+
var def = find(doc, FootnoteDefinition.class);
109+
assertThat(def.getLabel()).isEqualTo("1");
110+
var p1 = (Paragraph) def.getFirstChild();
111+
assertText("footnote p1", p1.getFirstChild());
112+
var p2 = (Paragraph) p1.getNext();
113+
assertText("footnote p2", p2.getFirstChild());
114+
}
115+
116+
@Test
117+
public void testDefFollowedByParagraph() {
118+
var doc = PARSER.parse("[^1]: footnote\n\nnormal paragraph\n");
119+
var def = find(doc, FootnoteDefinition.class);
120+
assertThat(def.getLabel()).isEqualTo("1");
121+
assertText("footnote", def.getFirstChild().getFirstChild());
122+
assertText("normal paragraph", def.getNext().getFirstChild());
123+
}
124+
105125
@Test
106126
public void testDefContainsList() {
107127
var doc = PARSER.parse("[^1]: - foo\n - bar\n");

commonmark-integration-test/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020
<groupId>org.commonmark</groupId>
2121
<artifactId>commonmark-ext-autolink</artifactId>
2222
</dependency>
23+
<dependency>
24+
<groupId>org.commonmark</groupId>
25+
<artifactId>commonmark-ext-footnotes</artifactId>
26+
</dependency>
2327
<dependency>
2428
<groupId>org.commonmark</groupId>
2529
<artifactId>commonmark-ext-ins</artifactId>

commonmark-integration-test/src/test/java/org/commonmark/integration/Extensions.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import org.commonmark.Extension;
44
import org.commonmark.ext.autolink.AutolinkExtension;
5+
import org.commonmark.ext.footnotes.FootnotesExtension;
56
import org.commonmark.ext.front.matter.YamlFrontMatterExtension;
67
import org.commonmark.ext.gfm.strikethrough.StrikethroughExtension;
78
import org.commonmark.ext.gfm.tables.TablesExtension;
@@ -15,6 +16,7 @@ public class Extensions {
1516

1617
static final List<Extension> ALL_EXTENSIONS = List.of(
1718
AutolinkExtension.create(),
19+
FootnotesExtension.create(),
1820
ImageAttributesExtension.create(),
1921
InsExtension.create(),
2022
StrikethroughExtension.create(),

commonmark-integration-test/src/test/java/org/commonmark/integration/MarkdownRendererIntegrationTest.java

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,8 @@
1818

1919
public class MarkdownRendererIntegrationTest {
2020

21-
private static final List<Extension> EXTENSIONS = List.of(
22-
AutolinkExtension.create(),
23-
ImageAttributesExtension.create(),
24-
InsExtension.create(),
25-
StrikethroughExtension.create(),
26-
TablesExtension.create(),
27-
TaskListItemsExtension.create(),
28-
YamlFrontMatterExtension.create());
29-
private static final Parser PARSER = Parser.builder().extensions(EXTENSIONS).build();
30-
private static final MarkdownRenderer RENDERER = MarkdownRenderer.builder().extensions(EXTENSIONS).build();
21+
private static final Parser PARSER = Parser.builder().extensions(Extensions.ALL_EXTENSIONS).build();
22+
private static final MarkdownRenderer RENDERER = MarkdownRenderer.builder().extensions(Extensions.ALL_EXTENSIONS).build();
3123

3224
@Test
3325
public void testStrikethroughInTable() {

pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@
139139
<artifactId>commonmark-ext-autolink</artifactId>
140140
<version>0.25.1-SNAPSHOT</version>
141141
</dependency>
142+
<dependency>
143+
<groupId>org.commonmark</groupId>
144+
<artifactId>commonmark-ext-footnotes</artifactId>
145+
<version>0.25.1-SNAPSHOT</version>
146+
</dependency>
142147
<dependency>
143148
<groupId>org.commonmark</groupId>
144149
<artifactId>commonmark-ext-image-attributes</artifactId>

0 commit comments

Comments
 (0)