Started working on TeX output, minor bugfixes.
This commit is contained in:
parent
a5e87aefde
commit
1e9054a909
5 changed files with 135 additions and 14 deletions
|
@ -9,8 +9,9 @@ from typing import List
|
||||||
from transform import transform
|
from transform import transform
|
||||||
from util import *
|
from util import *
|
||||||
from context import Context
|
from context import Context
|
||||||
from html import html
|
|
||||||
from katex import KatexClient
|
from katex import KatexClient
|
||||||
|
from html import html
|
||||||
|
from tex import tex
|
||||||
|
|
||||||
from mj_show import show
|
from mj_show import show
|
||||||
|
|
||||||
|
@ -25,3 +26,5 @@ print("---------------------")
|
||||||
#print(convert_text(doc, input_format="panflute", output_format="markdown"))
|
#print(convert_text(doc, input_format="panflute", output_format="markdown"))
|
||||||
katexClient = KatexClient()
|
katexClient = KatexClient()
|
||||||
open("output.html", "w").write("<head> <meta charset='utf-8'> <link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/katex.min.css' integrity='sha384-vKruj+a13U8yHIkAyGgK1J3ArTLzrFGBbBc0tDp4ad/EyewESeXE/Iv67Aj8gKZ0' crossorigin='anonymous'> </head>" + html(doc, katexClient))
|
open("output.html", "w").write("<head> <meta charset='utf-8'> <link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/katex.min.css' integrity='sha384-vKruj+a13U8yHIkAyGgK1J3ArTLzrFGBbBc0tDp4ad/EyewESeXE/Iv67Aj8gKZ0' crossorigin='anonymous'> </head>" + html(doc, katexClient))
|
||||||
|
open("output.tex", "w").write(tex(doc))
|
||||||
|
#print(tex(doc))
|
||||||
|
|
22
html.py
22
html.py
|
@ -18,6 +18,9 @@ def html(e: Element, k: KatexClient, indent_level: int=0, indent_str: str="\t")
|
||||||
content_foot = ""
|
content_foot = ""
|
||||||
content_head = ""
|
content_head = ""
|
||||||
|
|
||||||
|
if isinstance(e, Str):
|
||||||
|
return e.text.replace(" ", " ")
|
||||||
|
|
||||||
tags = {
|
tags = {
|
||||||
BulletList: "ul",
|
BulletList: "ul",
|
||||||
Doc: "main",
|
Doc: "main",
|
||||||
|
@ -56,7 +59,7 @@ def html(e: Element, k: KatexClient, indent_level: int=0, indent_str: str="\t")
|
||||||
Space: " ",
|
Space: " ",
|
||||||
Null: "",
|
Null: "",
|
||||||
LineBreak: f"\n{indent_level*indent_str}<br>\n{indent_level*indent_str}",
|
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}",
|
SoftBreak: f" ",
|
||||||
HorizontalRule: f"{indent_level*indent_str}<hr>\n"
|
HorizontalRule: f"{indent_level*indent_str}<hr>\n"
|
||||||
}
|
}
|
||||||
if type(e) in simple_string:
|
if type(e) in simple_string:
|
||||||
|
@ -165,9 +168,6 @@ def html(e: Element, k: KatexClient, indent_level: int=0, indent_str: str="\t")
|
||||||
else:
|
else:
|
||||||
return f'"{html(e.content, k, 0, "")}"'
|
return f'"{html(e.content, k, 0, "")}"'
|
||||||
|
|
||||||
if isinstance(e, Str):
|
|
||||||
return e.text.replace(" ", " ")
|
|
||||||
|
|
||||||
if isinstance(e, Math):
|
if isinstance(e, Math):
|
||||||
formats = {
|
formats = {
|
||||||
"DisplayMath": True,
|
"DisplayMath": True,
|
||||||
|
@ -178,11 +178,17 @@ def html(e: Element, k: KatexClient, indent_level: int=0, indent_str: str="\t")
|
||||||
# and are forgotten in the next one.
|
# and are forgotten in the next one.
|
||||||
return indent_level*indent_str + k.render(e.text, {"displayMode": formats[e.format]})
|
return indent_level*indent_str + k.render(e.text, {"displayMode": formats[e.format]})
|
||||||
|
|
||||||
if isinstance(e, RawInline) and e.format == "html":
|
if isinstance(e, RawInline):
|
||||||
return e.text
|
if e.format == "html":
|
||||||
|
return e.text
|
||||||
|
else:
|
||||||
|
return ""
|
||||||
|
|
||||||
if isinstance(e, RawBlock) and e.format == "html":
|
if isinstance(e, RawBlock):
|
||||||
return f'{e.text}\n'
|
if e.format == "html":
|
||||||
|
return f'{e.text}\n'
|
||||||
|
else:
|
||||||
|
return ""
|
||||||
|
|
||||||
if isinstance(e, Inline):
|
if isinstance(e, Inline):
|
||||||
return f"<{tag}{attributes}>{content_head}{html(e.content, k, 0, '')}{content_foot}</{tag}>"
|
return f"<{tag}{attributes}>{content_head}{html(e.content, k, 0, '')}{content_foot}</{tag}>"
|
||||||
|
|
8
test.md
8
test.md
|
@ -56,6 +56,8 @@ A non-breakable space bro
|
||||||
A lot of spaces
|
A lot of spaces
|
||||||
|
|
||||||
A text with some inline math: $\sum_{i=1}^nn^2$. Plus some display math:
|
A text with some inline math: $\sum_{i=1}^nn^2$. Plus some display math:
|
||||||
|
|
||||||
|
<!--
|
||||||
$$
|
$$
|
||||||
\def\eqalign#1{\begin{align*}#1\end{align*}}
|
\def\eqalign#1{\begin{align*}#1\end{align*}}
|
||||||
\eqalign{
|
\eqalign{
|
||||||
|
@ -63,7 +65,9 @@ $$
|
||||||
x_1 - 3 x_2 + 2 x_3 &= 5 \cr
|
x_1 - 3 x_2 + 2 x_3 &= 5 \cr
|
||||||
-x_1 + 4 x_2 + \phantom{1} x_3 &= 2
|
-x_1 + 4 x_2 + \phantom{1} x_3 &= 2
|
||||||
}
|
}
|
||||||
$$
|
$$-->
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
This should be seen by all^[This is a footnote].
|
This should be seen by all^[This is a footnote].
|
||||||
|
|
||||||
|
@ -71,7 +75,7 @@ This should be seen by all^[This is a footnote].
|
||||||
| Malostranské nám. 2/25
|
| Malostranské nám. 2/25
|
||||||
| 118 00 Praha 1
|
| 118 00 Praha 1
|
||||||
|
|
||||||
TODO:
|
To Do:
|
||||||
|
|
||||||
- buy eggs
|
- buy eggs
|
||||||
- buy milk
|
- buy milk
|
||||||
|
|
106
tex.py
Normal file
106
tex.py
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
from panflute import *
|
||||||
|
|
||||||
|
from whitespace import NBSP
|
||||||
|
from transform import FQuoted
|
||||||
|
|
||||||
|
# Heavily inspired by: git://git.ucw.cz/labsconf2022.git
|
||||||
|
def tex(e, indent_level: int=0, indent_str: str="\t") -> str:
|
||||||
|
|
||||||
|
content_foot = ""
|
||||||
|
content_head = ""
|
||||||
|
|
||||||
|
if isinstance(e, ListContainer):
|
||||||
|
return ''.join([tex(child, indent_level, indent_str) for child in 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 \n'
|
||||||
|
|
||||||
|
simple_string = {
|
||||||
|
NBSP: "~",
|
||||||
|
Space: " ",
|
||||||
|
Null: "",
|
||||||
|
LineBreak: f"\\\\",
|
||||||
|
SoftBreak: f" ",
|
||||||
|
HorizontalRule: "% TODO: hrule"
|
||||||
|
}
|
||||||
|
if type(e) in simple_string:
|
||||||
|
return simple_string[type(e)]
|
||||||
|
|
||||||
|
if isinstance(e, Str):
|
||||||
|
return e.text.replace(" ", "~").replace(" ", "~")
|
||||||
|
|
||||||
|
if isinstance(e, Para):
|
||||||
|
return tex(e.content, 0, "")+"\n\n"
|
||||||
|
|
||||||
|
if isinstance(e, Emph):
|
||||||
|
return f'{{\\it {tex(e.content, 0, "")}}}'
|
||||||
|
|
||||||
|
if isinstance(e, Strong):
|
||||||
|
return f'{{\\bf {tex(e.content, 0, "")}}}'
|
||||||
|
|
||||||
|
if isinstance(e, FQuoted):
|
||||||
|
if e.style == "cs":
|
||||||
|
if e.quote_type == "SingleQuote":
|
||||||
|
return f'‚{tex(e.content, 0, "")}‘'
|
||||||
|
elif e.quote_type == "DoubleQuote":
|
||||||
|
return f'„{tex(e.content, 0, "")}“'
|
||||||
|
elif e.style == "en":
|
||||||
|
if e.quote_type == "SingleQuote":
|
||||||
|
return f'‘{tex(e.content, 0, "")}’'
|
||||||
|
elif e.quote_type == "DoubleQuote":
|
||||||
|
return f'“{tex(e.content, 0, "")}”'
|
||||||
|
else:
|
||||||
|
if e.quote_type == "SingleQuote":
|
||||||
|
return f'\'{tex(e.content, 0, "")}\''
|
||||||
|
elif e.quote_type == "DoubleQuote":
|
||||||
|
return f'"{tex(e.content, 0, "")}"'
|
||||||
|
else:
|
||||||
|
return f'"{tex(e.content, 0, "")}"'
|
||||||
|
|
||||||
|
if isinstance(e, Math):
|
||||||
|
if e.format == "DisplayMath":
|
||||||
|
return f'$${e.text}$$\n'
|
||||||
|
else:
|
||||||
|
return f'${e.text}$'
|
||||||
|
|
||||||
|
if isinstance(e, RawInline):
|
||||||
|
if e.format == "tex":
|
||||||
|
return e.text
|
||||||
|
else:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
if isinstance(e, RawBlock):
|
||||||
|
if e.format == "tex":
|
||||||
|
return f'{e.text}\n'
|
||||||
|
else:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
if isinstance(e, Span) or isinstance(e, Plain):
|
||||||
|
return tex(e.content, 0, "")
|
||||||
|
|
||||||
|
if isinstance(e, Div):
|
||||||
|
return f'{tex(e.content, indent_level+1, indent_str)}'
|
||||||
|
|
||||||
|
if isinstance(e, Doc):
|
||||||
|
return tex(e.content, indent_level, indent_str)+"\n\\bye"
|
||||||
|
|
||||||
|
if isinstance(e, Inline):
|
||||||
|
return f"({e.tag}){content_head}{tex(e.content, 0, '')}{content_foot}(/{e.tag})"
|
||||||
|
|
||||||
|
out_str = ""
|
||||||
|
out_str = f"({e.tag}){{"
|
||||||
|
out_str += content_head
|
||||||
|
if hasattr(e, "_content"):
|
||||||
|
out_str += tex(e.content, indent_level+1, indent_str)
|
||||||
|
if hasattr(e, "text"):
|
||||||
|
out_str += e.text
|
||||||
|
out_str += f"{content_foot}}}\n\n"
|
||||||
|
|
||||||
|
return out_str
|
|
@ -49,13 +49,15 @@ def transform(e: Element, c: Context) -> Element: # Returns next sibling element
|
||||||
quote_styles = {
|
quote_styles = {
|
||||||
"cs": "cs",
|
"cs": "cs",
|
||||||
"en": "en",
|
"en": "en",
|
||||||
"sk": "cs"
|
"sk": "cs",
|
||||||
|
None: None
|
||||||
}
|
}
|
||||||
e = FQuoted(*e.content, quote_type=e.quote_type, style=quote_styles[c.get_metadata("language")])
|
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 = Div(*executeCommand(e.text, None, c))
|
||||||
|
e = e.walk(transform, c)
|
||||||
|
|
||||||
## Command defines
|
## Command defines
|
||||||
# possible TODO: def/longdef?
|
# possible TODO: def/longdef?
|
||||||
|
@ -91,6 +93,6 @@ def transform(e: Element, c: Context) -> Element: # Returns next sibling element
|
||||||
if not c.get_command(e.attributes["c"]):
|
if not c.get_command(e.attributes["c"]):
|
||||||
raise NameError(f"Command not defined '{e.attributes['c']}'.")
|
raise NameError(f"Command not defined '{e.attributes['c']}'.")
|
||||||
e = e.replaceSelf(executeCommand(c.get_command(e.attributes["c"]), e, c))
|
e = e.replaceSelf(executeCommand(c.get_command(e.attributes["c"]), e, c))
|
||||||
e.walk(transform, c)
|
e = e.walk(transform, c)
|
||||||
|
|
||||||
return e
|
return e
|
||||||
|
|
Loading…
Reference in a new issue