@ -1,18 +1,20 @@
from panflute import *
from panflute import *
import os
from whitespace import NBSP
from whitespace import NBSP
from transform import FQuoted
from transform import FQuoted
from util import inlinify
from util import inlinify
from group import Group
from group import Group
from images import ImageProcessor
# Heavily inspired by: git://git.ucw.cz/labsconf2022.git
# Heavily inspired by: git://git.ucw.cz/labsconf2022.git
def tex ( e , indent_level : int = 0 , indent_str : str = " \t " ) - > str :
def tex ( e : Element , i : ImageProcessor , indent_level : int = 0 , indent_str : str = " \t " ) - > str :
if hasattr ( e , " attributes " ) and " only " in e . attributes and e . attributes [ " only " ] != " tex " :
if hasattr ( e , " attributes " ) and " only " in e . attributes and e . attributes [ " only " ] != " tex " :
return " "
return " "
if isinstance ( e , ListContainer ) :
if isinstance ( e , ListContainer ) :
return ' ' . join ( [ tex ( child , indent_level , indent_str ) for child in e ] )
return ' ' . join ( [ tex ( child , i , i ndent_level, indent_str ) for child in e ] )
content_foot = " "
content_foot = " "
content_head = " "
content_head = " "
@ -55,26 +57,26 @@ def tex(e, indent_level: int=0, indent_str: str="\t") -> str:
return e . text . replace ( " " , " ~ " ) . replace ( " " , " ~ " )
return e . text . replace ( " " , " ~ " ) . replace ( " " , " ~ " )
if isinstance ( e , Para ) :
if isinstance ( e , Para ) :
return tex ( e . content , 0 , " " ) + " \n \n "
return tex ( e . content , i , 0 , " " ) + " \n \n "
if isinstance ( e , FQuoted ) :
if isinstance ( e , FQuoted ) :
if e . style == " cs " :
if e . style == " cs " :
if e . quote_type == " SingleQuote " :
if e . quote_type == " SingleQuote " :
return f ' ‚ { tex ( e . content , 0 , " " ) } ‘ '
return f ' ‚ { tex ( e . content , i , 0 , " " ) } ‘ '
elif e . quote_type == " DoubleQuote " :
elif e . quote_type == " DoubleQuote " :
return f ' „ { tex ( e . content , 0 , " " ) } “ '
return f ' „ { tex ( e . content , i , 0 , " " ) } “ '
elif e . style == " en " :
elif e . style == " en " :
if e . quote_type == " SingleQuote " :
if e . quote_type == " SingleQuote " :
return f ' ‘ { tex ( e . content , 0 , " " ) } ’ '
return f ' ‘ { tex ( e . content , i , 0 , " " ) } ’ '
elif e . quote_type == " DoubleQuote " :
elif e . quote_type == " DoubleQuote " :
return f ' “ { tex ( e . content , 0 , " " ) } ” '
return f ' “ { tex ( e . content , i , 0 , " " ) } ” '
else :
else :
if e . quote_type == " SingleQuote " :
if e . quote_type == " SingleQuote " :
return f ' \' { tex ( e . content , 0 , " " ) } \' '
return f ' \' { tex ( e . content , i , 0 , " " ) } \' '
elif e . quote_type == " DoubleQuote " :
elif e . quote_type == " DoubleQuote " :
return f ' " { tex ( e . content , 0 , " " ) } " '
return f ' " { tex ( e . content , i , 0 , " " ) } " '
else :
else :
return f ' " { tex ( e . content , 0 , " " ) } " '
return f ' " { tex ( e . content , i , 0 , " " ) } " '
if isinstance ( e , BulletList ) :
if isinstance ( e , BulletList ) :
tag = " list "
tag = " list "
@ -106,14 +108,33 @@ def tex(e, indent_level: int=0, indent_str: str="\t") -> str:
# FIXME: Starting number of list
# FIXME: Starting number of list
if isinstance ( e , Image ) :
if isinstance ( e , Image ) :
return f ' \\ image {{ width { e . attributes [ " width " ] if " width " in e . attributes else " " } }} {{ { e . url } }} '
url = e . url
_ , ext = os . path . splitext ( url )
ext = ext [ 1 : ]
if ext in [ " pdf " , " png " , " jpeg " ] :
url = i . process_image ( url , ext , relative = False )
elif ext in [ " svg " ] :
url = i . process_image ( url , " pdf " , relative = False )
elif ext in [ " epdf " ] :
url = i . process_image ( url , " pdf " , relative = False )
elif ext in [ " jpg " ] :
url = i . process_image ( url , " jpeg " , relative = False )
else :
url = i . process_image ( url , " pdf " , relative = False )
width = " "
if " width " in e . attributes :
width = e . attributes [ " width " ]
if e . attributes [ " width " ] [ - 1 ] == " % " :
width = str ( int ( e . attributes [ " width " ] [ : - 1 ] ) / 100 ) + " \\ hsize "
width = " width " + width
return f ' \\ image {{ { width } }} {{ { url } }} '
if isinstance ( e , Figure ) :
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 '
return f ' \\ figure {{ { tex ( e . content , i , i ndent_level+ 1 , indent_str ) } }} {{ { tex ( e . caption , i , indent_level + 1 , indent_str ) } }} \n \n '
if isinstance ( e , Caption ) :
if isinstance ( e , Caption ) :
if inlinify ( e ) is not None :
if inlinify ( e ) is not None :
return f ' \\ caption {{ { tex ( e . content , 0 , " " ) } }} '
return f ' \\ caption {{ { tex ( e . content , i , 0 , " " ) } }} '
if isinstance ( e , ListItem ) :
if isinstance ( e , ListItem ) :
tag = " : "
tag = " : "
@ -134,7 +155,7 @@ def tex(e, indent_level: int=0, indent_str: str="\t") -> str:
if isinstance ( e , Note ) :
if isinstance ( e , Note ) :
tag = " fn "
tag = " fn "
if inlinify ( e ) is not None :
if inlinify ( e ) is not None :
return f ' \\ fn {{ { tex ( inlinify ( e ) , 0 , " " ) } }} '
return f ' \\ fn {{ { tex ( inlinify ( e ) , i , 0 , " " ) } }} '
if isinstance ( e , Table ) :
if isinstance ( e , Table ) :
aligns = {
aligns = {
@ -144,16 +165,16 @@ def tex(e, indent_level: int=0, indent_str: str="\t") -> str:
" AlignDefault " : " \\ quad# \\ quad \\ hfil "
" AlignDefault " : " \\ quad# \\ quad \\ hfil "
}
}
text = " \ strut " + " & " . join ( [ aligns [ col [ 0 ] ] for col in e . colspec ] ) + " \ cr \n "
text = " \ strut " + " & " . join ( [ aligns [ col [ 0 ] ] for col in e . colspec ] ) + " \ cr \n "
text + = tex ( e . head . content , 0 , " " )
text + = tex ( e . head . content , i , 0 , " " )
text + = " \\ noalign { \\ hrule} \n "
text + = " \\ noalign { \\ hrule} \n "
text + = tex ( e . content [ 0 ] . content , 0 , " " )
text + = tex ( e . content [ 0 ] . content , i , 0 , " " )
text + = " \\ noalign { \\ hrule} \n "
text + = " \\ noalign { \\ hrule} \n "
text + = tex ( e . foot . content , 0 , " " )
text + = tex ( e . foot . content , i , 0 , " " )
return " \\ vskip1em \n \\ halign { " + text + " } \n \\ vskip1em \n "
return " \\ vskip1em \n \\ halign { " + text + " } \n \\ vskip1em \n "
# FIXME: Implement rowspan
# FIXME: Implement rowspan
if isinstance ( e , TableRow ) :
if isinstance ( e , TableRow ) :
return " & " . join ( [ ( " \\ multispan " + str ( cell . colspan ) + " " if cell . colspan > 1 else " " ) + tex ( cell . content , 0 , " " ) for cell in e . content ] ) + " \ cr \n "
return " & " . join ( [ ( " \\ multispan " + str ( cell . colspan ) + " " if cell . colspan > 1 else " " ) + tex ( cell . content , i , 0 , " " ) for cell in e . content ] ) + " \ cr \n "
if isinstance ( e , RawInline ) :
if isinstance ( e , RawInline ) :
if e . format == " tex " :
if e . format == " tex " :
@ -168,13 +189,13 @@ def tex(e, indent_level: int=0, indent_str: str="\t") -> str:
return " "
return " "
if isinstance ( e , Span ) or isinstance ( e , Plain ) :
if isinstance ( e , Span ) or isinstance ( e , Plain ) :
return tex ( e . content , 0 , " " )
return tex ( e . content , i , 0 , " " )
if isinstance ( e , LineItem ) :
if isinstance ( e , LineItem ) :
return tex ( e . content , 0 , " " ) + ( " \\ \\ \n " if e . next else " \n " )
return tex ( e . content , i , 0 , " " ) + ( " \\ \\ \n " if e . next else " \n " )
if isinstance ( e , LineBlock ) :
if isinstance ( e , LineBlock ) :
return f ' { tex ( e . content , indent_level + 1 , indent_str ) } \n '
return f ' { tex ( e . content , i , i ndent_level+ 1 , indent_str ) } \n '
if isinstance ( e , Group ) :
if isinstance ( e , Group ) :
tag = " begingroup "
tag = " begingroup "
@ -184,19 +205,19 @@ def tex(e, indent_level: int=0, indent_str: str="\t") -> str:
close = " \\ endgroup "
close = " \\ endgroup "
if isinstance ( e , Div ) :
if isinstance ( e , Div ) :
return f ' { tex ( e . content , indent_level + 1 , indent_str ) } '
return f ' { tex ( e . content , i , i ndent_level+ 1 , indent_str ) } '
if isinstance ( e , Doc ) :
if isinstance ( e , Doc ) :
return tex ( e . content , indent_level , indent_str ) + " \n \\ bye "
return tex ( e . content , i , i ndent_level, indent_str ) + " \n \\ bye "
if isinstance ( e , Inline ) :
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 } '
return f ' \\ { tag } { arguments } { open } { content_head } { tex ( e . content , i , 0 , " " ) if hasattr ( e , " _content " ) else " " } { e . text if hasattr ( e , " text " ) else " " } { content_foot } { close } '
out_str = " "
out_str = " "
out_str = f " \\ { tag } { arguments } { open } \n "
out_str = f " \\ { tag } { arguments } { open } \n "
out_str + = content_head
out_str + = content_head
if hasattr ( e , " _content " ) :
if hasattr ( e , " _content " ) :
out_str + = tex ( e . content , indent_level + 1 , indent_str )
out_str + = tex ( e . content , i , i ndent_level+ 1 , indent_str )
if hasattr ( e , " text " ) :
if hasattr ( e , " text " ) :
out_str + = e . text
out_str + = e . text
out_str + = f " { content_foot } \n { close } \n \n "
out_str + = f " { content_foot } \n { close } \n \n "