Browse Source

First working HTML generation.

pull/28/head
Jan Černohorský 2 years ago
parent
commit
aa46599f2e
  1. 3
      formatitko.py
  2. 166
      html.py
  3. 9
      test-partial.md
  4. 64
      test.md
  5. 15
      transform.py

3
formatitko.py

@ -22,6 +22,5 @@ doc = doc.walk(transform, context)
print("---------------------") print("---------------------")
#print(show(doc)) #print(show(doc))
#print(convert_text(doc, input_format="panflute", output_format="markdown")) #print(convert_text(doc, input_format="panflute", output_format="markdown"))
print(html(doc)) open("output.html", "w").write("<head> <meta charset='utf-8'> </head>" + html(doc))

166
html.py

@ -1,45 +1,71 @@
from panflute import * from panflute import *
from whitespace import NBSP from whitespace import NBSP
from transform import FQuoted
def html(e: Element, indent_level: int=0, indent_str: str="\t") -> str: 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() tag = e.tag.lower()
attributes = "" attributes = ""
content_foot = "" content_foot = ""
content_head = "" 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'<!-- FIXME: {type(e)}s not implemented -->'
simple_string = {
NBSP: "&nbsp;",
Space: " ",
Null: "",
LineBreak: f"\n{indent_level*indent_str}<br>\n{indent_level*indent_str}",
SoftBreak: f"\n{indent_level*indent_str}<br>\n{indent_level*indent_str}",
HorizontalRule: f"{indent_level*indent_str}<hr>\n"
}
if type(e) in simple_string:
return simple_string[type(e)]
if hasattr(e, "identifier") and e.identifier != "": if hasattr(e, "identifier") and e.identifier != "":
attributes += f' id="{e.identifier}"' attributes += f' id="{e.identifier}"'
if hasattr(e, "classes") and len(e.classes) != 0: if hasattr(e, "classes") and len(e.classes) != 0:
attributes += f' class="{" ".join(e.classes)}"' 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): if isinstance(e, CodeBlock):
# TODO: Syntax highlighting # TODO: Syntax highlighting
tag = "pre" 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): if isinstance(e, Figure):
content_foot = html(e.caption, indent_level+1, indent_str) 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" tag = "figcaption"
if isinstance(e, Image): if isinstance(e, Image):
tag = "img"
# TODO: Finish this
# TODO: Image processing # TODO: Image processing
return f'<img src="{e.url}" alt="{e.title or html(e.content, 0, "")}">'
if isinstance(e, LineBreak):
return f"\n{indent_level*indent_str}<br>\n{indent_level*indent_str}"
if isinstance(e, Para):
tag = "p"
if isinstance(e, Header): if isinstance(e, Header):
tag = "h"+str(e.level) 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): if isinstance(e, Link):
tag = "a" tag = "a"
attributes += f' href="{e.url}"' attributes += f' href="{e.url}"'
if len(e.title) != 0: if e.title:
attributes += f' title="{e.title}"' attributes += f' title="{e.title}"'
if isinstance(e, Str): if isinstance(e, LineItem):
return e.text return indent_level*indent_str + html(e.content) + "<br>\n"
if isinstance(e, NBSP): if isinstance(e, Note):
return "&nbsp;" content_head = "("
content_foot = ")"
if len(e.content) == 1 and isinstance(e.content[0], Para):
return f' <note>({html(e.content[0].content, 0, "")})</note>'
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, Space): if isinstance(e, Str):
return " " return e.text.replace(" ", "&nbsp;")
if isinstance(e, Null):
return ""
if isinstance(e, Math): if isinstance(e, Math):
# TODO
return "TODO: MATH" return "TODO: MATH"
if isinstance(e, RawInline): if isinstance(e, RawInline) and e.format == "html":
return e.text return e.text
if isinstance(e, RawBlock) and e.format == "html":
return f'{e.text}\n'
if isinstance(e, Inline): if isinstance(e, Inline):
return f"<{tag}{attributes}> {content_head} {''.join([html(child, 0, '') for child in e.content])} {content_foot} </{tag}>" return f"<{tag}{attributes}>{content_head}{html(e.content, 0, '')}{content_foot}</{tag}>"
out_str = "" out_str = ""
if not isinstance(e, Plain): 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 hasattr(e, "_content"):
if len(e.content) > 0 and isinstance(e.content[0], Inline): if len(e.content) > 0 and isinstance(e.content[0], Inline):
out_str += (indent_level+1)*indent_str out_str += (indent_level+1)*indent_str
for child in e.content: out_str += html(e.content, indent_level+1, indent_str)
out_str += html(child, indent_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" 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 return out_str

9
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") 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} ``` {.python .run}
ctx.unset_metadata("language") ctx.unset_metadata("language")

64
test.md

@ -36,15 +36,9 @@ def bruh(no):
This should only be shown to cats the second time 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]{} [!opendatatask]{}
@ -57,3 +51,59 @@ This should be seen by all.
[!nop]{a=b} <!-- A special command! WOW --> [!nop]{a=b} <!-- A special command! WOW -->
A non-breakable&nbsp;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}
<figure>
<video src="woah.mp4" autoplay></video>
<figcaption> This is indeed a video </figcaption>
</figure>
```
#. 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
------- ------ ---------- -------

15
transform.py

@ -7,6 +7,12 @@ from command import *
from util import * from util import *
from context 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 def transform(e: Element, c: Context) -> Element: # Returns next sibling element to transform
"""Transform the AST, making format-agnostic changes.""" """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) includedDoc = includedDoc.walk(transform, nContext)
e = Div(*includedDoc.content) 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 # 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: if isinstance(e, CodeBlock) and hasattr(e, "classes") and "python" in e.classes and "run" in e.classes:
e = executeCommand(e.text, None, c) e = executeCommand(e.text, None, c)

Loading…
Cancel
Save