from panflute import * from whitespace import NBSP from transform import FQuoted from util import inlinify from group import Group # Heavily inspired by: git://git.ucw.cz/labsconf2022.git def tex(e, indent_level: int=0, indent_str: str="\t") -> str: if hasattr(e, "attributes") and "only" in e.attributes and e.attributes["only"] != "tex": return "" if isinstance(e, ListContainer): return ''.join([tex(child, indent_level, indent_str) for child in e]) content_foot = "" content_head = "" arguments = "" open = "{" close = "}" tag = e.tag.lower() tags = { Header: "h"+chr(64 + e.level) if hasattr(e, "level") else "", } if type(e) in tags: tag = tags[type(e)] not_implemented = { Citation: True, Cite: True, Definition: True, DefinitionItem: True, DefinitionList: True } if type(e) in not_implemented: return f'% FIXME: {type(e)}s not implemented \n' simple_string = { NBSP: "~", Space: " ", Null: "", LineBreak: f"\\\\", SoftBreak: f" ", HorizontalRule: "\\hr\n\n" } if type(e) in simple_string: return simple_string[type(e)] if isinstance(e, Str): return e.text.replace(" ", "~").replace(" ", "~") if isinstance(e, Para): return tex(e.content, 0, "")+"\n\n" if isinstance(e, FQuoted): if e.style == "cs": if e.quote_type == "SingleQuote": return f'‚{tex(e.content, 0, "")}‘' elif e.quote_type == "DoubleQuote": return f'„{tex(e.content, 0, "")}“' elif e.style == "en": if e.quote_type == "SingleQuote": return f'‘{tex(e.content, 0, "")}’' elif e.quote_type == "DoubleQuote": return f'“{tex(e.content, 0, "")}”' else: if e.quote_type == "SingleQuote": return f'\'{tex(e.content, 0, "")}\'' elif e.quote_type == "DoubleQuote": return f'"{tex(e.content, 0, "")}"' else: return f'"{tex(e.content, 0, "")}"' if isinstance(e, BulletList): tag = "list" open = "" arguments = "{o}" close = "\\endlist" if isinstance(e, OrderedList): tag = "list" open = "" styles = { "DefaultStyle": "n", "Decimal": "n", "LowerRoman": "i", "UpperRoman:": "I", "LowerAlpha": "a", "UpperAlpha": "A" } style = styles[e.style] delimiters = { "DefaultDelim": f"{style}.", "Period": f"{style}.", "OneParen": f"{style})", "TwoParens": f"({style})" } style = delimiters[e.delimiter] arguments = f"{{{style}}}" close = "\\endlist" # FIXME: Starting number of list if isinstance(e, Image): return f'\\image{{width {e.attributes["width"] if "width" in e.attributes else ""}}}{{{e.url}}}' if isinstance(e, Figure): return f'\\figure{{{tex(e.content, indent_level+1, indent_str)}}}{{{tex(e.caption, indent_level+1, indent_str)}}}\n\n' if isinstance(e, Caption): if inlinify(e) is not None: return f'\\caption{{{tex(e.content, 0, "")}}}' if isinstance(e, ListItem): tag = ":" if isinstance(e, Link): if len(e.content) == 1 and isinstance(e.content[0], Str) and e.content[0].text == e.url: tag = "url" else: tag = "linkurl" arguments = f'{{{e.url}}}' if isinstance(e, Math): if e.format == "DisplayMath": return f'$${e.text}$$\n' else: return f'${e.text}$' if isinstance(e, Note): tag = "fn" if inlinify(e) is not None: return f'\\fn{{{tex(inlinify(e), 0, "")}}}' if isinstance(e, RawInline): if e.format == "tex": return e.text else: return "" if isinstance(e, RawBlock): if e.format == "tex": return f'{e.text}\n' else: return "" if isinstance(e, Span) or isinstance(e, Plain): return tex(e.content, 0, "") if isinstance(e, LineItem): return tex(e.content, 0, "") + ("\\\\\n" if e.next else "\n") if isinstance(e, LineBlock): return f'{tex(e.content, indent_level+1, indent_str)}\n' if isinstance(e, Group): tag = "begingroup" open = "" if "language" in e.metadata and e.metadata["language"] is not None: open = "\\language"+e.metadata["language"] close = "\\endgroup" if isinstance(e, Div): return f'{tex(e.content, indent_level+1, indent_str)}' if isinstance(e, Doc): return tex(e.content, indent_level, indent_str)+"\n\\bye" if isinstance(e, Inline): return f'\\{tag}{arguments}{open}{content_head}{tex(e.content, 0, "") if hasattr(e, "_content") else ""}{e.text if hasattr(e, "text") else ""}{content_foot}{close}' out_str = "" out_str = f"\\{tag}{arguments}{open}\n" out_str += content_head if hasattr(e, "_content"): out_str += tex(e.content, indent_level+1, indent_str) if hasattr(e, "text"): out_str += e.text out_str += f"{content_foot}\n{close}\n\n" return out_str