Skip to content

fix(md): size table to the widest row, not the header - #3823

Closed
santhreal wants to merge 1 commit into
docling-project:mainfrom
santhreal:fix/md-table-num-cols
Closed

fix(md): size table to the widest row, not the header#3823
santhreal wants to merge 1 commit into
docling-project:mainfrom
santhreal:fix/md-table-num-cols

Conversation

@santhreal

Copy link
Copy Markdown
Contributor

The Markdown table parser sets num_cols from the header row's cell count (num_cols = len(result_table[0])). When a body row has more cells than the header, the extra cells stay in table_cells but their column index falls outside num_cols, so export_to_markdown and export_to_dataframe build a header-width grid and silently drop them.

This sizes num_cols to the widest row instead, matching the CSV backend (num_cols = max(len(row) ...)), so wider body rows keep all their cells on export. The default=0 also removes a latent result_table[0] IndexError on an empty table.

Repro:

from docling.document_converter import DocumentConverter
from docling.datamodel.base_models import InputFormat

md = "| A | B |\n| --- | --- |\n| 1 | 2 | 3 |\n"
doc = DocumentConverter().convert_string(md, format=InputFormat.MD).document
print(doc.tables[0].data.num_cols)          # before: 2 (expected 3)
print("3" in doc.export_to_markdown())      # before: False -- the cell is lost

Added test_convert_table_body_row_wider_than_header.

Distinct from the trailing-pipe splitting in #3817 and the cell-duplication fix in #3781; this is the num_cols sizing on a different line.

The Markdown table parser set num_cols from the header row's cell count. When
a body row has more cells than the header, those extra cells stayed in
table_cells but their column index fell outside num_cols, so every exporter
(markdown, dataframe) dropped them and the data was silently lost.

Size num_cols to the widest row instead, matching the CSV backend, so wider
body rows keep all their cells on export.

Signed-off-by: santhreal <64453045+santhreal@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

DCO Check Passed

Thanks @santhreal, all your commits are properly signed off. 🎉

@mergify

mergify Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Merge Protections

🟢 Merge protection satisfied — ready to merge.

Show 1 satisfied protection

🟢 Enforce conventional commit

Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/

  • title ~= ^(fix|feat|docs|style|refactor|perf|test|build|ci|chore|revert)(?:\(.+\))?(!)?:

@codecov

codecov Bot commented Jul 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@ceberam

ceberam commented Jul 20, 2026

Copy link
Copy Markdown
Member

Thanks @santhreal for your interest in Docling and your contribution.

However, the changes on this PR are not a fix. Docling behaves as designed in the scenario described in this issue.
Even though the Markdown basic syntax does not natively support tables, most applications providing table extensions, such as GFM, state that the header and delimiter rows determine the strict structural layout and alignment properties for each column. Tools like GitHub, VS Code, or Jupyter will render tables according to that statement.
More precisely, according to GFM:

If there are a number of cells fewer than the number of cells in the header row, empty cells are inserted. If there are greater, the excess is ignored:

This is exactly how Docling handles these edge cases.

In your example, "| A | B |\n| --- | --- |\n| 1 | 2 | 3 |\n" is rendered in GitHub as a table with 2 columns:

A B
1 2

Please, follow the contributor's guidelines and open an issue if you identify a bug before suggesting a PR to avoid this type of situations.

@ceberam ceberam closed this Jul 20, 2026
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.

2 participants