Skip to content

Commit 238657f

Browse files
authored
fix: chunking dropping table content (#4352)
## Preserve mixed-content tail text in table HTML ### Summary `HtmlTable.from_html_text` compactification cleared every element's `.tail`, silently dropping any text between inline children of a `<td>`. In practice this deleted real content like `": do not..."` after `<b>NOTICE</b>`, bullet lines following each `<br/>`, and any inter-tag prose in rich table cells — visible whenever a table was chunked (any strategy: `basic`, `by_title`, `by_page`). Pure-whitespace tails are still stripped (those are just pretty-print indent). Tails carrying content are now kept, with internal whitespace runs collapsed and a single leading/trailing space preserved so adjacent text doesn't run together. ### Changes - `unstructured/common/html_table.py`: replace the blanket `e.tail = None` with whitespace-aware normalization. - `test_unstructured/common/test_html_table.py`: two regression tests covering mixed inline markup, `<br/>`-separated lines, and whitespace collapsing. - Bump to `0.22.28` + changelog entry. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk: localized change to table HTML minification that preserves previously-dropped text; main risk is minor whitespace/serialization differences in downstream table chunking output. > > **Overview** > Fixes `HtmlTable.from_html_text()` compactification to **stop deleting meaningful mixed-content tail text** (text between inline children like `<b>foo</b> bar` or between `<br/>` siblings), while still dropping pure formatting/indent whitespace and collapsing internal whitespace runs. > > Adds regression tests for mixed inline markup and `<br/>`-separated cell content, and bumps the library to `0.22.28` with a changelog entry describing the fix. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit fe27d35. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent 8daa154 commit 238657f

4 files changed

Lines changed: 41 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 0.22.28
2+
3+
### Fixes
4+
5+
- **Preserve mixed-content tail text in table HTML**: `HtmlTable` compactification previously cleared every element's `.tail`, silently dropping real text between inline children. Pure-whitespace tails are still removed, but tails carrying content are now kept with internal whitespace collapsed.
6+
17
## 0.22.27
28

39
### Fixes

test_unstructured/common/test_html_table.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,28 @@ def it_removes_any_extra_whitespace_between_elements_and_normalizes_whitespace_i
125125
)
126126
assert html_table.html == "<table><tr><td>abc def ghi</td></tr></table>"
127127

128+
def it_preserves_tail_text_in_mixed_content_cells(self):
129+
"""Tail text (between inline children) carries real content and must not be dropped."""
130+
html_table = HtmlTable.from_html_text(
131+
"<table><tr>"
132+
"<td><b>foo</b> bar <b>baz</b></td>"
133+
"<td><b>x</b><br/>y<br/>z</td>"
134+
"</tr></table>"
135+
)
136+
assert html_table.html == (
137+
"<table><tr>"
138+
"<td><b>foo</b> bar <b>baz</b></td>"
139+
"<td><b>x</b><br/>y<br/>z</td>"
140+
"</tr></table>"
141+
)
142+
143+
def and_it_normalizes_whitespace_within_tail_text(self):
144+
"""Tail whitespace runs are collapsed, but leading/trailing spaces are kept."""
145+
html_table = HtmlTable.from_html_text(
146+
"<table><tr><td><b>a</b> b\n c <b>d</b></td></tr></table>"
147+
)
148+
assert html_table.html == "<table><tr><td><b>a</b> b c <b>d</b></td></tr></table>"
149+
128150
def it_can_serialize_the_table_element_to_str_html_text(self):
129151
table = fragment_fromstring("<table><tr><td>foobar</td></tr></table>")
130152
html_table = HtmlTable(table)

unstructured/__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.22.27" # pragma: no cover
1+
__version__ = "0.22.28" # pragma: no cover

unstructured/common/html_table.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,19 @@ def from_html_text(cls, html_text: str) -> HtmlTable:
104104
if e.text:
105105
e.text = " ".join(e.text.split())
106106

107-
# -- remove all tails, those are newline + indent if anything --
107+
# -- normalize tails. A tail is the text between an element's closing tag and the
108+
# -- start of the next sibling. Pure-whitespace tails are pretty-printing noise and
109+
# -- can be dropped, but tails can also carry real content (e.g. mixed inline
110+
# -- markup like `<b>foo</b> bar <b>baz</b>` or text between `<br/>` tags), which
111+
# -- must be preserved.
108112
if e.tail:
109-
e.tail = None
113+
parts = e.tail.split()
114+
if not parts:
115+
e.tail = None
116+
else:
117+
prefix = " " if e.tail[0].isspace() else ""
118+
suffix = " " if e.tail[-1].isspace() else ""
119+
e.tail = prefix + " ".join(parts) + suffix
110120

111121
return cls(table, header_row_idxs=header_row_idxs, source_row_htmls=source_row_htmls)
112122

0 commit comments

Comments
 (0)