First working HTML generation.
This commit is contained in:
parent
f49085b309
commit
aa46599f2e
5 changed files with 202 additions and 55 deletions
|
@ -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("<head> <meta charset='utf-8'> </head>" + html(doc))
|
||||
|
||||
|
|
166
html.py
166
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'<!-- FIXME: {type(e)}s not implemented -->'
|
||||
|
||||
simple_string = {
|
||||
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 != "":
|
||||
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}<br>\n{indent_level*indent_str}"
|
||||
|
||||
if isinstance(e, Para):
|
||||
tag = "p"
|
||||
return f'<img src="{e.url}" alt="{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) + "<br>\n"
|
||||
|
||||
if isinstance(e, Note):
|
||||
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, 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} </{tag}>"
|
||||
return f"<{tag}{attributes}>{content_head}{html(e.content, 0, '')}{content_foot}</{tag}>"
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
64
test.md
64
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 special command! WOW -->
|
||||
|
||||
|
||||
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}
|
||||
<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
15
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)
|
||||
|
|
Loading…
Reference in a new issue