Coverage for hdl_registers/generator/html/page.py: 100%

42 statements  

« prev     ^ index     » next       coverage.py v7.6.10, created at 2025-01-28 20:51 +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# -------------------------------------------------------------------------------------------------- 

9 

10# Standard libraries 

11from pathlib import Path 

12from typing import Any, Optional 

13 

14# First party libraries 

15from hdl_registers.register_modes import REGISTER_MODES 

16 

17# Local folder libraries 

18from .constant_table import HtmlConstantTableGenerator 

19from .html_generator_common import HtmlGeneratorCommon 

20from .register_table import HtmlRegisterTableGenerator 

21 

22 

23class HtmlPageGenerator(HtmlGeneratorCommon): 

24 """ 

25 Generate a HTML page with register and constant information. 

26 See the :ref:`generator_html` article for usage details. 

27 """ 

28 

29 __version__ = "1.0.0" 

30 

31 SHORT_DESCRIPTION = "HTML page" 

32 

33 @property 

34 def output_file(self) -> Path: 

35 """ 

36 Result will be placed in this file. 

37 """ 

38 return self.output_folder / f"{self.name}_regs.html" 

39 

40 def get_code(self, **kwargs: Any) -> str: 

41 """ 

42 Get a complete HTML page with register and constant information. 

43 """ 

44 title = f"Documentation of {self.name} registers" 

45 html = f"""\ 

46<!DOCTYPE html> 

47<html> 

48<head> 

49 <title>{title}</title> 

50 <!-- Include the style both inline and as a link to a separate CSS file. --> 

51 <!-- Some tools, e.g. Jenkins, will not render with an inline stylesheet. --> 

52 <!-- For other tools, e.g. page inclusion in sphinx, the style must be in the file. --> 

53 <link rel="stylesheet" href="regs_style.css"> 

54 <style> 

55 {self.get_page_style()} 

56 </style> 

57</head> 

58<body> 

59 <h1>{title}</h1> 

60 <p>This document is a specification for the register interface of the FPGA module \ 

61<b>{self.name}</b>.</p> 

62 <p>{' '.join(self.generated_source_info)}</p> 

63 <h2>Register modes</h2> 

64 <p>The following register modes are available.</p> 

65{self._get_mode_descriptions()} 

66""" 

67 

68 html += " <h2>Registers</h2>\n" 

69 if self.register_list.register_objects: 

70 register_table_generator = HtmlRegisterTableGenerator( 

71 register_list=self.register_list, output_folder=self.output_folder 

72 ) 

73 html += f""" 

74 <p>The following registers make up the register list.</p> 

75{register_table_generator.get_code()} 

76""" 

77 else: 

78 html += " <p>This module does not have any registers.</p>" 

79 

80 html += " <h2>Constants</h2>\n" 

81 if self.register_list.constants: 

82 constant_table_generator = HtmlConstantTableGenerator( 

83 register_list=self.register_list, output_folder=self.output_folder 

84 ) 

85 html += f""" 

86 <p>The following constants are part of the register interface.</p> 

87{constant_table_generator.get_code()}""" 

88 else: 

89 html += " <p>This module does not have any constants.</p>" 

90 

91 html += """ 

92</body> 

93</html>""" 

94 

95 return html 

96 

97 @staticmethod 

98 def get_page_style( 

99 table_style: Optional[str] = None, font_style: Optional[str] = None, extra_style: str = "" 

100 ) -> str: 

101 """ 

102 Get a CSS style for the register pages. Shall be saved to a file called ``regs_style.css``. 

103 

104 Return: 

105 str: CSS code. 

106 """ 

107 if font_style is None: 

108 font_style = """ 

109html * { 

110 font-family: "Trebuchet MS", Arial, Helvetica, sans-serif; 

111}""" 

112 

113 if table_style is None: 

114 table_style = """ 

115table { 

116 border-collapse: collapse; 

117} 

118td, th { 

119 border-width: 1px; 

120 border-style: solid; 

121 border-color: #ddd; 

122 padding: 8px; 

123} 

124td.array_header { 

125 border-top-width: 10px; 

126 border-top-color: #4cacaf; 

127} 

128td.array_footer { 

129 border-bottom-width: 10px; 

130 border-bottom-color: #4cacaf; 

131} 

132tr:nth-child(even) { 

133 background-color: #f2f2f2; 

134} 

135th { 

136 padding-top: 12px; 

137 padding-bottom: 12px; 

138 text-align: left; 

139 background-color: #4CAF50; 

140 color: white; 

141}""" 

142 

143 style = f""" 

144{font_style} 

145{table_style} 

146{extra_style}""" 

147 return style 

148 

149 @staticmethod 

150 def _get_mode_descriptions() -> str: 

151 html = """ 

152<table> 

153<thead> 

154 <tr> 

155 <th>Mode</th> 

156 <th>Description</th> 

157 </tr> 

158</thead> 

159<tbody>""" 

160 

161 for mode in REGISTER_MODES.values(): 

162 html += f""" 

163<tr> 

164 <td>{mode.name}</td> 

165 <td>{mode.description}</td> 

166</tr> 

167""" 

168 html += """ 

169</tbody> 

170</table>""" 

171 return html