feat: count references during parsing for pictures

This commit is contained in:
Tim Grelka
2026-01-11 02:39:21 +01:00
parent 99e97ee3c6
commit b6a8b6686b
5 changed files with 77 additions and 27 deletions
+7
View File
@@ -0,0 +1,7 @@
import mistletoe
class Document(mistletoe.Document):
# margin_count = 0
# margin_anchor_count = 0
references = {}
+25 -12
View File
@@ -1,8 +1,9 @@
from jinja2 import Environment, FileSystemLoader
from mistletoe import Document, HtmlRenderer
from mistletoe import HtmlRenderer
from .comment import BlockComment
from .dash import Dash
from .document import Document
from .formula import Formula
from .halfwidth_spaces import HalfwidthSpaces
from .include import Include
@@ -25,8 +26,14 @@ table_alignment = {"l": "left", "c": "center", "r": "right"}
class FiftyOhmHtmlRenderer(HtmlRenderer):
margin_anchor_id = 0
margin_id = 0
section_url = "section.html"
ref_id = 0
edition: str = None
chapter: str = None
section: str = None
section_url: str = None
# TODO: Add type
references = {}
def __init__(
self,
@@ -88,6 +95,12 @@ class FiftyOhmHtmlRenderer(HtmlRenderer):
# Single unified counter for all figure types (pictures, photos, tables)
self.figure_counter = 0
def get_reference_label(self, marker: str):
if marker in self.references:
return f"{self.edition}-{self.chapter}.{self.section}.{self.references[marker]}", True
else:
return marker, False
def render_dash(self, token):
return " – "
@@ -249,6 +262,7 @@ class FiftyOhmHtmlRenderer(HtmlRenderer):
return self.question_renderer(token.question_number)
def render_document(self, token: Document) -> str:
self.references.update(token.references)
self.footnotes.update(token.footnotes)
inner = self.render_inner(token, "\n")
return f"{inner}\n" if inner else ""
@@ -257,21 +271,20 @@ class FiftyOhmHtmlRenderer(HtmlRenderer):
# Filter out None values, so block tokens can return None to not be rendered.
return base.join(filter(lambda x: x is not None, [self.render(child) for child in token.children]))
@staticmethod
def render_picture_helper(id, ref, text, number, alt_text):
return f"""
<figure class="picture" id="ref_{ref}" name="{ref}">
<img src="pictures/{id}.svg" alt="{alt_text}">
<figcaption>Abbildung {number}: {text}</figcaption>
</figure>
"""
def render_picture_helper(self, id, marker, text, label, alt_text):
return (
f'<figure class="picture" id="ref_{marker}" name="{marker}">\n'
f' <img src="pictures/{id}.svg" alt="{alt_text}">\n'
f" <figcaption>Abbildung {self.get_reference_label(marker)}: {text}</figcaption>\n"
"</figure>\n"
)
def render_picture(self, token):
alt_text = ""
if self.picture_handler is not None:
alt_text = self.picture_handler(token.id)
return self.render_picture_helper(token.id, token.ref, token.text, token.number, alt_text)
return self.render_picture_helper(token.id, token.marker, token.text, token.label, alt_text)
@staticmethod
def render_photo_helper(id, ref, text, number, alt_text):
+23 -9
View File
@@ -1,19 +1,33 @@
import re
from mistletoe.span_token import SpanToken
from mistletoe.block_tokenizer import FileWrapper
from renderer.referenced_token import ReferencedToken
class Picture(SpanToken):
class Picture(ReferencedToken):
"""
Span token for pictures.
Example: [picture:727:amplitude_periode_halbwellen:Positive und negative Halbwellen einer Sinusschwingung]
"""
parse_inner = False
pattern = re.compile(r"\[picture:(\d+):(.+):(.+)\]")
pattern = re.compile(r"^\[picture:(?P<id>\d+):(?P<marker>[^:\]]+):(?P<text>[^:\]]+)\]$")
def __init__(self, match_object):
self.id = match_object.group(1)
self.ref = match_object.group(2)
self.text = match_object.group(3)
self.number = "TODO"
@classmethod
def start(cls, line: str):
return cls.pattern.match(line.strip()) is not None
@classmethod
def check_interrupts_paragraph(cls, lines: FileWrapper):
return cls.pattern.match(lines.peek())
@classmethod
def read(cls, lines: FileWrapper):
match = cls.pattern.match(next(lines))
return match.group("id"), match.group("marker"), match.group("text")
def __init__(self, match):
id, marker, text = match
super().__init__(marker)
self.id = id
self.text = text
+17
View File
@@ -0,0 +1,17 @@
import mistletoe.token
from mistletoe.block_token import BlockToken
class ReferencedToken(BlockToken):
line_number: int = -1
marker: str = None
label: str = None
def __init__(self, marker: str):
self.marker = marker
if marker not in mistletoe.token._root_node.references:
self.label = len(mistletoe.token._root_node.references) + 1
mistletoe.token._root_node.references[marker] = self.label
else:
self.label = mistletoe._root_node.references[marker]
+4 -5
View File
@@ -1,19 +1,18 @@
import mistletoe
import pytest
from renderer.document import Document
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
from test.util import paragraph
@pytest.mark.html
def test_picture_html():
assertions = {
"[picture:0:abc:Text]": FiftyOhmHtmlRenderer.render_picture_helper("0", "abc", "Text", "TODO", ""),
}
assertions = {"[picture:0:abc:Text]": ("0", "abc", "Text", "A-5.7.1", "")}
with FiftyOhmHtmlRenderer(edition="A", chapter="5", section="7") as renderer:
for assertion in assertions:
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == paragraph(assertions[assertion])
assert renderer.render(Document(assertion)) == renderer.render_picture_helper(*assertions[assertion]) + "\n"
@pytest.mark.latex