# 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 + "" + tag + ">")
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)