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
+6 -3
View File
@@ -2,6 +2,9 @@ import mistletoe
class Document(mistletoe.Document): class Document(mistletoe.Document):
# margin_count = 0 def __init__(self, *args, **kwargs):
# margin_anchor_count = 0 # references must exist before super().__init__ tokenizes the lines,
references = {} # since ReferencedToken reads it from _root_node during tokenization.
self.references: dict[str, str] = {}
super().__init__(*args, **kwargs)
+34 -78
View File
@@ -8,16 +8,15 @@ from .dash import Dash
from .document import Document from .document import Document
from .formula import Formula from .formula import Formula
from .halfwidth_spaces import HalfwidthSpaces from .halfwidth_spaces import HalfwidthSpaces
from .image import Image
from .include import Include from .include import Include
from .index import Index from .index import Index
from .morse import Morse from .morse import Morse
from .nonbreaking_spaces import NonbreakingSpaces, NonbreakingSpacesDots from .nonbreaking_spaces import NonbreakingSpaces, NonbreakingSpacesDots
from .photo import Photo
from .picture import Picture
from .qso import Qso from .qso import Qso
from .question import Question from .question import Question
from .quote import Quote from .quote import Quote
from .references import References from .reference import Reference
from .table import Table, TableBody, TableCell, TableHeader, TableRow from .table import Table, TableBody, TableCell, TableHeader, TableRow
from .tag import Tag from .tag import Tag
from .underline import Underline from .underline import Underline
@@ -30,14 +29,6 @@ class FiftyOhmHtmlRenderer(HtmlRenderer):
margin_anchor_id = 0 margin_anchor_id = 0
margin_id = 0 margin_id = 0
edition: str = None
chapter: str = None
section: str = None
section_url: str = None
# TODO: Add type
references = {}
def __init__( def __init__(
self, self,
*extras, *extras,
@@ -62,10 +53,9 @@ class FiftyOhmHtmlRenderer(HtmlRenderer):
HalfwidthSpaces, HalfwidthSpaces,
NonbreakingSpaces, NonbreakingSpaces,
NonbreakingSpacesDots, NonbreakingSpacesDots,
References, Reference,
Question, Question,
Picture, Image,
Photo,
Table, Table,
TableHeader, TableHeader,
TableRow, TableRow,
@@ -90,23 +80,21 @@ class FiftyOhmHtmlRenderer(HtmlRenderer):
self.section = section self.section = section
# Set section URL if provided, otherwise use default # Set section URL if provided, otherwise use default
if section_url is not None: self.section_url = section_url if section_url is not None else "section.html"
self.section_url = section_url
# Figure map: stores ref -> hierarchical number mapping self.references: dict[str, str] = {}
self.figure_map = {}
# Single unified counter for all figure types (pictures, photos, tables)
self.figure_counter = 0
# Keep track of index ids already emitted in this document. # Keep track of index ids already emitted in this document.
self.index_anchor_ids = set() self.index_anchor_ids = set()
def get_reference_label(self, marker: str): def _format_reference_label(self, marker: str):
if marker in self.references: if marker in self.references:
return f"{self.edition}-{self.chapter}.{self.section}.{self.references[marker]}", True label = self.references[marker]
if self.edition and self.chapter and self.section:
label = f"{self.edition}-{self.chapter}.{self.section}.{label}"
return label
else: else:
return marker, False return None
def render_dash(self, token): def render_dash(self, token):
return " – " return " – "
@@ -222,47 +210,11 @@ class FiftyOhmHtmlRenderer(HtmlRenderer):
lookup = {"": "", " ": " "} lookup = {"": "", " ": " "}
return f"{lookup[token.first]}{token.second}{lookup[token.third]}" return f"{lookup[token.first]}{token.second}{lookup[token.third]}"
def collect_figures(self, document): def render_reference(self, token: Reference):
"""First pass: collect all figures and assign hierarchical numbers."""
self.figure_counter = 0
self.figure_map = {}
self._collect_figures_recursive(document)
def _collect_figures_recursive(self, token):
"""Recursively traverse the document tree to collect figures."""
if hasattr(token, "children") and token.children is not None:
for child in token.children:
# Check if this is a Picture, Photo, or Table token
if isinstance(child, Picture | Photo | Table):
# Get the reference ID (ref for Picture/Photo, name for Table)
ref_id = getattr(child, "ref", None) or getattr(child, "name", None)
if ref_id: # Only number figures with a reference ID
self.figure_counter += 1
hierarchical_num = self._format_figure_number(self.figure_counter)
self.figure_map[ref_id] = hierarchical_num
child.number = hierarchical_num
else:
child.number = ""
# Recurse into children
self._collect_figures_recursive(child)
def _format_figure_number(self, counter):
"""Format the hierarchical figure number based on context."""
if self.edition and self.chapter and self.section:
return f"{self.edition}-{self.chapter}.{self.section}.{counter}"
else:
# Fallback for tests or when context is not provided
return str(counter)
def render_references(self, token):
# Look up the figure number from the map # Look up the figure number from the map
figure_num = self.figure_map.get(token.first, "?") label = self._format_reference_label(token.marker) or "?"
return ( return (
f'<a href="{self.section_url}#ref_{token.first}"' f'<a href="{self.section_url}#ref_{token.marker}" onclick="highlightRef(\'{token.marker}\');">{label}</a>'
f" onclick=\"highlightRef('{token.first}');\">{figure_num}</a>"
) )
def render_question(self, token): def render_question(self, token):
@@ -282,31 +234,34 @@ class FiftyOhmHtmlRenderer(HtmlRenderer):
return ( return (
f'<figure class="picture" id="ref_{marker}" name="{marker}">\n' f'<figure class="picture" id="ref_{marker}" name="{marker}">\n'
f' <img src="pictures/{id}.svg" alt="{alt_text}">\n' f' <img src="pictures/{id}.svg" alt="{alt_text}">\n'
f" <figcaption>Abbildung {self.get_reference_label(marker)}: {text}</figcaption>\n" f" <figcaption>Abbildung {label}: {text}</figcaption>\n"
"</figure>\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.marker, token.text, token.label, alt_text)
@staticmethod @staticmethod
def render_photo_helper(id, ref, text, number, alt_text): def render_photo_helper(id, ref, text, label, alt_text):
return f""" return f"""
<figure class="photo" id="ref_{ref}" name="{ref}"> <figure class="photo" id="ref_{ref}" name="{ref}">
<img src="photos/{id}.png" alt="{alt_text}"> <img src="photos/{id}.png" alt="{alt_text}">
<figcaption>Abbildung {number}: {text}</figcaption> <figcaption>Abbildung {label}: {text}</figcaption>
</figure> </figure>
""" """
def render_photo(self, token): def render_image(self, token: Image):
label = self._format_reference_label(token.marker) or "?"
# Only supported kinds are photo and picture
if token.kind == "photo":
alt_text = "" alt_text = ""
if self.photo_handler is not None: if self.photo_handler is not None:
alt_text = self.photo_handler(token.id) or alt_text alt_text = self.photo_handler(token.id) or alt_text
return self.render_photo_helper(token.id, token.ref, token.text, token.number, alt_text) return self.render_photo_helper(token.id, token.marker, token.text, label, alt_text)
if token.kind == "picture":
alt_text = ""
if self.picture_handler is not None:
alt_text = self.picture_handler(token.id)
return self.render_picture_helper(token.id, token.marker, token.text, label, alt_text)
return ""
def render_table(self, token: Table): def render_table(self, token: Table):
# Add id and name attributes if table has a name # Add id and name attributes if table has a name
@@ -317,10 +272,11 @@ class FiftyOhmHtmlRenderer(HtmlRenderer):
table = f'<table class="table table-hover"{table_attrs}>\n{self.render_inner(token)}' table = f'<table class="table table-hover"{table_attrs}>\n{self.render_inner(token)}'
if token.caption != "": if token.caption != "":
# Include hierarchical number in caption if available # Include hierarchical number in caption if the table is named.
caption_text = token.caption caption_text = token.caption
if hasattr(token, "number") and token.number: label = self._format_reference_label(token.name)
caption_text = f"Tabelle {token.number}: {token.caption}" if label:
caption_text = f"Tabelle {label}: {token.caption}"
table += f"<caption>{caption_text}</caption>\n" table += f"<caption>{caption_text}</caption>\n"
table += "</table>" table += "</table>"
+8 -9
View File
@@ -3,10 +3,9 @@ from mistletoe.latex_renderer import LaTeXRenderer
from .comment import BlockComment from .comment import BlockComment
from .dash import Dash from .dash import Dash
from .halfwidth_spaces import HalfwidthSpaces from .halfwidth_spaces import HalfwidthSpaces
from .image import Image
from .index import Index from .index import Index
from .nonbreaking_spaces import NonbreakingSpaces, NonbreakingSpacesDots from .nonbreaking_spaces import NonbreakingSpaces, NonbreakingSpacesDots
from .photo import Photo
from .picture import Picture
from .question import Question from .question import Question
from .quote import Quote from .quote import Quote
from .table import Table, TableBody, TableCell, TableHeader, TableRow from .table import Table, TableBody, TableCell, TableHeader, TableRow
@@ -26,8 +25,7 @@ class FiftyOhmLaTeXRenderer(LaTeXRenderer):
NonbreakingSpaces, NonbreakingSpaces,
NonbreakingSpacesDots, NonbreakingSpacesDots,
Question, Question,
Picture, Image,
Photo,
Table, Table,
TableBody, TableBody,
TableRow, TableRow,
@@ -115,17 +113,18 @@ class FiftyOhmLaTeXRenderer(LaTeXRenderer):
\captionof{{figure}}{{{text}}} \captionof{{figure}}{{{text}}}
\label{{{ref}}}""" \label{{{ref}}}"""
def render_picture(self, token):
return self.render_picture_helper(token.id, token.ref, token.text, token.number)
@staticmethod @staticmethod
def render_photo_helper(id, ref, text, number): def render_photo_helper(id, ref, text, number):
return rf"""\includegraphics[width=1.0\linewidth]{{photo/{id}}} return rf"""\includegraphics[width=1.0\linewidth]{{photo/{id}}}
\captionof{{figure}}{{{text}}} \captionof{{figure}}{{{text}}}
\label{{{ref}}}""" \label{{{ref}}}"""
def render_photo(self, token): def render_image(self, token: Image):
return self.render_photo_helper(token.id, token.ref, token.text, token.number) if token.kind == "photo":
return self.render_photo_helper(token.id, token.marker, token.text, token.label)
if token.kind == "picture":
return self.render_picture_helper(token.id, token.marker, token.text, token.label)
return ""
def render_table(self, token): def render_table(self, token):
table = "\\begin{DARCtabular}" + f"{self.render_inner(token)}" + "\\end{DARCtabular}" table = "\\begin{DARCtabular}" + f"{self.render_inner(token)}" + "\\end{DARCtabular}"
+40
View File
@@ -0,0 +1,40 @@
import re
from mistletoe.block_tokenizer import FileWrapper
from renderer.referenced_token import ReferencedToken
class Image(ReferencedToken):
"""
Block token for pictures and photos.
Examples:
[picture:727:amplitude_periode_halbwellen:Positive und negative Halbwellen einer Sinusschwingung]
[photo:123:n_wasserfalldiagramm_trx_collage:Ansichten verschiedener Transceiver]
"""
pattern = re.compile(r"^\[(?P<kind>picture|photo):(?P<id>\d+):(?P<marker>[^:\]]+):(?P<text>[^:\]]+)\]$")
@classmethod
def start(cls, line: str):
return cls.pattern.match(line.strip()) is not None
@classmethod
def check_interrupts_paragraph(cls, lines: FileWrapper):
line = lines.peek()
if line is not None:
return cls.start(line)
else:
return False
@classmethod
def read(cls, lines: FileWrapper):
match = cls.pattern.match(next(lines).strip())
return match.group("kind"), match.group("id"), match.group("marker"), match.group("text")
def __init__(self, match):
kind, id, marker, text = match
super().__init__(marker)
self.kind = kind
self.id = id
self.text = text
-19
View File
@@ -1,19 +0,0 @@
import re
from mistletoe.span_token import SpanToken
class Photo(SpanToken):
"""
Span token for photos.
Example: [photo:123:n_wasserfalldiagramm_trx_collage:Ansichten verschiedener Transceiver]
"""
parse_inner = False
pattern = re.compile(r"\[photo:(\d+):([^:\]]+):([^:\]]+)\]")
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"
-33
View File
@@ -1,33 +0,0 @@
import re
from mistletoe.block_tokenizer import FileWrapper
from renderer.referenced_token import ReferencedToken
class Picture(ReferencedToken):
"""
Span token for pictures.
Example: [picture:727:amplitude_periode_halbwellen:Positive und negative Halbwellen einer Sinusschwingung]
"""
pattern = re.compile(r"^\[picture:(?P<id>\d+):(?P<marker>[^:\]]+):(?P<text>[^:\]]+)\]$")
@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
@@ -3,7 +3,7 @@ import re
from mistletoe.span_token import SpanToken from mistletoe.span_token import SpanToken
class References(SpanToken): class Reference(SpanToken):
""" """
Resolve references for html Resolve references for html
Identifies "[ref:$]" Identifies "[ref:$]"
@@ -12,4 +12,4 @@ class References(SpanToken):
pattern = re.compile(r"\[ref\:(\S+)\]") pattern = re.compile(r"\[ref\:(\S+)\]")
def __init__(self, match_object): def __init__(self, match_object):
self.first = match_object.group(1) self.marker: str = match_object.group(1)
+10 -9
View File
@@ -3,15 +3,16 @@ from mistletoe.block_token import BlockToken
class ReferencedToken(BlockToken): class ReferencedToken(BlockToken):
line_number: int = -1
marker: str = None
label: str = None
def __init__(self, marker: str): def __init__(self, marker: str):
if marker != "":
self.marker = marker self.marker = marker
references = mistletoe.token._root_node.references
if marker not in mistletoe.token._root_node.references: if marker not in references:
self.label = len(mistletoe.token._root_node.references) + 1 label = str(len(references) + 1)
mistletoe.token._root_node.references[marker] = self.label references[marker] = label
else: else:
self.label = mistletoe._root_node.references[marker] label = references[marker]
self.label = label
else:
self.marker = None
self.label = None
+8 -2
View File
@@ -4,6 +4,8 @@ from enum import Enum
from mistletoe import span_token from mistletoe import span_token
from mistletoe.block_token import BlockToken from mistletoe.block_token import BlockToken
from renderer.referenced_token import ReferencedToken
class CellAlignment(Enum): class CellAlignment(Enum):
LEFT = "l" LEFT = "l"
@@ -76,7 +78,7 @@ class TableBody(BlockToken):
self.children, self.header = rows, header self.children, self.header = rows, header
class Table(BlockToken): class Table(ReferencedToken):
name: str name: str
caption: str caption: str
header: list[TableHeader] header: list[TableHeader]
@@ -115,4 +117,8 @@ class Table(BlockToken):
return children, name, caption return children, name, caption
def __init__(self, match): def __init__(self, match):
self.children, self.name, self.caption = match children, name, caption = match
super().__init__(name)
self.children = children
self.name = name
self.caption = caption
+16 -28
View File
@@ -7,10 +7,10 @@ import zipfile
from pathlib import Path from pathlib import Path
from jinja2 import Environment, FileSystemLoader from jinja2 import Environment, FileSystemLoader
from mistletoe import Document
from rich.progress import BarColumn, Progress, TaskProgressColumn, TextColumn, TimeRemainingColumn from rich.progress import BarColumn, Progress, TaskProgressColumn, TextColumn, TimeRemainingColumn
from tqdm import tqdm from tqdm import tqdm
from renderer.document import Document
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_html_slide_renderer import FiftyOhmHtmlSlideRenderer from renderer.fifty_ohm_html_slide_renderer import FiftyOhmHtmlSlideRenderer
from renderer.index import Index from renderer.index import Index
@@ -222,12 +222,7 @@ class Build:
section=section_num, section=section_num,
section_url=section_filename, section_url=section_filename,
) as renderer: ) as renderer:
# First pass: collect all figures and assign hierarchical numbers section["content"] = renderer.render(Document(section["content"]))
doc = Document(section["content"])
renderer.collect_figures(doc)
# Second pass: render with hierarchical numbers
section["content"] = renderer.render(doc)
result = section_template.render( result = section_template.render(
edition=edition, edition=edition,
@@ -266,16 +261,6 @@ class Build:
# Note: filename uses original edition (e.g., "N"), not modified edition with "S" (e.g., "NS") # Note: filename uses original edition (e.g., "N"), not modified edition with "S" (e.g., "NS")
slide_filename = f"{edition}_slide_{chapter['ident']}.html" slide_filename = f"{edition}_slide_{chapter['ident']}.html"
with FiftyOhmHtmlSlideRenderer(
question_renderer=self.__build_question_slide,
picture_handler=self.__picture_handler,
photo_handler=self.__photo_handler,
include_handler=self.__include_handler,
edition=edition,
chapter=chapter_num,
section="0", # Will be updated per section
section_url=slide_filename,
) as renderer:
result = "<section>\n" result = "<section>\n"
result += f'<section data-background="#DAEEFA">\n<h1>{chapter["title"]}</h1>\n</section>\n' result += f'<section data-background="#DAEEFA">\n<h1>{chapter["title"]}</h1>\n</section>\n'
result += help_template.render() result += help_template.render()
@@ -290,22 +275,25 @@ class Build:
continue continue
section_counter += 1 section_counter += 1
# Update section number for this section
renderer.section = str(section_counter)
# Reset figure counter for each section
renderer.figure_counter = 0
renderer.figure_map = {}
if not section["slide"].startswith("---"): if not section["slide"].startswith("---"):
section["slide"] = "---\n" + section["slide"] section["slide"] = "---\n" + section["slide"]
# First pass: collect figures # A fresh renderer per section keeps the figure counter and
doc = Document(section["slide"]) # reference map scoped to that section.
renderer.collect_figures(doc) with FiftyOhmHtmlSlideRenderer(
question_renderer=self.__build_question_slide,
# Second pass: render with hierarchical numbers picture_handler=self.__picture_handler,
photo_handler=self.__photo_handler,
include_handler=self.__include_handler,
edition=edition,
chapter=chapter_num,
section=str(section_counter),
section_url=slide_filename,
) as renderer:
tmp = f'<section data-background="#DAEEFA">\n<h1>{section["title"]}</h1>\n</section>\n' tmp = f'<section data-background="#DAEEFA">\n<h1>{section["title"]}</h1>\n</section>\n'
tmp += renderer.render(doc) tmp += renderer.render(Document(section["slide"]))
result += f"<section>{tmp}</section>\n" result += f"<section>{tmp}</section>\n"
progress.remove_task(slides_task) progress.remove_task(slides_task)
+2 -3
View File
@@ -1,9 +1,8 @@
import mistletoe import mistletoe
import pytest import pytest
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
from test.util import paragraph from test.util import paragraph, render_html
@pytest.mark.html @pytest.mark.html
@@ -16,7 +15,7 @@ def test_comment_html():
} }
for assertion in assertions: for assertion in assertions:
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == assertions[assertion] assert render_html(assertion) == assertions[assertion]
@pytest.mark.latex @pytest.mark.latex
+2 -3
View File
@@ -1,9 +1,8 @@
import mistletoe import mistletoe
import pytest import pytest
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
from test.util import paragraph from test.util import paragraph, render_html
@pytest.mark.html @pytest.mark.html
@@ -14,7 +13,7 @@ def test_dash_html():
} }
for assertion in assertions: for assertion in assertions:
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == paragraph(assertions[assertion]) assert render_html(assertion) == paragraph(assertions[assertion])
@pytest.mark.latex @pytest.mark.latex
+2 -4
View File
@@ -1,7 +1,6 @@
import pytest import pytest
from mistletoe import Document
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer from test.util import render_html
@pytest.mark.html @pytest.mark.html
@@ -14,6 +13,5 @@ def test_formula_html():
r"Lorem Ipsum" + "\n" + r"$a \cdot b$": "<p>Lorem Ipsum</p>\n\n" + r"$$a \cdot b$$" + "\n\n", r"Lorem Ipsum" + "\n" + r"$a \cdot b$": "<p>Lorem Ipsum</p>\n\n" + r"$$a \cdot b$$" + "\n\n",
} }
with FiftyOhmHtmlRenderer() as renderer:
for assertion in assertions: for assertion in assertions:
assert renderer.render(Document(assertion)) == assertions[assertion] assert render_html(assertion) == assertions[assertion]
+2 -3
View File
@@ -1,9 +1,8 @@
import mistletoe import mistletoe
import pytest import pytest
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
from test.util import paragraph from test.util import paragraph, render_html
@pytest.mark.html @pytest.mark.html
@@ -11,7 +10,7 @@ def test_halfwidth_space_html():
input = "Dies ist z.B. ein Test. D.h. hier sollten d.h. Spaces ersetzt worden sein." input = "Dies ist z.B. ein Test. D.h. hier sollten d.h. Spaces ersetzt worden sein."
target = "Dies ist z.&#8239;B. ein Test. D.&#8239;h. hier sollten d.&#8239;h. Spaces ersetzt worden sein." target = "Dies ist z.&#8239;B. ein Test. D.&#8239;h. hier sollten d.&#8239;h. Spaces ersetzt worden sein."
assert mistletoe.markdown(input, FiftyOhmHtmlRenderer) == paragraph(target) assert render_html(input) == paragraph(target)
@pytest.mark.latex @pytest.mark.latex
+40 -66
View File
@@ -1,13 +1,13 @@
import mistletoe
import pytest import pytest
from renderer.document import Document
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_html_slide_renderer import FiftyOhmHtmlSlideRenderer from renderer.fifty_ohm_html_slide_renderer import FiftyOhmHtmlSlideRenderer
@pytest.mark.html @pytest.mark.html
def test_hierarchical_picture_numbering(): 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 = """ markdown_text = """
[picture:123:pic1:First picture] [picture:123:pic1:First picture]
@@ -20,30 +20,26 @@ Reference to second: [ref:pic2]
""" """
renderer = FiftyOhmHtmlRenderer(edition="E", chapter="2", section="3") renderer = FiftyOhmHtmlRenderer(edition="E", chapter="2", section="3")
doc = mistletoe.Document(markdown_text) doc = Document(markdown_text)
# First pass: collect figures # Counter is assigned in document order during parsing.
renderer.collect_figures(doc) 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) 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.1:" in result
assert "Abbildung E-2.3.2:" 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.1</a>" in result
assert ">E-2.3.2</a>" in result assert ">E-2.3.2</a>" in result
@pytest.mark.html @pytest.mark.html
def test_hierarchical_photo_numbering(): def test_hierarchical_photo_numbering():
"""Test that photos get hierarchical numbers""" """Photos get hierarchical numbers from the shared counter"""
markdown_text = """ markdown_text = """
[photo:789:photo1:First photo] [photo:789:photo1:First photo]
@@ -53,12 +49,10 @@ Reference: [ref:photo1]
""" """
renderer = FiftyOhmHtmlRenderer(edition="N", chapter="1", section="2") renderer = FiftyOhmHtmlRenderer(edition="N", chapter="1", section="2")
doc = mistletoe.Document(markdown_text) doc = Document(markdown_text)
renderer.collect_figures(doc) assert doc.references["photo1"] == "1"
assert doc.references["photo2"] == "2"
assert renderer.figure_map["photo1"] == "N-1.2.1"
assert renderer.figure_map["photo2"] == "N-1.2.2"
result = renderer.render(doc) result = renderer.render(doc)
@@ -69,7 +63,7 @@ Reference: [ref:photo1]
@pytest.mark.html @pytest.mark.html
def test_hierarchical_table_numbering(): 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 = """ markdown_text = """
| Header 1 | Header 2 | | Header 1 | Header 2 |
| Data 1 | Data 2 | | Data 1 | Data 2 |
@@ -83,12 +77,10 @@ Reference: [ref:table1]
""" """
renderer = FiftyOhmHtmlRenderer(edition="A", chapter="3", section="1") renderer = FiftyOhmHtmlRenderer(edition="A", chapter="3", section="1")
doc = mistletoe.Document(markdown_text) doc = Document(markdown_text)
renderer.collect_figures(doc) assert doc.references["table1"] == "1"
assert doc.references["table2"] == "2"
assert renderer.figure_map["table1"] == "A-3.1.1"
assert renderer.figure_map["table2"] == "A-3.1.2"
result = renderer.render(doc) result = renderer.render(doc)
@@ -99,7 +91,7 @@ Reference: [ref:table1]
@pytest.mark.html @pytest.mark.html
def test_mixed_figure_types_share_counter(): 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 = """ markdown_text = """
[picture:1:pic1:Picture one] [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") 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, assigned in document order.
assert doc.references["pic1"] == "1"
# All types share the same counter assert doc.references["photo1"] == "2"
assert renderer.figure_map["pic1"] == "E-5.2.1" assert doc.references["tab1"] == "3"
assert renderer.figure_map["photo1"] == "E-5.2.2" assert doc.references["pic2"] == "4"
assert renderer.figure_map["tab1"] == "E-5.2.3"
assert renderer.figure_map["pic2"] == "E-5.2.4"
result = renderer.render(doc) 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.1:" in result # pic1
assert "Abbildung E-5.2.2:" in result # photo1 assert "Abbildung E-5.2.2:" in result # photo1
assert "Tabelle E-5.2.3:" in result # tab1 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 @pytest.mark.slide
def test_slide_renderer_adds_s_suffix(): 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 = """ markdown_text = """
[picture:1:pic1:Slide picture] [picture:1:pic1:Slide picture]
@@ -144,17 +133,11 @@ Reference: [ref:pic1]
""" """
renderer = FiftyOhmHtmlSlideRenderer(edition="E", chapter="2", section="1") 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" assert renderer.edition == "ES"
renderer.collect_figures(doc) result = renderer.render(Document(markdown_text))
# Verify hierarchical number includes S
assert renderer.figure_map["pic1"] == "ES-2.1.1"
result = renderer.render(doc)
assert "Abbildung ES-2.1.1:" in result assert "Abbildung ES-2.1.1:" in result
assert ">ES-2.1.1</a>" in result assert ">ES-2.1.1</a>" in result
@@ -162,49 +145,38 @@ Reference: [ref:pic1]
@pytest.mark.html @pytest.mark.html
def test_fallback_numbering_without_context(): 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 = """ markdown_text = """
[picture:1:pic1:Picture] [picture:1:pic1:Picture]
Reference: [ref:pic1] Reference: [ref:pic1]
""" """
# No edition/chapter/section provided # No edition/chapter/section provided.
renderer = FiftyOhmHtmlRenderer() renderer = FiftyOhmHtmlRenderer()
doc = mistletoe.Document(markdown_text) result = renderer.render(Document(markdown_text))
renderer.collect_figures(doc)
# Should fall back to simple counter
assert renderer.figure_map["pic1"] == "1"
result = renderer.render(doc)
# Falls back to the bare counter.
assert "Abbildung 1:" in result assert "Abbildung 1:" in result
assert ">1</a>" in result assert ">1</a>" in result
@pytest.mark.html @pytest.mark.html
def test_unresolved_reference(): def test_unresolved_reference():
"""Test that references to non-existent figures show '?'""" """References to non-existent figures show '?'"""
markdown_text = """ markdown_text = """
Reference to non-existent: [ref:nonexistent] Reference to non-existent: [ref:nonexistent]
""" """
renderer = FiftyOhmHtmlRenderer(edition="E", chapter="1", section="1") 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 assert ">?</a>" in result
@pytest.mark.html @pytest.mark.html
def test_table_without_name_not_numbered(): 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 = """ markdown_text = """
| Header 1 | Header 2 | | Header 1 | Header 2 |
| Data 1 | Data 2 | | Data 1 | Data 2 |
@@ -213,10 +185,12 @@ def test_table_without_name_not_numbered():
""" """
renderer = FiftyOhmHtmlRenderer(edition="E", chapter="1", section="1") 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 result = renderer.render(doc)
assert renderer.figure_map["pic1"] == "E-1.1.1"
assert renderer.figure_counter == 1 assert "Abbildung E-1.1.1:" in result
assert "Tabelle" not in result
+1 -1
View File
@@ -2,9 +2,9 @@ import json
import pytest import pytest
from jinja2 import Environment, FileSystemLoader from jinja2 import Environment, FileSystemLoader
from mistletoe import Document
import src.config as config import src.config as config
from renderer.document import Document
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
conf = config.Config() conf = config.Config()
+1 -1
View File
@@ -3,9 +3,9 @@ import random
import pytest import pytest
from jinja2 import Environment, FileSystemLoader from jinja2 import Environment, FileSystemLoader
from mistletoe import Document
import src.config as config import src.config as config
from renderer.document import Document
from renderer.fifty_ohm_html_slide_renderer import FiftyOhmHtmlSlideRenderer from renderer.fifty_ohm_html_slide_renderer import FiftyOhmHtmlSlideRenderer
conf = config.Config() conf = config.Config()
+1 -1
View File
@@ -1,6 +1,6 @@
import pytest import pytest
from mistletoe import Document
from renderer.document import Document
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
+2 -3
View File
@@ -1,9 +1,8 @@
import mistletoe import mistletoe
import pytest import pytest
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
from test.util import paragraph from test.util import paragraph, render_html
@pytest.mark.html @pytest.mark.html
@@ -42,7 +41,7 @@ def test_index_html():
} }
for key, value in assertions.items(): for key, value in assertions.items():
assert mistletoe.markdown(key, FiftyOhmHtmlRenderer) == paragraph(value) assert render_html(key) == paragraph(value)
@pytest.mark.latex @pytest.mark.latex
+2 -3
View File
@@ -1,8 +1,7 @@
import mistletoe
import pytest import pytest
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from test.util import paragraph from test.util import paragraph, render_html
@pytest.mark.html @pytest.mark.html
@@ -17,4 +16,4 @@ def test_morse_html():
} }
for assertion in assertions: for assertion in assertions:
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == paragraph(assertions[assertion]) assert render_html(assertion) == paragraph(assertions[assertion])
+5 -6
View File
@@ -1,9 +1,8 @@
import mistletoe import mistletoe
import pytest import pytest
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
from test.util import paragraph from test.util import paragraph, render_html
@pytest.mark.html @pytest.mark.html
@@ -11,7 +10,7 @@ def test_paragraph_html():
input = "Der Test befindet sich unter §2 vielleicht aber auch § 3." input = "Der Test befindet sich unter §2 vielleicht aber auch § 3."
target = "Der Test befindet sich unter §&#160;2 vielleicht aber auch §&#160;3." target = "Der Test befindet sich unter §&#160;2 vielleicht aber auch §&#160;3."
assert mistletoe.markdown(input, FiftyOhmHtmlRenderer) == paragraph(target) assert render_html(input) == paragraph(target)
@pytest.mark.html @pytest.mark.html
@@ -24,7 +23,7 @@ def test_three_points_html():
} }
for key, value in assertions.items(): for key, value in assertions.items():
assert mistletoe.markdown(key, FiftyOhmHtmlRenderer) == paragraph(value) assert render_html(key) == paragraph(value)
@pytest.mark.html @pytest.mark.html
@@ -32,7 +31,7 @@ def test_absatz_html():
input = "Der Test befindet sich unter Abs.2 vielleicht aber auch Abs. 3." input = "Der Test befindet sich unter Abs.2 vielleicht aber auch Abs. 3."
target = "Der Test befindet sich unter Abs.&#160;2 vielleicht aber auch Abs.&#160;3." target = "Der Test befindet sich unter Abs.&#160;2 vielleicht aber auch Abs.&#160;3."
assert mistletoe.markdown(input, FiftyOhmHtmlRenderer) == paragraph(target) assert render_html(input) == paragraph(target)
@pytest.mark.html @pytest.mark.html
@@ -40,7 +39,7 @@ def test_class_html():
input = "Ich lerne für Klasse A, Klasse E und Klasse N." input = "Ich lerne für Klasse A, Klasse E und Klasse N."
target = "Ich lerne für Klasse&#160;A, Klasse&#160;E und Klasse&#160;N." target = "Ich lerne für Klasse&#160;A, Klasse&#160;E und Klasse&#160;N."
assert mistletoe.markdown(input, FiftyOhmHtmlRenderer) == paragraph(target) assert render_html(input) == paragraph(target)
@pytest.mark.latex @pytest.mark.latex
+6 -7
View File
@@ -1,19 +1,17 @@
import mistletoe
import pytest import pytest
from renderer.document import Document
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
from test.util import paragraph
@pytest.mark.html @pytest.mark.html
def test_photo_html(): def test_photo_html():
assertions = { assertions = {"[photo:123:abc:Text]": ("123", "abc", "Text", "A-5.7.1", "")}
"[photo:123:abc:Text]": FiftyOhmHtmlRenderer.render_photo_helper("123", "abc", "Text", "TODO", ""),
}
with FiftyOhmHtmlRenderer(edition="A", chapter="5", section="7") as renderer:
for assertion in assertions: for assertion in assertions:
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == paragraph(assertions[assertion]) assert renderer.render(Document(assertion)) == renderer.render_photo_helper(*assertions[assertion]) + "\n"
@pytest.mark.latex @pytest.mark.latex
@@ -22,5 +20,6 @@ def test_photo_latex():
"[photo:123:abc:Text]": FiftyOhmLaTeXRenderer.render_photo_helper("123", "abc", "Text", "TODO"), "[photo:123:abc:Text]": FiftyOhmLaTeXRenderer.render_photo_helper("123", "abc", "Text", "TODO"),
} }
with FiftyOhmLaTeXRenderer() as renderer:
for assertion in assertions: for assertion in assertions:
assert mistletoe.markdown(assertion, FiftyOhmLaTeXRenderer) == "\n" + assertions[assertion] + "\n" assert renderer.render(Document(assertion)) == assertions[assertion]
+2 -2
View File
@@ -1,4 +1,3 @@
import mistletoe
import pytest import pytest
from renderer.document import Document from renderer.document import Document
@@ -21,5 +20,6 @@ def test_picture_latex():
"[picture:0:abc:Text]": FiftyOhmLaTeXRenderer.render_picture_helper("0", "abc", "Text", "TODO"), "[picture:0:abc:Text]": FiftyOhmLaTeXRenderer.render_picture_helper("0", "abc", "Text", "TODO"),
} }
with FiftyOhmLaTeXRenderer() as renderer:
for assertion in assertions: for assertion in assertions:
assert mistletoe.markdown(assertion, FiftyOhmLaTeXRenderer) == "\n" + assertions[assertion] + "\n" assert renderer.render(Document(assertion)) == assertions[assertion]
+3 -4
View File
@@ -1,8 +1,7 @@
import mistletoe
import pytest import pytest
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_html_slide_renderer import FiftyOhmHtmlSlideRenderer from test.util import render_html, render_slide
@pytest.mark.html @pytest.mark.html
@@ -21,7 +20,7 @@ def test_qso_html():
} }
for assertion in assertions: for assertion in assertions:
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == assertions[assertion] assert render_html(assertion) == assertions[assertion]
@pytest.mark.slide @pytest.mark.slide
@@ -31,4 +30,4 @@ def test_qso_slide():
} }
for assertion in assertions: for assertion in assertions:
assert mistletoe.markdown(assertion, FiftyOhmHtmlSlideRenderer) == assertions[assertion] assert render_slide(assertion) == assertions[assertion]
+1 -1
View File
@@ -1,8 +1,8 @@
import json import json
import pytest import pytest
from mistletoe import Document
from renderer.document import Document
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
from test.util import paragraph from test.util import paragraph
+2 -3
View File
@@ -1,9 +1,8 @@
import mistletoe import mistletoe
import pytest import pytest
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
from test.util import paragraph from test.util import paragraph, render_html
@pytest.mark.html @pytest.mark.html
@@ -18,7 +17,7 @@ def test_quote_html():
} }
for assertion in assertions: for assertion in assertions:
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == paragraph(assertions[assertion]) assert render_html(assertion) == paragraph(assertions[assertion])
@pytest.mark.latex @pytest.mark.latex
+2 -4
View File
@@ -1,8 +1,6 @@
import mistletoe
import pytest import pytest
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer from test.util import paragraph, render_html
from test.util import paragraph
@pytest.mark.html @pytest.mark.html
@@ -15,4 +13,4 @@ def test_references_html():
} }
for key, value in assertions.items(): for key, value in assertions.items():
assert mistletoe.markdown(key, FiftyOhmHtmlRenderer) == paragraph(value) assert render_html(key) == paragraph(value)
+2 -2
View File
@@ -1,6 +1,6 @@
import pytest import pytest
from mistletoe import Document
from renderer.document import Document
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
@@ -15,7 +15,7 @@ def test_table_html():
"| l: a |\n| b |\n| c |": '<table class="table table-hover">\n<thead>\n<tr>\n<th style="text-align: left;">a</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style="text-align: left;">b</td>\n</tr>\n<tr>\n<td style="text-align: left;">c</td>\n</tr>\n</tbody>\n</table>\n', # noqa: E501 "| l: a |\n| b |\n| c |": '<table class="table table-hover">\n<thead>\n<tr>\n<th style="text-align: left;">a</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style="text-align: left;">b</td>\n</tr>\n<tr>\n<td style="text-align: left;">c</td>\n</tr>\n</tbody>\n</table>\n', # noqa: E501
"| a |\n| b |\n| c |": '<table class="table table-hover">\n<thead>\n<tr>\n<th>a</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>b</td>\n</tr>\n<tr>\n<td>c</td>\n</tr>\n</tbody>\n</table>\n', # noqa: E501 "| a |\n| b |\n| c |": '<table class="table table-hover">\n<thead>\n<tr>\n<th>a</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>b</td>\n</tr>\n<tr>\n<td>c</td>\n</tr>\n</tbody>\n</table>\n', # noqa: E501
"| l: a |\n| *b* |": '<table class="table table-hover">\n<thead>\n<tr>\n<th style="text-align: left;">a</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style="text-align: left;"><em>b</em></td>\n</tr>\n</tbody>\n</table>\n', # noqa: E501 "| l: a |\n| *b* |": '<table class="table table-hover">\n<thead>\n<tr>\n<th style="text-align: left;">a</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style="text-align: left;"><em>b</em></td>\n</tr>\n</tbody>\n</table>\n', # noqa: E501
"| l: a |\n| b |\n[table:n_ab:A und B]": '<table class="table table-hover" id="ref_n_ab" name="n_ab">\n<thead>\n<tr>\n<th style="text-align: left;">a</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style="text-align: left;">b</td>\n</tr>\n</tbody>\n<caption>A und B</caption>\n</table>\n', # noqa: E501 "| l: a |\n| b |\n[table:n_ab:A und B]": '<table class="table table-hover" id="ref_n_ab" name="n_ab">\n<thead>\n<tr>\n<th style="text-align: left;">a</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style="text-align: left;">b</td>\n</tr>\n</tbody>\n<caption>Tabelle 1: A und B</caption>\n</table>\n', # noqa: E501
"| l: *a* |": '<table class="table table-hover">\n<thead>\n<tr>\n<th style="text-align: left;"><em>a</em></th>\n</tr>\n</thead>\n</table>\n', # noqa: E501 "| l: *a* |": '<table class="table table-hover">\n<thead>\n<tr>\n<th style="text-align: left;"><em>a</em></th>\n</tr>\n</thead>\n</table>\n', # noqa: E501
"| l: a |\n| [morse:a] |": '<table class="table table-hover">\n<thead>\n<tr>\n<th style="text-align: left;">a</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style="text-align: left;"><span class="morse"><span class="morse_char">\n<span class="morse_symbol">\n▄</span>\n<span class="morse_symbol">\n▄▄▄</span>\n</span>\n</span></td>\n</tr>\n</tbody>\n</table>\n', # noqa: E501 "| l: a |\n| [morse:a] |": '<table class="table table-hover">\n<thead>\n<tr>\n<th style="text-align: left;">a</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style="text-align: left;"><span class="morse"><span class="morse_char">\n<span class="morse_symbol">\n▄</span>\n<span class="morse_symbol">\n▄▄▄</span>\n</span>\n</span></td>\n</tr>\n</tbody>\n</table>\n', # noqa: E501
"| l: abc | r: abc | X: abc |\n| 123 | 456 | 789 | \n | 987 | 654 | 321 | ": '<table class="table table-hover">\n<thead>\n<tr>\n<th style="text-align: left;">abc</th>\n<th style="text-align: right;">abc</th>\n<th>abc</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style="text-align: left;">123</td>\n<td style="text-align: right;">456</td>\n<td>789</td>\n</tr>\n<tr>\n<td style="text-align: left;">987</td>\n<td style="text-align: right;">654</td>\n<td>321</td>\n</tr>\n</tbody>\n</table>\n', # noqa: E501 "| l: abc | r: abc | X: abc |\n| 123 | 456 | 789 | \n | 987 | 654 | 321 | ": '<table class="table table-hover">\n<thead>\n<tr>\n<th style="text-align: left;">abc</th>\n<th style="text-align: right;">abc</th>\n<th>abc</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style="text-align: left;">123</td>\n<td style="text-align: right;">456</td>\n<td>789</td>\n</tr>\n<tr>\n<td style="text-align: left;">987</td>\n<td style="text-align: right;">654</td>\n<td>321</td>\n</tr>\n</tbody>\n</table>\n', # noqa: E501
+6 -7
View File
@@ -2,9 +2,8 @@ import mistletoe
import pytest import pytest
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_html_slide_renderer import FiftyOhmHtmlSlideRenderer
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
from test.util import paragraph from test.util import paragraph, render_html, render_slide
@pytest.mark.html @pytest.mark.html
@@ -15,7 +14,7 @@ def test_thematic_break_html():
} }
for assertion in assertions: for assertion in assertions:
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == assertions[assertion] assert render_html(assertion) == assertions[assertion]
@pytest.mark.html @pytest.mark.html
@@ -39,7 +38,7 @@ def test_tag_html():
} }
for assertion in assertions: for assertion in assertions:
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == assertions[assertion] assert render_html(assertion) == assertions[assertion]
@pytest.mark.html @pytest.mark.html
@@ -61,7 +60,7 @@ def test_thematic_break_and_tag_html():
} }
for assertion in assertions: for assertion in assertions:
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == assertions[assertion] assert render_html(assertion) == assertions[assertion]
@pytest.mark.latex @pytest.mark.latex
@@ -119,7 +118,7 @@ def test_tag_slide():
} }
for assertion in assertions: for assertion in assertions:
assert mistletoe.markdown(assertion, FiftyOhmHtmlSlideRenderer) == assertions[assertion] assert render_slide(assertion) == assertions[assertion]
@pytest.mark.slide @pytest.mark.slide
@@ -133,4 +132,4 @@ def test_slide_break():
} }
for assertion in assertions: for assertion in assertions:
assert mistletoe.markdown(assertion, FiftyOhmHtmlSlideRenderer) == assertions[assertion] assert render_slide(assertion) == assertions[assertion]
+2 -3
View File
@@ -1,9 +1,8 @@
import mistletoe import mistletoe
import pytest import pytest
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
from test.util import paragraph from test.util import paragraph, render_html
@pytest.mark.html @pytest.mark.html
@@ -15,7 +14,7 @@ def test_underline_html():
} }
for assertion in assertions: for assertion in assertions:
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == paragraph(assertions[assertion]) assert render_html(assertion) == paragraph(assertions[assertion])
@pytest.mark.latex @pytest.mark.latex
+4 -7
View File
@@ -1,9 +1,6 @@
import mistletoe
import pytest import pytest
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer from .util import paragraph, render_html
from .util import paragraph
@pytest.mark.html @pytest.mark.html
@@ -21,7 +18,7 @@ def test_basic_units_html():
} }
for input, output in assertions.items(): for input, output in assertions.items():
assert mistletoe.markdown(input, FiftyOhmHtmlRenderer) == paragraph(output) assert render_html(input) == paragraph(output)
@pytest.mark.html @pytest.mark.html
@@ -33,7 +30,7 @@ def test_translated_units_html():
} }
for input, output in assertions.items(): for input, output in assertions.items():
assert mistletoe.markdown(input, FiftyOhmHtmlRenderer) == paragraph(output) assert render_html(input) == paragraph(output)
@pytest.mark.html @pytest.mark.html
@@ -46,4 +43,4 @@ def test_special_units_html():
} }
for input, output in assertions.items(): for input, output in assertions.items():
assert mistletoe.markdown(input, FiftyOhmHtmlRenderer) == paragraph(output) assert render_html(input) == paragraph(output)
+17
View File
@@ -1,2 +1,19 @@
from renderer.document import Document
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_html_slide_renderer import FiftyOhmHtmlSlideRenderer
def paragraph(text): def paragraph(text):
return f"<p>{text}</p>\n" return f"<p>{text}</p>\n"
def render_html(markdown):
"""Render markdown with the HTML renderer through the project's Document."""
with FiftyOhmHtmlRenderer() as renderer:
return renderer.render(Document(markdown))
def render_slide(markdown):
"""Render markdown with the slide renderer through the project's Document."""
with FiftyOhmHtmlSlideRenderer() as renderer:
return renderer.render(Document(markdown))