diff --git a/renderer/document.py b/renderer/document.py new file mode 100644 index 0000000..71cad24 --- /dev/null +++ b/renderer/document.py @@ -0,0 +1,7 @@ +import mistletoe + + +class Document(mistletoe.Document): + # margin_count = 0 + # margin_anchor_count = 0 + references = {} diff --git a/renderer/fifty_ohm_html_renderer.py b/renderer/fifty_ohm_html_renderer.py index 2a54114..d13f960 100644 --- a/renderer/fifty_ohm_html_renderer.py +++ b/renderer/fifty_ohm_html_renderer.py @@ -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""" -
- {alt_text} -
Abbildung {number}: {text}
-
- """ + def render_picture_helper(self, id, marker, text, label, alt_text): + return ( + f'
\n' + f' {alt_text}\n' + f"
Abbildung {self.get_reference_label(marker)}: {text}
\n" + "
\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): diff --git a/renderer/picture.py b/renderer/picture.py index 0477185..b645126 100644 --- a/renderer/picture.py +++ b/renderer/picture.py @@ -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\d+):(?P[^:\]]+):(?P[^:\]]+)\]$") - 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 diff --git a/renderer/referenced_token.py b/renderer/referenced_token.py new file mode 100644 index 0000000..1f07b46 --- /dev/null +++ b/renderer/referenced_token.py @@ -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] diff --git a/test/test_picture.py b/test/test_picture.py index d9bb240..70b3bc3 100644 --- a/test/test_picture.py +++ b/test/test_picture.py @@ -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", "")} - for assertion in assertions: - assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == paragraph(assertions[assertion]) + with FiftyOhmHtmlRenderer(edition="A", chapter="5", section="7") as renderer: + for assertion in assertions: + assert renderer.render(Document(assertion)) == renderer.render_picture_helper(*assertions[assertion]) + "\n" @pytest.mark.latex