Source code for mistletoe.renderers.latex

"""
LaTeX renderer for mistletoe.
"""
from typing import Optional

from mistletoe import block_tokens, block_tokens_ext, span_tokens, span_tokens_ext
from mistletoe.parse_context import ParseContext
from mistletoe.renderers.base import BaseRenderer


[docs]class LaTeXRenderer(BaseRenderer): default_block_tokens = ( # block_tokens.HTMLBlock, block_tokens.BlockCode, block_tokens.Heading, block_tokens.Quote, block_tokens.CodeFence, block_tokens.ThematicBreak, block_tokens.List, block_tokens_ext.Table, # block_tokens_ext.Footnote, block_tokens.LinkDefinition, block_tokens.Paragraph, ) default_span_tokens = ( span_tokens.EscapeSequence, # span_tokens.HTMLSpan, span_tokens.AutoLink, span_tokens.CoreTokens, span_tokens_ext.Math, # span_tokens_ext.FootReference, span_tokens_ext.Strikethrough, span_tokens.InlineCode, span_tokens.LineBreak, span_tokens.RawText, )
[docs] def __init__(self, *, parse_context: Optional[ParseContext] = None): self.packages = {} super().__init__(parse_context=parse_context)
def render_strong(self, token): return "\\textbf{{{}}}".format(self.render_inner(token)) def render_emphasis(self, token): return "\\textit{{{}}}".format(self.render_inner(token)) def render_inline_code(self, token): return "\\verb|{}|".format(self.render_inner(token)) def render_strikethrough(self, token): self.packages["ulem"] = ["normalem"] return "\\sout{{{}}}".format(self.render_inner(token)) def render_image(self, token): self.packages["graphicx"] = [] return "\n\\includegraphics{{{}}}\n".format(token.src) def render_link(self, token): self.packages["hyperref"] = [] template = "\\href{{{target}}}{{{inner}}}" inner = self.render_inner(token) return template.format(target=token.target, inner=inner) def render_auto_link(self, token): self.packages["hyperref"] = [] return "\\url{{{}}}".format(token.target) @staticmethod def render_math(token): return token.content def render_escape_sequence(self, token): return self.render_inner(token) def render_raw_text(self, token, escape=True): return ( ( token.content.replace("$", "\\$") .replace("#", "\\#") .replace("{", "\\{") .replace("}", "\\}") .replace("&", "\\&") ) if escape else token.content ) def render_heading(self, token): inner = self.render_inner(token) if token.level == 1: return "\n\\section{{{}}}\n".format(inner) elif token.level == 2: return "\n\\subsection{{{}}}\n".format(inner) return "\n\\subsubsection{{{}}}\n".format(inner) def render_quote(self, token): self.packages["csquotes"] = [] template = "\\begin{{displayquote}}\n{inner}\\end{{displayquote}}\n" return template.format(inner=self.render_inner(token)) def render_paragraph(self, token): return "\n{}\n".format(self.render_inner(token)) def render_block_code(self, token): self.packages["listings"] = [] template = "\n\\begin{{lstlisting}}[language={}]\n" "{}" "\\end{{lstlisting}}\n" inner = self.render_raw_text(token.children[0], False) return template.format(token.language, inner) def render_list(self, token): self.packages["listings"] = [] template = "\\begin{{{tag}}}\n{inner}\\end{{{tag}}}\n" tag = "enumerate" if token.start_at is not None else "itemize" inner = self.render_inner(token) return template.format(tag=tag, inner=inner) def render_list_item(self, token): inner = self.render_inner(token) return "\\item {}\n".format(inner) def render_table(self, token): def render_align(column_align): if column_align != [None]: cols = [get_align(col) for col in token.column_align] return "{{{}}}".format(" ".join(cols)) else: return "" def get_align(col): if col is None: return "l" elif col == 0: return "c" elif col == 1: return "r" raise RuntimeError("Unrecognized align option: " + col) template = "\\begin{{tabular}}{align}\n" "{inner}" "\\end{{tabular}}\n" if getattr(token, "header", None) is not None: head_template = "{inner}\\hline\n" head_inner = self.render_table_row(token.header) head_rendered = head_template.format(inner=head_inner) else: head_rendered = "" inner = self.render_inner(token) align = render_align(token.column_align) return template.format(inner=head_rendered + inner, align=align) def render_table_row(self, token): cells = [self.render(child) for child in token.children] return " & ".join(cells) + " \\\\\n" def render_table_cell(self, token): return self.render_inner(token) @staticmethod def render_thematic_break(token): return "\\hrulefill\n" @staticmethod def render_line_break(token): return "\n" if token.soft else "\\newline\n" def render_packages(self): pattern = "\\usepackage{options}{{{package}}}\n" return "".join( pattern.format(options=options or "", package=package) for package, options in self.packages.items() ) def render_document(self, token): template = ( "\\documentclass{{article}}\n" "{packages}" "\\begin{{document}}\n" "{inner}" "\\end{{document}}\n" ) return template.format( inner=self.render_inner(token), packages=self.render_packages() )