@ -3,18 +3,31 @@ from panflute import Cite, Code, Emph, Image, LineBreak, Link, Math, Note, Quote
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 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 panflute import TableRow , TableCell , Caption , Doc
from panflute import MetaValue
from panflute import MetaValue
from panflute import stringify
from typing import Union , Callable
from typing import Union , Callable
from . whitespace import NBSP
from . whitespace import NBSP
from . elements import FQuoted
from . elements import FQuoted
from . context import Group , InlineGroup , BlockGroup , Context
from . context import Group , InlineGroup , BlockGroup , Context
import re
import re , sys
class UnknownElementError ( Exception ) :
class UnknownElementError ( Exception ) :
" An unknown Element has been passed to the OutputGenerator, probably because panflute introduced a new one. "
" An unknown Element has been passed to the OutputGenerator, probably because panflute introduced a new one. "
pass
pass
class OutputGeneratorError ( Exception ) :
" A generic exception which wraps other exceptions and adds element-based traceback "
elements : list [ Union [ Element , ListContainer , list [ Union [ Element , ListContainer ] ] ] ]
def __init__ ( self , e : Union [ Element , ListContainer , list [ Union [ Element , ListContainer ] ] ] , * args ) :
self . elements = [ e ]
super ( ) . __init__ ( args )
def add_element ( self , e : Union [ Element , ListContainer , list [ Union [ Element , ListContainer ] ] ] ) :
self . elements . append ( e )
class OutputGenerator :
class OutputGenerator :
_empty_lines : int
_empty_lines : int
context : Union [ Context , None ]
context : Union [ Context , None ]
@ -101,28 +114,53 @@ class OutputGenerator:
}
}
def generate ( self , e : Union [ Element , ListContainer , list [ Union [ Element , ListContainer ] ] ] ) :
def generate ( self , e : Union [ Element , ListContainer , list [ Union [ Element , ListContainer ] ] ] ) :
if isinstance ( e , Group ) :
try :
old_context = self . context
self . _generate ( e )
self . context = e . context
except OutputGeneratorError as err :
if isinstance ( e , list ) :
def eprint ( * args , * * kwargs ) :
self . generate_list ( e )
print ( * args , file = sys . stderr , * * kwargs )
elif isinstance ( e , ListContainer ) :
eprint ( " Error occured in " , end = " " )
self . generate_ListContainer ( e )
for i in range ( len ( err . elements ) - 1 , 0 , - 1 ) :
elif isinstance ( e , Inline ) :
if hasattr ( err . elements [ i ] , " content " ) and isinstance ( err . elements [ i ] . content [ 0 ] , Inline ) :
self . generate_Inline ( e )
eprint ( )
elif isinstance ( e , Block ) :
eprint ( ' on line: " ' + stringify ( err . elements [ i ] ) + ' " ' , end = " " )
self . generate_Block ( e )
break
elif isinstance ( e , MetaValue ) :
eprint ( type ( err . elements [ i ] ) . __name__ + " [ " + str ( err . elements [ i - 1 ] . index ) + " ] " , end = " : " )
self . generate_MetaValue ( e )
eprint ( )
elif isinstance ( e , MetaList ) :
eprint ( " in element: " + str ( err . elements [ 0 ] ) )
self . generate_MetaList ( e )
sys . tracebacklimit = 0
else :
raise err . __cause__ from None
try :
self . TYPE_DICT_MISC [ type ( e ) ] ( e )
def _generate ( self , e : Union [ Element , ListContainer , list [ Union [ Element , ListContainer ] ] ] ) :
except KeyError :
try :
raise UnknownElementError ( type ( e ) )
if isinstance ( e , Group ) :
if isinstance ( e , Group ) :
old_context = self . context
self . context = old_context
self . context = e . context
if isinstance ( e , list ) :
self . generate_list ( e )
elif isinstance ( e , ListContainer ) :
self . generate_ListContainer ( e )
elif isinstance ( e , Inline ) :
self . generate_Inline ( e )
elif isinstance ( e , Block ) :
self . generate_Block ( e )
elif isinstance ( e , MetaValue ) :
self . generate_MetaValue ( e )
elif isinstance ( e , MetaList ) :
self . generate_MetaList ( e )
else :
try :
self . TYPE_DICT_MISC [ type ( e ) ] ( e )
except KeyError as err :
raise UnknownElementError ( type ( e ) ) from err
if isinstance ( e , Group ) :
self . context = old_context
except OutputGeneratorError as err :
if not isinstance ( e , ListContainer ) :
err . add_element ( e )
raise err
except Exception as err :
raise OutputGeneratorError ( e ) from err
def escape_special_chars ( self , text : str ) - > str :
def escape_special_chars ( self , text : str ) - > str :
return text
return text
@ -210,13 +248,13 @@ class OutputGenerator:
def generate_simple_inline_tag ( self , tag : str , content : Union [ ListContainer , Element , list [ Union [ Element , ListContainer ] ] ] , attributes : dict [ str , str ] = { } ) :
def generate_simple_inline_tag ( self , tag : str , content : Union [ ListContainer , Element , list [ Union [ Element , ListContainer ] ] ] , attributes : dict [ str , str ] = { } ) :
self . write ( self . start_tag ( tag , attributes ) )
self . write ( self . start_tag ( tag , attributes ) )
self . generate ( content )
self . _ generate( content )
self . write ( self . end_tag ( tag ) )
self . write ( self . end_tag ( tag ) )
def generate_simple_block_tag ( self , tag : str , content : Union [ ListContainer , Element , list [ Union [ Element , ListContainer ] ] ] , attributes : dict [ str , str ] = { } ) :
def generate_simple_block_tag ( self , tag : str , content : Union [ ListContainer , Element , list [ Union [ Element , ListContainer ] ] ] , attributes : dict [ str , str ] = { } ) :
self . writeln ( self . start_tag ( tag , attributes ) )
self . writeln ( self . start_tag ( tag , attributes ) )
self . indent_more ( )
self . indent_more ( )
self . generate ( content )
self . _ generate( content )
self . indent_less ( )
self . indent_less ( )
self . writeln ( self . end_tag ( tag ) )
self . writeln ( self . end_tag ( tag ) )
@ -235,27 +273,27 @@ class OutputGenerator:
def generate_ListContainer ( self , e : ListContainer ) :
def generate_ListContainer ( self , e : ListContainer ) :
for child in e :
for child in e :
self . generate ( child )
self . _ generate( child )
def generate_list ( self , e : list ) :
def generate_list ( self , e : list ) :
for el in e :
for el in e :
self . generate ( el )
self . _ generate( el )
def generate_MetaList ( self , e : MetaList ) :
def generate_MetaList ( self , e : MetaList ) :
for child in e :
for child in e :
self . generate ( child )
self . _ generate( child )
def generate_MetaValue ( self , e : MetaValue ) :
def generate_MetaValue ( self , e : MetaValue ) :
try :
try :
self . TYPE_DICT_META [ type ( e ) ] ( e )
self . TYPE_DICT_META [ type ( e ) ] ( e )
except KeyError :
except KeyError :
self . generate ( e . content )
self . _ generate( e . content )
def generate_MetaBlocks ( self , e : MetaBlocks ) :
def generate_MetaBlocks ( self , e : MetaBlocks ) :
self . generate ( e . content )
self . _ generate( e . content )
def generate_MetaInlines ( self , e : MetaInlines ) :
def generate_MetaInlines ( self , e : MetaInlines ) :
self . generate ( e . content )
self . _ generate( e . content )
def generate_MetaBool ( self , e : MetaBool ) :
def generate_MetaBool ( self , e : MetaBool ) :
self . generate_simple_tag ( e )
self . generate_simple_tag ( e )
@ -285,33 +323,33 @@ class OutputGenerator:
if e . style == " cs " :
if e . style == " cs " :
if e . quote_type == " SingleQuote " :
if e . quote_type == " SingleQuote " :
self . write ( " ‚ " )
self . write ( " ‚ " )
self . generate ( e . content )
self . _ generate( e . content )
self . write ( " ‘ " )
self . write ( " ‘ " )
elif e . quote_type == " DoubleQuote " :
elif e . quote_type == " DoubleQuote " :
self . write ( " „ " )
self . write ( " „ " )
self . generate ( e . content )
self . _ generate( e . content )
self . write ( " “ " )
self . write ( " “ " )
elif e . style == " en " :
elif e . style == " en " :
if e . quote_type == " SingleQuote " :
if e . quote_type == " SingleQuote " :
self . write ( " ‘ " )
self . write ( " ‘ " )
self . generate ( e . content )
self . _ generate( e . content )
self . write ( " ’ " )
self . write ( " ’ " )
elif e . quote_type == " DoubleQuote " :
elif e . quote_type == " DoubleQuote " :
self . write ( " “ " )
self . write ( " “ " )
self . generate ( e . content )
self . _ generate( e . content )
self . write ( " ” " )
self . write ( " ” " )
else :
else :
if e . quote_type == " SingleQuote " :
if e . quote_type == " SingleQuote " :
self . write ( " ' " )
self . write ( " ' " )
self . generate ( e . content )
self . _ generate( e . content )
self . write ( " ' " )
self . write ( " ' " )
elif e . quote_type == " DoubleQuote " :
elif e . quote_type == " DoubleQuote " :
self . write ( " \" " )
self . write ( " \" " )
self . generate ( e . content )
self . _ generate( e . content )
self . write ( " \" " )
self . write ( " \" " )
else :
else :
self . write ( " \" " )
self . write ( " \" " )
self . generate ( e . content )
self . _ generate( e . content )
self . write ( " \" " )
self . write ( " \" " )
@ -434,10 +472,10 @@ class OutputGenerator:
def generate_Doc ( self , e : Doc ) :
def generate_Doc ( self , e : Doc ) :
if " header_content " in e . metadata :
if " header_content " in e . metadata :
self . generate ( e . metadata [ " header_content " ] )
self . _ generate( e . metadata [ " header_content " ] )
self . generate_simple_tag ( e )
self . generate_simple_tag ( e )
if " footer_content " in e . metadata :
if " footer_content " in e . metadata :
self . generate ( e . metadata [ " footer_content " ] )
self . _ generate( e . metadata [ " footer_content " ] )
def generate_BlockGroup ( self , e : BlockGroup ) :
def generate_BlockGroup ( self , e : BlockGroup ) :
self . generate_simple_tag ( e )
self . generate_simple_tag ( e )