Pull request #13: feat: render units with non-breaking space
Merge in FRAG/50ohm.de from feature/unit-html-renderer to main * commit '4c82c9fb146332bd3abe8e2d1d0308aafbdc54d4': refactor: improve code readability feat: improve tests for unit rendering refactor: use helper to format unit refactor: create module feat: render units with non-breaking space
This commit is contained in:
@@ -1,8 +0,0 @@
|
|||||||
import sys
|
|
||||||
|
|
||||||
import mistletoe
|
|
||||||
from fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
with open(sys.argv[1]) as fin, open(sys.argv[2], "w") as fout:
|
|
||||||
fout.write(mistletoe.markdown(fin, FiftyOhmHtmlRenderer))
|
|
||||||
@@ -10,6 +10,7 @@ from renderer.quote import Quote
|
|||||||
from renderer.references import References
|
from renderer.references import References
|
||||||
from renderer.tag import Tag
|
from renderer.tag import Tag
|
||||||
from renderer.underline import Underline
|
from renderer.underline import Underline
|
||||||
|
from renderer.unit import Unit
|
||||||
|
|
||||||
|
|
||||||
class FiftyOhmHtmlRenderer(HtmlRenderer):
|
class FiftyOhmHtmlRenderer(HtmlRenderer):
|
||||||
@@ -24,6 +25,7 @@ class FiftyOhmHtmlRenderer(HtmlRenderer):
|
|||||||
BlockComment,
|
BlockComment,
|
||||||
SpanComment,
|
SpanComment,
|
||||||
Quote,
|
Quote,
|
||||||
|
Unit,
|
||||||
Underline,
|
Underline,
|
||||||
Tag,
|
Tag,
|
||||||
HalfwidthSpaces,
|
HalfwidthSpaces,
|
||||||
@@ -50,6 +52,31 @@ class FiftyOhmHtmlRenderer(HtmlRenderer):
|
|||||||
def render_underline(self, token):
|
def render_underline(self, token):
|
||||||
return f"<u>{self.render_inner(token)}</u>"
|
return f"<u>{self.render_inner(token)}</u>"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def render_unit(cls, token: Unit):
|
||||||
|
unit = token.prefix + cls.convert_unit_helper(token.unit)
|
||||||
|
if token.unit in ["°", "%"]:
|
||||||
|
# Special cases with no space between value and unit.
|
||||||
|
return f"{token.value}{unit}"
|
||||||
|
else:
|
||||||
|
# Default case is rendered with a narrow no-break space.
|
||||||
|
return f"{token.value} {unit}"
|
||||||
|
|
||||||
|
units = {
|
||||||
|
"Ohm": "Ω",
|
||||||
|
}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def convert_unit_helper(cls, unit: str) -> str:
|
||||||
|
"""Converts human-typable units to their preferred representation.
|
||||||
|
|
||||||
|
:param str unit: The unit to convert
|
||||||
|
"""
|
||||||
|
if unit in cls.units.keys():
|
||||||
|
return cls.units[unit]
|
||||||
|
else:
|
||||||
|
return unit
|
||||||
|
|
||||||
def render_thematic_break(self, token):
|
def render_thematic_break(self, token):
|
||||||
self.margin_anchor_id += 1
|
self.margin_anchor_id += 1
|
||||||
return f'<a id="margin_{self.margin_anchor_id}"></a>'
|
return f'<a id="margin_{self.margin_anchor_id}"></a>'
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
import re
|
||||||
|
|
||||||
|
from mistletoe.span_token import SpanToken
|
||||||
|
|
||||||
|
|
||||||
|
class Unit(SpanToken):
|
||||||
|
units = [
|
||||||
|
"A",
|
||||||
|
"Ah",
|
||||||
|
"A/mm²",
|
||||||
|
"baud",
|
||||||
|
"Bit",
|
||||||
|
"Bit/s",
|
||||||
|
"dB",
|
||||||
|
"dBi",
|
||||||
|
"dBm",
|
||||||
|
"dBW",
|
||||||
|
"F",
|
||||||
|
"J",
|
||||||
|
"Hz",
|
||||||
|
"H",
|
||||||
|
"cm",
|
||||||
|
"m",
|
||||||
|
"m²",
|
||||||
|
"Ohm",
|
||||||
|
"ppm",
|
||||||
|
"pps",
|
||||||
|
"s",
|
||||||
|
"V",
|
||||||
|
"W",
|
||||||
|
"Wh",
|
||||||
|
"°",
|
||||||
|
"%",
|
||||||
|
]
|
||||||
|
prefixes = ["p", "n", "μ", "m", "k", "M", "G"]
|
||||||
|
|
||||||
|
pattern = re.compile(
|
||||||
|
r"(?P<value>[0-9,]+) ?(?P<prefix>"
|
||||||
|
# Group all prefixes together in a capture group
|
||||||
|
# Empty string at end of list is required so the group always exists in the resulting match
|
||||||
|
+ "|".join(prefixes + [""])
|
||||||
|
+ ")(?P<unit>"
|
||||||
|
# Group all units together in a capture group.
|
||||||
|
+ "|".join(units)
|
||||||
|
+ r")(?!\w)"
|
||||||
|
)
|
||||||
|
|
||||||
|
value: str
|
||||||
|
prefix: str
|
||||||
|
unit: str
|
||||||
|
|
||||||
|
def __init__(self, match: re.Match):
|
||||||
|
self.value = match.group("value")
|
||||||
|
self.prefix = match.group("prefix") or ""
|
||||||
|
self.unit = match.group("unit")
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
import mistletoe
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
|
||||||
|
|
||||||
|
from .util import paragraph
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.html
|
||||||
|
def test_basic_units_html():
|
||||||
|
"""Test basic units: Insert non-breaking, smaller space."""
|
||||||
|
assertions = {
|
||||||
|
"1 V": "1 V",
|
||||||
|
"0,12 V": "0,12 V",
|
||||||
|
"0,75 kW": "0,75 kW",
|
||||||
|
"33 A": "33 A",
|
||||||
|
"1 Ah": "1 Ah", # Ah can be a tricky case if the RegEx is wrong, as A might match before Ah, thus rendering the output with an "A" unit
|
||||||
|
}
|
||||||
|
|
||||||
|
for input, output in assertions.items():
|
||||||
|
assert mistletoe.markdown(input, FiftyOhmHtmlRenderer) == paragraph(output)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.html
|
||||||
|
def test_translated_units_html():
|
||||||
|
"""Test translated units: Replace Ohm with Ω."""
|
||||||
|
assertions = {
|
||||||
|
"50 Ohm": "50 Ω",
|
||||||
|
"100 mOhm": "100 mΩ",
|
||||||
|
}
|
||||||
|
|
||||||
|
for input, output in assertions.items():
|
||||||
|
assert mistletoe.markdown(input, FiftyOhmHtmlRenderer) == paragraph(output)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.html
|
||||||
|
def test_special_units_html():
|
||||||
|
"""Test special units: Don't put space before ° and %."""
|
||||||
|
assertions = {
|
||||||
|
"100%": "100%",
|
||||||
|
"42,24°": "42,24°",
|
||||||
|
}
|
||||||
|
|
||||||
|
for input, output in assertions.items():
|
||||||
|
assert mistletoe.markdown(input, FiftyOhmHtmlRenderer) == paragraph(output)
|
||||||
+2
-2
@@ -1,2 +1,2 @@
|
|||||||
def paragraph(text) :
|
def paragraph(text):
|
||||||
return f'<p>{text}</p>\n'
|
return f"<p>{text}</p>\n"
|
||||||
|
|||||||
Reference in New Issue
Block a user