@@ -120,8 +120,9 @@ def __init__(
120120 "level" : "level" ,
121121 "data" : "data" ,
122122 "blank" : "blank" ,
123+ "foot" : "foot" ,
123124 }
124-
125+ self . concatenated : StylerRenderer | None = None
125126 # add rendering variables
126127 self .hide_index_names : bool = False
127128 self .hide_column_names : bool = False
@@ -148,6 +149,35 @@ def __init__(
148149 tuple [int , int ], Callable [[Any ], str ]
149150 ] = defaultdict (lambda : partial (_default_formatter , precision = precision ))
150151
152+ def _render (
153+ self ,
154+ sparse_index : bool ,
155+ sparse_columns : bool ,
156+ max_rows : int | None = None ,
157+ max_cols : int | None = None ,
158+ blank : str = "" ,
159+ ):
160+ """
161+ Computes and applies styles and then generates the general render dicts
162+ """
163+ self ._compute ()
164+ dx = None
165+ if self .concatenated is not None :
166+ self .concatenated .hide_index_ = self .hide_index_
167+ self .concatenated .hidden_columns = self .hidden_columns
168+ self .concatenated .css = {
169+ ** self .css ,
170+ "data" : f"{ self .css ['foot' ]} _{ self .css ['data' ]} " ,
171+ "row_heading" : f"{ self .css ['foot' ]} _{ self .css ['row_heading' ]} " ,
172+ "row" : f"{ self .css ['foot' ]} _{ self .css ['row' ]} " ,
173+ "foot" : self .css ["foot" ],
174+ }
175+ dx , _ = self .concatenated ._render (
176+ sparse_index , sparse_columns , max_rows , max_cols , blank
177+ )
178+ d = self ._translate (sparse_index , sparse_columns , max_rows , max_cols , blank , dx )
179+ return d , dx
180+
151181 def _render_html (
152182 self ,
153183 sparse_index : bool ,
@@ -160,9 +190,7 @@ def _render_html(
160190 Renders the ``Styler`` including all applied styles to HTML.
161191 Generates a dict with necessary kwargs passed to jinja2 template.
162192 """
163- self ._compute ()
164- # TODO: namespace all the pandas keys
165- d = self ._translate (sparse_index , sparse_columns , max_rows , max_cols )
193+ d , _ = self ._render (sparse_index , sparse_columns , max_rows , max_cols , " " )
166194 d .update (kwargs )
167195 return self .template_html .render (
168196 ** d ,
@@ -176,16 +204,12 @@ def _render_latex(
176204 """
177205 Render a Styler in latex format
178206 """
179- self ._compute ()
180-
181- d = self ._translate (sparse_index , sparse_columns , blank = "" )
207+ d , _ = self ._render (sparse_index , sparse_columns , None , None )
182208 self ._translate_latex (d , clines = clines )
183-
184209 self .template_latex .globals ["parse_wrap" ] = _parse_latex_table_wrapping
185210 self .template_latex .globals ["parse_table" ] = _parse_latex_table_styles
186211 self .template_latex .globals ["parse_cell" ] = _parse_latex_cell_styles
187212 self .template_latex .globals ["parse_header" ] = _parse_latex_header_span
188-
189213 d .update (kwargs )
190214 return self .template_latex .render (** d )
191215
@@ -200,10 +224,7 @@ def _render_string(
200224 """
201225 Render a Styler in string format
202226 """
203- self ._compute ()
204-
205- d = self ._translate (sparse_index , sparse_columns , max_rows , max_cols , blank = "" )
206-
227+ d , _ = self ._render (sparse_index , sparse_columns , max_rows , max_cols )
207228 d .update (kwargs )
208229 return self .template_string .render (** d )
209230
@@ -231,6 +252,7 @@ def _translate(
231252 max_rows : int | None = None ,
232253 max_cols : int | None = None ,
233254 blank : str = " " ,
255+ dx : dict | None = None ,
234256 ):
235257 """
236258 Process Styler data and settings into a dict for template rendering.
@@ -246,10 +268,12 @@ def _translate(
246268 sparse_cols : bool
247269 Whether to sparsify the columns or print all hierarchical column elements.
248270 Upstream defaults are typically to `pandas.options.styler.sparse.columns`.
249- blank : str
250- Entry to top-left blank cells.
251271 max_rows, max_cols : int, optional
252272 Specific max rows and cols. max_elements always take precedence in render.
273+ blank : str
274+ Entry to top-left blank cells.
275+ dx : dict
276+ The render dict of the concatenated Styler.
253277
254278 Returns
255279 -------
@@ -295,7 +319,7 @@ def _translate(
295319 self .cellstyle_map_index : DefaultDict [
296320 tuple [CSSPair , ...], list [str ]
297321 ] = defaultdict (list )
298- body = self ._translate_body (idx_lengths , max_rows , max_cols )
322+ body : list = self ._translate_body (idx_lengths , max_rows , max_cols )
299323 d .update ({"body" : body })
300324
301325 ctx_maps = {
@@ -310,6 +334,11 @@ def _translate(
310334 ]
311335 d .update ({k : map })
312336
337+ if dx is not None : # self.concatenated is not None
338+ d ["body" ].extend (dx ["body" ]) # type: ignore[union-attr]
339+ d ["cellstyle" ].extend (dx ["cellstyle" ]) # type: ignore[union-attr]
340+ d ["cellstyle_index" ].extend (dx ["cellstyle" ]) # type: ignore[union-attr]
341+
313342 table_attr = self .table_attributes
314343 if not get_option ("styler.html.mathjax" ):
315344 table_attr = table_attr or ""
0 commit comments