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:
Prof.Dr. Matthias Jung DL9MJ
2024-12-10 23:55:51 +00:00
committed by Tim Grelka DA2TG
9 changed files with 242 additions and 18 deletions
+97
View File
@@ -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]}"
+7 -4
View File
@@ -6,20 +6,23 @@ captures = [
"margin",
"indepth",
"webmargin",
"warning",
"attention",
"tip",
"webtip",
"webindepth",
"fullwidth",
"unit",
"danger",
"webonly",
"latexonly",
]
class Tag(BlockToken):
class Tag(BlockToken):
@staticmethod
def start(line):
return re.match(r"^\s*<("+"|".join(captures)+r")+>", line)
return re.match(r"^\s*<(" + "|".join(captures) + r")+>", line)
@classmethod
def read(cls, lines):
@@ -31,9 +34,9 @@ class Tag(BlockToken):
for line in lines:
if line.startswith(f"</{tagtype}>"):
break
else :
else:
child_lines.append(line)
return tagtype, tokenize(child_lines)
def __init__(self, match):
self.tagtype, self.children = match
self.tagtype, self.children = match
+14 -5
View File
@@ -1,13 +1,10 @@
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 test.util import paragraph
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
def test_comment_html(capsys) :
def test_comment_html() :
assertions = {
"%Comment\nBar" : "<p>Bar</p>\n",
@@ -18,3 +15,15 @@ def test_comment_html(capsys) :
for assertion in assertions:
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]
+10
View File
@@ -1,6 +1,7 @@
import mistletoe
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
from test.util import paragraph
@@ -12,3 +13,12 @@ def test_dash_html() :
for assertion in assertions:
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]
+12 -8
View File
@@ -1,15 +1,19 @@
import mistletoe
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
from test.util import paragraph
def test_halfwidth_space_html():
assertions = {
"Dies ist z.B. ein Test. D.h. hier sollten d.h. Spaces ersetzt worden sein." : "Dies ist z.&#8239;B. ein Test. D.&#8239;h. hier sollten d.&#8239;h. Spaces ersetzt worden sein.",
"Dies ist z. B. ein Test. D. h. hier sollten d. h. Spaces ersetzt worden sein." : "Dies ist z.&#8239;B. ein Test. D.&#8239;h. hier sollten d.&#8239;h. Spaces ersetzt worden sein.",
"Z. B. die D.B. wird auch ersetzt, aber das macht nix." : "Z.&#8239;B. die D.&#8239;B. wird auch ersetzt, aber das macht nix."
}
for key, value in assertions.items():
assert mistletoe.markdown(key, FiftyOhmHtmlRenderer) == paragraph(value)
input = "Dies ist z.B. ein Test. D.h. hier sollten d.h. Spaces ersetzt worden sein."
target = "Dies ist z.&#8239;B. ein Test. D.&#8239;h. hier sollten d.&#8239;h. Spaces ersetzt worden sein."
assert mistletoe.markdown(input, FiftyOhmHtmlRenderer) == paragraph(target)
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
+31
View File
@@ -1,8 +1,10 @@
import mistletoe
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
from test.util import paragraph
def test_paragraph_html():
input = "Der Test befindet sich unter §2 vielleicht aber auch § 3."
target = "Der Test befindet sich unter §&#160;2 vielleicht aber auch §&#160;3."
@@ -33,4 +35,33 @@ def test_class_html():
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
+15
View File
@@ -1,6 +1,7 @@
import mistletoe
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
from test.util import paragraph
@@ -17,3 +18,17 @@ def test_quote_html() :
for assertion in assertions:
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]
+44 -1
View File
@@ -1,6 +1,8 @@
import mistletoe
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
def test_thematic_break_html() :
@@ -39,4 +41,45 @@ def test_thematic_break_and_tag_html() :
}
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]
+12
View File
@@ -1,6 +1,7 @@
import mistletoe
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
from renderer.fifty_ohm_latex_renderer import FiftyOhmLaTeXRenderer
from test.util import paragraph
@@ -14,3 +15,14 @@ def test_underline_html() :
for assertion in assertions:
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]