|
|
@ -11,10 +11,14 @@ from .output_generator import OutputGenerator |
|
|
|
from .images import ImageProcessor, ImageProcessorNamespaceSearcher |
|
|
|
|
|
|
|
from .whitespace import NBSP |
|
|
|
from .elements import FQuoted |
|
|
|
from .elements import FQuoted, FLineMarkup |
|
|
|
from .context import Group, InlineGroup, BlockGroup, Context |
|
|
|
from .util import inlinify |
|
|
|
|
|
|
|
def color_to_rgb(color): |
|
|
|
import matplotlib.colors |
|
|
|
return matplotlib.colors.to_rgb(color) |
|
|
|
|
|
|
|
class UCWTexGenerator(OutputGenerator): |
|
|
|
imageProcessor: ImageProcessor |
|
|
|
_bold: int |
|
|
@ -24,22 +28,30 @@ class UCWTexGenerator(OutputGenerator): |
|
|
|
self.imageProcessor = imageProcessor |
|
|
|
self._bold = 0 |
|
|
|
self._italic = 0 |
|
|
|
|
|
|
|
self._floatpages = {} |
|
|
|
super().__init__(output_file, *args, **kwargs) |
|
|
|
|
|
|
|
def escape_special_chars(self, text: str) -> str: |
|
|
|
text = text.replace("&", r"\&") |
|
|
|
text = text.replace("%", r"\%") |
|
|
|
text = text.replace("$", r"\$") |
|
|
|
text = text.replace("#", r"\#") |
|
|
|
text = text.replace("_", r"\_") |
|
|
|
text = text.replace("{", r"\{") |
|
|
|
text = text.replace("}", r"\}") |
|
|
|
text = text.replace("~", r"\textasciitilde{}") |
|
|
|
text = text.replace("^", r"\textasciicircum{}") |
|
|
|
text = text.replace("\\", r"\textbackslash{}") |
|
|
|
text = text.replace(" ", "~") # We use unicode no-break spaces to force nbsp in output |
|
|
|
text = text.replace("", "") |
|
|
|
return text |
|
|
|
if '\\' in text: |
|
|
|
print("ESCAPE", text) |
|
|
|
out = "" |
|
|
|
for char in text: |
|
|
|
out += { |
|
|
|
'&': r"\&", |
|
|
|
'%': r"\%", |
|
|
|
'$': r"\$", |
|
|
|
'#': r"\#", |
|
|
|
'_': r"\_", |
|
|
|
'{': r"\{", |
|
|
|
'}': r"\}", |
|
|
|
'~': r"\textasciitilde{}", |
|
|
|
'^': r"\textasciicircum{}", |
|
|
|
'\\': r"\textbackslash{}", |
|
|
|
' ': r"~", |
|
|
|
'': r"", |
|
|
|
}.get(char, char) |
|
|
|
return out |
|
|
|
|
|
|
|
def generate(self, e: Union[Element, ListContainer]): |
|
|
|
if hasattr(e, "attributes") and "only" in e.attributes and e.attributes["only"] != "tex": |
|
|
@ -67,21 +79,17 @@ class UCWTexGenerator(OutputGenerator): |
|
|
|
self.writepar(r"\vskip5pt\hrule\hfil\vskip5pt{}") |
|
|
|
|
|
|
|
def generate_Doc(self, e: Doc): |
|
|
|
self.writeln(r"\input ucwmac2.tex") |
|
|
|
self.writeln(r"\ucwmodule{ofs}") |
|
|
|
self.writeln(r"\ucwmodule{verb}") |
|
|
|
self.writeln(r"\ucwmodule{link}") |
|
|
|
self.writeln(r"\input formatitko.tex") |
|
|
|
self.generate(e.content) |
|
|
|
self.writeln(r"\bye") |
|
|
|
|
|
|
|
def get_language_macro(self, lang: str): |
|
|
|
if lang == "cs": |
|
|
|
return r"\chyph\lefthyphenmin=2\righthyphenmin=2{}" |
|
|
|
return r"\uselanguage{czech}\frenchspacing\lefthyphenmin=2\righthyphenmin=2{}" |
|
|
|
elif lang == "sk": |
|
|
|
return r"\shyph\lefthyphenmin=2\righthyphenmin=2{}" |
|
|
|
return r"\uselanguage{slovak}\frenchspacing\lefthyphenmin=2\righthyphenmin=2{}" |
|
|
|
elif lang == "en": |
|
|
|
return r"\ehyph\lefthyphenmin=2\righthyphenmin=2{}" |
|
|
|
return r"\uselanguage{USenglish}\nonfrenchspacing\lefthyphenmin=2\righthyphenmin=2{}" |
|
|
|
else: |
|
|
|
return "" |
|
|
|
|
|
|
@ -101,7 +109,7 @@ class UCWTexGenerator(OutputGenerator): |
|
|
|
|
|
|
|
def generate_Header(self, e: Header): |
|
|
|
self.ensure_empty(2) |
|
|
|
self.write("\\"+"sub"*(e.level-1)+"section{") |
|
|
|
self.write("\\"+"sub"*(e.level-1)+"section{"+".".join(map(str, e.attributes["number"]))+"}{") |
|
|
|
self.generate(e.content) |
|
|
|
self.write(r"}") |
|
|
|
self.ensure_empty(2) |
|
|
@ -147,31 +155,58 @@ class UCWTexGenerator(OutputGenerator): |
|
|
|
width = str(int(e.attributes["width"][:-1])/100) + "\\hsize" |
|
|
|
width = "width " + width |
|
|
|
|
|
|
|
if isinstance(e.parent.parent, Figure): |
|
|
|
self.writeln(f'\\putimage{{{width}}}{{{url}}}') |
|
|
|
else: |
|
|
|
self.writepar(f'\\putimage{{{width}}}{{{url}}}') |
|
|
|
self.writeln(f'\\centerline{{\\putimage{{{width}}}{{{url}}}}}') |
|
|
|
|
|
|
|
def generate_Code(self, e: Code): |
|
|
|
self.write(r"\verb`") |
|
|
|
self.write(e.text) |
|
|
|
self.write(r"`") |
|
|
|
|
|
|
|
def generate_Figure(self, e: Figure): |
|
|
|
self.ensure_empty(2) |
|
|
|
self.writeln(r"\vskip5pt") |
|
|
|
self.writeln(r"\centerline{") |
|
|
|
def generate_nonfloat_Figure(self, e: Figure): |
|
|
|
self.writeln(r"\figure{") |
|
|
|
self.indent_more() |
|
|
|
self.generate(e.content) |
|
|
|
self.indent_less() |
|
|
|
self.writeln(r"}") |
|
|
|
self.writeln(r"\centerline{") |
|
|
|
self.writeln(r"}{") |
|
|
|
self.indent_more() |
|
|
|
if 'number' in e.attributes: |
|
|
|
type_text = e.attributes.get("type_text", "Obrázek") |
|
|
|
self.writeln(f"{type_text} {e.attributes['number']}:") |
|
|
|
self.generate(e.caption) |
|
|
|
if 'number' in e.attributes: |
|
|
|
tocmac = e.attributes.get("tocmac", "tocpicture") |
|
|
|
if tocmac: |
|
|
|
self.writeln("\\addtoc\\"+tocmac+r"{"+str(e.attributes['number'])+"}{}{") |
|
|
|
self.indent_more() |
|
|
|
self.generate(e.caption.content) |
|
|
|
self.indent_less() |
|
|
|
self.writeln("}") |
|
|
|
self.indent_less() |
|
|
|
self.writeln(r"}") |
|
|
|
self.writeln(r"\vskip5pt{}") |
|
|
|
self.ensure_empty(2) |
|
|
|
self.writeln(r"}{}{}") |
|
|
|
|
|
|
|
|
|
|
|
def generate_Figure(self, e: Figure): |
|
|
|
if "floatpage" in e.attributes: |
|
|
|
fp = e.attributes["floatpage"] |
|
|
|
flush = fp[-1]=="!" |
|
|
|
if flush: |
|
|
|
fp = fp[:-1] |
|
|
|
self._floatpages.setdefault(fp, []) |
|
|
|
self._floatpages[fp].append(e) |
|
|
|
if flush: |
|
|
|
self.writeln(r"\floatpage{") |
|
|
|
self.writeln(r"\vfill") |
|
|
|
for x in self._floatpages[fp]: |
|
|
|
self.generate_nonfloat_Figure(x) |
|
|
|
self.writeln(r"\vfill") |
|
|
|
self.writeln(r"}") |
|
|
|
del self._floatpages[fp] |
|
|
|
else: |
|
|
|
self.ensure_empty(2) |
|
|
|
self.writeln(r"\floatinsert{") |
|
|
|
self.generate_nonfloat_Figure(e) |
|
|
|
self.writeln(r"}") |
|
|
|
self.ensure_empty(2) |
|
|
|
|
|
|
|
def generate_Emph(self, e: Emph): |
|
|
|
if self._bold > 0: |
|
|
@ -183,6 +218,11 @@ class UCWTexGenerator(OutputGenerator): |
|
|
|
self._italic-=1 |
|
|
|
self.write(r"}") |
|
|
|
|
|
|
|
def generate_Slanted(self, e: Emph): |
|
|
|
self.write(r"{\sl{}") |
|
|
|
self.generate(e.content) |
|
|
|
self.write(r"}") |
|
|
|
|
|
|
|
def generate_Strong(self, e: Strong): |
|
|
|
if self._italic > 0: |
|
|
|
self.write(r"{\bi{}") |
|
|
@ -194,15 +234,15 @@ class UCWTexGenerator(OutputGenerator): |
|
|
|
self.write(r"}") |
|
|
|
|
|
|
|
def generate_Caption(self, e: Caption): |
|
|
|
self.generate_Emph(e) |
|
|
|
self.generate(e.content) |
|
|
|
|
|
|
|
def generate_Math(self, e: Math): |
|
|
|
if e.format == "DisplayMath": |
|
|
|
self.ensure_empty(2) |
|
|
|
self.ensure_empty(1) |
|
|
|
self.writeraw("$$") |
|
|
|
self.writeraw(e.text.strip()) |
|
|
|
self.writeraw("$$") |
|
|
|
self.ensure_empty(2) |
|
|
|
self.ensure_empty(1) |
|
|
|
else: |
|
|
|
self.write("$") |
|
|
|
self.write(e.text) |
|
|
@ -214,22 +254,23 @@ class UCWTexGenerator(OutputGenerator): |
|
|
|
self.write(r"}") |
|
|
|
|
|
|
|
def generate_Table(self, e: Table): |
|
|
|
hskip = r"\hskip 0.6em\relax" |
|
|
|
aligns = { |
|
|
|
"AlignLeft": r"\quad#\quad\hfil", |
|
|
|
"AlignRight": r"\quad\hfil#\quad", |
|
|
|
"AlignCenter": r"\quad\hfil#\hfil\quad", |
|
|
|
"AlignDefault": r"\quad#\quad\hfil" |
|
|
|
"AlignLeft": hskip+r"\relax#\hfil"+hskip, |
|
|
|
"AlignRight": hskip+r"\hfil#"+hskip, |
|
|
|
"AlignCenter": hskip+r"\hfil#\hfil"+hskip, |
|
|
|
"AlignDefault": hskip+r"#\hfil"+hskip, |
|
|
|
} |
|
|
|
self.writeln(r"\vskip1em") |
|
|
|
self.writeln(r"\halign{\strut"+"&".join([aligns[col[0]] for col in e.colspec])+r"\cr") |
|
|
|
self.writeln(r"\leavevmode\vbox{\halign{\strut"+"&".join([aligns[col[0]] for col in e.colspec])+r"\cr") |
|
|
|
self.indent_more() |
|
|
|
self.generate(e.head.content) |
|
|
|
self.writeln(r"\noalign{\hrule}") |
|
|
|
self.writeln(r"\noalign{\vskip 0.3em\hrule\vskip 0.3em}") |
|
|
|
self.generate(e.content[0].content) |
|
|
|
self.writeln(r"\noalign{\hrule}") |
|
|
|
self.writeln(r"\noalign{\vskip 0.3em\hrule\vskip 0.3em}") |
|
|
|
self.generate(e.foot.content) |
|
|
|
self.indent_less() |
|
|
|
self.writeln("}") |
|
|
|
self.writeln("}}") |
|
|
|
self.writeln(r"\vskip1em") |
|
|
|
|
|
|
|
def generate_TableRow(self, e: TableRow): |
|
|
@ -263,6 +304,16 @@ class UCWTexGenerator(OutputGenerator): |
|
|
|
|
|
|
|
def generate_Div(self, e: Div): |
|
|
|
self.generate(e.content) |
|
|
|
|
|
|
|
def generate_FLineMarkup(self, e: FLineMarkup): |
|
|
|
self.ensure_empty(2) |
|
|
|
r,g,b = color_to_rgb(e.color) |
|
|
|
self.writeln(r"\linemarkup{\rgb{"+f"{r} {g} {b}"+"}}{") |
|
|
|
self.indent_more() |
|
|
|
self.generate(e.content) |
|
|
|
self.indent_less() |
|
|
|
self.writeln(r"}") |
|
|
|
self.ensure_empty(2) |
|
|
|
|
|
|
|
def generate_LineBlock(self, e: LineBlock): |
|
|
|
self.writeln() |
|
|
@ -323,6 +374,11 @@ class UCWTexGenerator(OutputGenerator): |
|
|
|
self.writeln(r"}") |
|
|
|
|
|
|
|
def generate_Link(self, e: Link): |
|
|
|
if len(e.content) == 0: |
|
|
|
if e.url.startswith('#'): |
|
|
|
obj = e.obj_map[e.url[1:]] |
|
|
|
self.write(str(obj.attributes["number"])) |
|
|
|
return |
|
|
|
if len(e.content) == 1 and isinstance(e.content[0], Str) and e.content[0].text == e.url: |
|
|
|
self.write(r"\url{") |
|
|
|
else: |
|
|
@ -348,7 +404,7 @@ class UCWTexGenerator(OutputGenerator): |
|
|
|
self.writeln("% FIXME: Citations not implemented") |
|
|
|
|
|
|
|
def generate_Cite(self, e: Cite): |
|
|
|
self.writeln("% FIXME: Cites not implemented") |
|
|
|
self.generate(e.content) |
|
|
|
|
|
|
|
def generate_Definition(self, e: Definition): |
|
|
|
self.writeln("% FIXME: Definitions not implemented") |
|
|
@ -364,3 +420,8 @@ class UCWTexGenerator(OutputGenerator): |
|
|
|
|
|
|
|
def generate_Strikeout(self, e: Strikeout): |
|
|
|
self.writeln("% FIXME: Strikeouts not implemented") |
|
|
|
|
|
|
|
def generate_SmallCaps(self, e: Strikeout): |
|
|
|
self.write(r"{\csc{}") |
|
|
|
self.generate(e.content) |
|
|
|
self.write(r"}") |
|
|
|