1# -*- coding: utf-8 -*-23from typing import List, Optional, Union4import re56from wireviz.DataClasses import Color7from wireviz.wv_colors import translate_color8from wireviz.wv_helper import remove_links910def nested_html_table(rows: List[Union[str, List[Optional[str]], None]], table_attrs: str = '') -> str:11 # input: list, each item may be scalar or list12 # output: a parent table with one child table per parent item that is list, and one cell per parent item that is scalar13 # purpose: create the appearance of one table, where cell widths are independent between rows14 # attributes in any leading <tdX> inside a list are injected into to the preceeding <td> tag15 html = []16 html.append(f'<table border="0" cellspacing="0" cellpadding="0"{table_attrs or ""}>')17 for row in rows:18 if isinstance(row, List):19 if len(row) > 0 and any(row):20 html.append(' <tr><td>')21 html.append(' <table border="0" cellspacing="0" cellpadding="3" cellborder="1"><tr>')22 for cell in row:23 if cell is not None:24 # Inject attributes to the preceeding <td> tag where needed25 html.append(f' <td balign="left">{cell}</td>'.replace('><tdX', ''))26 html.append(' </tr></table>')27 html.append(' </td></tr>')28 elif row is not None:29 html.append(' <tr><td>')30 html.append(f' {row}')31 html.append(' </td></tr>')32 html.append('</table>')33 return html3435def html_bgcolor_attr(color: Color) -> str:36 """Return attributes for bgcolor or '' if no color."""37 return f' bgcolor="{translate_color(color, "HEX")}"' if color else ''3839def html_bgcolor(color: Color, _extra_attr: str = '') -> str:40 """Return <td> attributes prefix for bgcolor or '' if no color."""41 return f'<tdX{html_bgcolor_attr(color)}{_extra_attr}>' if color else ''4243def html_colorbar(color: Color) -> str:44 """Return <tdX> attributes prefix for bgcolor and minimum width or None if no color."""45 return html_bgcolor(color, ' width="4"') if color else None4647def html_image(image):48 from wireviz.DataClasses import Image49 if not image:50 return None51 # The leading attributes belong to the preceeding tag. See where used below.52 html = f'{html_size_attr(image)}><img scale="{image.scale}" src="{image.src}"/>'53 if image.fixedsize:54 # Close the preceeding tag and enclose the image cell in a table without55 # borders to avoid narrow borders when the fixed width < the node width.56 html = f'''>57 <table border="0" cellspacing="0" cellborder="0"><tr>58 <td{html}</td>59 </tr></table>60 '''61 return f'''<tdX{' sides="TLR"' if image.caption else ''}{html_bgcolor_attr(image.bgcolor)}{html}'''6263def html_caption(image):64 from wireviz.DataClasses import Image65 return (f'<tdX sides="BLR"{html_bgcolor_attr(image.bgcolor)}>{html_line_breaks(image.caption)}'66 if image and image.caption else None)6768def html_size_attr(image):69 from wireviz.DataClasses import Image70 # Return Graphviz HTML attributes to specify minimum or fixed size of a TABLE or TD object71 return ((f' width="{image.width}"' if image.width else '')72 + (f' height="{image.height}"' if image.height else '')73 + ( ' fixedsize="true"' if image.fixedsize else '')) if image else ''7475def html_line_breaks(inp):76 return remove_links(inp).replace('\n', '<br />') if isinstance(inp, str) else inp