from panflute import Element, ListContainer, Inline, Block from panflute import Cite, Code, Emph, Image, LineBreak, Link, Math, Note, Quoted, RawInline, SmallCaps, SoftBreak, Space, Span, Str, Strikeout, Strong, Subscript, Superscript, Underline 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 typing import Union, Dict from .whitespace import NBSP from .transform import FQuoted from .context import Group class UnknownElementError(Exception): "An unknown Element has been passed to the Output_generator, probably because panflute introduced a new one." pass class OutputGenerator: def __init__(self, output_file, indent_str: str="\t", initial_indent_level: int=0): self.output_file = output_file self.indent_str = indent_str self.indent_level = initial_indent_level self._at_start_of_line = True def indent(self) -> str: return self.indent_str*self.indent_level def iup(self): self.indent_level += 1 def ido(self): self.indent_level -= 1 def write(self, text: str): if self._at_start_of_line: self.output_file.write(self.indent()) self.output_file.write(text) self._at_start_of_line = False def writeln(self, text: str): if not self._at_start_of_line: self.output_file.write("\n") self.output_file.write(self.indent()) self.output_file.write(text+"\n") self._at_start_of_line = True def writeraw(self, text: str): if not self._at_start_of_line: self.output_file.write("\n") self.output_file.write(text+"\n") self._at_start_of_line = True def endln(self): if not self._at_start_of_line: self.output_file.write("\n") self._at_start_of_line = True def stag(self, tag: str, attributes: Dict[str,str]={}) -> str: return tag def etag(self, tag: str, attributes: Dict[str,str]={}) -> str: return "/" + tag def ntag(self, tag: str, attributes: Dict[str,str]={}) -> str: return "/" + tag + "/" def tagname(self, e) -> str: return type(e).__name__ def common_attributes(self, e) -> Dict[str,str]: return {} def generate(self, e: Union[Element, ListContainer]): if isinstance(e, ListContainer): self.generate_ListContainer(e) elif isinstance(e, Inline): self.generate_Inline(e) elif isinstance(e, Block): self.generate_Block(e) else: try: { TableRow: self.generate_TableRow, TableCell: self.generate_TableCell, Caption: self.generate_Caption, Doc: self.generate_Doc, LineItem: self.generate_LineItem, ListItem: self.generate_ListItem }[type(e)](e) except KeyError: raise UnknownElementError(type(e)) def generate_ListContainer(self, e: ListContainer): for child in e: self.generate(child) def generate_Inline(self, e: Inline): { Cite: self.generate_Cite, Code: self.generate_Code, Emph: self.generate_Emph, Image: self.generate_Image, LineBreak: self.generate_LineBreak, Link: self.generate_Link, Math: self.generate_Math, Note: self.generate_Note, Quoted: self.generate_Quoted, RawInline: self.generate_RawInline, SmallCaps: self.generate_SmallCaps, SoftBreak: self.generate_SoftBreak, Space: self.generate_Space, Span: self.generate_Span, Str: self.generate_Str, Strikeout: self.generate_Strikeout, Strong: self.generate_Strong, Subscript: self.generate_Subscript, Superscript: self.generate_Superscript, Underline: self.generate_Underline, NBSP: self.generate_NBSP, FQuoted: self.generate_FQuoted }[type(e)](e) def generate_Str(self, e: Str): self.write(e.text) def generate_Space(self, e: Space): self.write(" ") def generate_NBSP(self, e: NBSP): self.write("~") def generate_SoftBreak(self, e: SoftBreak): self.endln() def generate_FQuoted(self, e: FQuoted): if e.style == "cs": if e.quote_type == "SingleQuote": self.write("‚") self.generate(e.content) self.write("‘") elif e.quote_type == "DoubleQuote": self.write("„") self.generate(e.content) self.write("“") elif e.style == "en": if e.quote_type == "SingleQuote": self.write("‘") self.generate(e.content) self.write("’") elif e.quote_type == "DoubleQuote": self.write("“") self.generate(e.content) self.write("”") else: if e.quote_type == "SingleQuote": self.write("'") self.generate(e.content) self.write("'") elif e.quote_type == "DoubleQuote": self.write("\"") self.generate(e.content) self.write("\"") else: self.write("\"") self.generate(e.content) self.write("\"") def generate_Cite(self, e: Cite): self.generate_simple_inline_tag(e, self.tagname(e), self.common_attributes(e)) def generate_Emph(self, e: Emph): self.generate_simple_inline_tag(e, self.tagname(e), self.common_attributes(e)) def generate_Image(self, e: Image): self.generate_simple_inline_tag(e, self.tagname(e), self.common_attributes(e)) def generate_Link(self, e: Link): self.generate_simple_inline_tag(e, self.tagname(e), self.common_attributes(e)) def generate_Note(self, e: Note): self.generate_simple_inline_tag(e, self.tagname(e), self.common_attributes(e)) def generate_Quoted(self, e: Quoted): self.generate_simple_inline_tag(e, self.tagname(e), self.common_attributes(e)) def generate_SmallCaps(self, e: SmallCaps): self.generate_simple_inline_tag(e, self.tagname(e), self.common_attributes(e)) def generate_Span(self, e: Span): self.generate_simple_inline_tag(e, self.tagname(e), self.common_attributes(e)) def generate_Strikeout(self, e: Strikeout): self.generate_simple_inline_tag(e, self.tagname(e), self.common_attributes(e)) def generate_Strong(self, e: Strong): self.generate_simple_inline_tag(e, self.tagname(e), self.common_attributes(e)) def generate_Subscript(self, e: Subscript): self.generate_simple_inline_tag(e, self.tagname(e), self.common_attributes(e)) def generate_Superscript(self, e: Superscript): self.generate_simple_inline_tag(e, self.tagname(e), self.common_attributes(e)) def generate_Underline(self, e: Underline): self.generate_simple_inline_tag(e, self.tagname(e), self.common_attributes(e)) def generate_simple_inline_tag(self, e, tag: str, attributes: Dict[str,str]={}): self.write(self.stag(tag, attributes)) self.generate(e.content) self.write(self.etag(tag)) def generate_Math(self, e: Math): self.generate_raw_inline_tag(e, self.tagname(e), self.common_attributes(e)) def generate_Code(self, e: Code): self.generate_raw_inline_tag(e, self.tagname(e), self.common_attributes(e)) def generate_RawInline(self, e: RawInline): self.generate_raw_inline_tag(e, self.tagname(e), self.common_attributes(e)) def generate_raw_inline_tag(self, e, tag: str, attributes: Dict[str,str]={}): self.write(self.stag(tag, attributes)) self.write(e.text) self.write(self.etag(tag)) def generate_Block(self, e: Block): { BlockQuote: self.generate_BlockQuote, BulletList: self.generate_BulletList, Citation: self.generate_Citation, CodeBlock: self.generate_CodeBlock, Definition: self.generate_Definition, DefinitionItem: self.generate_DefinitionItem, DefinitionList: self.generate_DefinitionList, Div: self.generate_Div, Figure: self.generate_Figure, Header: self.generate_Header, HorizontalRule: self.generate_HorizontalRule, LineBlock: self.generate_LineBlock, MetaBlocks: self.generate_MetaBlocks, MetaBool: self.generate_MetaBool, MetaInlines: self.generate_MetaInlines, MetaList: self.generate_MetaList, MetaMap: self.generate_MetaMap, MetaString: self.generate_MetaString, Null: self.generate_Null, OrderedList: self.generate_OrderedList, Para: self.generate_Para, Plain: self.generate_Plain, RawBlock: self.generate_RawBlock, Table: self.generate_Table, TableBody: self.generate_TableBody, TableFoot: self.generate_TableFoot, TableHead: self.generate_TableHead, Group: self.generate_Group }[type(e)](e) def generate_BlockQuote(self, e: BlockQuote): self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_BulletList(self, e: BulletList): self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_Citation(self, e: Citation): self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_Definition(self, e: Definition): self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_DefinitionItem(self, e: DefinitionItem): self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_DefinitionList(self, e: DefinitionList): self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_Div(self, e: Div): self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_Header(self, e: Header): self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_LineBlock(self, e: LineBlock): self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_LineItem(self, e: LineItem): self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_ListItem(self, e: ListItem): self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_MetaBlocks(self, e: MetaBlocks): self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_MetaBool(self, e: MetaBool): self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_MetaInlines(self, e: MetaInlines): self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_MetaList(self, e: MetaList): self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_MetaMap(self, e: MetaMap): self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_MetaString(self, e: MetaString): self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_OrderedList(self, e: OrderedList): self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_Para(self, e: Para): self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_Plain(self, e: Plain): self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_Caption(self, e: Caption): self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_TableBody(self, e: TableBody): self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_TableCell(self, e: TableCell): self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_TableFoot(self, e: TableFoot): self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_TableHead(self, e: TableHead): self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_TableRow(self, e: TableRow): self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_Doc(self, e: Doc): self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_Group(self, e: Group): self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_simple_block_tag(self, e, tag: str, attributes: Dict[str,str]={}): self.writeln(self.stag(tag, attributes)) self.iup() self.generate(e.content) self.ido() self.writeln(self.etag(tag)) def generate_Table(self, e: Table): tag = self.tagname(e) self.writeln(self.stag(tag, self.common_attributes(e))) self.iup() self.generate(e.head) self.generate(e.content) self.generate(e.foot) self.ido() self.writeln(self.etag(tag)) def generate_Figure(self, e: Figure): tag = self.tagname(e) self.writeln(self.stag(tag, self.common_attributes(e))) self.iup() self.generate(e.content) self.generate(e.caption) self.ido() self.writeln(self.etag(tag)) def generate_Null(self, e: Null): self.generate_empty_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_HorizontalRule(self, e: HorizontalRule): self.generate_empty_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_LineBreak(self, e: LineBreak): self.generate_empty_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_empty_block_tag(self, e, tag: str, attributes: Dict[str,str]={}): self.writeln(self.ntag(tag, attributes)) def generate_CodeBlock(self, e: CodeBlock): self.generate_raw_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_RawBlock(self, e: RawBlock): self.generate_raw_block_tag(e, self.tagname(e), self.common_attributes(e)) def generate_raw_block_tag(self, e, tag: str, attributes: Dict[str,str]={}): self.writeln(self.stag(tag, attributes)) self.writeraw(e.text) self.writeln(self.etag(tag))