from panflute import Element, ListContainer, Inline, Block from panflute import Cite, Code, Emph, Image, LineBreak, Link, Math, Note, Quoted, RawInline, SmallCaps, SoftBreak, Space, Span, Str, Strikeout, Strong, Subscript, Superscript, Underline from panflute import BlockQuote, BulletList, Citation, CodeBlock, Definition, DefinitionItem, DefinitionList, Div, Figure, Header, HorizontalRule, LineBlock, LineItem, ListItem, MetaBlocks, MetaBool, MetaInlines, MetaList, MetaMap, MetaString, Null, OrderedList, Para, Plain, RawBlock, Table, TableBody, TableFoot, TableHead from panflute import TableRow, TableCell, Caption, Doc from typing import Union, Dict from .whitespace import NBSP from .transform import FQuoted from .context import Group from .output_generator import OutputGenerator from .images import ImageProcessor import re class LaTeXGenerator(OutputGenerator): def __init__(self, output_file, imageProcessor: ImageProcessor, *args, **kwargs): self.imageProcessor = imageProcessor super().__init__(output_file, *args, **kwargs) def generate(self, e: Union[Element, ListContainer]): if hasattr(e, "attributes") and "only" in e.attributes and e.attributes["only"] != "tex": return super().generate(e) def escape_special_chars(self, text: str) -> str: text = text.replace("&", "\\&") text = text.replace("%", "\\%") text = text.replace("$", "\\$") text = text.replace("#", "\\#") text = text.replace("_", "\\_") text = text.replace("{", "\\{") text = text.replace("}", "\\}") text = text.replace("~", "\\textasciitilde{}") text = text.replace("^", "\\textasciicircum{}") text = text.replace("\\", "\\textbackslash{}") text = text.replace(" ", "~") # We use unicode no-break spaces to force nbsp in output return text def stag(self, tag: str, attributes: Dict[str,str]={}) -> str: return "\\" + tag + "{" def etag(self, tag: str, attributes: Dict[str,str]={}) -> str: return "}" def ntag(self, tag: str, attributes: Dict[str,str]={}) -> str: return "\\" + tag + "{}" def generate_NBSP(self, e: NBSP): self.write("~") def generate_Null(self, e: Null): pass def generate_LineBreak(self, e: LineBreak): self.write("\\\\") self.endln() def generate_Para(self, e: Para): self.generate(e) self.writeln("") # This ensures an empty line def generate_Plain(self, e: Plain): self.generate(e.content) def generate_Span(self, e: Plain): self.generate(e.content) def generate_Header(self, e: Header): tag = { 1: "section", 2: "subsection", 3: "subsubsection", 4: "paragraph", 5: "subparagraph", 6: "textbf" } self.generate_simple_tag(e, tag=tag[e.level]) def generate_HorizontalRule(self, e: HorizontalRule): self.writeln("\\begin{center}\\rule{0.5\\linewidth}{0.5pt}\\end{center}") # These are also disabled in pandoc so they shouldn't appear in the AST at all. def generate_Citation(self, e: Citation): self.writeln("% FIXME: Citations not implemented") def generate_Cite(self, e: Cite): self.writeln("% FIXME: Cites not implemented") def generate_Definition(self, e: Definition): self.writeln("% FIXME: Definitions not implemented") def generate_DefinitionItem(self, e: DefinitionItem): self.writeln("% FIXME: DefinitionItems not implemented") def generate_DefinitionList(self, e: DefinitionList): self.writeln("% FIXME: DefinitionLists not implemented")