Merge remote-tracking branch 'origin/main' into feature--member-registration

This commit is contained in:
Matthias Jung
2026-07-09 00:05:35 +02:00
33 changed files with 304 additions and 340 deletions
+10
View File
@@ -0,0 +1,10 @@
import mistletoe
class Document(mistletoe.Document):
def __init__(self, *args, **kwargs):
# references must exist before super().__init__ tokenizes the lines,
# since ReferencedToken reads it from _root_node during tokenization.
self.references: dict[str, str] = {}
super().__init__(*args, **kwargs)
+49 -80
View File
@@ -1,22 +1,22 @@
import re
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 .image import Image
from .include import Include
from .index import Index
from .morse import Morse
from .nonbreaking_spaces import NonbreakingSpaces, NonbreakingSpacesDots
from .photo import Photo
from .picture import Picture
from .qso import Qso
from .question import Question
from .quote import Quote
from .references import References
from .reference import Reference
from .table import Table, TableBody, TableCell, TableHeader, TableRow
from .tag import Tag
from .underline import Underline
@@ -28,8 +28,6 @@ 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
def __init__(
self,
@@ -55,10 +53,9 @@ class FiftyOhmHtmlRenderer(HtmlRenderer):
HalfwidthSpaces,
NonbreakingSpaces,
NonbreakingSpacesDots,
References,
Reference,
Question,
Picture,
Photo,
Image,
Table,
TableHeader,
TableRow,
@@ -83,18 +80,22 @@ class FiftyOhmHtmlRenderer(HtmlRenderer):
self.section = section
# Set section URL if provided, otherwise use default
if section_url is not None:
self.section_url = section_url
self.section_url = section_url if section_url is not None else "section.html"
# Figure map: stores ref -> hierarchical number mapping
self.figure_map = {}
# Single unified counter for all figure types (pictures, photos, tables)
self.figure_counter = 0
self.references: dict[str, str] = {}
# Keep track of index ids already emitted in this document.
self.index_anchor_ids = set()
def _format_reference_label(self, marker: str):
if marker in self.references:
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:
return None
def render_dash(self, token):
return " – "
@@ -209,53 +210,18 @@ class FiftyOhmHtmlRenderer(HtmlRenderer):
lookup = {"": "", " ": " "}
return f"{lookup[token.first]}{token.second}{lookup[token.third]}"
def collect_figures(self, document):
"""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):
def render_reference(self, token: Reference):
# 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 (
f'<a href="{self.section_url}#ref_{token.first}"'
f" onclick=\"highlightRef('{token.first}');\">{figure_num}</a>"
f'<a href="{self.section_url}#ref_{token.marker}" onclick="highlightRef(\'{token.marker}\');">{label}</a>'
)
def render_question(self, token):
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 ""
@@ -264,36 +230,38 @@ 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(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)
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 {label}: {text}</figcaption>\n"
"</figure>\n"
)
@staticmethod
def render_photo_helper(id, ref, text, number, alt_text):
def render_photo_helper(id, ref, text, label, alt_text):
return f"""
<figure class="photo" id="ref_{ref}" name="{ref}">
<img src="photos/{id}.png" alt="{alt_text}">
<figcaption>Abbildung {number}: {text}</figcaption>
<figcaption>Abbildung {label}: {text}</figcaption>
</figure>
"""
def render_photo(self, token):
alt_text = ""
if self.photo_handler is not None:
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)
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 = ""
if self.photo_handler is not None:
alt_text = self.photo_handler(token.id) or 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):
# Add id and name attributes if table has a name
@@ -304,10 +272,11 @@ class FiftyOhmHtmlRenderer(HtmlRenderer):
table = f'<table class="table table-hover"{table_attrs}>\n{self.render_inner(token)}'
if token.caption != "":
# Include hierarchical number in caption if available
# Include hierarchical number in caption if the table is named.
caption_text = token.caption
if hasattr(token, "number") and token.number:
caption_text = f"Tabelle {token.number}: {token.caption}"
label = self._format_reference_label(token.name)
if label:
caption_text = f"Tabelle {label}: {token.caption}"
table += f"<caption>{caption_text}</caption>\n"
table += "</table>"
+8 -9
View File
@@ -3,10 +3,9 @@ from mistletoe.latex_renderer import LaTeXRenderer
from .comment import BlockComment
from .dash import Dash
from .halfwidth_spaces import HalfwidthSpaces
from .image import Image
from .index import Index
from .nonbreaking_spaces import NonbreakingSpaces, NonbreakingSpacesDots
from .photo import Photo
from .picture import Picture
from .question import Question
from .quote import Quote
from .table import Table, TableBody, TableCell, TableHeader, TableRow
@@ -26,8 +25,7 @@ class FiftyOhmLaTeXRenderer(LaTeXRenderer):
NonbreakingSpaces,
NonbreakingSpacesDots,
Question,
Picture,
Photo,
Image,
Table,
TableBody,
TableRow,
@@ -115,17 +113,18 @@ class FiftyOhmLaTeXRenderer(LaTeXRenderer):
\captionof{{figure}}{{{text}}}
\label{{{ref}}}"""
def render_picture(self, token):
return self.render_picture_helper(token.id, token.ref, token.text, token.number)
@staticmethod
def render_photo_helper(id, ref, text, number):
return rf"""\includegraphics[width=1.0\linewidth]{{photo/{id}}}
\captionof{{figure}}{{{text}}}
\label{{{ref}}}"""
def render_photo(self, token):
return self.render_photo_helper(token.id, token.ref, token.text, token.number)
def render_image(self, token: Image):
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):
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"
-19
View File
@@ -1,19 +0,0 @@
import re
from mistletoe.span_token import SpanToken
class Picture(SpanToken):
"""
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+):(.+):(.+)\]")
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"
@@ -3,7 +3,7 @@ import re
from mistletoe.span_token import SpanToken
class References(SpanToken):
class Reference(SpanToken):
"""
Resolve references for html
Identifies "[ref:$]"
@@ -12,4 +12,4 @@ class References(SpanToken):
pattern = re.compile(r"\[ref\:(\S+)\]")
def __init__(self, match_object):
self.first = match_object.group(1)
self.marker: str = match_object.group(1)
+18
View File
@@ -0,0 +1,18 @@
import mistletoe.token
from mistletoe.block_token import BlockToken
class ReferencedToken(BlockToken):
def __init__(self, marker: str):
if marker != "":
self.marker = marker
references = mistletoe.token._root_node.references
if marker not in references:
label = str(len(references) + 1)
references[marker] = label
else:
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.block_token import BlockToken
from renderer.referenced_token import ReferencedToken
class CellAlignment(Enum):
LEFT = "l"
@@ -76,7 +78,7 @@ class TableBody(BlockToken):
self.children, self.header = rows, header
class Table(BlockToken):
class Table(ReferencedToken):
name: str
caption: str
header: list[TableHeader]
@@ -115,4 +117,8 @@ class Table(BlockToken):
return children, name, caption
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
+40 -52
View File
@@ -7,10 +7,10 @@ import zipfile
from pathlib import Path
from jinja2 import Environment, FileSystemLoader
from mistletoe import Document
from rich.progress import BarColumn, Progress, TaskProgressColumn, TextColumn, TimeRemainingColumn
from tqdm import tqdm
from renderer.document import Document
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_html_slide_renderer import FiftyOhmHtmlSlideRenderer
from renderer.index import Index
@@ -222,12 +222,7 @@ class Build:
section=section_num,
section_url=section_filename,
) as renderer:
# First pass: collect all figures and assign hierarchical numbers
doc = Document(section["content"])
renderer.collect_figures(doc)
# Second pass: render with hierarchical numbers
section["content"] = renderer.render(doc)
section["content"] = renderer.render(Document(section["content"]))
result = section_template.render(
edition=edition,
@@ -266,58 +261,51 @@ class Build:
# Note: filename uses original edition (e.g., "N"), not modified edition with "S" (e.g., "NS")
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 += f'<section data-background="#DAEEFA">\n<h1>{chapter["title"]}</h1>\n</section>\n'
result += help_template.render()
result += "</section>\n"
result = "<section>\n"
result += f'<section data-background="#DAEEFA">\n<h1>{chapter["title"]}</h1>\n</section>\n'
result += help_template.render()
result += "</section>\n"
section_counter = 0
slides_task = progress.add_task("Rendering slides ...")
for section in progress.track(sections, task_id=slides_task):
progress.update(slides_task, description=f"Rendering slides of {section['title']}")
section_counter = 0
slides_task = progress.add_task("Rendering slides ...")
for section in progress.track(sections, task_id=slides_task):
progress.update(slides_task, description=f"Rendering slides of {section['title']}")
if section["slide"] is None:
continue
if section["slide"] is None:
continue
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 = {}
section_counter += 1
if not section["slide"].startswith("---"):
section["slide"] = "---\n" + section["slide"]
if not section["slide"].startswith("---"):
section["slide"] = "---\n" + section["slide"]
# First pass: collect figures
doc = Document(section["slide"])
renderer.collect_figures(doc)
# Second pass: render with hierarchical numbers
tmp = f'<section data-background="#DAEEFA">\n<h1>{section["title"]}</h1>\n</section>\n'
tmp += renderer.render(doc)
result += f"<section>{tmp}</section>\n"
progress.remove_task(slides_task)
result += next_template.render(
# A fresh renderer per section keeps the figure counter and
# reference map scoped to that section.
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,
next_chapter=next_chapter,
chapter=chapter,
)
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 += renderer.render(Document(section["slide"]))
result = slide_template.render(content=result)
file.write(result)
result += f"<section>{tmp}</section>\n"
progress.remove_task(slides_task)
result += next_template.render(
edition=edition,
next_chapter=next_chapter,
chapter=chapter,
)
result = slide_template.render(content=result)
file.write(result)
def __filter_shuffle_answers(self, seq):
answers = []
+13 -13
View File
@@ -108,8 +108,8 @@
<h5>Mitglied werden</h5>
<p>Der <a href="https://darc.de">DARC e. V.</a> unterstützt Dich auf deinem Weg zum Amateurfunkzeugnis und ist die größte Interessensvertretung der Funkamateure in Deutschland.</p>
<div class="row row-cols-lg-2">
<div class="col"><a href="https://www.darc.de/mitgliedschaft/mitglied-werden/" class="btn btn-outline-dark w-100">Mitglied werden</a></div>
<div class="col"><a href="https://www.darc.de/mitgliedschaft/mitglied-werden/#c154065" class="btn btn-outline-dark w-100">Gastmitgliedschaft</a></div>
<div class="col"><a href="https://antrag.darc.de/?typ=voll" class="btn btn-outline-dark w-100" target="_blank">Mitglied werden</a></div>
<div class="col"><a href="https://antrag.darc.de/?typ=gast" class="btn btn-outline-dark w-100" target="_blank">Gastmitgliedschaft</a></div>
</div>
</div>
</div>
@@ -121,9 +121,9 @@
<h2>Videokurse</h2>
<p>In Zusammenarbeit mit DL2YMR ist ein Videokurs für die Klasse N entstanden, der auf seinem YouTube-Kanal abrufbar ist. Weiterhin gibt es noch Vorlesungen für N+E sowie A. </p>
<div class="d-grid gap-2 d-sm-flex flex-sm-wrap mb-5">
<a href="https://www.youtube.com/playlist?list=PLDpWnjHk5ERbcgpLPUaU0iTsD-wrmfENk" class="btn btn-primary">Zum Videokurs Klasse N</a>
<a href="https://www.youtube.com/playlist?list=PL_JZo16Mzs5XGeN5N81MwQ70dp7478VkM" class="btn btn-primary">Vorlesung Klasse N+E</a>
<a href="https://www.youtube.com/playlist?list=PL_JZo16Mzs5XebdJhoIDLNp1MObBy7F5d" class="btn btn-primary">Vorlesung Klasse A</a>
<a href="https://www.youtube.com/playlist?list=PLDpWnjHk5ERbcgpLPUaU0iTsD-wrmfENk" class="btn btn-outline-dark">Zum Videokurs Klasse N</a>
<a href="https://www.youtube.com/playlist?list=PL_JZo16Mzs5XGeN5N81MwQ70dp7478VkM" class="btn btn-outline-dark">Vorlesung Klasse N+E</a>
<a href="https://www.youtube.com/playlist?list=PL_JZo16Mzs5XebdJhoIDLNp1MObBy7F5d" class="btn btn-outline-dark">Vorlesung Klasse A</a>
</div>
</div>
<div class="feature col">
@@ -134,8 +134,8 @@
<h2>Buch Klasse N</h2>
<p>Die Lernhinhalte für die Klasse N gibt es auch als gedrucktes Buch. Es ist passend zum Online-Kurs ausgelegt.</p>
<div class="d-grid gap-2 d-md-block mb-5">
<a href="https://darcverlag.de/DARC-Amateurfunklehrgang-Klasse-N" class="btn btn-primary">Beim DARC-Verlag kaufen</a>
<a href="https://www.amazon.de/dp/388692100X" class="btn btn-primary">Amazon</a>
<a href="https://darcverlag.de/DARC-Amateurfunklehrgang-Klasse-N" class="btn btn-outline-dark">Beim DARC-Verlag kaufen</a>
<a href="https://www.amazon.de/dp/388692100X" class="btn btn-outline-dark">Amazon</a>
</div>
</div>
<div class="feature col">
@@ -145,8 +145,8 @@
<h2>Kurse</h2>
<p>Einige unserer Ortsverbände bieten Präsenz- oder Onlinekurse mit erfahrenen Ausbildern an. Finde heraus, ob es einen für dich passenden Kurs bei dir in der Nähe gibt!</p>
<div class="d-grid gap-2 d-md-block mb-5">
<a href="kurse_vor_ort_karte.html" class="btn btn-primary">Präsenz</a>
<a href="kurse_vor_ort_liste.html" class="btn btn-primary">Online</a>
<a href="kurse_vor_ort_karte.html" class="btn btn-outline-dark">Präsenz</a>
<a href="kurse_vor_ort_liste.html" class="btn btn-outline-dark">Online</a>
</div>
</div>
<div class="feature col">
@@ -156,7 +156,7 @@
<h2>Ausbildungs&shy;paten</h2>
<p>Unsere Ausbildungspaten sind erfahrene Funkamateure, die dich gerne unterstützen. Sie können mit dir auch praktisch üben und nützliche Tipps für die Praxis geben.</p>
<div class="d-grid gap-2 d-md-block mb-5">
<a href="patenkarte.html" class="btn btn-primary">Zur Patenkarte</a>
<a href="patenkarte.html" class="btn btn-outline-dark">Zur Patenkarte</a>
</div>
</div>
<div class="feature col">
@@ -166,7 +166,7 @@
<h2>Fragenkatalog</h2>
<p>Den Fragenkatalog mit den amtlichen Prüfungsfragen gibt es digital bei der <a href="https://50ohm.de/fk">Bundesnetzagentur</a>. Beim DARC-Verlag kann man auch eine gedruckte Version bestellen.</p>
<div class="d-grid gap-2 d-md-block mb-5">
<a href="https://darcverlag.de/Fragenkatalog-Klasse-N" class="btn btn-primary">Beim DARC-Verlag kaufen</a>
<a href="https://darcverlag.de/Fragenkatalog-Klasse-N" class="btn btn-outline-dark">Beim DARC-Verlag kaufen</a>
</div>
</div>
<div class="feature col">
@@ -176,8 +176,8 @@
<h2>Trainings App</h2>
<p>Zum Trainieren der Fragen gibt es die 50Ohm App. Sie ist passend zum Online-Kurs ausgelegt.</p>
<div class="d-grid gap-2 d-md-block mb-5">
<a href="https://play.google.com/store/apps/details?id=de.darc.fuenfizigohm" class="btn btn-primary">Android</a>
<a href="https://apps.apple.com/de/app/50ohm/id6474642114" class="btn btn-primary">iOS</a>
<a href="https://play.google.com/store/apps/details?id=de.darc.fuenfizigohm" class="btn btn-outline-dark">Android</a>
<a href="https://apps.apple.com/de/app/50ohm/id6474642114" class="btn btn-outline-dark">iOS</a>
</div>
</div>
</div>
+2 -3
View File
@@ -1,9 +1,8 @@
import mistletoe
import pytest
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
from test.util import paragraph
from test.util import paragraph, render_html
@pytest.mark.html
@@ -16,7 +15,7 @@ def test_comment_html():
}
for assertion in assertions:
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == assertions[assertion]
assert render_html(assertion) == assertions[assertion]
@pytest.mark.latex
+2 -3
View File
@@ -1,9 +1,8 @@
import mistletoe
import pytest
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
from test.util import paragraph
from test.util import paragraph, render_html
@pytest.mark.html
@@ -14,7 +13,7 @@ def test_dash_html():
}
for assertion in assertions:
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == paragraph(assertions[assertion])
assert render_html(assertion) == paragraph(assertions[assertion])
@pytest.mark.latex
+3 -5
View File
@@ -1,7 +1,6 @@
import pytest
from mistletoe import Document
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from test.util import render_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",
}
with FiftyOhmHtmlRenderer() as renderer:
for assertion in assertions:
assert renderer.render(Document(assertion)) == assertions[assertion]
for assertion in assertions:
assert render_html(assertion) == assertions[assertion]
+2 -3
View File
@@ -1,9 +1,8 @@
import mistletoe
import pytest
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
from test.util import paragraph
from test.util import paragraph, render_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."
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
+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
+1 -1
View File
@@ -2,9 +2,9 @@ import json
import pytest
from jinja2 import Environment, FileSystemLoader
from mistletoe import Document
import src.config as config
from renderer.document import Document
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
conf = config.Config()
+1 -1
View File
@@ -3,9 +3,9 @@ import random
import pytest
from jinja2 import Environment, FileSystemLoader
from mistletoe import Document
import src.config as config
from renderer.document import Document
from renderer.fifty_ohm_html_slide_renderer import FiftyOhmHtmlSlideRenderer
conf = config.Config()
+1 -1
View File
@@ -1,6 +1,6 @@
import pytest
from mistletoe import Document
from renderer.document import Document
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
+2 -3
View File
@@ -1,9 +1,8 @@
import mistletoe
import pytest
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
from test.util import paragraph
from test.util import paragraph, render_html
@pytest.mark.html
@@ -42,7 +41,7 @@ def test_index_html():
}
for key, value in assertions.items():
assert mistletoe.markdown(key, FiftyOhmHtmlRenderer) == paragraph(value)
assert render_html(key) == paragraph(value)
@pytest.mark.latex
+2 -3
View File
@@ -1,8 +1,7 @@
import mistletoe
import pytest
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from test.util import paragraph
from test.util import paragraph, render_html
@pytest.mark.html
@@ -17,4 +16,4 @@ def test_morse_html():
}
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 pytest
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
from test.util import paragraph
from test.util import paragraph, render_html
@pytest.mark.html
@@ -11,7 +10,7 @@ def test_paragraph_html():
input = "Der Test befindet sich unter §2 vielleicht aber auch § 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
@@ -24,7 +23,7 @@ def test_three_points_html():
}
for key, value in assertions.items():
assert mistletoe.markdown(key, FiftyOhmHtmlRenderer) == paragraph(value)
assert render_html(key) == paragraph(value)
@pytest.mark.html
@@ -32,7 +31,7 @@ def test_absatz_html():
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."
assert mistletoe.markdown(input, FiftyOhmHtmlRenderer) == paragraph(target)
assert render_html(input) == paragraph(target)
@pytest.mark.html
@@ -40,7 +39,7 @@ def test_class_html():
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."
assert mistletoe.markdown(input, FiftyOhmHtmlRenderer) == paragraph(target)
assert render_html(input) == paragraph(target)
@pytest.mark.latex
+8 -9
View File
@@ -1,19 +1,17 @@
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_photo_html():
assertions = {
"[photo:123:abc:Text]": FiftyOhmHtmlRenderer.render_photo_helper("123", "abc", "Text", "TODO", ""),
}
assertions = {"[photo:123:abc:Text]": ("123", "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_photo_helper(*assertions[assertion]) + "\n"
@pytest.mark.latex
@@ -22,5 +20,6 @@ def test_photo_latex():
"[photo:123:abc:Text]": FiftyOhmLaTeXRenderer.render_photo_helper("123", "abc", "Text", "TODO"),
}
for assertion in assertions:
assert mistletoe.markdown(assertion, FiftyOhmLaTeXRenderer) == "\n" + assertions[assertion] + "\n"
with FiftyOhmLaTeXRenderer() as renderer:
for assertion in assertions:
assert renderer.render(Document(assertion)) == assertions[assertion]
+8 -9
View File
@@ -1,19 +1,17 @@
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
@@ -22,5 +20,6 @@ def test_picture_latex():
"[picture:0:abc:Text]": FiftyOhmLaTeXRenderer.render_picture_helper("0", "abc", "Text", "TODO"),
}
for assertion in assertions:
assert mistletoe.markdown(assertion, FiftyOhmLaTeXRenderer) == "\n" + assertions[assertion] + "\n"
with FiftyOhmLaTeXRenderer() as renderer:
for assertion in assertions:
assert renderer.render(Document(assertion)) == assertions[assertion]
+3 -4
View File
@@ -1,8 +1,7 @@
import mistletoe
import pytest
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
@@ -21,7 +20,7 @@ def test_qso_html():
}
for assertion in assertions:
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == assertions[assertion]
assert render_html(assertion) == assertions[assertion]
@pytest.mark.slide
@@ -31,4 +30,4 @@ def test_qso_slide():
}
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 pytest
from mistletoe import Document
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
+2 -3
View File
@@ -1,9 +1,8 @@
import mistletoe
import pytest
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
from test.util import paragraph
from test.util import paragraph, render_html
@pytest.mark.html
@@ -18,7 +17,7 @@ def test_quote_html():
}
for assertion in assertions:
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == paragraph(assertions[assertion])
assert render_html(assertion) == paragraph(assertions[assertion])
@pytest.mark.latex
+2 -4
View File
@@ -1,8 +1,6 @@
import mistletoe
import pytest
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from test.util import paragraph
from test.util import paragraph, render_html
@pytest.mark.html
@@ -15,4 +13,4 @@ def test_references_html():
}
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
from mistletoe import Document
from renderer.document import Document
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
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
"| 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 |\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 |\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
+6 -7
View File
@@ -2,9 +2,8 @@ import mistletoe
import pytest
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 test.util import paragraph
from test.util import paragraph, render_html, render_slide
@pytest.mark.html
@@ -15,7 +14,7 @@ def test_thematic_break_html():
}
for assertion in assertions:
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == assertions[assertion]
assert render_html(assertion) == assertions[assertion]
@pytest.mark.html
@@ -39,7 +38,7 @@ def test_tag_html():
}
for assertion in assertions:
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == assertions[assertion]
assert render_html(assertion) == assertions[assertion]
@pytest.mark.html
@@ -61,7 +60,7 @@ def test_thematic_break_and_tag_html():
}
for assertion in assertions:
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == assertions[assertion]
assert render_html(assertion) == assertions[assertion]
@pytest.mark.latex
@@ -119,7 +118,7 @@ def test_tag_slide():
}
for assertion in assertions:
assert mistletoe.markdown(assertion, FiftyOhmHtmlSlideRenderer) == assertions[assertion]
assert render_slide(assertion) == assertions[assertion]
@pytest.mark.slide
@@ -133,4 +132,4 @@ def test_slide_break():
}
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 pytest
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
from test.util import paragraph
from test.util import paragraph, render_html
@pytest.mark.html
@@ -15,7 +14,7 @@ def test_underline_html():
}
for assertion in assertions:
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == paragraph(assertions[assertion])
assert render_html(assertion) == paragraph(assertions[assertion])
@pytest.mark.latex
+4 -7
View File
@@ -1,9 +1,6 @@
import mistletoe
import pytest
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from .util import paragraph
from .util import paragraph, render_html
@pytest.mark.html
@@ -21,7 +18,7 @@ def test_basic_units_html():
}
for input, output in assertions.items():
assert mistletoe.markdown(input, FiftyOhmHtmlRenderer) == paragraph(output)
assert render_html(input) == paragraph(output)
@pytest.mark.html
@@ -33,7 +30,7 @@ def test_translated_units_html():
}
for input, output in assertions.items():
assert mistletoe.markdown(input, FiftyOhmHtmlRenderer) == paragraph(output)
assert render_html(input) == paragraph(output)
@pytest.mark.html
@@ -46,4 +43,4 @@ def test_special_units_html():
}
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):
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))