@@ -297,15 +297,33 @@ def _serialize_table(table: Tag, *, remove_inline_citations: bool = False) -> st
297297 return f"$$ { eqn_text } $$"
298298
299299 rows = []
300- for row in table .find_all ("tr" , recursive = False ):
301- cells = row .find_all (["th" , "td" ], recursive = False )
302- if not cells :
303- continue
304- values = []
305- for cell in cells :
306- cell_text = _cleanup_inline_text (_serialize_inline (cell , remove_inline_citations = remove_inline_citations )).replace ("\n " , "<br>" )
307- values .append (cell_text )
308- rows .append (values )
300+ # Find rows in tbody, thead, tfoot, or directly in table
301+ # Handle nested structure where rows might be inside tbody/thead/tfoot
302+ tbody_elements = table .find_all (["tbody" , "thead" , "tfoot" ], recursive = False )
303+
304+ if tbody_elements :
305+ # Table has tbody/thead/tfoot structure - find rows within them
306+ for tbody in tbody_elements :
307+ for row in tbody .find_all ("tr" , recursive = False ):
308+ cells = row .find_all (["th" , "td" ], recursive = False )
309+ if not cells :
310+ continue
311+ values = []
312+ for cell in cells :
313+ cell_text = _cleanup_inline_text (_serialize_inline (cell , remove_inline_citations = remove_inline_citations )).replace ("\n " , "<br>" )
314+ values .append (cell_text )
315+ rows .append (values )
316+ else :
317+ # Table has no tbody/thead/tfoot - find rows directly in table
318+ for row in table .find_all ("tr" , recursive = False ):
319+ cells = row .find_all (["th" , "td" ], recursive = False )
320+ if not cells :
321+ continue
322+ values = []
323+ for cell in cells :
324+ cell_text = _cleanup_inline_text (_serialize_inline (cell , remove_inline_citations = remove_inline_citations )).replace ("\n " , "<br>" )
325+ values .append (cell_text )
326+ rows .append (values )
309327
310328 if not rows :
311329 return ""
@@ -323,18 +341,40 @@ def _serialize_table(table: Tag, *, remove_inline_citations: bool = False) -> st
323341
324342
325343def _serialize_figure (figure : Tag , * , remove_inline_citations : bool = False ) -> str :
344+ # Check if this is a table figure (ltx_table class)
345+ figure_classes = " " .join (figure .get ("class" , []))
346+ is_table_figure = "ltx_table" in figure_classes
347+
326348 caption_tag = figure .find ("figcaption" )
327349 caption = _normalize_text (_serialize_inline (caption_tag , remove_inline_citations = remove_inline_citations )) if caption_tag else ""
328- img = figure .find ("img" )
329- src = img .get ("src" ) if img else None
330- alt = img .get ("alt" ) if img else None
331350
332351 lines = []
333- if caption :
334- lines .append (f"Figure: { caption } " )
335- if src :
336- image_label = alt or "Image"
337- lines .append (f"{ image_label } : { src } " )
352+
353+ if is_table_figure :
354+ # Handle table figures - find and serialize the embedded table
355+ # Note: fix_tabular_tables strips attributes, so search for any table element
356+ table = figure .find ("table" )
357+ if table :
358+ table_md = _serialize_table (table , remove_inline_citations = remove_inline_citations )
359+ if caption :
360+ lines .append (f"**{ caption } **" )
361+ if table_md :
362+ lines .append (table_md )
363+ elif caption :
364+ # Fallback if no table found but has caption
365+ lines .append (f"Table: { caption } " )
366+ else :
367+ # Handle regular image figures
368+ img = figure .find ("img" )
369+ src = img .get ("src" ) if img else None
370+ alt = img .get ("alt" ) if img else None
371+
372+ if caption :
373+ lines .append (f"Figure: { caption } " )
374+ if src :
375+ image_label = alt or "Image"
376+ lines .append (f"{ image_label } : { src } " )
377+
338378 return "\n " .join (lines ).strip ()
339379
340380
0 commit comments