You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

164 lines
3.8 KiB

from panflute import *
from whitespace import NBSP
from transform import FQuoted
# 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, ListItem):
tag = ":"
if isinstance(e, Link):
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 len(e.content) == 1 and isinstance(e.content[0], Para):
return f'\\fn{{{tex(e.content[0].content, 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, 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