Pull request #20: Feature/latex
Merge in FRAG/50ohm.de from feature/latex to main * commit 'f0a131994cccf0b4beeaf7da2057ec5ae0ad359b': feature: add latex renderer feature: add latex underline feature: add latex tag feature: add latex quote feature: add latex spaces feature: add latex dash feature: add latex comment bugfix: add missing tag names
This commit is contained in:
committed by
Tim Grelka DA2TG
commit
db02ee3ff4
@@ -0,0 +1,97 @@
|
|||||||
|
from mistletoe.latex_renderer import LaTeXRenderer
|
||||||
|
|
||||||
|
from renderer.comment import BlockComment, SpanComment
|
||||||
|
from renderer.dash import Dash
|
||||||
|
from renderer.halfwidth_spaces import HalfwidthSpaces
|
||||||
|
from renderer.nonbreaking_spaces import NonbreakingSpaces, NonbreakingSpacesDots
|
||||||
|
from renderer.quote import Quote
|
||||||
|
from renderer.tag import Tag
|
||||||
|
from renderer.underline import Underline
|
||||||
|
|
||||||
|
|
||||||
|
class FiftyOhmLaTeXRenderer(LaTeXRenderer):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__(
|
||||||
|
Dash,
|
||||||
|
BlockComment,
|
||||||
|
SpanComment,
|
||||||
|
Quote,
|
||||||
|
Underline,
|
||||||
|
Tag,
|
||||||
|
HalfwidthSpaces,
|
||||||
|
NonbreakingSpaces,
|
||||||
|
NonbreakingSpacesDots,
|
||||||
|
)
|
||||||
|
|
||||||
|
def render_document(self, token):
|
||||||
|
self.footnotes.update(token.footnotes)
|
||||||
|
return self.render_inner(token)
|
||||||
|
|
||||||
|
def render_dash(self, token):
|
||||||
|
return " -- "
|
||||||
|
|
||||||
|
def render_block_comment(self, token):
|
||||||
|
return "" # TODO propagate comments to the LaTeX document
|
||||||
|
|
||||||
|
def render_span_comment(self, token):
|
||||||
|
return "" # TODO propagate comments to the LaTeX document
|
||||||
|
|
||||||
|
def render_quote(self, token):
|
||||||
|
return fr"\enquote{{{self.render_inner(token)}}}"
|
||||||
|
|
||||||
|
def render_emphasis(self, token):
|
||||||
|
return fr"\emph{{{self.render_inner(token)}}}"
|
||||||
|
|
||||||
|
def render_underline(self, token):
|
||||||
|
return fr"\underline{{{self.render_inner(token)}}}"
|
||||||
|
|
||||||
|
def render_thematic_break(self, token):
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def render_tag(self, token): # noqa: C901
|
||||||
|
|
||||||
|
tagtype = None
|
||||||
|
|
||||||
|
match token.tagtype:
|
||||||
|
case "danger":
|
||||||
|
tagtype = "MarginDanger"
|
||||||
|
case "warning":
|
||||||
|
tagtype = "MarginWarning"
|
||||||
|
case "attention":
|
||||||
|
tagtype = "MarginAttention"
|
||||||
|
case "tip":
|
||||||
|
tagtype = "MarginTip"
|
||||||
|
case "webtip":
|
||||||
|
tagtype = "WebTip"
|
||||||
|
case "unit":
|
||||||
|
tagtype = "MarginUnit"
|
||||||
|
case "indepth":
|
||||||
|
tagtype = "MarginInDepth"
|
||||||
|
case "webindepth":
|
||||||
|
tagtype = "MarginWebInDepth"
|
||||||
|
case "webmargin":
|
||||||
|
tagtype = "WebMargin"
|
||||||
|
case "fullwidth":
|
||||||
|
tagtype = "FullWidth"
|
||||||
|
case "latexonly":
|
||||||
|
return self.render_inner(token)
|
||||||
|
case "webonly":
|
||||||
|
return ""
|
||||||
|
case _:
|
||||||
|
tagtype = "Margin"
|
||||||
|
|
||||||
|
return fr"\{tagtype}{{{self.render_inner(token)}}}"
|
||||||
|
|
||||||
|
def render_halfwidth_spaces(self, token):
|
||||||
|
return f"{token.first}.\,{token.second}."
|
||||||
|
|
||||||
|
def render_nonbreaking_spaces(self, token):
|
||||||
|
return f"{token.first}~{token.second}"
|
||||||
|
|
||||||
|
def render_nonbreaking_spaces_dots(self, token):
|
||||||
|
lookup = {
|
||||||
|
"" : "",
|
||||||
|
" " : "~"
|
||||||
|
}
|
||||||
|
return f"{lookup[token.first]}{token.second}{lookup[token.third]}"
|
||||||
+6
-3
@@ -6,20 +6,23 @@ captures = [
|
|||||||
"margin",
|
"margin",
|
||||||
"indepth",
|
"indepth",
|
||||||
"webmargin",
|
"webmargin",
|
||||||
|
"warning",
|
||||||
|
"attention",
|
||||||
"tip",
|
"tip",
|
||||||
"webtip",
|
"webtip",
|
||||||
"webindepth",
|
"webindepth",
|
||||||
|
"fullwidth",
|
||||||
"unit",
|
"unit",
|
||||||
"danger",
|
"danger",
|
||||||
"webonly",
|
"webonly",
|
||||||
"latexonly",
|
"latexonly",
|
||||||
]
|
]
|
||||||
|
|
||||||
class Tag(BlockToken):
|
|
||||||
|
|
||||||
|
class Tag(BlockToken):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def start(line):
|
def start(line):
|
||||||
return re.match(r"^\s*<("+"|".join(captures)+r")+>", line)
|
return re.match(r"^\s*<(" + "|".join(captures) + r")+>", line)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def read(cls, lines):
|
def read(cls, lines):
|
||||||
@@ -31,7 +34,7 @@ class Tag(BlockToken):
|
|||||||
for line in lines:
|
for line in lines:
|
||||||
if line.startswith(f"</{tagtype}>"):
|
if line.startswith(f"</{tagtype}>"):
|
||||||
break
|
break
|
||||||
else :
|
else:
|
||||||
child_lines.append(line)
|
child_lines.append(line)
|
||||||
return tagtype, tokenize(child_lines)
|
return tagtype, tokenize(child_lines)
|
||||||
|
|
||||||
|
|||||||
+14
-5
@@ -1,13 +1,10 @@
|
|||||||
import mistletoe
|
import mistletoe
|
||||||
import pytest
|
|
||||||
from mistletoe.ast_renderer import AstRenderer
|
|
||||||
|
|
||||||
from renderer.comment import BlockComment, SpanComment
|
|
||||||
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
|
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
|
||||||
from test.util import paragraph
|
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
|
||||||
|
|
||||||
|
|
||||||
def test_comment_html(capsys) :
|
def test_comment_html() :
|
||||||
|
|
||||||
assertions = {
|
assertions = {
|
||||||
"%Comment\nBar" : "<p>Bar</p>\n",
|
"%Comment\nBar" : "<p>Bar</p>\n",
|
||||||
@@ -18,3 +15,15 @@ def test_comment_html(capsys) :
|
|||||||
|
|
||||||
for assertion in assertions:
|
for assertion in assertions:
|
||||||
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == assertions[assertion]
|
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == assertions[assertion]
|
||||||
|
|
||||||
|
def test_comment_latex() :
|
||||||
|
|
||||||
|
assertions = {
|
||||||
|
"%Comment\nBar" : "\nBar\n",
|
||||||
|
# TODO: This test is not working as expected. The comment should be removed
|
||||||
|
#"%Comment\n" : "a",
|
||||||
|
"Foo\n%Comment\nBar" : "\nFoo\nBar\n",
|
||||||
|
}
|
||||||
|
|
||||||
|
for assertion in assertions:
|
||||||
|
assert mistletoe.markdown(assertion, FiftyOhmLaTeXRenderer) == assertions[assertion]
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import mistletoe
|
import mistletoe
|
||||||
|
|
||||||
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
|
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
|
||||||
|
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
|
||||||
from test.util import paragraph
|
from test.util import paragraph
|
||||||
|
|
||||||
|
|
||||||
@@ -12,3 +13,12 @@ def test_dash_html() :
|
|||||||
|
|
||||||
for assertion in assertions:
|
for assertion in assertions:
|
||||||
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == paragraph(assertions[assertion])
|
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == paragraph(assertions[assertion])
|
||||||
|
|
||||||
|
def test_dash_latex() :
|
||||||
|
|
||||||
|
assertions = {
|
||||||
|
"Foo - Bar" : "\nFoo -- Bar\n",
|
||||||
|
}
|
||||||
|
|
||||||
|
for assertion in assertions:
|
||||||
|
assert mistletoe.markdown(assertion, FiftyOhmLaTeXRenderer) == assertions[assertion]
|
||||||
|
|||||||
@@ -1,15 +1,19 @@
|
|||||||
import mistletoe
|
import mistletoe
|
||||||
|
|
||||||
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
|
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
|
||||||
|
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
|
||||||
from test.util import paragraph
|
from test.util import paragraph
|
||||||
|
|
||||||
|
|
||||||
def test_halfwidth_space_html():
|
def test_halfwidth_space_html():
|
||||||
assertions = {
|
input = "Dies ist z.B. ein Test. D.h. hier sollten d.h. Spaces ersetzt worden sein."
|
||||||
"Dies ist z.B. ein Test. D.h. hier sollten d.h. Spaces ersetzt worden sein." : "Dies ist z. B. ein Test. D. h. hier sollten d. h. Spaces ersetzt worden sein.",
|
target = "Dies ist z. B. ein Test. D. h. hier sollten d. h. Spaces ersetzt worden sein."
|
||||||
"Dies ist z. B. ein Test. D. h. hier sollten d. h. Spaces ersetzt worden sein." : "Dies ist z. B. ein Test. D. h. hier sollten d. h. Spaces ersetzt worden sein.",
|
|
||||||
"Z. B. die D.B. wird auch ersetzt, aber das macht nix." : "Z. B. die D. B. wird auch ersetzt, aber das macht nix."
|
|
||||||
}
|
|
||||||
|
|
||||||
for key, value in assertions.items():
|
assert mistletoe.markdown(input, FiftyOhmHtmlRenderer) == paragraph(target)
|
||||||
assert mistletoe.markdown(key, FiftyOhmHtmlRenderer) == paragraph(value)
|
|
||||||
|
|
||||||
|
def test_halfwidth_space_latex():
|
||||||
|
input = "Dies ist z.B. ein Test. D.h. hier sollten d.h. Spaces ersetzt worden sein."
|
||||||
|
target = "\nDies ist z.\,B. ein Test. D.\,h. hier sollten d.\,h. Spaces ersetzt worden sein.\n"
|
||||||
|
|
||||||
|
assert mistletoe.markdown(input, FiftyOhmLaTeXRenderer) == target
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import mistletoe
|
import mistletoe
|
||||||
|
|
||||||
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
|
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
|
||||||
|
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
|
||||||
from test.util import paragraph
|
from test.util import paragraph
|
||||||
|
|
||||||
|
|
||||||
def test_paragraph_html():
|
def test_paragraph_html():
|
||||||
input = "Der Test befindet sich unter §2 vielleicht aber auch § 3."
|
input = "Der Test befindet sich unter §2 vielleicht aber auch § 3."
|
||||||
target = "Der Test befindet sich unter § 2 vielleicht aber auch § 3."
|
target = "Der Test befindet sich unter § 2 vielleicht aber auch § 3."
|
||||||
@@ -33,4 +35,33 @@ def test_class_html():
|
|||||||
|
|
||||||
assert mistletoe.markdown(input, FiftyOhmHtmlRenderer) == paragraph(target)
|
assert mistletoe.markdown(input, FiftyOhmHtmlRenderer) == paragraph(target)
|
||||||
|
|
||||||
|
def test_paragraph_latex():
|
||||||
|
input = "Der Test befindet sich unter §2 vielleicht aber auch § 3."
|
||||||
|
target = "\nDer Test befindet sich unter §~2 vielleicht aber auch §~3.\n"
|
||||||
|
|
||||||
|
assert mistletoe.markdown(input, FiftyOhmLaTeXRenderer) == target
|
||||||
|
|
||||||
|
def test_three_points_latex():
|
||||||
|
assertions = {
|
||||||
|
"Heute hatte ich ... zum Mittagessen." : "\nHeute hatte ich~...~zum Mittagessen.\n",
|
||||||
|
"Niemals hätte ich gedacht, dass...ich ...nicht kann." : "\nNiemals hätte ich gedacht, dass...ich~...nicht kann.\n",
|
||||||
|
"Oh nein ...ein Pinguin." : "\nOh nein~...ein Pinguin.\n",
|
||||||
|
"Haha .. . Hahaha" : "\nHaha .. . Hahaha\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
for key, value in assertions.items():
|
||||||
|
assert mistletoe.markdown(key, FiftyOhmLaTeXRenderer) == value
|
||||||
|
|
||||||
|
def test_absatz_latex():
|
||||||
|
input = "Der Test befindet sich unter Abs.2 vielleicht aber auch Abs. 3."
|
||||||
|
target = "\nDer Test befindet sich unter Abs.~2 vielleicht aber auch Abs.~3.\n"
|
||||||
|
|
||||||
|
assert mistletoe.markdown(input, FiftyOhmLaTeXRenderer) == target
|
||||||
|
|
||||||
|
def test_class_latex():
|
||||||
|
input = "Ich lerne für Klasse A, Klasse E und Klasse N."
|
||||||
|
target = "\nIch lerne für Klasse~A, Klasse~E und Klasse~N.\n"
|
||||||
|
|
||||||
|
assert mistletoe.markdown(input, FiftyOhmLaTeXRenderer) == target
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import mistletoe
|
import mistletoe
|
||||||
|
|
||||||
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
|
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
|
||||||
|
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
|
||||||
from test.util import paragraph
|
from test.util import paragraph
|
||||||
|
|
||||||
|
|
||||||
@@ -17,3 +18,17 @@ def test_quote_html() :
|
|||||||
|
|
||||||
for assertion in assertions:
|
for assertion in assertions:
|
||||||
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == paragraph(assertions[assertion])
|
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == paragraph(assertions[assertion])
|
||||||
|
|
||||||
|
def test_quote_latex() :
|
||||||
|
|
||||||
|
assertions = {
|
||||||
|
'"quote"' : '\n\enquote{quote}\n',
|
||||||
|
'" quote "' : '\n\enquote{ quote }\n',
|
||||||
|
'"quote" "' : '\n\enquote{quote} "\n',
|
||||||
|
'"quo te1" filltext "qu ot e2"' : '\n\enquote{quo te1} filltext \enquote{qu ot e2}\n',
|
||||||
|
'"quo *te1*" filltext "qu ot e2"' : '\n\enquote{quo \emph{te1}} filltext \enquote{qu ot e2}\n',
|
||||||
|
'""' : '\n""\n',
|
||||||
|
}
|
||||||
|
|
||||||
|
for assertion in assertions:
|
||||||
|
assert mistletoe.markdown(assertion, FiftyOhmLaTeXRenderer) == assertions[assertion]
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import mistletoe
|
import mistletoe
|
||||||
|
|
||||||
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
|
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
|
||||||
|
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_thematic_break_html() :
|
def test_thematic_break_html() :
|
||||||
@@ -40,3 +42,44 @@ def test_thematic_break_and_tag_html() :
|
|||||||
|
|
||||||
for assertion in assertions:
|
for assertion in assertions:
|
||||||
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == assertions[assertion]
|
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == assertions[assertion]
|
||||||
|
|
||||||
|
def test_thematic_break_latex() :
|
||||||
|
assertions = {
|
||||||
|
"---" : '',
|
||||||
|
"---\n---" : '',
|
||||||
|
}
|
||||||
|
|
||||||
|
for assertion in assertions:
|
||||||
|
assert mistletoe.markdown(assertion, FiftyOhmLaTeXRenderer) == assertions[assertion]
|
||||||
|
|
||||||
|
def test_tag_latex() :
|
||||||
|
|
||||||
|
assertions = {
|
||||||
|
"<margin>\nFoo\n</margin>" : "\Margin{\nFoo\n}",
|
||||||
|
"<danger>\nFoo\n</danger>" : "\MarginDanger{\nFoo\n}",
|
||||||
|
"<warning>\nFoo\n</warning>" : "\MarginWarning{\nFoo\n}",
|
||||||
|
"<attention>\nFoo\n</attention>" : "\MarginAttention{\nFoo\n}",
|
||||||
|
"<tip>\nFoo\n</tip>" : "\MarginTip{\nFoo\n}",
|
||||||
|
"<webtip>\nFoo\n</webtip>" : "\WebTip{\nFoo\n}",
|
||||||
|
"<unit>\nFoo\n</unit>" : "\MarginUnit{\nFoo\n}",
|
||||||
|
"<indepth>\nFoo\n</indepth>" : "\MarginInDepth{\nFoo\n}",
|
||||||
|
"<webindepth>\nFoo\n</webindepth>" : "\MarginWebInDepth{\nFoo\n}",
|
||||||
|
"<webmargin>\nFoo\n</webmargin>" : "\WebMargin{\nFoo\n}",
|
||||||
|
"<fullwidth>\nFoo\n</fullwidth>" : "\FullWidth{\nFoo\n}",
|
||||||
|
"<latexonly>\nFoo\n</latexonly>" : "\nFoo\n",
|
||||||
|
"<webonly>\nFoo\n</webonly>" : "",
|
||||||
|
}
|
||||||
|
|
||||||
|
for assertion in assertions:
|
||||||
|
assert mistletoe.markdown(assertion, FiftyOhmLaTeXRenderer) == assertions[assertion]
|
||||||
|
|
||||||
|
def test_thematic_break_and_tag_latex() :
|
||||||
|
|
||||||
|
assertions = {
|
||||||
|
"---\n<margin>\nFoo\n</margin>" : "\Margin{\nFoo\n}",
|
||||||
|
"---\n<margin>\nFoo\n</margin>\n<margin>\nFoo\n</margin>" : "\Margin{\nFoo\n}\Margin{\nFoo\n}",
|
||||||
|
"---\n<margin>\nFoo\n</margin>\n---\n<margin>\nFoo\n</margin>" : "\Margin{\nFoo\n}\Margin{\nFoo\n}",
|
||||||
|
}
|
||||||
|
|
||||||
|
for assertion in assertions:
|
||||||
|
assert mistletoe.markdown(assertion, FiftyOhmLaTeXRenderer) == assertions[assertion]
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import mistletoe
|
import mistletoe
|
||||||
|
|
||||||
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
|
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
|
||||||
|
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
|
||||||
from test.util import paragraph
|
from test.util import paragraph
|
||||||
|
|
||||||
|
|
||||||
@@ -14,3 +15,14 @@ def test_underline_html() :
|
|||||||
|
|
||||||
for assertion in assertions:
|
for assertion in assertions:
|
||||||
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == paragraph(assertions[assertion])
|
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == paragraph(assertions[assertion])
|
||||||
|
|
||||||
|
def test_underline_latex() :
|
||||||
|
|
||||||
|
assertions = {
|
||||||
|
"<u>Text</u>" : "\n\\underline{Text}\n",
|
||||||
|
"<u> Text Text </u>" : "\n\\underline{ Text Text }\n",
|
||||||
|
"<u> Text *Text* </u>" : "\n\\underline{ Text \emph{Text} }\n",
|
||||||
|
}
|
||||||
|
|
||||||
|
for assertion in assertions:
|
||||||
|
assert mistletoe.markdown(assertion, FiftyOhmLaTeXRenderer) == assertions[assertion]
|
||||||
|
|||||||
Reference in New Issue
Block a user