Skip to content

Preserve explicit table lines outside the natural edge span (fixes #1335)#1371

Open
Cyberfilo wants to merge 1 commit into
jsvine:developfrom
Cyberfilo:fix/issue-1335-explicit-last-column
Open

Preserve explicit table lines outside the natural edge span (fixes #1335)#1371
Cyberfilo wants to merge 1 commit into
jsvine:developfrom
Cyberfilo:fix/issue-1335-explicit-last-column

Conversation

@Cyberfilo

Copy link
Copy Markdown

What

When page.extract_table(...) is called with vertical_strategy="explicit" (or horizontal_strategy="explicit"), the user-supplied lines define the column / row boundaries. Edges of the opposite orientation are still derived from text clustering or detected page lines, and those are only as wide as the underlying objects.

words_to_edges_h (and the lines variants for horizontal edges) span just min_x0..max_x1 of the rows they detect. edges_to_intersections then keeps only the vertical edges whose x0 falls inside [h.x0 - x_tol, h.x1 + x_tol]. When an explicit vertical line sits outside that span — common when the leftmost or rightmost column is narrow, right-aligned, or contains only short / multi-line text — the intersection is rejected and the entire column collapses into its neighbour (or disappears entirely if it is the only one beyond the span).

Fix

In TableFinder.get_edges(), after the base + explicit edges are concatenated, extend each horizontal edge's x0 / x1 to cover the x-range of any explicit vertical lines (and symmetrically extend vertical edges' top / bottom to cover any explicit horizontals).

Explicit edges already span the full page when supplied as floats, and span their declared bbox when supplied as dicts — so this only ever widens edges derived from words or page lines, never narrows or moves anything. Tables that do not use explicit lines are untouched.

Repro / test

Added test_issue_1335_explicit_outside_text_span in tests/test_table.py. It constructs a three-row, three-column layout with a narrow last column (text ends ~130 px before the rightmost explicit vertical) and asserts that:

  • all four explicit vertical positions produce intersections;
  • the resulting table contains rows with all three column-cells present.

Without the patch, only the inner two explicit verticals produce intersections and the table collapses to a single column. Running the new test against develop:

$ pytest tests/test_table.py::Test::test_issue_1335_explicit_outside_text_span
... FAILED  (assert [200.0, 350.0] == [50, 200, 350, 500])

With the patch:

$ pytest tests/test_table.py::Test::test_issue_1335_explicit_outside_text_span
... PASSED

Verification

  • make tests — 165 passed (the pre-existing test_repair.py::test_from_issue_932 failure on systems without Ghostscript is unchanged).
  • make lint — clean (flake8, mypy --strict, black --check, isort --check).
  • Added entry under ## Unreleased in CHANGELOG.md and added myself to the contributors list per CONTRIBUTING.md.

Fixes #1335.

When `extract_table` is called with `vertical_strategy="explicit"` (or
`horizontal_strategy="explicit"`), the user-supplied lines define the
column (resp. row) boundaries.  Edges of the opposite orientation are
still derived from text clustering or detected lines, and `words_to_edges_h`
/ `words_to_edges_v` only span the range of the underlying objects.  When
an explicit line sits outside that span — common when the leftmost or
rightmost column is narrow, right-aligned, or contains only short text —
`edges_to_intersections` rejects the intersection and the entire column
collapses into a neighbour.

Extend the horizontal edges to cover the x-range of any explicit vertical
lines (and symmetrically for explicit horizontals) before computing
intersections.  Explicit edges already span the full page, so this only
widens edges derived from words or page lines; no other tables are
affected.

Fixes jsvine#1335.
@Cyberfilo

Cyberfilo commented May 13, 2026

Copy link
Copy Markdown
Author

@jsvine @samkit-jain please review

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.

1 participant