Skip to content

Commit 9458c5e

Browse files
vnykmshrkjk
authored andcommitted
fix: track fenced code state inside list items
Lines inside a fenced code block within a list item (e.g. `- test` or `1. item`) were being misinterpreted as new list items or other block-level structures. This caused the list to break incorrectly whenever the fenced content happened to match list item syntax. Add a fenceMarker variable to the gatherlines loop that tracks whether we are inside a fenced code block. When inside a fence, lines are gathered verbatim, skipping structure detection. Only fences with indent > 0 are tracked (part of list item content). A fence at indent 0 ends the list as before. If an unclosed fence encounters a non-indented line, the fence state is abandoned to prevent swallowing subsequent list items. Fixes #346
1 parent c901e06 commit 9458c5e

3 files changed

Lines changed: 128 additions & 0 deletions

File tree

block_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,12 @@ func TestCodeInList(t *testing.T) {
179179
doTestsParam(t, tests, TestParams{extensions: exts})
180180
}
181181

182+
func TestBug346(t *testing.T) {
183+
tests := readTestFile2(t, "bug346.tests")
184+
exts := parser.CommonExtensions
185+
doTestsParam(t, tests, TestParams{extensions: exts})
186+
}
187+
182188
func TestLists(t *testing.T) {
183189
tests := readTestFile2(t, "Lists.tests")
184190
exts := parser.CommonExtensions

parser/block.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1409,6 +1409,9 @@ func (p *Parser) listItem(data []byte, flags *ast.ListType) int {
14091409
// process the following lines
14101410
containsBlankLine := false
14111411
sublist := 0
1412+
// track fenced code blocks inside list items so that lines within
1413+
// the fence are gathered verbatim (not misinterpreted as list items)
1414+
fenceMarker := ""
14121415

14131416
gatherlines:
14141417
for line < len(data) {
@@ -1442,6 +1445,39 @@ gatherlines:
14421445

14431446
chunk := data[line+indentIndex : i]
14441447

1448+
// track fenced code blocks inside list items;
1449+
// only track fences that are indented (part of the list item content),
1450+
// a fence at indent 0 ends the list (handled below)
1451+
if !isDefinitionList && p.extensions&FencedCode != 0 {
1452+
if fenceMarker != "" {
1453+
if indent == 0 {
1454+
// non-indented line while inside a fence means we
1455+
// left the list item content -- abandon the fence
1456+
fenceMarker = ""
1457+
} else {
1458+
// inside a fence: check for closing fence
1459+
_, marker := isFenceLine(chunk, nil, fenceMarker)
1460+
if marker != "" {
1461+
fenceMarker = ""
1462+
}
1463+
// gather the line verbatim, skip structure detection
1464+
if containsBlankLine {
1465+
containsBlankLine = false
1466+
raw.WriteByte('\n')
1467+
}
1468+
raw.Write(chunk)
1469+
line = i
1470+
continue
1471+
}
1472+
} else if indent > 0 {
1473+
// not inside a fence: check for opening fence (indented only)
1474+
_, marker := isFenceLine(chunk, nil, "")
1475+
if marker != "" {
1476+
fenceMarker = marker
1477+
}
1478+
}
1479+
}
1480+
14451481
// If there is a fence line (marking starting of a code block)
14461482
// without indent do not process it as part of the list.
14471483
//

testdata/bug346.tests

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
- test1
2+
3+
```
4+
- test
5+
```
6+
- test2
7+
8+
```
9+
- test
10+
```
11+
- test3
12+
13+
```
14+
- test
15+
```
16+
+++
17+
<ul>
18+
<li><p>test1</p>
19+
20+
<pre><code>- test
21+
</code></pre></li>
22+
23+
<li><p>test2</p>
24+
25+
<pre><code> - test
26+
</code></pre></li>
27+
28+
<li><p>test3</p>
29+
30+
<pre><code> - test
31+
</code></pre></li>
32+
</ul>
33+
+++
34+
- item
35+
36+
```
37+
1. not a list
38+
```
39+
+++
40+
<ul>
41+
<li><p>item</p>
42+
43+
<pre><code>1. not a list
44+
</code></pre></li>
45+
</ul>
46+
+++
47+
- item
48+
49+
```
50+
# not a heading
51+
```
52+
+++
53+
<ul>
54+
<li><p>item</p>
55+
56+
<pre><code># not a heading
57+
</code></pre></li>
58+
</ul>
59+
+++
60+
- item
61+
62+
~~~
63+
- dash in tilde fence
64+
~~~
65+
+++
66+
<ul>
67+
<li><p>item</p>
68+
69+
<pre><code>- dash in tilde fence
70+
</code></pre></li>
71+
</ul>
72+
+++
73+
- item1
74+
75+
```
76+
- should be code
77+
- item2
78+
+++
79+
<ul>
80+
<li><p>item1</p>
81+
82+
<p>```
83+
- should be code</p></li>
84+
85+
<li><p>item2</p></li>
86+
</ul>

0 commit comments

Comments
 (0)