Merge branch 'main' into feature/unit-html-renderer
This commit is contained in:
+11
@@ -0,0 +1,11 @@
|
|||||||
|
kind: pipeline
|
||||||
|
type: docker
|
||||||
|
name: default
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: 50ohm.de
|
||||||
|
image: ghcr.io/astral-sh/uv:python3.12-bookworm
|
||||||
|
environment:
|
||||||
|
commands:
|
||||||
|
- uv pip install --system --break-system-packages --requirements requirements.txt
|
||||||
|
- cd test && pytest --junitxml=./test-reports/junit.xml
|
||||||
+11
-1
@@ -1,7 +1,17 @@
|
|||||||
|
import re
|
||||||
|
|
||||||
from mistletoe.block_token import BlockToken
|
from mistletoe.block_token import BlockToken
|
||||||
|
from mistletoe.span_token import SpanToken
|
||||||
|
|
||||||
|
|
||||||
class Comment(BlockToken):
|
class SpanComment(SpanToken):
|
||||||
|
"""
|
||||||
|
Coment span token (% Eiersalat).
|
||||||
|
Identifies a comment in text.
|
||||||
|
"""
|
||||||
|
pattern = re.compile(r'(%.*\n?)')
|
||||||
|
|
||||||
|
class BlockComment(BlockToken):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def start(line):
|
def start(line):
|
||||||
return line.startswith("%")
|
return line.startswith("%")
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import re
|
||||||
|
|
||||||
|
from mistletoe.span_token import SpanToken
|
||||||
|
|
||||||
|
|
||||||
|
class Dash(SpanToken):
|
||||||
|
"""
|
||||||
|
Dash span token ( - ).
|
||||||
|
Identifies a dash in a text.
|
||||||
|
"""
|
||||||
|
pattern = re.compile(r'(\s-\s)')
|
||||||
@@ -2,11 +2,15 @@ import textwrap
|
|||||||
|
|
||||||
from mistletoe import HtmlRenderer
|
from mistletoe import HtmlRenderer
|
||||||
|
|
||||||
from .comment import Comment
|
from renderer.comment import BlockComment, SpanComment
|
||||||
from .quote import Quote
|
from renderer.dash import Dash
|
||||||
from .tag import Tag
|
from renderer.halfwidth_spaces import HalfwidthSpaces
|
||||||
from .underline import Underline
|
from renderer.nonbreaking_spaces import NonbreakingSpaces, NonbreakingSpacesDots
|
||||||
from .unit import Unit
|
from renderer.quote import Quote
|
||||||
|
from renderer.references import References
|
||||||
|
from renderer.tag import Tag
|
||||||
|
from renderer.underline import Underline
|
||||||
|
from renderer.unit import Unit
|
||||||
|
|
||||||
units = {
|
units = {
|
||||||
"A": "A",
|
"A": "A",
|
||||||
@@ -26,7 +30,6 @@ units = {
|
|||||||
"cm": "cm",
|
"cm": "cm",
|
||||||
"m": "m",
|
"m": "m",
|
||||||
"m²": "m²",
|
"m²": "m²",
|
||||||
"Ohm": "Ω",
|
|
||||||
"ppm": "ppm",
|
"ppm": "ppm",
|
||||||
"pps": "pps",
|
"pps": "pps",
|
||||||
"s": "s",
|
"s": "s",
|
||||||
@@ -43,12 +46,35 @@ no_space_units = ["°", "%"]
|
|||||||
class FiftyOhmHtmlRenderer(HtmlRenderer):
|
class FiftyOhmHtmlRenderer(HtmlRenderer):
|
||||||
margin_anchor_id = 0
|
margin_anchor_id = 0
|
||||||
margin_id = 0
|
margin_id = 0
|
||||||
|
section_url = "section.html"
|
||||||
|
ref_id = 0
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__(Comment, Unit, Quote, Underline, Tag)
|
super().__init__(
|
||||||
|
Dash,
|
||||||
|
BlockComment,
|
||||||
|
SpanComment,
|
||||||
|
Quote,
|
||||||
|
Unit,
|
||||||
|
Underline,
|
||||||
|
Tag,
|
||||||
|
HalfwidthSpaces,
|
||||||
|
NonbreakingSpaces,
|
||||||
|
NonbreakingSpacesDots,
|
||||||
|
HalfwidthSpaces,
|
||||||
|
NonbreakingSpaces,
|
||||||
|
NonbreakingSpacesDots,
|
||||||
|
References,
|
||||||
|
)
|
||||||
|
|
||||||
def render_comment():
|
def render_dash(self, token):
|
||||||
return None
|
return " – "
|
||||||
|
|
||||||
|
def render_block_comment(self, token):
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def render_span_comment(self, token):
|
||||||
|
return ""
|
||||||
|
|
||||||
def render_quote(self, token):
|
def render_quote(self, token):
|
||||||
return f"„{self.render_inner(token)}“"
|
return f"„{self.render_inner(token)}“"
|
||||||
@@ -104,7 +130,7 @@ class FiftyOhmHtmlRenderer(HtmlRenderer):
|
|||||||
|
|
||||||
if token.tagtype == "webmargin":
|
if token.tagtype == "webmargin":
|
||||||
type = "margin"
|
type = "margin"
|
||||||
elif token.tagtype == "webtip":
|
elif token.tagtype == "webtipp":
|
||||||
type = "tipp"
|
type = "tipp"
|
||||||
elif token.tagtype == "webindepth":
|
elif token.tagtype == "webindepth":
|
||||||
type = "indepth"
|
type = "indepth"
|
||||||
@@ -114,3 +140,16 @@ class FiftyOhmHtmlRenderer(HtmlRenderer):
|
|||||||
return self.render_tag_helper(
|
return self.render_tag_helper(
|
||||||
type, self.render_inner(token), self.margin_id, self.margin_anchor_id
|
type, self.render_inner(token), self.margin_id, self.margin_anchor_id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
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]}"
|
||||||
|
|
||||||
|
def render_references(self, token):
|
||||||
|
return f'<a href="{self.section_url}#ref_{token.first}" onclick="highlightRef(\'{token.first}\');">{self.ref_id}</a>'
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import re
|
||||||
|
|
||||||
|
from mistletoe.span_token import SpanToken
|
||||||
|
|
||||||
|
|
||||||
|
class HalfwidthSpaces(SpanToken):
|
||||||
|
"""
|
||||||
|
Insert halfwidth space into span token (Z. B.)
|
||||||
|
Identifies "z.B.", "d.h." and "D.h." with and without space in between.
|
||||||
|
"""
|
||||||
|
pattern = re.compile(r"\b(z|d|D)\.(B|h)\.")
|
||||||
|
|
||||||
|
def __init__(self, match_object):
|
||||||
|
self.first = match_object.group(1)
|
||||||
|
self.second = match_object.group(2)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import re
|
||||||
|
|
||||||
|
from mistletoe.span_token import SpanToken
|
||||||
|
|
||||||
|
|
||||||
|
class NonbreakingSpaces(SpanToken):
|
||||||
|
"""
|
||||||
|
Insert unbreakable space into span token (§ 3)
|
||||||
|
Identifies "§$number", "Abs.$number", "Klasse [A,E,N]" w/ and w\ space between.
|
||||||
|
"""
|
||||||
|
pattern = re.compile(r"(§|Abs\.|Klasse)\s?(\d|[NEA])")
|
||||||
|
|
||||||
|
def __init__(self, match_object):
|
||||||
|
self.first = match_object.group(1)
|
||||||
|
self.second = match_object.group(2)
|
||||||
|
|
||||||
|
class NonbreakingSpacesDots(SpanToken):
|
||||||
|
"""
|
||||||
|
Insert unbreakable space before and after "..." if there is a space
|
||||||
|
Identifies "..." with leading and/or trailing space
|
||||||
|
"""
|
||||||
|
pattern = re.compile(r"(\s?)(\.\.\.)(\s?)")
|
||||||
|
|
||||||
|
def __init__(self, match_object):
|
||||||
|
self.first = match_object.group(1)
|
||||||
|
self.second = match_object.group(2)
|
||||||
|
self.third = match_object.group(3)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import re
|
||||||
|
|
||||||
|
from mistletoe.span_token import SpanToken
|
||||||
|
|
||||||
|
|
||||||
|
class References(SpanToken):
|
||||||
|
"""
|
||||||
|
Resolve references for html
|
||||||
|
Identifies "[ref:$]"
|
||||||
|
"""
|
||||||
|
pattern = re.compile(r"\[ref\:(\S+)\]")
|
||||||
|
|
||||||
|
def __init__(self, match_object):
|
||||||
|
self.first = match_object.group(1)
|
||||||
|
|
||||||
+13
-1
@@ -2,12 +2,24 @@ import re
|
|||||||
|
|
||||||
from mistletoe.block_token import BlockToken, tokenize
|
from mistletoe.block_token import BlockToken, tokenize
|
||||||
|
|
||||||
|
captures = [
|
||||||
|
"margin",
|
||||||
|
"indepth",
|
||||||
|
"webmargin",
|
||||||
|
"tipp",
|
||||||
|
"webtipp",
|
||||||
|
"webindepth",
|
||||||
|
"unit",
|
||||||
|
"danger",
|
||||||
|
"webonly",
|
||||||
|
"latexonly",
|
||||||
|
]
|
||||||
|
|
||||||
class Tag(BlockToken):
|
class Tag(BlockToken):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def start(line):
|
def start(line):
|
||||||
return re.match(r"^\s*<[^>]+>", line)
|
return re.match(r"^\s*<("+"|".join(captures)+r")+>", line)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def read(cls, lines):
|
def read(cls, lines):
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
coverage==7.6.9
|
||||||
|
iniconfig==2.0.0
|
||||||
|
mistletoe==1.4.0
|
||||||
|
packaging==24.2
|
||||||
|
pluggy==1.5.0
|
||||||
|
pytest==8.3.4
|
||||||
|
pytest-cov==6.0.0
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
def test_comment_html(capsys) :
|
||||||
|
|
||||||
|
assertions = {
|
||||||
|
"%Comment\nBar" : "<p>Bar</p>\n",
|
||||||
|
# TODO: This test is not working as expected. The comment should be removed
|
||||||
|
#"%Comment\n" : "a",
|
||||||
|
"Foo\n%Comment\nBar" : "<p>Foo\nBar</p>\n",
|
||||||
|
}
|
||||||
|
|
||||||
|
for assertion in assertions:
|
||||||
|
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == assertions[assertion]
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import mistletoe
|
||||||
|
|
||||||
|
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
|
||||||
|
from test.util import paragraph
|
||||||
|
|
||||||
|
|
||||||
|
def test_dash_html() :
|
||||||
|
|
||||||
|
assertions = {
|
||||||
|
"Foo - Bar" : "Foo – Bar",
|
||||||
|
}
|
||||||
|
|
||||||
|
for assertion in assertions:
|
||||||
|
assert mistletoe.markdown(assertion, FiftyOhmHtmlRenderer) == paragraph(assertions[assertion])
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import mistletoe
|
||||||
|
|
||||||
|
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
|
||||||
|
from test.util import paragraph
|
||||||
|
|
||||||
|
def test_halfwidth_space_html():
|
||||||
|
input = "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."
|
||||||
|
|
||||||
|
assert mistletoe.markdown(input, FiftyOhmHtmlRenderer) == paragraph(target)
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import mistletoe
|
||||||
|
|
||||||
|
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
|
||||||
|
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 § 2 vielleicht aber auch § 3."
|
||||||
|
|
||||||
|
assert mistletoe.markdown(input, FiftyOhmHtmlRenderer) == paragraph(target)
|
||||||
|
|
||||||
|
def test_three_points_html():
|
||||||
|
assertions = {
|
||||||
|
"Heute hatte ich ... zum Mittagessen." : "Heute hatte ich ... zum Mittagessen.",
|
||||||
|
"Niemals hätte ich gedacht, dass...ich ...nicht kann." : "Niemals hätte ich gedacht, dass...ich ...nicht kann.",
|
||||||
|
"Oh nein ...ein Pinguin." : "Oh nein ...ein Pinguin.",
|
||||||
|
"Haha .. . Hahaha" : "Haha .. . Hahaha"
|
||||||
|
}
|
||||||
|
|
||||||
|
for key, value in assertions.items():
|
||||||
|
assert mistletoe.markdown(key, FiftyOhmHtmlRenderer) == paragraph(value)
|
||||||
|
|
||||||
|
|
||||||
|
def test_absatz_html():
|
||||||
|
input = "Der Test befindet sich unter Abs.2 vielleicht aber auch Abs. 3."
|
||||||
|
target = "Der Test befindet sich unter Abs. 2 vielleicht aber auch Abs. 3."
|
||||||
|
|
||||||
|
assert mistletoe.markdown(input, FiftyOhmHtmlRenderer) == paragraph(target)
|
||||||
|
|
||||||
|
def test_class_html():
|
||||||
|
input = "Ich lerne für Klasse A, Klasse E und Klasse N."
|
||||||
|
target = "Ich lerne für Klasse A, Klasse E und Klasse N."
|
||||||
|
|
||||||
|
assert mistletoe.markdown(input, FiftyOhmHtmlRenderer) == paragraph(target)
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import mistletoe
|
||||||
|
|
||||||
|
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
|
||||||
|
from test.util import paragraph
|
||||||
|
|
||||||
|
|
||||||
|
def test_references_html():
|
||||||
|
# Right now this tests only the default values.
|
||||||
|
# The correct behavior can be tested when the information is added to the renderer class
|
||||||
|
assertions = {
|
||||||
|
"[ref:e_oszilloskop_bildschirmfoto_sinus]": '<a href="section.html#ref_e_oszilloskop_bildschirmfoto_sinus" onclick="highlightRef(\'e_oszilloskop_bildschirmfoto_sinus\');">0</a>',
|
||||||
|
"[ref:n_rst_r]": '<a href="section.html#ref_n_rst_r" onclick="highlightRef(\'n_rst_r\');">0</a>',
|
||||||
|
"[ref:Uuuuuh]": '<a href="section.html#ref_Uuuuuh" onclick="highlightRef(\'Uuuuuh\');">0</a>', # Test the default parameters
|
||||||
|
}
|
||||||
|
|
||||||
|
for key, value in assertions.items():
|
||||||
|
assert mistletoe.markdown(key, FiftyOhmHtmlRenderer) == paragraph(value)
|
||||||
+1
-1
@@ -18,7 +18,7 @@ def test_tag_html() :
|
|||||||
"<indepth>\nFoo\n</indepth>" : FiftyOhmHtmlRenderer.render_tag_helper("indepth","<p>Foo</p>",1,0)+'\n',
|
"<indepth>\nFoo\n</indepth>" : FiftyOhmHtmlRenderer.render_tag_helper("indepth","<p>Foo</p>",1,0)+'\n',
|
||||||
"<webmargin>\nFoo\n</webmargin>" : FiftyOhmHtmlRenderer.render_tag_helper("margin","<p>Foo</p>",1,0)+'\n',
|
"<webmargin>\nFoo\n</webmargin>" : FiftyOhmHtmlRenderer.render_tag_helper("margin","<p>Foo</p>",1,0)+'\n',
|
||||||
"<tipp>\nFoo\n</tipp>" : FiftyOhmHtmlRenderer.render_tag_helper("tipp","<p>Foo</p>",1,0)+'\n',
|
"<tipp>\nFoo\n</tipp>" : FiftyOhmHtmlRenderer.render_tag_helper("tipp","<p>Foo</p>",1,0)+'\n',
|
||||||
"<webtipp>\nFoo\n</webtipp>" : FiftyOhmHtmlRenderer.render_tag_helper("webtipp","<p>Foo</p>",1,0)+'\n',
|
"<webtipp>\nFoo\n</webtipp>" : FiftyOhmHtmlRenderer.render_tag_helper("tipp","<p>Foo</p>",1,0)+'\n',
|
||||||
"<webindepth>\nFoo\n</webindepth>" : FiftyOhmHtmlRenderer.render_tag_helper("indepth","<p>Foo</p>",1,0)+'\n',
|
"<webindepth>\nFoo\n</webindepth>" : FiftyOhmHtmlRenderer.render_tag_helper("indepth","<p>Foo</p>",1,0)+'\n',
|
||||||
"<unit>\nFoo\n</unit>" : FiftyOhmHtmlRenderer.render_tag_helper("unit","<p>Foo</p>",1,0)+'\n',
|
"<unit>\nFoo\n</unit>" : FiftyOhmHtmlRenderer.render_tag_helper("unit","<p>Foo</p>",1,0)+'\n',
|
||||||
"<danger>\nFoo\n</danger>" : FiftyOhmHtmlRenderer.render_tag_helper("danger","<p>Foo</p>",1,0)+'\n',
|
"<danger>\nFoo\n</danger>" : FiftyOhmHtmlRenderer.render_tag_helper("danger","<p>Foo</p>",1,0)+'\n',
|
||||||
|
|||||||
Reference in New Issue
Block a user