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("---------------------")
|
||||||
#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
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: " ",
|
||||||
|
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, 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):
|
if isinstance(e, Str):
|
||||||
return e.text
|
return e.text.replace(" ", " ")
|
||||||
|
|
||||||
if isinstance(e, NBSP):
|
|
||||||
return " "
|
|
||||||
|
|
||||||
if isinstance(e, Space):
|
|
||||||
return " "
|
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
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.
|
|
||||||
|
|
||||||
\
|
|
||||||
|
|
||||||
[!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 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 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…
Reference in a new issue