Files
50ohm/renderer/fifty_ohm_latex_renderer.py

158 lines
4.9 KiB
Python

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 .question import Question
from .quote import Quote
from .table import Table, TableBody, TableCell, TableHeader, TableRow
from .tag import Tag
from .underline import Underline
class FiftyOhmLaTeXRenderer(LaTeXRenderer):
def __init__(self, question_renderer=None):
super().__init__(
Dash,
BlockComment,
Quote,
Underline,
Tag,
HalfwidthSpaces,
NonbreakingSpaces,
NonbreakingSpacesDots,
Question,
Image,
Table,
TableBody,
TableRow,
TableHeader,
TableCell,
Index,
)
self.question_renderer = question_renderer
def render_inner(self, token, base="") -> str:
# 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]))
def render_document(self, token):
self.footnotes.update(token.footnotes)
return self.render_inner(token)
def render_dash(self, token):
return " -- "
def render_block_comment(self, token):
return f"% {token.content}\n"
def render_quote(self, token):
return rf"\enquote{{{self.render_inner(token)}}}"
def render_emphasis(self, token):
return rf"\emph{{{self.render_inner(token)}}}"
def render_underline(self, token):
return rf"\underline{{{self.render_inner(token)}}}"
def render_thematic_break(self, token):
return ""
def render_tag(self, token): # noqa: C901
tagtype = None
match token.tagtype:
case "danger":
tagtype = "MarginDanger"
case "warning":
tagtype = "MarginWarning"
case "attention":
tagtype = "MarginAttention"
case "tip":
tagtype = "MarginTip"
case "webtip":
tagtype = "WebTip"
case "unit":
tagtype = "MarginUnit"
case "indepth":
tagtype = "MarginInDepth"
case "webindepth":
tagtype = "MarginWebInDepth"
case "webmargin":
tagtype = "WebMargin"
case "fullwidth":
tagtype = "FullWidth"
case "latexonly":
return self.render_inner(token)
case "webonly":
return ""
case _:
tagtype = "Margin"
return rf"\{tagtype}{{{self.render_inner(token)}}}"
def render_halfwidth_spaces(self, token):
return rf"{token.first}.\,{token.second}."
def render_nonbreaking_spaces(self, token):
return f"{token.first}~{token.second}"
def render_nonbreaking_spaces_dots(self, token):
lookup = {"": "", " ": "~"}
return f"{lookup[token.first]}{token.second}{lookup[token.third]}"
def render_question(self, token):
return self.question_renderer(token.question_number)
@staticmethod
def render_picture_helper(id, ref, text, number):
return rf"""\DARCimage{{1.0\linewidth}}{{{id}include}}
\captionof{{figure}}{{{text}}}
\label{{{ref}}}"""
@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_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}"
if token.caption != "":
table += f"\\captionof{{figure}}{{{token.caption}}}\n"
table += f"\\label{{{token.name}}}\n"
return table
def render_table_body(self, token: TableBody):
return self.render_inner(token)
def render_table_row(self, token: TableRow):
return rf"{self.render_inner(token, ' & ')}\\" + "\n"
def render_table_header(self, token: TableHeader):
align = ""
for alignment in token.alignment:
align += alignment
return f"{{{align}}}\n{self.render_table_row(token)}"
def render_table_cell(self, token: TableCell):
return self.render_inner(token)
def render_index(self, token):
if token.second:
return f"\\index{{{token.first}!{token.second}}}"
else:
return f"\\index{{{token.first}}}"