From 009697d25bc8393831e3f8b05681c8b8859cf372 Mon Sep 17 00:00:00 2001 From: bendichter Date: Thu, 9 Nov 2023 11:50:40 -0500 Subject: [PATCH] improve html display: * improve the title code * render tables correctly --- src/hdmf/common/table.py | 11 +++++ src/hdmf/container.py | 103 +++++++++++++++++++++------------------ 2 files changed, 66 insertions(+), 48 deletions(-) diff --git a/src/hdmf/common/table.py b/src/hdmf/common/table.py index e6f492022..b2b9d3f82 100644 --- a/src/hdmf/common/table.py +++ b/src/hdmf/common/table.py @@ -1192,6 +1192,17 @@ def to_dataframe(self, **kwargs): ret = self.__get_selection_as_df(sel) return ret + def generate_html_repr(self, level=0, access_code=""): + out = "" + for key, value in self.fields.items(): + if key not in ("id", "colnames", "columns"): + out += self._generate_field_html(key, value, level, access_code) + out += ( + f'
table{self.to_dataframe().to_html()}
' + ) + return out + @classmethod @docval( {'name': 'df', 'type': pd.DataFrame, 'doc': 'source DataFrame'}, diff --git a/src/hdmf/container.py b/src/hdmf/container.py index c83f85e1c..ccc7a3df7 100644 --- a/src/hdmf/container.py +++ b/src/hdmf/container.py @@ -562,8 +562,10 @@ def __repr__(self): template += " {}: {}\n".format(k, v) return template - def _repr_html_(self): - CSS_STYLE = """ + @property + def css_style(self) -> str: + """CSS styles for the HTML representation.""" + return """ """ - JS_SCRIPT = """ + @property + def js_script(self) -> str: + """JavaScript for the HTML representation.""" + return """ """ - if self.name == self.__class__.__name__: - header_text = self.name - else: - header_text = f"{self.name} ({self.__class__.__name__})" - html_repr = CSS_STYLE - html_repr += JS_SCRIPT + + def _repr_html_(self) -> str: + """Generates the HTML representation of the object.""" + header_text = self.name if self.name == self.__class__.__name__ else f"{self.name} ({self.__class__.__name__})" + html_repr = self.css_style + self.js_script html_repr += "
" - html_repr += ( - f"

{header_text}

" - ) - html_repr += self._generate_html_repr(self.fields) + html_repr += f"

{header_text}

" + html_repr += self._generate_html_repr(self.fields, is_field=True) html_repr += "
" return html_repr - def _generate_html_repr(self, fields, level=0, access_code=".fields"): + def _generate_html_repr(self, fields, level=0, access_code="", is_field=False): + """Recursively generates HTML representation for fields.""" html_repr = "" if isinstance(fields, dict): for key, value in fields.items(): - current_access_code = f"{access_code}['{key}']" - if ( - isinstance(value, (list, dict, np.ndarray)) - or hasattr(value, "fields") - ): - label = key - if isinstance(value, dict): - label += f" ({len(value)})" - - html_repr += ( - f'
{label}' - ) - if hasattr(value, "fields"): - value = value.fields - current_access_code = current_access_code + ".fields" - html_repr += self._generate_html_repr( - value, level + 1, current_access_code - ) - html_repr += "
" - else: - html_repr += ( - f'
{key}: {value}
' - ) + current_access_code = f"{access_code}.{key}" if is_field else f"{access_code}['{key}']" + html_repr += self._generate_field_html(key, value, level, current_access_code) elif isinstance(fields, list): for index, item in enumerate(fields): - current_access_code = f"{access_code}[{index}]" - html_repr += ( - f'
{str(item)}
' - ) + access_code += f'[{index}]' + html_repr += self._generate_field_html(index, item, level, access_code) elif isinstance(fields, np.ndarray): - str_ = str(fields).replace("\n", "
") - html_repr += ( - f'
{str_}
' - ) + html_repr += self._generate_array_html(fields, level) else: pass return html_repr + def _generate_field_html(self, key, value, level, access_code): + """Generates HTML for a single field.""" + + if isinstance(value, (int, float, str, bool)): + return f'
{key}: {value}
' + + if hasattr(value, "generate_html_repr"): + html_content = value.generate_html_repr(level + 1, access_code) + + elif hasattr(value, '__repr_html__'): + html_content = value.__repr_html__() + + elif hasattr(value, "fields"): + html_content = self._generate_html_repr(value.fields, level + 1, access_code, is_field=True) + elif isinstance(value, (list, dict, np.ndarray)): + html_content = self._generate_html_repr(value, level + 1, access_code, is_field=False) + else: + html_content = f'{value}' + html_repr = ( + f'
{key}' + ) + html_repr += html_content + html_repr += "
" + + return html_repr + + def _generate_array_html(self, array, level): + """Generates HTML for a NumPy array.""" + str_ = str(array).replace("\n", "
") + return f'
{str_}
' + @staticmethod def __smart_str(v, num_indent): """