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}}}"