11"""HTML formatting utilities for DataFusion DataFrames."""
22
3- from typing import Dict , Optional , Any , Union
3+ from typing import Dict , Optional , Any , Union , List
44
55
66class DataFrameHtmlFormatter :
@@ -56,26 +56,47 @@ def format_html(
5656 return "No data to display"
5757
5858 # Generate a unique ID if none provided
59- table_uuid = table_uuid or "df-" + str ( id (batches ))
59+ table_uuid = table_uuid or f "df-{ id (batches )} "
6060
61- # Start building HTML string
61+ # Build HTML components
6262 html = []
63+ html .extend (self ._build_html_header ())
64+ html .extend (self ._build_table_container_start ())
6365
64- # Add CSS styles
66+ html .extend (self ._build_table_header (schema ))
67+ html .extend (self ._build_table_body (batches , table_uuid ))
68+
69+ html .append ("</table>" )
70+ html .append ("</div>" )
71+
72+ # Add footer (JavaScript and messages)
73+ html .extend (self ._build_html_footer (has_more ))
74+
75+ return "\n " .join (html )
76+
77+ def _build_html_header (self ) -> List [str ]:
78+ """Build the HTML header with CSS styles."""
79+ html = []
6580 html .append ("<style>" )
6681 html .append (self ._get_default_css ())
6782 if self .custom_css :
6883 html .append (self .custom_css )
6984 html .append ("</style>" )
85+ return html
7086
71- # Create table container
87+ def _build_table_container_start (self ) -> List [str ]:
88+ """Build the opening tags for the table container."""
89+ html = []
7290 html .append (
7391 f'<div style="width: 100%; max-width: { self .max_width } px; '
7492 f'max-height: { self .max_height } px; overflow: auto; border: 1px solid #ccc;">'
7593 )
7694 html .append ('<table style="border-collapse: collapse; min-width: 100%">' )
95+ return html
7796
78- # Add table header
97+ def _build_table_header (self , schema : Any ) -> List [str ]:
98+ """Build the HTML table header with column names."""
99+ html = []
79100 html .append ("<thead>" )
80101 html .append ("<tr>" )
81102 for field in schema :
@@ -87,11 +108,13 @@ def format_html(
87108 )
88109 html .append ("</tr>" )
89110 html .append ("</thead>" )
111+ return html
90112
91- # Add table body
113+ def _build_table_body (self , batches : list , table_uuid : str ) -> List [str ]:
114+ """Build the HTML table body with data rows."""
115+ html = []
92116 html .append ("<tbody>" )
93117
94- # Process and add rows
95118 row_count = 0
96119 for batch in batches :
97120 for row_idx in range (batch .num_rows ):
@@ -105,34 +128,49 @@ def format_html(
105128 len (str (cell_value )) > self .max_cell_length
106129 and self .enable_cell_expansion
107130 ):
108- # Add expandable cell
109- short_value = str (cell_value )[: self .max_cell_length ]
110131 html .append (
111- f"<td style='border: 1px solid black; padding: 8px; "
112- f"text-align: left; white-space: nowrap;'>"
113- f"<div class='expandable-container'>"
114- f"<span class='expandable' id='{ table_uuid } -min-text-{ row_count } -{ col_idx } '>"
115- f"{ short_value } </span>"
116- f"<span class='full-text' id='{ table_uuid } -full-text-{ row_count } -{ col_idx } '>"
117- f"{ cell_value } </span>"
118- f"<button class='expand-btn' "
119- f"onclick=\" toggleDataFrameCellText('{ table_uuid } ',{ row_count } ,{ col_idx } )\" >"
120- f"...</button>"
121- f"</div>"
122- f"</td>"
132+ self ._build_expandable_cell (
133+ cell_value , row_count , col_idx , table_uuid
134+ )
123135 )
124136 else :
125- # Add regular cell
126- html .append (
127- f"<td style='border: 1px solid black; padding: 8px; "
128- f"text-align: left; white-space: nowrap;'>{ cell_value } </td>"
129- )
137+ html .append (self ._build_regular_cell (cell_value ))
130138
131139 html .append ("</tr>" )
132140
133141 html .append ("</tbody>" )
134- html .append ("</table>" )
135- html .append ("</div>" )
142+ return html
143+
144+ def _build_expandable_cell (
145+ self , cell_value : Any , row_count : int , col_idx : int , table_uuid : str
146+ ) -> str :
147+ """Build an expandable cell for long content."""
148+ short_value = str (cell_value )[: self .max_cell_length ]
149+ return (
150+ f"<td style='border: 1px solid black; padding: 8px; "
151+ f"text-align: left; white-space: nowrap;'>"
152+ f"<div class='expandable-container'>"
153+ f"<span class='expandable' id='{ table_uuid } -min-text-{ row_count } -{ col_idx } '>"
154+ f"{ short_value } </span>"
155+ f"<span class='full-text' id='{ table_uuid } -full-text-{ row_count } -{ col_idx } '>"
156+ f"{ cell_value } </span>"
157+ f"<button class='expand-btn' "
158+ f"onclick=\" toggleDataFrameCellText('{ table_uuid } ',{ row_count } ,{ col_idx } )\" >"
159+ f"...</button>"
160+ f"</div>"
161+ f"</td>"
162+ )
163+
164+ def _build_regular_cell (self , cell_value : Any ) -> str :
165+ """Build a regular table cell."""
166+ return (
167+ f"<td style='border: 1px solid black; padding: 8px; "
168+ f"text-align: left; white-space: nowrap;'>{ cell_value } </td>"
169+ )
170+
171+ def _build_html_footer (self , has_more : bool ) -> List [str ]:
172+ """Build the HTML footer with JavaScript and messages."""
173+ html = []
136174
137175 # Add JavaScript for interactivity
138176 if self .enable_cell_expansion :
@@ -142,7 +180,7 @@ def format_html(
142180 if has_more and self .show_truncation_message :
143181 html .append ("<div>Data truncated due to size.</div>" )
144182
145- return " \n " . join ( html )
183+ return html
146184
147185 def _format_cell_value (self , column : Any , row_idx : int ) -> str :
148186 """Format a cell value for display.
0 commit comments