# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: OpenMDW-1.1 """Relocate only plain above-chart captions with geometric/preservation guards.""" import re from bs4 import BeautifulSoup BLOCK=re.compile(r'()(.*?)(]+)>)',re.S) def plain(text): text=text.replace('','').strip() if any(marker in text for marker in ['**','__','~~','`']):return None if re.search(r'(?other[1]:continue # Attach above-object captions only; retain notes below as standalone. width=min(box[2]-box[0],other[2]-other[0]);overlap=max(0,min(box[2],other[2])-max(box[0],other[0]));gap=max(other[1]-box[3],box[1]-other[3]) if width>0 and overlap/width>=.8 and 0<=gap<=.03:candidates.append((gap,j)) candidates.sort() if not candidates or (len(candidates)>1 and abs(candidates[0][0]-candidates[1][0])<1e-9):continue gap,j=candidates[0];eligible.setdefault(j,[]).append((gap,i)) for j,caps in eligible.items(): caps.sort() if len(caps)>1 and abs(caps[0][0]-caps[1][0])<1e-9:continue caption_index=caps[0][1];label=plain(matches[caption_index][4]);m=matches[j];body=m[4] if len(re.findall(r']*>)',lambda q:q[0]+'\ntitle: '+label,body,count=1) derived=m[1]+body+m[5] rendered=render_base(derived) # Do not move text unless it survives inside an actual table caption. captions=BeautifulSoup(rendered,'html.parser').find_all('caption') if not any(label in cap.get_text(' ',strip=True) for cap in captions):continue targets[m.start()]=derived moved.add(matches[caption_index].start()) if not targets:return markdown derived=BLOCK.sub(lambda m:'' if m.start() in moved else targets.get(m.start(),m[0]),raw) return render_base(derived)