@@ -77,8 +77,12 @@ class DataFrameHtmlFormatter:
77
77
custom_css: Additional CSS to include in the HTML output
78
78
show_truncation_message: Whether to display a message when data is truncated
79
79
style_provider: Custom provider for cell and header styles
80
+ use_shared_styles: Whether to load styles and scripts only once per notebook session
80
81
"""
81
82
83
+ # Class variable to track if styles have been loaded in the notebook
84
+ _styles_loaded = False
85
+
82
86
def __init__ (
83
87
self ,
84
88
max_cell_length : int = 25 ,
@@ -88,6 +92,7 @@ def __init__(
88
92
custom_css : Optional [str ] = None ,
89
93
show_truncation_message : bool = True ,
90
94
style_provider : Optional [StyleProvider ] = None ,
95
+ use_shared_styles : bool = True ,
91
96
):
92
97
# Validate numeric parameters
93
98
if not isinstance (max_cell_length , int ) or max_cell_length <= 0 :
@@ -102,6 +107,8 @@ def __init__(
102
107
raise TypeError ("enable_cell_expansion must be a boolean" )
103
108
if not isinstance (show_truncation_message , bool ):
104
109
raise TypeError ("show_truncation_message must be a boolean" )
110
+ if not isinstance (use_shared_styles , bool ):
111
+ raise TypeError ("use_shared_styles must be a boolean" )
105
112
106
113
# Validate custom_css
107
114
if custom_css is not None and not isinstance (custom_css , str ):
@@ -118,6 +125,7 @@ def __init__(
118
125
self .custom_css = custom_css
119
126
self .show_truncation_message = show_truncation_message
120
127
self .style_provider = style_provider or DefaultStyleProvider ()
128
+ self .use_shared_styles = use_shared_styles
121
129
# Registry for custom type formatters
122
130
self ._type_formatters : Dict [Type , CellFormatter ] = {}
123
131
# Custom cell builders
@@ -181,7 +189,20 @@ def format_html(
181
189
182
190
# Build HTML components
183
191
html = []
184
- html .extend (self ._build_html_header ())
192
+
193
+ # Only include styles and scripts if:
194
+ # 1. Not using shared styles, OR
195
+ # 2. Using shared styles but they haven't been loaded yet
196
+ include_styles = (
197
+ not self .use_shared_styles or not DataFrameHtmlFormatter ._styles_loaded
198
+ )
199
+
200
+ if include_styles :
201
+ html .extend (self ._build_html_header ())
202
+ # If we're using shared styles, mark them as loaded
203
+ if self .use_shared_styles :
204
+ DataFrameHtmlFormatter ._styles_loaded = True
205
+
185
206
html .extend (self ._build_table_container_start ())
186
207
187
208
# Add table header and body
@@ -191,8 +212,13 @@ def format_html(
191
212
html .append ("</table>" )
192
213
html .append ("</div>" )
193
214
194
- # Add footer (JavaScript and messages)
195
- html .extend (self ._build_html_footer (has_more ))
215
+ # Add footer with JavaScript only if needed
216
+ if include_styles and self .enable_cell_expansion :
217
+ html .append (self ._get_javascript ())
218
+
219
+ # Always add truncation message if needed (independent of styles)
220
+ if has_more and self .show_truncation_message :
221
+ html .append ("<div>Data truncated due to size.</div>" )
196
222
197
223
return "\n " .join (html )
198
224
@@ -353,7 +379,8 @@ def _build_html_footer(self, has_more: bool) -> List[str]:
353
379
html = []
354
380
355
381
# Add JavaScript for interactivity only if cell expansion is enabled
356
- if self .enable_cell_expansion :
382
+ # and we're not using the shared styles approach
383
+ if self .enable_cell_expansion and not self .use_shared_styles :
357
384
html .append (self ._get_javascript ())
358
385
359
386
# Add truncation message if needed
@@ -457,10 +484,22 @@ def reset_formatter() -> None:
457
484
global _default_formatter
458
485
_default_formatter = DataFrameHtmlFormatter ()
459
486
487
+ # Reset the styles_loaded flag to ensure styles will be reloaded
488
+ DataFrameHtmlFormatter ._styles_loaded = False
489
+
460
490
# Ensure the changes are reflected in existing DataFrames
461
491
_refresh_formatter_reference ()
462
492
463
493
494
+ def reset_styles_loaded_state () -> None :
495
+ """Reset the styles loaded state to force reloading of styles.
496
+
497
+ This can be useful when switching between notebook sessions or
498
+ when styles need to be refreshed.
499
+ """
500
+ DataFrameHtmlFormatter ._styles_loaded = False
501
+
502
+
464
503
def _refresh_formatter_reference () -> None :
465
504
"""Refresh formatter reference in any modules using it.
466
505
0 commit comments