# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: OpenMDW-1.1 """Decode known rich inline commands for the legacy tabular fallback. Used only after strict rich-grid parsing fails. This preserves unknown commands and malformed arguments; it never invents cell contents or repairs table spans. """ import html import re try: from .hybrid_cleanup import decode_styles except ImportError: from hybrid_cleanup import decode_styles try: from .rich_table_reader import TAGS, LITERALS, argument except ImportError: from rich_table_reader import TAGS, LITERALS, argument def decode_known_inline(text, _depth=0): """Decode balanced, recognized inline arguments without exposing delimiters.""" if _depth > 64: return text out = [] i = 0 known = set(TAGS) | set(LITERALS) | {'thead', 'linebreak', 'mbox', 'hl', 'colorbox'} while i < len(text): # Preserve escaped literal characters. In particular, an escaped # backslash followed by 'thead' must not become a formatting command. if text[i] == '\\' and i + 1 < len(text) and not text[i + 1].isalpha(): literal = text[i + 1] out.append('\\&#' + str(ord(literal)) + ';' if literal in '&%$#_*{}' else text[i:i + 2]) i += 2 continue match = re.match(r'\\([A-Za-z]+)\{', text[i:]) if not match or match[1] not in known: out.append(text[i]) i += 1 continue command = match[1] try: body, end = argument(text, i + len(command) + 1) except ValueError: out.append(text[i]) i += 1 continue if command in {'hl', 'colorbox'}: try: from .semantic_styles import mark_open except ImportError: from semantic_styles import mark_open from bs4 import BeautifulSoup node = BeautifulSoup('', 'html.parser').mark if command == 'colorbox': node['background'] = body try:body, end = argument(text, end) except ValueError: out.append(text[i:end]); i = end; continue out.append(mark_open(node) + decode_known_inline(body, _depth + 1) + '') elif command in TAGS or command == 'thead': inner = decode_known_inline(body, _depth + 1) tag = 'nvp-header-cell' if command == 'thead' else TAGS[command] out.append('<' + tag + '>' + inner + '') elif command in LITERALS and not body: # Entities cannot be mistaken for LaTeX row/column delimiters. out.append('\\&#' + str(ord(LITERALS[command])) + ';') elif command == 'linebreak' and not body: out.append('') elif command == 'mbox' and not body: pass else: out.append(text[i:end]) i = end return decode_styles(''.join(out)) def restore_header_cells(html_text): from bs4 import BeautifulSoup # Restore explicit breaks after legacy whitespace normalization, which # otherwise collapses consecutive linebreak commands. html_text = html_text.replace('', '
') if '' not in html_text: return html_text soup = BeautifulSoup(html_text, 'html.parser') for cell in soup.find_all(['td', 'th']): markers = cell.find_all('nvp-header-cell') if markers: cell.name = 'th' for marker in markers: marker.unwrap() return str(soup)