refactor: avoid parsing document twice for figure numbers

This commit is contained in:
Tim Grelka
2026-06-24 16:18:39 +02:00
parent c15b3f709b
commit f6ceb4cf49
32 changed files with 263 additions and 349 deletions
+40 -66
View File
@@ -1,13 +1,13 @@
import mistletoe
import pytest
from renderer.document import Document
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_html_slide_renderer import FiftyOhmHtmlSlideRenderer
@pytest.mark.html
def test_hierarchical_picture_numbering():
"""Test that pictures get hierarchical numbers in format edition-chapter.section.counter"""
"""Pictures get hierarchical numbers in format edition-chapter.section.counter"""
markdown_text = """
[picture:123:pic1:First picture]
@@ -20,30 +20,26 @@ Reference to second: [ref:pic2]
"""
renderer = FiftyOhmHtmlRenderer(edition="E", chapter="2", section="3")
doc = mistletoe.Document(markdown_text)
doc = Document(markdown_text)
# First pass: collect figures
renderer.collect_figures(doc)
# Counter is assigned in document order during parsing.
assert doc.references["pic1"] == "1"
assert doc.references["pic2"] == "2"
# Verify figure map
assert renderer.figure_map["pic1"] == "E-2.3.1"
assert renderer.figure_map["pic2"] == "E-2.3.2"
# Second pass: render
result = renderer.render(doc)
# Verify hierarchical numbers in output
# Hierarchical numbers in the figure captions.
assert "Abbildung E-2.3.1:" in result
assert "Abbildung E-2.3.2:" in result
# Verify references are resolved
# References are resolved to the same numbers.
assert ">E-2.3.1</a>" in result
assert ">E-2.3.2</a>" in result
@pytest.mark.html
def test_hierarchical_photo_numbering():
"""Test that photos get hierarchical numbers"""
"""Photos get hierarchical numbers from the shared counter"""
markdown_text = """
[photo:789:photo1:First photo]
@@ -53,12 +49,10 @@ Reference: [ref:photo1]
"""
renderer = FiftyOhmHtmlRenderer(edition="N", chapter="1", section="2")
doc = mistletoe.Document(markdown_text)
doc = Document(markdown_text)
renderer.collect_figures(doc)
assert renderer.figure_map["photo1"] == "N-1.2.1"
assert renderer.figure_map["photo2"] == "N-1.2.2"
assert doc.references["photo1"] == "1"
assert doc.references["photo2"] == "2"
result = renderer.render(doc)
@@ -69,7 +63,7 @@ Reference: [ref:photo1]
@pytest.mark.html
def test_hierarchical_table_numbering():
"""Test that tables with names get hierarchical numbers"""
"""Tables with names get hierarchical numbers from the shared counter"""
markdown_text = """
| Header 1 | Header 2 |
| Data 1 | Data 2 |
@@ -83,12 +77,10 @@ Reference: [ref:table1]
"""
renderer = FiftyOhmHtmlRenderer(edition="A", chapter="3", section="1")
doc = mistletoe.Document(markdown_text)
doc = Document(markdown_text)
renderer.collect_figures(doc)
assert renderer.figure_map["table1"] == "A-3.1.1"
assert renderer.figure_map["table2"] == "A-3.1.2"
assert doc.references["table1"] == "1"
assert doc.references["table2"] == "2"
result = renderer.render(doc)
@@ -99,7 +91,7 @@ Reference: [ref:table1]
@pytest.mark.html
def test_mixed_figure_types_share_counter():
"""Test that pictures, photos, and tables share a single unified counter"""
"""Pictures, photos, and tables share a single unified counter in document order"""
markdown_text = """
[picture:1:pic1:Picture one]
@@ -115,19 +107,16 @@ References: [ref:pic1], [ref:photo1], [ref:tab1], [ref:pic2]
"""
renderer = FiftyOhmHtmlRenderer(edition="E", chapter="5", section="2")
doc = mistletoe.Document(markdown_text)
doc = Document(markdown_text)
renderer.collect_figures(doc)
# All types share the same counter
assert renderer.figure_map["pic1"] == "E-5.2.1"
assert renderer.figure_map["photo1"] == "E-5.2.2"
assert renderer.figure_map["tab1"] == "E-5.2.3"
assert renderer.figure_map["pic2"] == "E-5.2.4"
# All types share the same counter, assigned in document order.
assert doc.references["pic1"] == "1"
assert doc.references["photo1"] == "2"
assert doc.references["tab1"] == "3"
assert doc.references["pic2"] == "4"
result = renderer.render(doc)
# Verify all references are resolved with correct numbers
assert "Abbildung E-5.2.1:" in result # pic1
assert "Abbildung E-5.2.2:" in result # photo1
assert "Tabelle E-5.2.3:" in result # tab1
@@ -136,7 +125,7 @@ References: [ref:pic1], [ref:photo1], [ref:tab1], [ref:pic2]
@pytest.mark.slide
def test_slide_renderer_adds_s_suffix():
"""Test that slide renderer adds 'S' suffix to edition"""
"""The slide renderer adds an 'S' suffix to the edition"""
markdown_text = """
[picture:1:pic1:Slide picture]
@@ -144,17 +133,11 @@ Reference: [ref:pic1]
"""
renderer = FiftyOhmHtmlSlideRenderer(edition="E", chapter="2", section="1")
doc = mistletoe.Document(markdown_text)
# Verify edition has S suffix
# Edition gains the S suffix.
assert renderer.edition == "ES"
renderer.collect_figures(doc)
# Verify hierarchical number includes S
assert renderer.figure_map["pic1"] == "ES-2.1.1"
result = renderer.render(doc)
result = renderer.render(Document(markdown_text))
assert "Abbildung ES-2.1.1:" in result
assert ">ES-2.1.1</a>" in result
@@ -162,49 +145,38 @@ Reference: [ref:pic1]
@pytest.mark.html
def test_fallback_numbering_without_context():
"""Test that numbering falls back to simple counter when context is missing"""
"""Numbering falls back to a simple counter when context is missing"""
markdown_text = """
[picture:1:pic1:Picture]
Reference: [ref:pic1]
"""
# No edition/chapter/section provided
# No edition/chapter/section provided.
renderer = FiftyOhmHtmlRenderer()
doc = mistletoe.Document(markdown_text)
renderer.collect_figures(doc)
# Should fall back to simple counter
assert renderer.figure_map["pic1"] == "1"
result = renderer.render(doc)
result = renderer.render(Document(markdown_text))
# Falls back to the bare counter.
assert "Abbildung 1:" in result
assert ">1</a>" in result
@pytest.mark.html
def test_unresolved_reference():
"""Test that references to non-existent figures show '?'"""
"""References to non-existent figures show '?'"""
markdown_text = """
Reference to non-existent: [ref:nonexistent]
"""
renderer = FiftyOhmHtmlRenderer(edition="E", chapter="1", section="1")
doc = mistletoe.Document(markdown_text)
result = renderer.render(Document(markdown_text))
renderer.collect_figures(doc)
result = renderer.render(doc)
# Should show ? for unresolved reference
assert ">?</a>" in result
@pytest.mark.html
def test_table_without_name_not_numbered():
"""Test that tables without names are not numbered"""
"""Tables without names are not numbered and do not consume a counter slot"""
markdown_text = """
| Header 1 | Header 2 |
| Data 1 | Data 2 |
@@ -213,10 +185,12 @@ def test_table_without_name_not_numbered():
"""
renderer = FiftyOhmHtmlRenderer(edition="E", chapter="1", section="1")
doc = mistletoe.Document(markdown_text)
doc = Document(markdown_text)
renderer.collect_figures(doc)
# Only the picture is registered.
assert doc.references == {"pic1": "1"}
# Only the picture should be numbered
assert renderer.figure_map["pic1"] == "E-1.1.1"
assert renderer.figure_counter == 1
result = renderer.render(doc)
assert "Abbildung E-1.1.1:" in result
assert "Tabelle" not in result