Coverage for lintro / formatters / styles / html.py: 100%

16 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2026-04-03 18:53 +0000

1"""HTML output style implementation.""" 

2 

3from typing import Any 

4 

5from lintro.formatters.core.format_registry import OutputStyle 

6 

7 

8class HtmlStyle(OutputStyle): 

9 """Output format that renders data as HTML table.""" 

10 

11 def format( 

12 self, 

13 columns: list[str], 

14 rows: list[list[Any]], 

15 tool_name: str | None = None, 

16 **kwargs: Any, 

17 ) -> str: 

18 """Format a table given columns and rows as HTML. 

19 

20 Args: 

21 columns: List of column header names. 

22 rows: List of row values (each row is a list of cell values). 

23 tool_name: Optional tool name to include in context. 

24 **kwargs: Extra options ignored by this formatter. 

25 

26 Returns: 

27 Formatted data as HTML table string. 

28 """ 

29 if not rows: 

30 return "<p>No issues found.</p>" 

31 

32 # Build the header 

33 header_cells = "".join(f"<th>{col}</th>" for col in columns) 

34 header = f"<tr>{header_cells}</tr>" 

35 

36 # Build the rows 

37 formatted_rows = [] 

38 for row in rows: 

39 # Ensure row has same number of elements as columns 

40 padded_row = row + [""] * (len(columns) - len(row)) 

41 # Escape HTML characters in cell values 

42 escaped_cells = [ 

43 str(cell) 

44 .replace("&", "&amp;") 

45 .replace("<", "&lt;") 

46 .replace(">", "&gt;") 

47 for cell in padded_row 

48 ] 

49 row_cells = "".join(f"<td>{cell}</td>" for cell in escaped_cells) 

50 formatted_rows.append(f"<tr>{row_cells}</tr>") 

51 

52 # Combine all parts 

53 table_content = header + "".join(formatted_rows) 

54 return f"<table>{table_content}</table>"