Coverage for hdl_registers/generator/html/html_translator.py: 100%
26 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-02-15 20:50 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-02-15 20:50 +0000
1# --------------------------------------------------------------------------------------------------
2# Copyright (c) Lukas Vik. All rights reserved.
3#
4# This file is part of the hdl-registers project, an HDL register generator fast enough to run
5# in real time.
6# https://hdl-registers.com
7# https://github.com/hdl-registers/hdl-registers
8# --------------------------------------------------------------------------------------------------
10import re
13class HtmlTranslator:
14 r"""
15 Translate a raw text with markdown/rst annotations into HTML code.
17 Supports:
19 * Strong: **double asterisks**
20 * Emphasis: *single asterisks*
22 Literal asterisks should be escaped: \*
23 """
25 _not_escaped = r"(?<!\\)"
26 _double_asterisks = r"\*\*"
27 _single_asterisk = r"\*"
28 _match_text = r"(.*?)"
30 # These patterns match asterisks only if they are not preceded by \escape
31 _re_strong_pattern = re.compile(
32 _not_escaped + _double_asterisks + _match_text + _not_escaped + _double_asterisks
33 )
34 _re_emphasis_pattern = re.compile(
35 _not_escaped + _single_asterisk + _match_text + _not_escaped + _single_asterisk
36 )
38 # This pattern matches escaped asterisks
39 _re_escaped_literal_pattern = re.compile(r"\\(\*)")
41 # Consecutive newlines is a paragraph separator
42 _re_paragraph_separator = re.compile(r"\n{2,}")
44 def translate(self, text: str) -> str:
45 """
46 Translate the text to have HTML tags where appropriate.
47 """
48 result = self._translate_angle_brackets(text)
49 result = self._annotate(result)
50 return self._insert_line_breaks(result)
52 def _annotate(self, text: str) -> str:
53 """
54 Replace markdown/rst syntax with HTML tags.
55 """
56 result = re.sub(self._re_strong_pattern, r"<strong>\g<1></strong>", text)
57 result = re.sub(self._re_emphasis_pattern, r"<em>\g<1></em>", result)
59 # Remove the escape sign
60 return re.sub(self._re_escaped_literal_pattern, r"\g<1>", result)
62 def _insert_line_breaks(self, text: str) -> str:
63 """
64 Insert HTML line break tag instead of consecutive newlines.
65 """
66 # Two line breaks to get new paragraph.
67 result = re.sub(self._re_paragraph_separator, "<br /><br />", text)
69 # A single newline in Markdown should be a space
70 result = result.replace("\n", " ")
72 # Split to get nicer HTML file formatting
73 return result.replace("<br />", "<br />\n")
75 @staticmethod
76 def _translate_angle_brackets(text: str) -> str:
77 """
78 The HTML may not contain raw angle brackets ("<", ">") since they will be interpreted as
79 HTML tags by the web browse.
80 """
81 result = text.replace("<", "<")
82 return result.replace(">", ">")