Coverage for src/pyTRLCConverter/render_config.py: 100%
77 statements
« prev ^ index » next coverage.py v7.14.3, created at 2026-06-26 12:41 +0000
« prev ^ index » next coverage.py v7.14.3, created at 2026-06-26 12:41 +0000
1""" Provides the render configuration to all converters.
3 Author: Andreas Merkle (andreas.merkle@newtec.de)
4"""
6# pyTRLCConverter - A tool to convert TRLC files to specific formats.
7# Copyright (c) 2024 - 2026 NewTec GmbH
8#
9# This file is part of pyTRLCConverter program.
10#
11# The pyTRLCConverter program is free software: you can redistribute it and/or modify it under
12# the terms of the GNU General Public License as published by the Free Software Foundation,
13# either version 3 of the License, or (at your option) any later version.
14#
15# The pyTRLCConverter program is distributed in the hope that it will be useful, but
16# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License along with pyTRLCConverter.
20# If not, see <https://www.gnu.org/licenses/>.
22# Imports **********************************************************************
23import json
24import re
26from pyTRLCConverter.logger import log_verbose
28# Variables ********************************************************************
30# Classes **********************************************************************
33class RenderConfig():
34 # lobster-trace: SwRequirements.sw_req_render_configuration
35 """Render configuration provider.
36 """
38 FORMAT_SPECIFIER_PLAIN = "plain" # Plain text format; no special formatting, e.g. for line breaks, lists, etc.
39 FORMAT_SPECIFIER_MD = "md" # CommonMark Markdown format; https://spec.commonmark.org/0.31.2/
40 FORMAT_SPECIFIER_RST = "rst" # ReStructuredText format; https://docutils.sourceforge.io/rst.html
41 FORMAT_SPECIFIER_GFM = "gfm" # GitHub Flavored Markdown format; https://github.github.com/gfm/
42 FORMAT_SPECIFIER_XHTML = "xhtml" # XHTML format; https://www.w3.org/TR/xhtml1/
43 FORMAT_SPECIFIER_PATH = "path" # File path format; the value is a path to an external file.
45 def __init__(self):
46 """Constructs the render configuration provider.
47 """
48 # The render configuration as dict.
49 #
50 # Example in JSON format:
51 # { "renderCfg": [{ "package": "XX", "type": "YY", "attribute": "ZZ", "format": "md",
52 # "tableOptions": { "border": "<css-style>", "headingStyle": "<css-style>" } }] }
53 self._cfg = {}
55 def load(self, file_name: str) -> bool:
56 """Loads the render configuration from the given file.
58 Args:
59 file_name (str): Path to the render configuration file.
61 Returns:
62 bool: True if successful, False otherwise.
63 """
64 status = False
66 log_verbose(f"Loading render configuration {file_name}.")
68 try:
69 with open(file_name, 'r', encoding='utf-8') as f:
70 self._cfg = json.load(f)
71 status = True
73 except FileNotFoundError:
74 pass
76 return status
78 def _is_package_match(self, item: dict, trlc_package: str) -> bool:
79 """Checks if the given TRLC package matches the package pattern in the given item.
81 Args:
82 item (dict): Single render configuration item.
83 trlc_package (str): The TRLC package.
85 Returns:
86 bool: If the given TRLC package matches the package pattern in the given item.
87 """
88 it_matches = False
90 if "package" in item:
91 if re.match(item["package"], trlc_package):
92 it_matches = True
94 return it_matches
96 def _is_type_match(self, item: dict, trlc_type: str) -> bool:
97 """Checks if the given TRLC type matches the type pattern in the given item.
99 Args:
100 item (dict): Single render configuration item.
101 trlc_type (str): The TRLC type.
103 Returns:
104 bool: If the given TRLC type matches the type pattern in the given item.
105 """
106 it_matches = False
108 if "type" in item:
109 if re.match(item["type"], trlc_type):
110 it_matches = True
112 return it_matches
114 def _is_type_attribute_match(self, item: dict, trlc_type_attribute: str) -> bool:
115 """Checks if the given TRLC type attribute matches the type attribute pattern in the given item.
117 Args:
118 item (dict): Single render configuration item.
119 trlc_type (str): The TRLC type attribute.
121 Returns:
122 bool: If the given TRLC type attribute matches the type attribute pattern in the given item.
123 """
124 it_matches = False
126 if "attribute" in item:
127 if re.match(item["attribute"], trlc_type_attribute):
128 it_matches = True
130 return it_matches
132 def get_format_specifier(self, trlc_package: str, trlc_type: str, trlc_type_attribute: str) -> str:
133 """Returns the format specifier for the given TRLC package, type and attribute.
135 Args:
136 trlc_package (str): The TRLC package.
137 trlc_type (str): The TRLC type.
138 trlc_type_attribute (str): The TRLC type attribute.
140 Returns:
141 str: The format specifier for the given TRLC package, type and attribute.
142 """
143 format_specifier = RenderConfig.FORMAT_SPECIFIER_PLAIN
145 if "renderCfg" in self._cfg:
146 for item in self._cfg["renderCfg"]:
147 match_list = []
149 match_list.append(self._is_package_match(item, trlc_package))
150 match_list.append(self._is_type_match(item, trlc_type))
151 match_list.append(self._is_type_attribute_match(item, trlc_type_attribute))
153 # All of the available ones must match!
154 if all(match_list):
155 if "format" in item:
156 format_specifier = item["format"]
158 # First match wins.
159 break
161 return format_specifier
163 def get_table_options(self, trlc_package: str, trlc_type: str, trlc_type_attribute: str) -> dict:
164 # lobster-trace: SwRequirements.sw_req_reqif_render_table_options
165 """Returns the table rendering options for the given TRLC package, type and attribute.
167 The returned dictionary may contain the following optional keys:
169 - ``"border"`` (str): CSS style value applied to the ``<table>`` element's ``style``
170 attribute (e.g. ``"border: 1px solid black; border-collapse: collapse;"``).
171 - ``"headingStyle"`` (str): CSS style value applied to each ``<th>`` cell's ``style``
172 attribute (e.g. ``"background-color: #c0c0c0;"``).
174 Args:
175 trlc_package (str): The TRLC package.
176 trlc_type (str): The TRLC type.
177 trlc_type_attribute (str): The TRLC type attribute.
179 Returns:
180 dict: Table options dict, or empty dict if no table options are configured.
181 """
182 table_options = {}
184 if "renderCfg" in self._cfg:
185 for item in self._cfg["renderCfg"]:
186 match_list = []
188 match_list.append(self._is_package_match(item, trlc_package))
189 match_list.append(self._is_type_match(item, trlc_type))
190 match_list.append(self._is_type_attribute_match(item, trlc_type_attribute))
192 # All of the available ones must match!
193 if all(match_list):
194 table_options = item.get("tableOptions", {})
196 # First match wins.
197 break
199 return table_options
201 def is_format_plain(self, trlc_package: str, trlc_type: str, trlc_type_attribute: str) -> bool:
202 """Checks if the given TRLC package, type and attribute should be rendered in plain text format.
204 Args:
205 trlc_package (str): The TRLC package.
206 trlc_type (str): The TRLC type.
207 trlc_type_attribute (str): The TRLC type attribute.
209 Returns:
210 bool: True if the given TRLC attribute has plain text format, otherwise False.
211 """
212 return self.get_format_specifier(trlc_package, trlc_type, trlc_type_attribute) == self.FORMAT_SPECIFIER_PLAIN
214 def is_format_md(self, trlc_package: str, trlc_type: str, trlc_type_attribute: str) -> bool:
215 """Checks if the given TRLC package, type and attribute should be rendered in markdown format.
217 Args:
218 trlc_package (str): The TRLC package.
219 trlc_type (str): The TRLC type.
220 trlc_type_attribute (str): The TRLC type attribute.
222 Returns:
223 bool: True if the given TRLC attribute has Markdown format, otherwise False.
224 """
225 return self.get_format_specifier(trlc_package, trlc_type, trlc_type_attribute) == self.FORMAT_SPECIFIER_MD
227 def is_format_rst(self, trlc_package: str, trlc_type: str, trlc_type_attribute: str) -> bool:
228 """Checks if the given TRLC package, type and attribute should be rendered in reStructuredText format.
230 Args:
231 trlc_package (str): The TRLC package.
232 trlc_type (str): The TRLC type.
233 trlc_type_attribute (str): The TRLC type attribute.
235 Returns:
236 bool: True if the given TRLC attribute has reStructuredText format, otherwise False.
237 """
238 return self.get_format_specifier(trlc_package, trlc_type, trlc_type_attribute) == self.FORMAT_SPECIFIER_RST
240 def is_format_gfm(self, trlc_package: str, trlc_type: str, trlc_type_attribute: str) -> bool:
241 """Checks if the given TRLC package, type and attribute should be rendered in GitHub Flavored Markdown format.
243 Args:
244 trlc_package (str): The TRLC package.
245 trlc_type (str): The TRLC type.
246 trlc_type_attribute (str): The TRLC type attribute.
248 Returns:
249 bool: True if the given TRLC attribute has GitHub Flavored Markdown format, otherwise False.
250 """
251 return self.get_format_specifier(trlc_package, trlc_type, trlc_type_attribute) == self.FORMAT_SPECIFIER_GFM
253 def is_format_xhtml(self, trlc_package: str, trlc_type: str, trlc_type_attribute: str) -> bool:
254 """Checks if the given TRLC package, type and attribute should be rendered in XHTML format.
256 Args:
257 trlc_package (str): The TRLC package.
258 trlc_type (str): The TRLC type.
259 trlc_type_attribute (str): The TRLC type attribute.
261 Returns:
262 bool: True if the given TRLC attribute has XHTML format, otherwise False.
263 """
264 return self.get_format_specifier(trlc_package, trlc_type, trlc_type_attribute) == self.FORMAT_SPECIFIER_XHTML
266 def is_format_path(self, trlc_package: str, trlc_type: str, trlc_type_attribute: str) -> bool:
267 """Checks if the given TRLC package, type and attribute should be rendered as a file path.
269 Args:
270 trlc_package (str): The TRLC package.
271 trlc_type (str): The TRLC type.
272 trlc_type_attribute (str): The TRLC type attribute.
274 Returns:
275 bool: True if the given TRLC attribute has path format, otherwise False.
276 """
277 return self.get_format_specifier(trlc_package, trlc_type, trlc_type_attribute) == self.FORMAT_SPECIFIER_PATH
280# Functions ********************************************************************
282# Main *************************************************************************