fix(serializer): derive markdown table header rows from column_header flags - #723
Open
acharyaanusha wants to merge 3 commits into
Open
fix(serializer): derive markdown table header rows from column_header flags#723acharyaanusha wants to merge 3 commits into
acharyaanusha wants to merge 3 commits into
Conversation
Contributor
|
✅ DCO Check Passed Thanks @acharyaanusha, all your commits are properly signed off. 🎉 |
Contributor
Merge Protections🔴 1 of 2 protections blocking · waiting on 👀 reviews
🔴 Require two reviewer for test updatesWaiting for
This rule is failing.When test data is updated, we require two reviewers
Show 1 satisfied protection🟢 Enforce conventional commitMake sure that we follow https://www.conventionalcommits.org/en/v1.0.0/
|
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
… flags MarkdownTableSerializer hardcoded grid row 0 as the only header row, while TableItem._export_to_dataframe_with_options, the HTML serializer and the OTSL export all derive the header rows from TableCell.column_header. A table with a stacked header therefore serialized to markdown with its lower header rows demoted to data rows, and HybridChunker repeated only the first of them at the top of each chunk of an oversized table. Take the header row count from the flags and flatten those rows into the single header row GFM allows, dropping the repeated text a cell spanning several header rows produces. When no cell in the table carries column_header the previous behavior is kept, since backends that never set the flag cannot be told apart from genuinely headerless tables. Signed-off-by: Anusha Acharya <acharyaanusha123@gmail.com>
The empty-header-block branch of _flatten_header_rows was the one line of the patch left uncovered. Pin the behavior it produces: with no leading run of flagged rows there is no header to promote, so the header is empty and every row stays in the body rather than one being consumed. Signed-off-by: Anusha Acharya <acharyaanusha123@gmail.com>
Review feedback: a blank space loses the boundary between header levels, so "native backend" over "TTS" is indistinguishable from a single cell reading "native backend TTS". Join with " - " instead, kept as a module constant, and document the header-resolution contract on MarkdownTableSerializer. Signed-off-by: Anusha Acharya <acharyaanusha123@gmail.com>
acharyaanusha
force-pushed
the
fix/markdown-table-column-header
branch
from
August 19, 2026 17:18
4327e8a to
0158bf1
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #722.
MarkdownTableSerializerhardcoded grid row 0 as the only header row, whileTableItem._export_to_dataframe_with_options, the HTML serializer andexport_to_otslall derive the header rows fromTableCell.column_header. A table with a stacked header serialized to Markdown with its lower header rows demoted to data rows, andHybridChunkerrepeated only the first of them atop each chunk of an oversized table.This takes the header row count from the flags and flattens those rows into the single header row GFM allows, dropping the repeated text a cell spanning several header rows produces (so
human/humanstayshuman, nothuman human).When no cell in the table carries
column_header, the previous behavior is kept. Backends that never set the flag cannot be told apart from genuinely headerless tables, and several*.dt.jsonfixtures round-trip with zero flags. Making it unconditional instead changed output for those too, so I left it — see the first open question in #722 if you would rather it be strict.Ground truth
Five ground-truth files are regenerated. Every diff recovers real column names from the body:
2206.01062.yaml.md/.paged.md(DocLayNet) —class label | Count | % of Total Train | ...was a body row under a header of% of Totalrepeats; likewiseMRCNN R50/MRCNN R101,Class-count Split,Testing on PLN2408.09869v3_enriched_p1_mark_meta_{true,false}.gt.md—native backend TTS | native backend Pages/s | native backend Mem0b_out_chunks.json/0d_out_chunks.json— the same headers as repeated in chunksNumeric columns shift to right-alignment in a few places, because
_column_typeno longer sees the former header row when detecting the column type.Verification
docling-coresuite: no new failures, +3 from the tests added here. My environment has pre-existing unrelated failures (missingcv2stubs,doclangschema resources, and a Pillow that re-encodes the fixture PNGs), so I diffed the failure sets before and after rather than trusting the totals; the sets are identical.ruff format,ruff check, andmypyclean on the changed files.docling2.120.2 and diffed the full 248-line Markdown export before and after. Exactly one table changes; the two single-header tables in the same document are byte-identical.Tests
Three cases in
test/test_serialization.py: a stacked header flattened, repeated span text deduplicated, and a table with no header flags keeping its first row as the header.