From fe63458a51cb40cd3cf4bebbcd83ffd5185c7d21 Mon Sep 17 00:00:00 2001 From: Greenscreener Date: Thu, 20 Jul 2023 22:15:55 +0200 Subject: [PATCH] =?UTF-8?q?Zm=C4=9Bn=C4=9Bn=20interface=20OutputGeneratoru?= =?UTF-8?q?.=20Viz=20posledn=C3=AD=20koment=C3=A1=C5=99=20v=20#13.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/formatitko/html_generator.py | 14 +- src/formatitko/latex_generator.py | 19 ++- src/formatitko/output_generator.py | 240 ++++++++++++++++------------- 3 files changed, 153 insertions(+), 120 deletions(-) diff --git a/src/formatitko/html_generator.py b/src/formatitko/html_generator.py index 31399f5..bc0535b 100644 --- a/src/formatitko/html_generator.py +++ b/src/formatitko/html_generator.py @@ -99,10 +99,8 @@ class HTMLGenerator(OutputGenerator): def generate_Doc(self, e: Doc): formatter = HtmlFormatter(style=e.get_metadata("highlight-style") if e.get_metadata("highlight-style") is not None else "default") - self.writeln("") - self.generate_simple_block_tag(e, "main", self.common_attributes(e)) + self.generate_simple_tag(tag="style", attributes={}, content=formatter.get_style_defs(".highlight")) + self.generate_simple_tag(e, tag="main") def generate_CodeBlock(self, e: CodeBlock): lexer = None @@ -122,7 +120,7 @@ class HTMLGenerator(OutputGenerator): result = highlight(e.text, lexer, formatter) self.writeraw(result) else: - self.generate_raw_block_tag(e, "pre", self.common_attributes(e)) + self.generate_simple_tag(e, tag="pre") def generate_Image(self, e: Image): url = e.url @@ -243,7 +241,7 @@ class HTMLGenerator(OutputGenerator): attributes["href"] = e.url if e.title: attributes["title"] = e.title - self.generate_simple_inline_tag(e, self.tagname(e), self.common_attributes(e) | attributes) + self.generate_simple_tag(e, attributes=self.common_attributes(e) | attributes) def generate_OrderedList(self, e: OrderedList): attributes = {} @@ -259,7 +257,7 @@ class HTMLGenerator(OutputGenerator): if e.style and e.style != "DefaultStyle": attributes["type"] = html_styles[e.style] # FIXME: Delimeter styles: 1. 1) (1) - self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e) | attributes) + self.generate_simple_tag(e, attributes=self.common_attributes(e) | attributes) def generate_TableCell(self, e: TableCell): attributes = self.common_attributes(e) @@ -274,7 +272,7 @@ class HTMLGenerator(OutputGenerator): } if e.alignment and e.alignment != "AlignDefault": attributes["style"] = attributes.get("style", "")+f"text-align: {aligns[e.alignment]};" - self.generate_simple_block_tag(e, self.tagname(e), attributes) + self.generate_simple_tag(e, attributes=attributes) # These are also disabled in pandoc so they shouldn't appear in the AST at all. def generate_Citation(self, e: Citation): diff --git a/src/formatitko/latex_generator.py b/src/formatitko/latex_generator.py index 34f680c..a6adf85 100644 --- a/src/formatitko/latex_generator.py +++ b/src/formatitko/latex_generator.py @@ -15,7 +15,7 @@ import re class LaTeXGenerator(OutputGenerator): def __init__(self, output_file, imageProcessor: ImageProcessor, *args, **kwargs): self.imageProcessor = imageProcessor - super().__init__(outpout_file, *args, **kwargs) + super().__init__(output_file, *args, **kwargs) def generate(self, e: Union[Element, ListContainer]): if hasattr(e, "attributes") and "only" in e.attributes and e.attributes["only"] != "tex": @@ -45,8 +45,6 @@ class LaTeXGenerator(OutputGenerator): def ntag(self, tag: str, attributes: Dict[str,str]={}) -> str: return "\\" + tag + "{}" - - def generate_NBSP(self, e: NBSP): @@ -61,7 +59,13 @@ class LaTeXGenerator(OutputGenerator): def generate_Para(self, e: Para): self.generate(e) - self.endln() + self.writeln("") # This ensures an empty line + + def generate_Plain(self, e: Plain): + self.generate(e.content) + + def generate_Span(self, e: Plain): + self.generate(e.content) def generate_Header(self, e: Header): tag = { @@ -72,10 +76,15 @@ class LaTeXGenerator(OutputGenerator): 5: "subparagraph", 6: "textbf" } - self.generate_simple_block_tag(e, tag[e.level]) + + self.generate_simple_tag(e, tag=tag[e.level]) def generate_HorizontalRule(self, e: HorizontalRule): self.writeln("\\begin{center}\\rule{0.5\\linewidth}{0.5pt}\\end{center}") + + + + # These are also disabled in pandoc so they shouldn't appear in the AST at all. def generate_Citation(self, e: Citation): diff --git a/src/formatitko/output_generator.py b/src/formatitko/output_generator.py index 7566e02..6f51d72 100644 --- a/src/formatitko/output_generator.py +++ b/src/formatitko/output_generator.py @@ -21,7 +21,27 @@ class OutputGenerator: self.indent_level = initial_indent_level self._at_start_of_line = True - def escape_special_chars(self, text: str) -> str: + 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 escape_special_chars(self, text: str) -> str: return text def indent(self) -> str: @@ -69,28 +89,61 @@ class OutputGenerator: def tagname(self, e) -> str: return type(e).__name__ - def common_attributes(self, e) -> Dict[str,str]: + def common_attributes(self, e: Element) -> 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) + def generate_simple_tag(self, e: Union[Element, None]=None, tag: str="", attributes: Union[Dict[str,str],None]=None, content: Union[ListContainer, Element, str, None]=None, inline: Union[bool, None]=None): + if not tag and e: + tag = self.tagname(e) + if attributes is None and e: + attributes = self.common_attributes(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)) + attributes = {} + if content is None and e and e.content: + content = e.content + if content is None and e and hasattr(e, "text"): + content = e.text + if inline is None and e: + inline = isinstance(e, Inline) + + if content is None: + self.generate_empty_block_tag(tag, attributes) + + if inline: + if isinstance(content, str): + self.generate_raw_inline_tag(tag, content, attributes) + else: + self.generate_simple_inline_tag(tag, content, attributes) + else: + if isinstance(content, str): + self.generate_raw_block_tag(tag, content, attributes) + else: + self.generate_simple_block_tag(tag, content, attributes) + + def generate_simple_inline_tag(self, tag: str, content: Union[ListContainer, Element], attributes: Dict[str,str]={}): + self.write(self.stag(tag, attributes)) + self.generate(content) + self.write(self.etag(tag)) + + def generate_simple_block_tag(self, tag: str, content: Union[ListContainer, Element], attributes: Dict[str,str]={}): + self.writeln(self.stag(tag, attributes)) + self.iup() + self.generate(content) + self.ido() + self.writeln(self.etag(tag)) + + def generate_raw_inline_tag(self, tag: str, text: str, attributes: Dict[str,str]={}): + self.write(self.stag(tag, attributes)) + self.write(text) + self.write(self.etag(tag)) + + def generate_raw_block_tag(self, tag: str, text: str, attributes: Dict[str,str]={}): + self.writeln(self.stag(tag, attributes)) + self.writeraw(text) + self.writeln(self.etag(tag)) + + def generate_empty_block_tag(self, tag: str, attributes: Dict[str,str]={}): + self.writeln(self.ntag(tag, attributes)) def generate_ListContainer(self, e: ListContainer): for child in e: @@ -167,63 +220,58 @@ class OutputGenerator: self.generate(e.content) self.write("\"") + + # Inline Elements def generate_Cite(self, e: Cite): - self.generate_simple_inline_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_Emph(self, e: Emph): - self.generate_simple_inline_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_Image(self, e: Image): - self.generate_simple_inline_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_Link(self, e: Link): - self.generate_simple_inline_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_Note(self, e: Note): - self.generate_simple_inline_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_Quoted(self, e: Quoted): - self.generate_simple_inline_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_SmallCaps(self, e: SmallCaps): - self.generate_simple_inline_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_Span(self, e: Span): - self.generate_simple_inline_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_Strikeout(self, e: Strikeout): - self.generate_simple_inline_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_Strong(self, e: Strong): - self.generate_simple_inline_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_Subscript(self, e: Subscript): - self.generate_simple_inline_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_Superscript(self, e: Superscript): - self.generate_simple_inline_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_Underline(self, e: Underline): - self.generate_simple_inline_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(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)) + # Raw Inline elements def generate_Math(self, e: Math): - self.generate_raw_inline_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_Code(self, e: Code): - self.generate_raw_inline_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_RawInline(self, e: RawInline): - self.generate_raw_inline_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(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): { @@ -257,139 +305,117 @@ class OutputGenerator: Group: self.generate_Group }[type(e)](e) + + # Block elements def generate_BlockQuote(self, e: BlockQuote): - self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_BulletList(self, e: BulletList): - self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_Citation(self, e: Citation): - self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_Definition(self, e: Definition): - self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_DefinitionItem(self, e: DefinitionItem): - self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_DefinitionList(self, e: DefinitionList): - self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_Div(self, e: Div): - self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_Header(self, e: Header): - self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_LineBlock(self, e: LineBlock): - self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_LineItem(self, e: LineItem): - self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_ListItem(self, e: ListItem): - self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_MetaBlocks(self, e: MetaBlocks): - self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_MetaBool(self, e: MetaBool): - self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_MetaInlines(self, e: MetaInlines): - self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_MetaList(self, e: MetaList): - self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_MetaMap(self, e: MetaMap): - self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_MetaString(self, e: MetaString): - self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_OrderedList(self, e: OrderedList): - self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_Para(self, e: Para): - self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_Plain(self, e: Plain): - self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_Caption(self, e: Caption): - self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_TableBody(self, e: TableBody): - self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_TableCell(self, e: TableCell): - self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_TableFoot(self, e: TableFoot): - self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_TableHead(self, e: TableHead): - self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_TableRow(self, e: TableRow): - self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_Doc(self, e: Doc): - self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_Group(self, e: Group): - self.generate_simple_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(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)) - + # Special elements with more contents 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)) + self.generate_simple_tag(e, content=ListContainer(e.head, e.content, e.foot)) 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)) + self.generate_simple_tag(e, content=ListContainer(e.content, e.caption)) + # Emtpy tags def generate_Null(self, e: Null): - self.generate_empty_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(e) def generate_HorizontalRule(self, e: HorizontalRule): - self.generate_empty_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(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)) + self.generate_simple_tag(e) + # Raw Block tags def generate_CodeBlock(self, e: CodeBlock): - self.generate_raw_block_tag(e, self.tagname(e), self.common_attributes(e)) + self.generate_simple_tag(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)) + self.generate_simple_tag(e) + # Maybe move this to ImageProcessor? def get_image_processor_args(self, attributes:Dict[str,str]) -> Dict: # Attributes → image processor args additional_args = {}