1
1
"""HTML formatting utilities for DataFusion DataFrames."""
2
2
3
- from typing import Dict , Optional , Any , Union
3
+ from typing import Dict , Optional , Any , Union , List
4
4
5
5
6
6
class DataFrameHtmlFormatter :
@@ -56,26 +56,47 @@ def format_html(
56
56
return "No data to display"
57
57
58
58
# 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 )} "
60
60
61
- # Start building HTML string
61
+ # Build HTML components
62
62
html = []
63
+ html .extend (self ._build_html_header ())
64
+ html .extend (self ._build_table_container_start ())
63
65
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
8000
+ 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 = []
65
80
html .append ("<style>" )
66
81
html .append (self ._get_default_css ())
67
82
if self .custom_css :
68
83
html .append (self .custom_css )
69
84
html .append ("</style>" )
85
+ return html
70
86
71
- # Create table container
87
+ def _build_table_container_start (self ) -> List [str ]:
88
+ """Build the opening tags for the table container."""
89
+ html = []
72
90
html .append (
73
91
f'<div style="width: 100%; max-width: { self .max_width } px; '
74
92
f'max-height: { self .max_height } px; overflow: auto; border: 1px solid #ccc;">'
75
93
)
76
94
html .append ('<table style="border-collapse: collapse; min-width: 100%">' )
95
+ return html
77
96
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 = []
79
100
html .append ("<thead>" )
80
101
html .append ("<tr>" )
81
102
for field in schema :
@@ -87,11 +108,13 @@ def format_html(
87
108
)
88
109
html .append ("</tr>" )
89
110
html .append ("</thead>" )
111
+ return html
90
112
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 = []
92
116
html .append ("<tbody>" )
93
117
94
- # Process and add rows
95
118
row_count = 0
96
119
for batch in batches :
97
120
for row_idx in range (batch .num_rows ):
@@ -105,34 +128,49 @@ def format_html(
105
128
len (str (cell_value )) > self .max_cell_length
106
129
and self .enable_cell_expansion
107
130
):
108
- # Add expandable cell
109
- short_value = str (cell_value )[: self .max_cell_length ]
110
131
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
+ )
123
135
)
124
136
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 ))
130
138
131
139
html .append ("</tr>" )
132
140
133
141
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 )
CECA
-> List [str ]:
172
+ """Build the HTML footer with JavaScript and messages."""
173
+ html = []
136
174
137
175
# Add JavaScript for interactivity
138
176
if self .enable_cell_expansion :
@@ -142,7 +180,7 @@ def format_html(
142
180
if has_more and self .show_truncation_message :
143
181
html .append ("<div>Data truncated due to size.</div>" )
144
182
145
- return " \n " . join ( html )
183
+ return html
146
184
147
185
def _format_cell_value (self , column : Any , row_idx : int ) -> str :
148
186
"""Format a cell value for display.
0 commit comments