")
+
+
+def _fences_closed(text: str) -> bool:
+ """Every opening ``` fence has a closing line that consists only of backticks."""
+ open_fence = None
+ for line in text.splitlines():
+ s = line.strip()
+ if open_fence is None:
+ m = re.match(r"(`{3,})", s)
+ if m:
+ open_fence = m.group(1)
+ elif re.fullmatch(r"`{3,}", s) and len(s) >= len(open_fence):
+ open_fence = None
+ return open_fence is None
+
+
+def test_backlink_after_code_block_does_not_break_fence_commonmark(convert):
+ """QA2-02: the ↩ backlink was appended to the closing ``` line, leaving the fence open."""
+ run = convert(Book(docs=[Doc("c.xhtml", NOTE_WITH_CODE)]), "--format", "commonmark")
+ text = run.chapter("001")
+ assert _fences_closed(text), text
+ assert not re.search(r"\*\*\d+[:.]\*\* ```", text), "Fence hinter Notennummer ist kein Codeblock"
+ assert "[↩](#fnref-001)" in text
+
+
+def test_backlink_after_code_block_does_not_break_fence_end_of_book(convert):
+ run = convert(Book(docs=[Doc("c.xhtml", NOTE_WITH_CODE)]), "--footnotes", "end-of-book")
+ notes = run.chapter("999")
+ assert _fences_closed(notes), notes
+ assert not re.search(r"\*\*\d+[:.]\*\* ```", notes), "Fence hinter Notennummer ist kein Codeblock"
+ assert "[↩](001-k.md#fnref-001)" in notes