From aa46599f2e80f4c926325f7c1c2f2b57d88e2f31 Mon Sep 17 00:00:00 2001 From: Greenscreener Date: Thu, 2 Feb 2023 16:39:18 +0100 Subject: [PATCH] First working HTML generation. --- formatitko.py | 3 +- html.py | 166 +++++++++++++++++++++++++++++++++++------------- test-partial.md | 9 ++- test.md | 64 +++++++++++++++++-- transform.py | 15 +++++ 5 files changed, 202 insertions(+), 55 deletions(-) diff --git a/formatitko.py b/formatitko.py index 6d14a2d..62c4f33 100755 --- a/formatitko.py +++ b/formatitko.py @@ -22,6 +22,5 @@ doc = doc.walk(transform, context) print("---------------------") #print(show(doc)) #print(convert_text(doc, input_format="panflute", output_format="markdown")) -print(html(doc)) - +open("output.html", "w").write(" " + html(doc)) diff --git a/html.py b/html.py index 0c1a6a1..207619d 100644 --- a/html.py +++ b/html.py @@ -1,45 +1,71 @@ from panflute import * from whitespace import NBSP - +from transform import FQuoted def html(e: Element, indent_level: int=0, indent_str: str="\t") -> str: + if isinstance(e, ListContainer): + return ''.join([html(child, indent_level, indent_str) for child in e]) + tag = e.tag.lower() attributes = "" content_foot = "" content_head = "" + tags = { + BulletList: "ul", + Doc: "main", + Emph: "em", + Caption: "figcaption", + Para: "p", + Header: "h"+str(e.level) if hasattr(e, "level") else "", + LineBlock: "p", + ListItem: "li", + SmallCaps: "span", + Strikeout: "strike", + Subscript: "sub", + Superscript: "sup", + Underline: "u", + TableBody: "tbody", + TableHead: "thead", + TableFoot: "tfoot", + TableRow: "tr", + TableCell: "td", + } + if type(e) in tags: + tag = tags[type(e)] + + not_implemented = { + Citation: True, + Cite: True, + Definition: True, + DefinitionItem: True, + DefinitionList: True + } + if type(e) in not_implemented: + return f'' + + simple_string = { + NBSP: " ", + Space: " ", + Null: "", + LineBreak: f"\n{indent_level*indent_str}
\n{indent_level*indent_str}", + SoftBreak: f"\n{indent_level*indent_str}
\n{indent_level*indent_str}", + HorizontalRule: f"{indent_level*indent_str}
\n" + } + if type(e) in simple_string: + return simple_string[type(e)] + if hasattr(e, "identifier") and e.identifier != "": attributes += f' id="{e.identifier}"' if hasattr(e, "classes") and len(e.classes) != 0: attributes += f' class="{" ".join(e.classes)}"' - if isinstance(e, BulletList): - tag = "ul" - - if isinstance(e, Citation): - return "TODO: " + e.tag - - if isinstance(e, Cite): - return "TODO: " + e.tag - if isinstance(e, CodeBlock): # TODO: Syntax highlighting tag = "pre" - if isinstance(e, Definition): - return "TODO: " + e.tag - - if isinstance(e, DefinitionItem): - return "TODO: " + e.tag - - if isinstance(e, DefinitionList): - return "TODO: " + e.tag - - if isinstance(e, Emph): - tag = "em" - if isinstance(e, Figure): content_foot = html(e.caption, indent_level+1, indent_str) @@ -47,15 +73,8 @@ def html(e: Element, indent_level: int=0, indent_str: str="\t") -> str: tag = "figcaption" if isinstance(e, Image): - tag = "img" - # TODO: Finish this # TODO: Image processing - - if isinstance(e, LineBreak): - return f"\n{indent_level*indent_str}
\n{indent_level*indent_str}" - - if isinstance(e, Para): - tag = "p" + return f'{e.title or html(e.content, 0, ' if isinstance(e, Header): tag = "h"+str(e.level) @@ -63,29 +82,86 @@ def html(e: Element, indent_level: int=0, indent_str: str="\t") -> str: if isinstance(e, Link): tag = "a" attributes += f' href="{e.url}"' - if len(e.title) != 0: + if e.title: attributes += f' title="{e.title}"' + + if isinstance(e, LineItem): + return indent_level*indent_str + html(e.content) + "
\n" + + if isinstance(e, Note): + content_head = "(" + content_foot = ")" + if len(e.content) == 1 and isinstance(e.content[0], Para): + return f' ({html(e.content[0].content, 0, "")})' + + if isinstance(e, OrderedList): + tag = "ol" + if e.start and e.start != 1: + attributes += f' start="{e.start}"' + html_styles = { + "Decimal": "1", + "LowerRoman": "i", + "UpperRoman:": "I", + "LowerAlpha": "a", + "UpperAlpha": "A" + } + if e.style and e.style != "DefaultStyle": + attributes += f' type="{html_styles[e.style]}"' + # FIXME: Delimeter styles + + if isinstance(e, Table): + content_head = html(e.head, indent_level+1, indent_str) + content_foot = html(e.foot, indent_level+1, indent_str) + # FIXME: Fancy pandoc tables, using colspec + + if isinstance(e, TableCell): + tag = "td" + if e.colspan != 1: + attributes += f' colspan="{e.colspan}"' + if e.rowspan != 1: + attributes += f' rowspan="{e.rowspan}"' + aligns = { + "AlignLeft": "left", + "AlignRight": "right", + "AlignCenter": "center" + } + if e.alignment and e.alignment != "AlignDefault": + attributes += f' style="text-align: {aligns[e.alignment]}"' + + if isinstance(e, FQuoted): + if e.style == "cs": + if e.quote_type == "SingleQuote": + return f'‚{html(e.content, 0, "")}‘' + elif e.quote_type == "DoubleQuote": + return f'„{html(e.content, 0, "")}“' + elif e.style == "en": + if e.quote_type == "SingleQuote": + return f'‘{html(e.content, 0, "")}’' + elif e.quote_type == "DoubleQuote": + return f'“{html(e.content, 0, "")}”' + else: + if e.quote_type == "SingleQuote": + return f'\'{html(e.content, 0, "")}\'' + elif e.quote_type == "DoubleQuote": + return f'"{html(e.content, 0, "")}"' + else: + return f'"{html(e.content, 0, "")}"' if isinstance(e, Str): - return e.text - - if isinstance(e, NBSP): - return " " - - if isinstance(e, Space): - return " " - - if isinstance(e, Null): - return "" + return e.text.replace(" ", " ") if isinstance(e, Math): + # TODO return "TODO: MATH" - if isinstance(e, RawInline): + if isinstance(e, RawInline) and e.format == "html": return e.text + if isinstance(e, RawBlock) and e.format == "html": + return f'{e.text}\n' + if isinstance(e, Inline): - return f"<{tag}{attributes}> {content_head} {''.join([html(child, 0, '') for child in e.content])} {content_foot} " + return f"<{tag}{attributes}>{content_head}{html(e.content, 0, '')}{content_foot}" out_str = "" if not isinstance(e, Plain): @@ -94,8 +170,7 @@ def html(e: Element, indent_level: int=0, indent_str: str="\t") -> str: if hasattr(e, "_content"): if len(e.content) > 0 and isinstance(e.content[0], Inline): out_str += (indent_level+1)*indent_str - for child in e.content: - out_str += html(child, indent_level+1, indent_str) + out_str += html(e.content, indent_level+1, indent_str) if hasattr(e, "text"): out_str += e.text out_str += f"{content_foot}\n" @@ -104,3 +179,4 @@ def html(e: Element, indent_level: int=0, indent_str: str="\t") -> str: return out_str + diff --git a/test-partial.md b/test-partial.md index 8e021f8..2f0dd87 100644 --- a/test-partial.md +++ b/test-partial.md @@ -22,7 +22,14 @@ println(f"The subdocument's subtitle is \n\n## {ctx.get_metadata('subtitle')}") ctx.set_metadata("language", "cs") ``` -Tak toto je v prádelně pánové! +Tak toto je "v prádelně" pánové! + +``` {.python .run} +ctx.set_metadata("language", "en") +``` + +This is "in a laundry room" gentlemen! + ``` {.python .run} ctx.unset_metadata("language") diff --git a/test.md b/test.md index 651764a..2fec3a2 100644 --- a/test.md +++ b/test.md @@ -36,15 +36,9 @@ def bruh(no): This should only be shown to cats the second time :::: -A non-breakable space bro -A lot of spaces - -A text with some $math$. -This should be seen by all. - -![This is a figure, go figure...](/this/image/does/not/exist.jpg)\ +![This is a figure, go figure...](/this/image/does/not/exist.jpg) [!opendatatask]{} @@ -57,3 +51,59 @@ This should be seen by all. [!nop]{a=b} +A non-breakable space bro + +A lot of spaces + +A text with some $math$. + +This should be seen by all^[This is a footnote]. + +| Matematicko-fyzikální fakulta University Karlovy +| Malostranské nám. 2/25 +| 118 00 Praha 1 + +TODO: + +- buy eggs +- buy milk +- ??? +- profit + - also create sublists preferrably + +1. Woah +2. Wooo +3. no + +``` {=html} +
+ +
This is indeed a video
+
+``` + +#. brum +#. BRUHHH +#. woah + +i. bro +ii. wym bro + ++---------------------+-----------------------+ +| Location | Temperature 1961-1990 | +| | in degree Celsius | +| +-------+-------+-------+ +| | min | mean | max | ++=====================+=======+=======+======:+ +| Antarctica | -89.2 | N/A | 19.8 | ++---------------------+-------+-------+-------+ +| Earth | -89.2 | 14 | 56.7 | ++---------------------+-------+-------+-------+ + + +------- ------ ---------- ------- + 12 12 12 12 + 123 123 123 123 + 1 1 1 1 +------- ------ ---------- ------- + diff --git a/transform.py b/transform.py index c88fe1c..9bd78dd 100644 --- a/transform.py +++ b/transform.py @@ -7,6 +7,12 @@ from command import * from util import * from context import * +class FQuoted(Quoted): + def __init__(self, *args, **kwargs): + self.style = kwargs["style"] + del kwargs["style"] + super().__init__(*args, **kwargs) + def transform(e: Element, c: Context) -> Element: # Returns next sibling element to transform """Transform the AST, making format-agnostic changes.""" @@ -39,6 +45,15 @@ def transform(e: Element, c: Context) -> Element: # Returns next sibling element includedDoc = includedDoc.walk(transform, nContext) e = Div(*includedDoc.content) + + if isinstance(e, Quoted): + quote_styles = { + "cs": "cs", + "en": "en", + "sk": "cs" + } + e = FQuoted(*e.content, quote_type=e.quote_type, style=quote_styles[c.get_metadata("language")]) + # Execute python code inside source code block if isinstance(e, CodeBlock) and hasattr(e, "classes") and "python" in e.classes and "run" in e.classes: e = executeCommand(e.text, None, c)