Skip to content

fix(html-snapshot): stop merged cells and nested tables misaligning parameter tables (closes #81) - #87

Merged
CarlLee1983 merged 2 commits into
mainfrom
agent/issue-81-html-table-cells
Aug 16, 2026
Merged

fix(html-snapshot): stop merged cells and nested tables misaligning parameter tables (closes #81)#87
CarlLee1983 merged 2 commits into
mainfrom
agent/issue-81-html-table-cells

Conversation

@CarlLee1983

Copy link
Copy Markdown
Owner

Closes #81 —— #73 盤點裡排名第二的短板。

問題

html_snapshot.pyrender_table 有四個已驗證的缺口:_walk(table) 收集整棵子樹的每個 tr(巢狀表格的列併進外層)、colspan/rowspan 屬性從未被讀取(跨欄跨列的儲存格讓整列往左錯位)、header, *body = rows 一律以第一列當表頭、短列以空字串補齊而不視為錯誤。

錯位的表格接著被 source_facts/markdown.py 當成參數表吃進來源事實。假事實比漏掉事實貴:語意完整性閘門是 fail-closed 的,一筆來源根本沒寫的欄位會擋掉正確的擷取,而 operator 讀到的訊息是「來源明明寫了、擷取卻空著」——完全誤導。

改法

  • 只收自己的列:own_rows 遇到巢狀 table 就不往下走,thead 的列排在前面(來源把 tbody 寫在 thead 之前也照樣正確)。
  • 展開 colspan/rowspan 成矩形格網,重複 HTML 說該儲存格佔住的那些位置。留白會丟掉「這幾列屬於哪個群組」的標籤,而那正是巢狀欄位的歸屬資訊。
  • 巢狀表格另成區塊:不併進外層,也不丟掉;外層儲存格的文字不再把內層內容吞成 SubTypephoneString 這種跑馬燈。
  • 超範圍/非數字的 span 當 1,不夾到上限:colspan="9999" 是壞掉的文件,把它當成「我們允許的最寬」等於生出一張沒人寫過的表。

真實來源驗證

benchmarks/tappay-backend 那張含三層巢狀與 rowspan="3" 的表,修改前巢狀列混進外層、欄數不一;修改後三個區塊各自欄數內部一致(14 列 3 欄 / 12 列 4 欄 / 7 列 5 欄)。

範圍說明

benchmark 期望值未變動:各 case 的 sources/ 是已經正規化過的 Markdown,這次改的是產生它們的那一步,不會回頭重跑。既有 benchmark 全綠,代表沒有非預期的連帶影響。日後以 normalize-html-snapshot 重新產生來源時,受影響 case 的來源事實數會改變,屆時照實更新。

版本 metadata 與 release notes 依慣例留給獨立的 release 準備 commit(0.36.0 剛發布)。

Test plan

  • 新增 tests/test_html_snapshot_tables.py(9 個案例,seam 是公開純函式 html_to_markdown)
  • uv run pytest —— 2184 passed
  • uv run ruff check . / npm run docs:check

…saligning parameter tables

render_table 先前把整棵子樹的每個 tr 都當成自己的列(巢狀表格的列因此併進外層)、
完全不讀 colspan/rowspan(跨欄跨列的儲存格讓整列往左錯位)、並一律以第一列當表頭。
錯位的表格接著被 source_facts 當成參數表吃進來源事實,而假事實在 fail-closed 閘門下
會擋掉正確的擷取——operator 看到的是「來源明明寫了、擷取卻空著」這種完全誤導的訊息。

改法:只收自己的列(thead 優先、巢狀表格留給自己)、把 colspan/rowspan 展開成矩形
格網(重複 HTML 說它佔住的那些位置,留白會丟掉標示欄位歸屬的群組標籤)、巢狀表格
另render成自己的區塊而不併進外層,外層儲存格也不再把它的文字吞成跑馬燈。
超出範圍或非數字的 span 一律當 1,不夾到上限——colspan="9999" 是壞掉的文件,
把它當成「我們允許的最寬」等於生出一張沒人寫過的表。

以真實來源驗證:tappay 那張含三層巢狀與 rowspan=3 的表,修改前巢狀列混進外層,
修改後三個區塊各自欄數一致(14/12/7 列,4/5/6 欄)。
… source facts

code review 找到一個 CRITICAL,而且它踩的正是這張票自己的否決項。

把跨欄儲存格的文字重複填進它蓋到的每一欄,會毀掉下游用來認出分組標題列的訊號
(source_facts/markdown.py:367 判「其餘欄位全空」)。實測 `<td colspan='3'>Header</td>`
在修改前後:main 得到 ['api_key'],上一版分支得到 ['Header', 'api_key'],並宣稱有個
型別是 Header、必要是 Header 的參數——來源根本沒寫的欄位變成來源事實,而假事實在
fail-closed 閘門下會擋掉正確的擷取。同一個機制也讓帶分組列的錯誤碼表整張作廢,
記載下界靜靜歸零(['1001'] → [])。

改法:文字只留在自己的位置,跨到的欄位補空;rowspan 例外,沿自己的欄往下重複——
那裡帶下來的是每一列都成立的真值。對齊由格網幾何提供,不需要靠複製文字。

其餘 review 項目一併修掉:未閉合 </tr> 會讓後續每一列變成上一列的子節點,原本整個
表身消失,改為往 tr 內遞迴;重疊的 span 不再靜靜覆蓋,整張表放棄(與錯誤碼表「一列
壞掉作廢整張」同一偏誤);寫在 tbody 之前的 tfoot 排到最後;多列 thead 併成 GFM 唯一
允許的那一列表頭,不再降級成資料列。

順手把 own_rows / nested_tables / span / table_grid 提到模組層級(html_to_markdown
不再是一個 250 行的閉包),註解語言統一為英文,並同步 AGENTS.md 與正規化 spec。
@CarlLee1983

Copy link
Copy Markdown
Owner Author

Code review 的 CRITICAL 成立,而且踩的正是這張票自己的否決項。已修正並推上 9088294

CRITICAL — 跨欄重複填字會生出假參數。 我原本把跨欄儲存格的文字重複填進它蓋到的每一欄,那會毀掉下游認分組標題列的訊號(source_facts/markdown.py:367 判「其餘欄位全空」)。實測 <td colspan='3'>Header</td> 在三欄參數表裡:main 得到 ['api_key'],我的上一版得到 ['Header', 'api_key'],並宣稱有個型別是 Header、必要也是 Header 的參數——來源根本沒寫的欄位變成來源事實。改法:文字只留在自己的位置,跨到的欄位補空;rowspan 例外,沿自己的欄往下重複——那裡帶下來的是每一列都成立的真值。對齊由格網幾何提供,不需要靠複製文字。

HIGH — 錯誤碼表被靜靜作廢。 同一個機制:帶 <td colspan='2'>支付類</td> 分組列的錯誤碼表,我的上一版讓整張表被丟棄(['1001'][]),記載下界歸零。同一個修正解決。

HIGH — 未閉合 </tr> 讓表身整個消失。 解析器沒有 implied end tag,<tr> 未閉合時後續每一列都變成上一列的子節點,而我的 own_rows 遇到 tr 就不往下走。改為往 tr 內遞迴(仍在 table 停住)。

MEDIUM 全部採納:重疊 span 不再靜靜覆蓋,整張表放棄(與錯誤碼表「一列壞掉作廢整張」同一偏誤);寫在 tbody 之前的 tfoot 排到最後;多列 thead 併成 GFM 唯一允許的那一列表頭,不再降級成會被當參數的資料列。

LOW 全部採納:新增七個回歸測試,其中兩個直接組合 html_to_markdown + scan_markdown,斷言的正是「不得產生來源沒寫的事實」這條性質——那是這個檔案自稱要保護、原本卻沒測的東西;絕對值 span 的測試改成斷言精確形狀;own_rows/nested_tables/span/table_grid 提到模組層級(html_to_markdown 不再是 250 行閉包);註解語言統一英文;AGENTS.mddocs/HTML_SNAPSHOT_NORMALIZATION_SPEC.md 依新行為同步。

uv run pytest 2190 passed。真實來源(tappay 三層巢狀 + rowspan=3)三個區塊欄數仍各自一致。

@CarlLee1983
CarlLee1983 merged commit f6dacbc into main Aug 16, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

HTML 表格的合併儲存格與巢狀表格被拉平成錯位的參數表

1 participant