Skip to content

Commit 719107f

Browse files
authored
Merge pull request #464 from chuenchen309/fix/list-break-directive-fence-quantifier
Only relax the indent bound when recompiling list break rules
2 parents 060f73a + 03eacc5 commit 719107f

2 files changed

Lines changed: 28 additions & 2 deletions

File tree

src/mistune/list_parser.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,8 +233,11 @@ def _build_list_item_source(text: str, src: str, continue_width: int) -> str:
233233
def _compile_list_break_sc(block: "BlockParser", leading_width: int) -> Pattern[str]:
234234
pairs = [(name, block.specification[name]) for name in _get_list_break_rules(block)]
235235
if leading_width < 3:
236-
_repl_w = str(leading_width)
237-
pairs = [(n, p.replace("3", _repl_w, 1)) for n, p in pairs]
236+
# Relax the leading indent bound only. Matching on a bare "3" would
237+
# rewrite the first quantifier of any rule that has no indent prefix --
238+
# e.g. a fenced directive's "{3,}" marker run.
239+
_repl = " {0,%d}" % leading_width
240+
pairs = [(n, p.replace(" {0,3}", _repl, 1)) for n, p in pairs]
238241

239242
regex = "|".join(r"(?P<%s>(?<=\n)%s)" % pair for pair in pairs)
240243
return re.compile(regex, re.M)

tests/test_directives.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,29 @@ def test_colon_fenced_toc(self):
7676
self.assertIn('<a href="#t-1">h1</a>', html)
7777

7878

79+
class TestFencedDirectiveInList(BaseTestCase):
80+
md = create_markdown( # type: ignore[list-item]
81+
escape=False,
82+
plugins=[FencedDirective([Admonition()], markers=":")],
83+
)
84+
85+
def test_marker_run_below_fence_length_is_not_a_directive(self):
86+
# A directive needs three or more markers, inside a list item as well
87+
# as outside one. The list break rules are recompiled per item, and a
88+
# marker run shorter than the fence must stay literal text.
89+
for text in (":{note}\nlazy\n", "100. item\n:{note}\nlazy\n"):
90+
self.assertNotIn("admonition", self.md(text))
91+
92+
html = self.md("- item\n:{note}\nlazy\n")
93+
self.assertNotIn("admonition", html)
94+
self.assertIn(":{note}", html)
95+
96+
def test_directive_still_breaks_a_list(self):
97+
html = self.md("- item\n:::{note}\nbody\n:::\n")
98+
self.assertIn('<section class="admonition note">', html)
99+
self.assertIn("<p>body</p>", html)
100+
101+
79102
class TestDirectiveInclude(BaseTestCase):
80103
md = create_markdown(escape=False, plugins=[RSTDirective([Include()])]) # type: ignore[list-item]
81104

0 commit comments

Comments
 (0)